From 41974ae5265fbc23a06f276f9e008d5dad020e0b Mon Sep 17 00:00:00 2001
From: Ben Longbons <b.r.longbons@gmail.com>
Date: Thu, 30 Aug 2012 16:16:25 -0700
Subject: Rename files for C++ conversion. Does not compile.

After updating, you can remove these files, as shown in 'git status':

 Untracked files:
   (use "git add <file>..." to include in what will be committed)

	src/map/magic-interpreter-lexer.c
	src/map/magic-interpreter-parser.c
	src/map/magic-interpreter-parser.h
---
 .gitignore                           |     9 +-
 GNUmakefile                          |    43 +-
 deps.make                            |   308 -
 make.defs                            |    15 +-
 src/char/char.c                      |  4076 -----------
 src/char/char.cpp                    |  4076 +++++++++++
 src/char/char.h                      |    32 -
 src/char/char.hpp                    |    32 +
 src/char/int_guild.c                 |  1757 -----
 src/char/int_guild.cpp               |  1757 +++++
 src/char/int_guild.h                 |    16 -
 src/char/int_guild.hpp               |    16 +
 src/char/int_party.c                 |   673 --
 src/char/int_party.cpp               |   673 ++
 src/char/int_party.h                 |    14 -
 src/char/int_party.hpp               |    14 +
 src/char/int_storage.c               |   576 --
 src/char/int_storage.cpp             |   576 ++
 src/char/int_storage.h               |    18 -
 src/char/int_storage.hpp             |    18 +
 src/char/inter.c                     |   635 --
 src/char/inter.cpp                   |   635 ++
 src/char/inter.h                     |    19 -
 src/char/inter.hpp                   |    19 +
 src/common/core.c                    |    97 -
 src/common/core.cpp                  |    97 +
 src/common/core.h                    |    19 -
 src/common/core.hpp                  |    19 +
 src/common/db.c                      |   546 --
 src/common/db.cpp                    |   546 ++
 src/common/db.h                      |    87 -
 src/common/db.hpp                    |    87 +
 src/common/grfio.c                   |   212 -
 src/common/grfio.cpp                 |   212 +
 src/common/grfio.h                   |    17 -
 src/common/grfio.hpp                 |    17 +
 src/common/lock.c                    |    36 -
 src/common/lock.cpp                  |    36 +
 src/common/lock.h                    |     8 -
 src/common/lock.hpp                  |     8 +
 src/common/md5calc.c                 |   339 -
 src/common/md5calc.cpp               |   339 +
 src/common/md5calc.h                 |    64 -
 src/common/md5calc.hpp               |    64 +
 src/common/mmo.h                     |   283 -
 src/common/mmo.hpp                   |   283 +
 src/common/mt_rand.c                 |   116 -
 src/common/mt_rand.cpp               |   116 +
 src/common/mt_rand.h                 |    24 -
 src/common/mt_rand.hpp               |    24 +
 src/common/nullpo.c                  |    66 -
 src/common/nullpo.cpp                |    66 +
 src/common/nullpo.h                  |    61 -
 src/common/nullpo.hpp                |    61 +
 src/common/sanity.h                  |    36 -
 src/common/sanity.hpp                |    31 +
 src/common/socket.c                  |   405 --
 src/common/socket.cpp                |   405 ++
 src/common/socket.h                  |   135 -
 src/common/socket.hpp                |   135 +
 src/common/timer.c                   |   257 -
 src/common/timer.cpp                 |   257 +
 src/common/timer.h                   |    61 -
 src/common/timer.hpp                 |    61 +
 src/common/utils.h                   |    18 -
 src/common/utils.hpp                 |    18 +
 src/common/version.h                 |    24 -
 src/common/version.hpp               |    24 +
 src/ladmin/ladmin.c                  |  6476 -----------------
 src/ladmin/ladmin.cpp                |  6476 +++++++++++++++++
 src/ladmin/ladmin.h                  |    11 -
 src/ladmin/ladmin.hpp                |    11 +
 src/login/login.c                    |  5038 --------------
 src/login/login.cpp                  |  5038 ++++++++++++++
 src/login/login.h                    |    41 -
 src/login/login.hpp                  |    41 +
 src/map/atcommand.c                  |  8728 -----------------------
 src/map/atcommand.cpp                |  8728 +++++++++++++++++++++++
 src/map/atcommand.h                  |   226 -
 src/map/atcommand.hpp                |   226 +
 src/map/battle.c                     |  6282 -----------------
 src/map/battle.cpp                   |  6282 +++++++++++++++++
 src/map/battle.h                     |   357 -
 src/map/battle.hpp                   |   357 +
 src/map/chat.c                       |   395 --
 src/map/chat.cpp                     |   395 ++
 src/map/chat.h                       |    25 -
 src/map/chat.hpp                     |    25 +
 src/map/chrif.c                      |  1307 ----
 src/map/chrif.cpp                    |  1307 ++++
 src/map/chrif.h                      |    36 -
 src/map/chrif.hpp                    |    36 +
 src/map/clif.c                       | 10332 ---------------------------
 src/map/clif.cpp                     | 10332 +++++++++++++++++++++++++++
 src/map/clif.h                       |   285 -
 src/map/clif.hpp                     |   285 +
 src/map/guild.c                      |  1915 -----
 src/map/guild.cpp                    |  1915 +++++
 src/map/guild.h                      |    95 -
 src/map/guild.hpp                    |    95 +
 src/map/intif.c                      |  1201 ----
 src/map/intif.cpp                    |  1201 ++++
 src/map/intif.h                      |    56 -
 src/map/intif.hpp                    |    56 +
 src/map/itemdb.c                     |   753 --
 src/map/itemdb.cpp                   |   753 ++
 src/map/itemdb.h                     |    82 -
 src/map/itemdb.hpp                   |    82 +
 src/map/magic-expr-eval.h            |    44 -
 src/map/magic-expr-eval.hpp          |    44 +
 src/map/magic-expr.c                 |  1655 -----
 src/map/magic-expr.cpp               |  1655 +++++
 src/map/magic-expr.h                 |    95 -
 src/map/magic-expr.hpp               |    95 +
 src/map/magic-interpreter-aux.h      |     8 -
 src/map/magic-interpreter-aux.hpp    |     8 +
 src/map/magic-interpreter-base.c     |   562 --
 src/map/magic-interpreter-base.cpp   |   562 ++
 src/map/magic-interpreter-lexer.l    |   140 -
 src/map/magic-interpreter-lexer.lpp  |   140 +
 src/map/magic-interpreter-parser.y   |  1089 ---
 src/map/magic-interpreter-parser.ypp |  1089 +++
 src/map/magic-interpreter.h          |   500 --
 src/map/magic-interpreter.hpp        |   500 ++
 src/map/magic-stmt.c                 |  1597 -----
 src/map/magic-stmt.cpp               |  1597 +++++
 src/map/magic.c                      |   130 -
 src/map/magic.cpp                    |   130 +
 src/map/magic.h                      |    90 -
 src/map/magic.hpp                    |    90 +
 src/map/map.c                        |  2215 ------
 src/map/map.cpp                      |  2215 ++++++
 src/map/map.h                        |   822 ---
 src/map/map.hpp                      |   822 +++
 src/map/mob.c                        |  5070 --------------
 src/map/mob.cpp                      |  5070 ++++++++++++++
 src/map/mob.h                        |   151 -
 src/map/mob.hpp                      |   151 +
 src/map/npc.c                        |  2378 -------
 src/map/npc.cpp                      |  2378 +++++++
 src/map/npc.h                        |    64 -
 src/map/npc.hpp                      |    64 +
 src/map/party.c                      |   790 ---
 src/map/party.cpp                    |   790 +++
 src/map/party.h                      |    52 -
 src/map/party.hpp                    |    52 +
 src/map/path.c                       |   445 --
 src/map/path.cpp                     |   445 ++
 src/map/pc.c                         |  9032 ------------------------
 src/map/pc.cpp                       |  9032 ++++++++++++++++++++++++
 src/map/pc.h                         |   210 -
 src/map/pc.hpp                       |   210 +
 src/map/script.c                     |  8145 ----------------------
 src/map/script.cpp                   |  8145 ++++++++++++++++++++++
 src/map/script.h                     |    52 -
 src/map/script.hpp                   |    52 +
 src/map/skill-pools.c                |   158 -
 src/map/skill-pools.cpp              |   158 +
 src/map/skill.c                      | 12279 ---------------------------------
 src/map/skill.cpp                    | 12279 +++++++++++++++++++++++++++++++++
 src/map/skill.h                      |   891 ---
 src/map/skill.hpp                    |   891 +++
 src/map/storage.c                    |   787 ---
 src/map/storage.cpp                  |   787 +++
 src/map/storage.h                    |    54 -
 src/map/storage.hpp                  |    54 +
 src/map/tmw.c                        |   187 -
 src/map/tmw.cpp                      |   187 +
 src/map/tmw.h                        |    14 -
 src/map/tmw.hpp                      |    14 +
 src/map/trade.c                      |   432 --
 src/map/trade.cpp                    |   432 ++
 src/map/trade.h                      |    14 -
 src/map/trade.hpp                    |    14 +
 src/tool/adduser.c                   |   115 -
 src/tool/adduser.cpp                 |   115 +
 src/tool/convert.c                   |   302 -
 src/tool/convert.cpp                 |   302 +
 src/tool/eathena-monitor.c           |   223 -
 src/tool/eathena-monitor.cpp         |   223 +
 src/tool/itemfrob.c                  |   130 -
 src/tool/itemfrob.cpp                |   130 +
 src/tool/mapfrob.c                   |   129 -
 src/tool/mapfrob.cpp                 |   129 +
 src/tool/marriage-info.c             |   482 --
 src/tool/marriage-info.cpp           |   482 ++
 src/tool/moneycount/athena_text.cpp  |     4 +-
 src/tool/moneycount/athena_text.h    |     9 -
 src/tool/moneycount/athena_text.hpp  |     9 +
 src/tool/moneycount/main.cpp         |     4 +-
 src/tool/moneycount/mmo.h            |   309 -
 src/tool/moneycount/mmo.hpp          |   309 +
 src/tool/skillfrob.c                 |    80 -
 src/tool/skillfrob.cpp               |    80 +
 src/webserver/generate.c             |    35 -
 src/webserver/generate.cpp           |    35 +
 src/webserver/htmlstyle.c            |    45 -
 src/webserver/htmlstyle.cpp          |    45 +
 src/webserver/logs.c                 |     8 -
 src/webserver/logs.cpp               |     8 +
 src/webserver/main.c                 |   145 -
 src/webserver/main.cpp               |   145 +
 src/webserver/pages/about.c          |     6 -
 src/webserver/pages/about.cpp        |     6 +
 src/webserver/pages/notdone.c        |     6 -
 src/webserver/pages/notdone.cpp      |     6 +
 src/webserver/pages/sample.c         |    22 -
 src/webserver/pages/sample.cpp       |    22 +
 src/webserver/parse.c                |   132 -
 src/webserver/parse.cpp              |   132 +
 210 files changed, 106729 insertions(+), 107045 deletions(-)
 delete mode 100644 deps.make
 delete mode 100644 src/char/char.c
 create mode 100644 src/char/char.cpp
 delete mode 100644 src/char/char.h
 create mode 100644 src/char/char.hpp
 delete mode 100644 src/char/int_guild.c
 create mode 100644 src/char/int_guild.cpp
 delete mode 100644 src/char/int_guild.h
 create mode 100644 src/char/int_guild.hpp
 delete mode 100644 src/char/int_party.c
 create mode 100644 src/char/int_party.cpp
 delete mode 100644 src/char/int_party.h
 create mode 100644 src/char/int_party.hpp
 delete mode 100644 src/char/int_storage.c
 create mode 100644 src/char/int_storage.cpp
 delete mode 100644 src/char/int_storage.h
 create mode 100644 src/char/int_storage.hpp
 delete mode 100644 src/char/inter.c
 create mode 100644 src/char/inter.cpp
 delete mode 100644 src/char/inter.h
 create mode 100644 src/char/inter.hpp
 delete mode 100644 src/common/core.c
 create mode 100644 src/common/core.cpp
 delete mode 100644 src/common/core.h
 create mode 100644 src/common/core.hpp
 delete mode 100644 src/common/db.c
 create mode 100644 src/common/db.cpp
 delete mode 100644 src/common/db.h
 create mode 100644 src/common/db.hpp
 delete mode 100644 src/common/grfio.c
 create mode 100644 src/common/grfio.cpp
 delete mode 100644 src/common/grfio.h
 create mode 100644 src/common/grfio.hpp
 delete mode 100644 src/common/lock.c
 create mode 100644 src/common/lock.cpp
 delete mode 100644 src/common/lock.h
 create mode 100644 src/common/lock.hpp
 delete mode 100644 src/common/md5calc.c
 create mode 100644 src/common/md5calc.cpp
 delete mode 100644 src/common/md5calc.h
 create mode 100644 src/common/md5calc.hpp
 delete mode 100644 src/common/mmo.h
 create mode 100644 src/common/mmo.hpp
 delete mode 100644 src/common/mt_rand.c
 create mode 100644 src/common/mt_rand.cpp
 delete mode 100644 src/common/mt_rand.h
 create mode 100644 src/common/mt_rand.hpp
 delete mode 100644 src/common/nullpo.c
 create mode 100644 src/common/nullpo.cpp
 delete mode 100644 src/common/nullpo.h
 create mode 100644 src/common/nullpo.hpp
 delete mode 100644 src/common/sanity.h
 create mode 100644 src/common/sanity.hpp
 delete mode 100644 src/common/socket.c
 create mode 100644 src/common/socket.cpp
 delete mode 100644 src/common/socket.h
 create mode 100644 src/common/socket.hpp
 delete mode 100644 src/common/timer.c
 create mode 100644 src/common/timer.cpp
 delete mode 100644 src/common/timer.h
 create mode 100644 src/common/timer.hpp
 delete mode 100644 src/common/utils.h
 create mode 100644 src/common/utils.hpp
 delete mode 100644 src/common/version.h
 create mode 100644 src/common/version.hpp
 delete mode 100644 src/ladmin/ladmin.c
 create mode 100644 src/ladmin/ladmin.cpp
 delete mode 100644 src/ladmin/ladmin.h
 create mode 100644 src/ladmin/ladmin.hpp
 delete mode 100644 src/login/login.c
 create mode 100644 src/login/login.cpp
 delete mode 100644 src/login/login.h
 create mode 100644 src/login/login.hpp
 delete mode 100644 src/map/atcommand.c
 create mode 100644 src/map/atcommand.cpp
 delete mode 100644 src/map/atcommand.h
 create mode 100644 src/map/atcommand.hpp
 delete mode 100644 src/map/battle.c
 create mode 100644 src/map/battle.cpp
 delete mode 100644 src/map/battle.h
 create mode 100644 src/map/battle.hpp
 delete mode 100644 src/map/chat.c
 create mode 100644 src/map/chat.cpp
 delete mode 100644 src/map/chat.h
 create mode 100644 src/map/chat.hpp
 delete mode 100644 src/map/chrif.c
 create mode 100644 src/map/chrif.cpp
 delete mode 100644 src/map/chrif.h
 create mode 100644 src/map/chrif.hpp
 delete mode 100644 src/map/clif.c
 create mode 100644 src/map/clif.cpp
 delete mode 100644 src/map/clif.h
 create mode 100644 src/map/clif.hpp
 delete mode 100644 src/map/guild.c
 create mode 100644 src/map/guild.cpp
 delete mode 100644 src/map/guild.h
 create mode 100644 src/map/guild.hpp
 delete mode 100644 src/map/intif.c
 create mode 100644 src/map/intif.cpp
 delete mode 100644 src/map/intif.h
 create mode 100644 src/map/intif.hpp
 delete mode 100644 src/map/itemdb.c
 create mode 100644 src/map/itemdb.cpp
 delete mode 100644 src/map/itemdb.h
 create mode 100644 src/map/itemdb.hpp
 delete mode 100644 src/map/magic-expr-eval.h
 create mode 100644 src/map/magic-expr-eval.hpp
 delete mode 100644 src/map/magic-expr.c
 create mode 100644 src/map/magic-expr.cpp
 delete mode 100644 src/map/magic-expr.h
 create mode 100644 src/map/magic-expr.hpp
 delete mode 100644 src/map/magic-interpreter-aux.h
 create mode 100644 src/map/magic-interpreter-aux.hpp
 delete mode 100644 src/map/magic-interpreter-base.c
 create mode 100644 src/map/magic-interpreter-base.cpp
 delete mode 100644 src/map/magic-interpreter-lexer.l
 create mode 100644 src/map/magic-interpreter-lexer.lpp
 delete mode 100644 src/map/magic-interpreter-parser.y
 create mode 100644 src/map/magic-interpreter-parser.ypp
 delete mode 100644 src/map/magic-interpreter.h
 create mode 100644 src/map/magic-interpreter.hpp
 delete mode 100644 src/map/magic-stmt.c
 create mode 100644 src/map/magic-stmt.cpp
 delete mode 100644 src/map/magic.c
 create mode 100644 src/map/magic.cpp
 delete mode 100644 src/map/magic.h
 create mode 100644 src/map/magic.hpp
 delete mode 100644 src/map/map.c
 create mode 100644 src/map/map.cpp
 delete mode 100644 src/map/map.h
 create mode 100644 src/map/map.hpp
 delete mode 100644 src/map/mob.c
 create mode 100644 src/map/mob.cpp
 delete mode 100644 src/map/mob.h
 create mode 100644 src/map/mob.hpp
 delete mode 100644 src/map/npc.c
 create mode 100644 src/map/npc.cpp
 delete mode 100644 src/map/npc.h
 create mode 100644 src/map/npc.hpp
 delete mode 100644 src/map/party.c
 create mode 100644 src/map/party.cpp
 delete mode 100644 src/map/party.h
 create mode 100644 src/map/party.hpp
 delete mode 100644 src/map/path.c
 create mode 100644 src/map/path.cpp
 delete mode 100644 src/map/pc.c
 create mode 100644 src/map/pc.cpp
 delete mode 100644 src/map/pc.h
 create mode 100644 src/map/pc.hpp
 delete mode 100644 src/map/script.c
 create mode 100644 src/map/script.cpp
 delete mode 100644 src/map/script.h
 create mode 100644 src/map/script.hpp
 delete mode 100644 src/map/skill-pools.c
 create mode 100644 src/map/skill-pools.cpp
 delete mode 100644 src/map/skill.c
 create mode 100644 src/map/skill.cpp
 delete mode 100644 src/map/skill.h
 create mode 100644 src/map/skill.hpp
 delete mode 100644 src/map/storage.c
 create mode 100644 src/map/storage.cpp
 delete mode 100644 src/map/storage.h
 create mode 100644 src/map/storage.hpp
 delete mode 100644 src/map/tmw.c
 create mode 100644 src/map/tmw.cpp
 delete mode 100644 src/map/tmw.h
 create mode 100644 src/map/tmw.hpp
 delete mode 100644 src/map/trade.c
 create mode 100644 src/map/trade.cpp
 delete mode 100644 src/map/trade.h
 create mode 100644 src/map/trade.hpp
 delete mode 100644 src/tool/adduser.c
 create mode 100644 src/tool/adduser.cpp
 delete mode 100644 src/tool/convert.c
 create mode 100644 src/tool/convert.cpp
 delete mode 100644 src/tool/eathena-monitor.c
 create mode 100644 src/tool/eathena-monitor.cpp
 delete mode 100644 src/tool/itemfrob.c
 create mode 100644 src/tool/itemfrob.cpp
 delete mode 100644 src/tool/mapfrob.c
 create mode 100644 src/tool/mapfrob.cpp
 delete mode 100644 src/tool/marriage-info.c
 create mode 100644 src/tool/marriage-info.cpp
 delete mode 100644 src/tool/moneycount/athena_text.h
 create mode 100644 src/tool/moneycount/athena_text.hpp
 delete mode 100644 src/tool/moneycount/mmo.h
 create mode 100644 src/tool/moneycount/mmo.hpp
 delete mode 100644 src/tool/skillfrob.c
 create mode 100644 src/tool/skillfrob.cpp
 delete mode 100644 src/webserver/generate.c
 create mode 100644 src/webserver/generate.cpp
 delete mode 100644 src/webserver/htmlstyle.c
 create mode 100644 src/webserver/htmlstyle.cpp
 delete mode 100644 src/webserver/logs.c
 create mode 100644 src/webserver/logs.cpp
 delete mode 100644 src/webserver/main.c
 create mode 100644 src/webserver/main.cpp
 delete mode 100644 src/webserver/pages/about.c
 create mode 100644 src/webserver/pages/about.cpp
 delete mode 100644 src/webserver/pages/notdone.c
 create mode 100644 src/webserver/pages/notdone.cpp
 delete mode 100644 src/webserver/pages/sample.c
 create mode 100644 src/webserver/pages/sample.cpp
 delete mode 100644 src/webserver/parse.c
 create mode 100644 src/webserver/parse.cpp

diff --git a/.gitignore b/.gitignore
index d59b2ef..361fe2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,8 @@
 /map-server
 /eathena-monitor
 # Generated source files
-src/map/magic-interpreter-parser.h
-src/map/magic-interpreter-parser.c
-src/map/magic-interpreter-lexer.c
-
+/src/map/magic-interpreter-parser.hpp
+/src/map/magic-interpreter-parser.cpp
+/src/map/magic-interpreter-lexer.cpp
+# generated header dependencies
+/deps.make
diff --git a/GNUmakefile b/GNUmakefile
index 4162d7a..b00e55c 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -11,29 +11,29 @@ include make.defs
 	+mkdir -p $@
 
 # The default recipe is suboptimal
-%.c: %.l
+%.cpp: %.lpp
 	$(LEX) -o $@ $<
-%.c %.h: %.y
-	$(BISON) -d -o $*.c $<
+%.cpp %.h: %.ypp
+	$(BISON) -d -o $*.cpp $<
 
 
 # All this duplication is required because make handles pattern rules specially
-${BUILD_DIR}/char/%.o: src/char/%.c | ${BUILD_DIR}/char/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/common/%.o: src/common/%.c | ${BUILD_DIR}/common/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/ladmin/%.o: src/ladmin/%.c | ${BUILD_DIR}/ladmin/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/login/%.o: src/login/%.c | ${BUILD_DIR}/login/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/map/%.o: src/map/%.c | ${BUILD_DIR}/map/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/tool/%.o: src/tool/%.c | ${BUILD_DIR}/tool/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/webserver/%.o: src/webserver/%.c | ${BUILD_DIR}/webserver/
-	$(COMPILE.c) -o $@ $<
-${BUILD_DIR}/webserver/pages/%.o: src/webserver/pages/%.c | ${BUILD_DIR}/webserver/pages/
-	$(COMPILE.c) -o $@ $<
+${BUILD_DIR}/char/%.o: src/char/%.cpp | ${BUILD_DIR}/char/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/common/%.o: src/common/%.cpp | ${BUILD_DIR}/common/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/ladmin/%.o: src/ladmin/%.cpp | ${BUILD_DIR}/ladmin/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/login/%.o: src/login/%.cpp | ${BUILD_DIR}/login/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/map/%.o: src/map/%.cpp | ${BUILD_DIR}/map/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/tool/%.o: src/tool/%.cpp | ${BUILD_DIR}/tool/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/webserver/%.o: src/webserver/%.cpp | ${BUILD_DIR}/webserver/
+	$(COMPILE.cpp) -o $@ $<
+${BUILD_DIR}/webserver/pages/%.o: src/webserver/pages/%.cpp | ${BUILD_DIR}/webserver/pages/
+	$(COMPILE.cpp) -o $@ $<
 
 PROGS = login-server char-server map-server ladmin eathena-monitor webserver
 # Things to actually make
@@ -60,7 +60,6 @@ webserver: ${BUILD_DIR}/webserver/main
 ${BUILD_DIR}/char/char: ${BUILD_DIR}/char/char.o ${BUILD_DIR}/char/inter.o ${BUILD_DIR}/char/int_party.o ${BUILD_DIR}/char/int_guild.o ${BUILD_DIR}/char/int_storage.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/mt_rand.o
 ${BUILD_DIR}/ladmin/ladmin: ${BUILD_DIR}/ladmin/ladmin.o ${BUILD_DIR}/common/md5calc.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/mt_rand.o
 ${BUILD_DIR}/login/login: ${BUILD_DIR}/login/login.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/md5calc.o
-${BUILD_DIR}/map/map: LDLIBS=-lm
 ${BUILD_DIR}/map/map: ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/tmw.o ${BUILD_DIR}/map/magic-interpreter-lexer.o ${BUILD_DIR}/map/magic-interpreter-parser.o ${BUILD_DIR}/map/magic-interpreter-base.o ${BUILD_DIR}/map/magic-expr.o ${BUILD_DIR}/map/magic-stmt.o ${BUILD_DIR}/map/magic.o ${BUILD_DIR}/map/map.o ${BUILD_DIR}/map/chrif.o ${BUILD_DIR}/map/clif.o ${BUILD_DIR}/map/pc.o ${BUILD_DIR}/map/npc.o ${BUILD_DIR}/map/chat.o ${BUILD_DIR}/map/path.o ${BUILD_DIR}/map/itemdb.o ${BUILD_DIR}/map/mob.o ${BUILD_DIR}/map/script.o ${BUILD_DIR}/map/storage.o ${BUILD_DIR}/map/skill.o ${BUILD_DIR}/map/skill-pools.o ${BUILD_DIR}/map/atcommand.o ${BUILD_DIR}/map/battle.o ${BUILD_DIR}/map/intif.o ${BUILD_DIR}/map/trade.o ${BUILD_DIR}/map/party.o ${BUILD_DIR}/map/guild.o ${BUILD_DIR}/common/core.o ${BUILD_DIR}/common/socket.o ${BUILD_DIR}/common/timer.o ${BUILD_DIR}/common/grfio.o ${BUILD_DIR}/common/db.o ${BUILD_DIR}/common/lock.o ${BUILD_DIR}/common/nullpo.o ${BUILD_DIR}/common/mt_rand.o ${BUILD_DIR}/common/md5calc.o
 ${BUILD_DIR}/tool/eathena-monitor: ${BUILD_DIR}/tool/eathena-monitor.o
 ${BUILD_DIR}/tool/adduser: ${BUILD_DIR}/tool/adduser.o ${BUILD_DIR}/common/socket.o
@@ -70,8 +69,8 @@ ${BUILD_DIR}/tool/marriage-info: ${BUILD_DIR}/tool/marriage-info.o ${BUILD_DIR}/
 ${BUILD_DIR}/webserver/main: ${BUILD_DIR}/webserver/main.o ${BUILD_DIR}/webserver/parse.o ${BUILD_DIR}/webserver/generate.o ${BUILD_DIR}/webserver/htmlstyle.o ${BUILD_DIR}/webserver/logs.o ${BUILD_DIR}/webserver/pages/about.o ${BUILD_DIR}/webserver/pages/sample.o ${BUILD_DIR}/webserver/pages/notdone.o
 
 deps.make:
-	for F in `find src/ -name '*.c'`; do \
-	    gcc -m32 -std=c99 -MM "$$F" -MT "$$(sed 's/src/$${BUILD_DIR}/;s/\.c/.o/' <<< "$$F")"; \
+	for F in `find src/ -name '*.cpp'`; do \
+	    ${CXX} ${CPPFLAGS} -MM "$$F" -MT "$$(sed 's/src/$${BUILD_DIR}/;s/\.cpp/.o/' <<< "$$F")"; \
 	done > deps.make
 
 include deps.make
diff --git a/deps.make b/deps.make
deleted file mode 100644
index 34c7328..0000000
--- a/deps.make
+++ /dev/null
@@ -1,308 +0,0 @@
-${BUILD_DIR}/webserver/main.o: src/webserver/main.c
-${BUILD_DIR}/webserver/logs.o: src/webserver/logs.c
-${BUILD_DIR}/webserver/generate.o: src/webserver/generate.c
-${BUILD_DIR}/webserver/parse.o: src/webserver/parse.c
-${BUILD_DIR}/webserver/pages/about.o: src/webserver/pages/about.c
-${BUILD_DIR}/webserver/pages/notdone.o: src/webserver/pages/notdone.c
-${BUILD_DIR}/webserver/pages/sample.o: src/webserver/pages/sample.c
-${BUILD_DIR}/webserver/htmlstyle.o: src/webserver/htmlstyle.c
-${BUILD_DIR}/common/mt_rand.o: src/common/mt_rand.c src/common/mt_rand.h \
- src/common/sanity.h
-${BUILD_DIR}/common/timer.o: src/common/timer.c src/common/timer.h \
- src/common/sanity.h src/common/utils.h
-${BUILD_DIR}/common/nullpo.o: src/common/nullpo.c src/common/nullpo.h \
- src/common/sanity.h
-${BUILD_DIR}/common/lock.o: src/common/lock.c src/common/lock.h \
- src/common/socket.h src/common/sanity.h
-${BUILD_DIR}/common/grfio.o: src/common/grfio.c src/common/utils.h \
- src/common/grfio.h src/common/mmo.h src/common/socket.h \
- src/common/sanity.h
-${BUILD_DIR}/common/md5calc.o: src/common/md5calc.c src/common/md5calc.h \
- src/common/sanity.h src/common/mt_rand.h
-${BUILD_DIR}/common/dbtest.o: src/common/dbtest.c src/common/db.h \
- src/common/sanity.h
-${BUILD_DIR}/common/db.o: src/common/db.c src/common/db.h \
- src/common/sanity.h src/common/utils.h
-${BUILD_DIR}/common/socket.o: src/common/socket.c src/common/mmo.h \
- src/common/utils.h src/common/socket.h src/common/sanity.h
-${BUILD_DIR}/common/core.o: src/common/core.c src/common/core.h \
- src/common/socket.h src/common/sanity.h src/common/timer.h \
- src/common/version.h src/common/mt_rand.h src/common/nullpo.h
-${BUILD_DIR}/login/login.o: src/login/login.c src/login/../common/core.h \
- src/login/../common/socket.h src/login/../common/sanity.h \
- src/login/../common/timer.h src/login/login.h src/login/../common/mmo.h \
- src/login/../common/utils.h src/login/../common/version.h \
- src/login/../common/db.h src/login/../common/lock.h \
- src/login/../common/mt_rand.h src/login/../common/md5calc.h
-${BUILD_DIR}/char/int_guild.o: src/char/int_guild.c src/char/inter.h \
- src/char/int_guild.h src/char/int_storage.h src/char/../common/mmo.h \
- src/char/../common/utils.h src/char/char.h src/char/../common/socket.h \
- src/char/../common/sanity.h src/char/../common/db.h \
- src/char/../common/lock.h
-${BUILD_DIR}/char/inter.o: src/char/inter.c src/char/../common/mmo.h \
- src/char/../common/utils.h src/char/char.h src/char/../common/socket.h \
- src/char/../common/sanity.h src/char/../common/timer.h \
- src/char/../common/db.h src/char/inter.h src/char/int_party.h \
- src/char/int_guild.h src/char/int_storage.h src/char/../common/lock.h
-${BUILD_DIR}/char/int_party.o: src/char/int_party.c src/char/inter.h \
- src/char/int_party.h src/char/../common/mmo.h src/char/../common/utils.h \
- src/char/char.h src/char/../common/socket.h src/char/../common/sanity.h \
- src/char/../common/db.h src/char/../common/lock.h
-${BUILD_DIR}/char/int_storage.o: src/char/int_storage.c \
- src/char/../common/mmo.h src/char/../common/utils.h \
- src/char/../common/socket.h src/char/../common/sanity.h \
- src/char/../common/db.h src/char/../common/lock.h src/char/char.h \
- src/char/inter.h src/char/int_storage.h src/char/int_guild.h
-${BUILD_DIR}/char/char.o: src/char/char.c src/char/../common/core.h \
- src/char/../common/socket.h src/char/../common/sanity.h \
- src/char/../common/timer.h src/char/../common/mmo.h \
- src/char/../common/utils.h src/char/../common/version.h \
- src/char/../common/lock.h src/char/char.h src/char/inter.h \
- src/char/int_guild.h src/char/int_party.h src/char/int_storage.h
-${BUILD_DIR}/tool/itemfrob.o: src/tool/itemfrob.c \
- src/tool/../common/mmo.h src/tool/../common/utils.h \
- src/tool/../char/char.c src/tool/../char/../common/core.h \
- src/tool/../char/../common/socket.h src/tool/../char/../common/sanity.h \
- src/tool/../char/../common/timer.h src/tool/../char/../common/mmo.h \
- src/tool/../char/../common/version.h src/tool/../char/../common/lock.h \
- src/tool/../char/char.h src/tool/../char/inter.h \
- src/tool/../char/int_guild.h src/tool/../char/int_party.h \
- src/tool/../char/int_storage.h
-${BUILD_DIR}/tool/eathena-monitor.o: src/tool/eathena-monitor.c
-${BUILD_DIR}/tool/adduser.o: src/tool/adduser.c
-${BUILD_DIR}/tool/marriage-info.o: src/tool/marriage-info.c \
- src/tool/../login/login.h src/tool/../common/mmo.h \
- src/tool/../common/utils.h src/tool/../char/char.c \
- src/tool/../char/../common/core.h src/tool/../char/../common/socket.h \
- src/tool/../char/../common/sanity.h src/tool/../char/../common/timer.h \
- src/tool/../char/../common/mmo.h src/tool/../char/../common/version.h \
- src/tool/../char/../common/lock.h src/tool/../char/char.h \
- src/tool/../char/inter.h src/tool/../char/int_guild.h \
- src/tool/../char/int_party.h src/tool/../char/int_storage.h
-${BUILD_DIR}/tool/skillfrob.o: src/tool/skillfrob.c \
- src/tool/../common/mmo.h src/tool/../common/utils.h \
- src/tool/../char/char.c src/tool/../char/../common/core.h \
- src/tool/../char/../common/socket.h src/tool/../char/../common/sanity.h \
- src/tool/../char/../common/timer.h src/tool/../char/../common/mmo.h \
- src/tool/../char/../common/version.h src/tool/../char/../common/lock.h \
- src/tool/../char/char.h src/tool/../char/inter.h \
- src/tool/../char/int_guild.h src/tool/../char/int_party.h \
- src/tool/../char/int_storage.h
-${BUILD_DIR}/tool/convert.o: src/tool/convert.c
-${BUILD_DIR}/tool/mapfrob.o: src/tool/mapfrob.c src/tool/../common/mmo.h \
- src/tool/../common/utils.h src/tool/../char/char.c \
- src/tool/../char/../common/core.h src/tool/../char/../common/socket.h \
- src/tool/../char/../common/sanity.h src/tool/../char/../common/timer.h \
- src/tool/../char/../common/mmo.h src/tool/../char/../common/version.h \
- src/tool/../char/../common/lock.h src/tool/../char/char.h \
- src/tool/../char/inter.h src/tool/../char/int_guild.h \
- src/tool/../char/int_party.h src/tool/../char/int_storage.h
-${BUILD_DIR}/map/itemdb.o: src/map/itemdb.c src/map/../common/db.h \
- src/map/../common/sanity.h src/map/../common/grfio.h \
- src/map/../common/nullpo.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/timer.h src/map/battle.h \
- src/map/itemdb.h src/map/script.h src/map/pc.h \
- src/map/../common/socket.h src/map/../common/mt_rand.h
-${BUILD_DIR}/map/magic.o: src/map/magic.c src/map/magic-interpreter.h \
- src/map/../common/nullpo.h src/map/../common/sanity.h src/map/battle.h \
- src/map/chat.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/timer.h \
- src/map/../common/db.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/intif.h src/map/itemdb.h src/map/magic.h src/map/mob.h \
- src/map/npc.h src/map/pc.h src/map/party.h src/map/script.h \
- src/map/skill.h src/map/trade.h src/map/../common/socket.h
-${BUILD_DIR}/map/guild.o: src/map/guild.c src/map/guild.h \
- src/map/storage.h src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/db.h src/map/../common/sanity.h \
- src/map/../common/timer.h src/map/../common/socket.h \
- src/map/../common/nullpo.h src/map/battle.h src/map/npc.h src/map/pc.h \
- src/map/map.h src/map/mob.h src/map/intif.h src/map/clif.h src/map/tmw.h
-${BUILD_DIR}/map/mob.o: src/map/mob.c src/map/../common/timer.h \
- src/map/../common/sanity.h src/map/../common/socket.h \
- src/map/../common/db.h src/map/../common/nullpo.h \
- src/map/../common/mt_rand.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/clif.h src/map/storage.h \
- src/map/intif.h src/map/pc.h src/map/mob.h src/map/guild.h \
- src/map/itemdb.h src/map/skill.h src/map/magic.h src/map/battle.h \
- src/map/party.h src/map/npc.h
-${BUILD_DIR}/map/storage.o: src/map/storage.c src/map/../common/db.h \
- src/map/../common/sanity.h src/map/../common/nullpo.h src/map/storage.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/chrif.h \
- src/map/itemdb.h src/map/map.h src/map/../common/timer.h src/map/clif.h \
- src/map/intif.h src/map/pc.h src/map/guild.h src/map/battle.h \
- src/map/atcommand.h
-${BUILD_DIR}/map/path.o: src/map/path.c src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/db.h src/map/battle.h src/map/../common/nullpo.h
-${BUILD_DIR}/map/magic-interpreter-parser.o: \
- src/map/magic-interpreter-parser.c src/map/magic-interpreter.h \
- src/map/../common/nullpo.h src/map/../common/sanity.h src/map/battle.h \
- src/map/chat.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/timer.h \
- src/map/../common/db.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/intif.h src/map/itemdb.h src/map/magic.h src/map/mob.h \
- src/map/npc.h src/map/pc.h src/map/party.h src/map/script.h \
- src/map/skill.h src/map/trade.h src/map/../common/socket.h \
- src/map/magic-expr.h src/map/magic-interpreter-aux.h
-${BUILD_DIR}/map/skill.o: src/map/skill.c src/map/../common/timer.h \
- src/map/../common/sanity.h src/map/../common/nullpo.h \
- src/map/../common/mt_rand.h src/map/magic.h src/map/clif.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/../common/db.h \
- src/map/storage.h src/map/intif.h src/map/battle.h src/map/itemdb.h \
- src/map/mob.h src/map/party.h src/map/pc.h src/map/script.h \
- src/map/skill.h src/map/../common/socket.h
-${BUILD_DIR}/map/magic-interpreter-lexer.o: \
- src/map/magic-interpreter-lexer.c src/map/magic-interpreter.h \
- src/map/../common/nullpo.h src/map/../common/sanity.h src/map/battle.h \
- src/map/chat.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/timer.h \
- src/map/../common/db.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/intif.h src/map/itemdb.h src/map/magic.h src/map/mob.h \
- src/map/npc.h src/map/pc.h src/map/party.h src/map/script.h \
- src/map/skill.h src/map/trade.h src/map/../common/socket.h \
- src/map/magic-interpreter-parser.h
-${BUILD_DIR}/map/magic-stmt.o: src/map/magic-stmt.c \
- src/map/magic-interpreter.h src/map/../common/nullpo.h \
- src/map/../common/sanity.h src/map/battle.h src/map/chat.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/db.h src/map/chrif.h \
- src/map/clif.h src/map/storage.h src/map/intif.h src/map/itemdb.h \
- src/map/magic.h src/map/mob.h src/map/npc.h src/map/pc.h src/map/party.h \
- src/map/script.h src/map/skill.h src/map/trade.h \
- src/map/../common/socket.h src/map/magic-expr.h \
- src/map/magic-interpreter-aux.h src/map/magic-expr-eval.h
-${BUILD_DIR}/map/chat.o: src/map/chat.c src/map/../common/db.h \
- src/map/../common/sanity.h src/map/../common/nullpo.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/clif.h src/map/storage.h src/map/pc.h \
- src/map/chat.h src/map/npc.h
-${BUILD_DIR}/map/skill-pools.o: src/map/skill-pools.c \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/nullpo.h src/map/../common/mt_rand.h src/map/magic.h \
- src/map/clif.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/db.h src/map/storage.h \
- src/map/intif.h src/map/battle.h src/map/itemdb.h src/map/mob.h \
- src/map/party.h src/map/pc.h src/map/script.h src/map/skill.h \
- src/map/../common/socket.h
-${BUILD_DIR}/map/trade.o: src/map/trade.c src/map/clif.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/db.h src/map/storage.h src/map/itemdb.h \
- src/map/trade.h src/map/pc.h src/map/npc.h src/map/battle.h \
- src/map/../common/nullpo.h
-${BUILD_DIR}/map/party.o: src/map/party.c src/map/party.h \
- src/map/../common/db.h src/map/../common/sanity.h \
- src/map/../common/timer.h src/map/../common/socket.h \
- src/map/../common/nullpo.h src/map/pc.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/battle.h \
- src/map/intif.h src/map/clif.h src/map/storage.h src/map/skill.h \
- src/map/magic.h src/map/tmw.h
-${BUILD_DIR}/map/npc.o: src/map/npc.c src/map/../common/nullpo.h \
- src/map/../common/sanity.h src/map/../common/timer.h src/map/battle.h \
- src/map/clif.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/db.h src/map/storage.h \
- src/map/intif.h src/map/itemdb.h src/map/mob.h src/map/npc.h \
- src/map/pc.h src/map/script.h src/map/skill.h src/map/magic.h \
- src/map/../common/socket.h
-${BUILD_DIR}/map/magic-interpreter-base.o: \
- src/map/magic-interpreter-base.c src/map/magic.h src/map/clif.h \
- src/map/map.h src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/db.h src/map/storage.h src/map/intif.h \
- src/map/magic-interpreter.h src/map/../common/nullpo.h src/map/battle.h \
- src/map/chat.h src/map/chrif.h src/map/itemdb.h src/map/mob.h \
- src/map/npc.h src/map/pc.h src/map/party.h src/map/script.h \
- src/map/skill.h src/map/trade.h src/map/../common/socket.h \
- src/map/magic-expr.h src/map/magic-interpreter-aux.h
-${BUILD_DIR}/map/pc.o: src/map/pc.c src/map/../common/socket.h \
- src/map/../common/sanity.h src/map/../common/timer.h \
- src/map/../common/db.h src/map/../common/nullpo.h \
- src/map/../common/mt_rand.h src/map/atcommand.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/battle.h \
- src/map/chat.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/guild.h src/map/intif.h src/map/itemdb.h src/map/mob.h \
- src/map/npc.h src/map/party.h src/map/pc.h src/map/script.h \
- src/map/skill.h src/map/magic.h src/map/trade.h
-${BUILD_DIR}/map/tmw.o: src/map/tmw.c src/map/tmw.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/db.h src/map/../common/socket.h \
- src/map/../common/version.h src/map/../common/nullpo.h \
- src/map/atcommand.h src/map/battle.h src/map/chat.h src/map/chrif.h \
- src/map/clif.h src/map/storage.h src/map/guild.h src/map/intif.h \
- src/map/itemdb.h src/map/magic.h src/map/mob.h src/map/npc.h \
- src/map/party.h src/map/pc.h src/map/script.h src/map/skill.h \
- src/map/trade.h
-${BUILD_DIR}/map/intif.o: src/map/intif.c src/map/../common/nullpo.h \
- src/map/../common/sanity.h src/map/../common/socket.h \
- src/map/../common/timer.h src/map/battle.h src/map/chrif.h \
- src/map/clif.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/db.h src/map/storage.h \
- src/map/guild.h src/map/intif.h src/map/party.h src/map/pc.h
-${BUILD_DIR}/map/magic-expr.o: src/map/magic-expr.c src/map/magic-expr.h \
- src/map/magic-interpreter.h src/map/../common/nullpo.h \
- src/map/../common/sanity.h src/map/battle.h src/map/chat.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/timer.h src/map/../common/db.h src/map/chrif.h \
- src/map/clif.h src/map/storage.h src/map/intif.h src/map/itemdb.h \
- src/map/magic.h src/map/mob.h src/map/npc.h src/map/pc.h src/map/party.h \
- src/map/script.h src/map/skill.h src/map/trade.h \
- src/map/../common/socket.h src/map/magic-interpreter-aux.h \
- src/map/magic-expr-eval.h src/map/../common/mt_rand.h
-${BUILD_DIR}/map/battle.o: src/map/battle.c src/map/battle.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/nullpo.h src/map/clif.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/../common/db.h \
- src/map/storage.h src/map/guild.h src/map/itemdb.h src/map/mob.h \
- src/map/pc.h src/map/skill.h src/map/magic.h src/map/intif.h \
- src/map/../common/socket.h src/map/../common/mt_rand.h
-${BUILD_DIR}/map/script.o: src/map/script.c src/map/../common/socket.h \
- src/map/../common/sanity.h src/map/../common/timer.h \
- src/map/../common/lock.h src/map/../common/mt_rand.h src/map/atcommand.h \
- src/map/map.h src/map/../common/mmo.h src/map/../common/utils.h \
- src/map/../common/db.h src/map/battle.h src/map/chat.h src/map/chrif.h \
- src/map/clif.h src/map/storage.h src/map/guild.h src/map/intif.h \
- src/map/itemdb.h src/map/mob.h src/map/npc.h src/map/party.h \
- src/map/pc.h src/map/script.h src/map/skill.h src/map/magic.h
-${BUILD_DIR}/map/clif.o: src/map/clif.c src/map/../common/socket.h \
- src/map/../common/sanity.h src/map/../common/timer.h \
- src/map/../common/version.h src/map/../common/nullpo.h \
- src/map/../common/md5calc.h src/map/../common/mt_rand.h \
- src/map/atcommand.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/../common/db.h src/map/battle.h \
- src/map/chat.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/guild.h src/map/intif.h src/map/itemdb.h src/map/magic.h \
- src/map/mob.h src/map/npc.h src/map/party.h src/map/pc.h \
- src/map/script.h src/map/skill.h src/map/tmw.h src/map/trade.h
-${BUILD_DIR}/map/chrif.o: src/map/chrif.c src/map/../common/socket.h \
- src/map/../common/sanity.h src/map/../common/timer.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/../common/db.h \
- src/map/battle.h src/map/chrif.h src/map/clif.h src/map/storage.h \
- src/map/intif.h src/map/npc.h src/map/pc.h src/map/../common/nullpo.h \
- src/map/itemdb.h
-${BUILD_DIR}/map/atcommand.o: src/map/atcommand.c \
- src/map/../common/socket.h src/map/../common/sanity.h \
- src/map/../common/timer.h src/map/../common/nullpo.h \
- src/map/../common/mt_rand.h src/map/atcommand.h src/map/map.h \
- src/map/../common/mmo.h src/map/../common/utils.h src/map/../common/db.h \
- src/map/battle.h src/map/clif.h src/map/storage.h src/map/chrif.h \
- src/map/guild.h src/map/intif.h src/map/itemdb.h src/map/mob.h \
- src/map/npc.h src/map/pc.h src/map/party.h src/map/script.h \
- src/map/skill.h src/map/magic.h src/map/trade.h src/map/../common/core.h \
- src/map/tmw.h
-${BUILD_DIR}/map/map.o: src/map/map.c src/map/../common/core.h \
- src/map/../common/timer.h src/map/../common/sanity.h \
- src/map/../common/db.h src/map/../common/grfio.h \
- src/map/../common/mt_rand.h src/map/map.h src/map/../common/mmo.h \
- src/map/../common/utils.h src/map/chrif.h src/map/clif.h \
- src/map/storage.h src/map/intif.h src/map/npc.h src/map/pc.h \
- src/map/mob.h src/map/chat.h src/map/itemdb.h src/map/skill.h \
- src/map/magic.h src/map/trade.h src/map/party.h src/map/battle.h \
- src/map/script.h src/map/guild.h src/map/atcommand.h \
- src/map/../common/nullpo.h src/map/../common/socket.h
-${BUILD_DIR}/ladmin/ladmin.o: src/ladmin/ladmin.c \
- src/ladmin/../common/core.h src/ladmin/../common/socket.h \
- src/ladmin/../common/sanity.h src/ladmin/ladmin.h \
- src/ladmin/../common/version.h src/ladmin/../common/mmo.h \
- src/ladmin/../common/utils.h src/ladmin/../common/md5calc.h
diff --git a/make.defs b/make.defs
index 067c22b..9328688 100644
--- a/make.defs
+++ b/make.defs
@@ -1,16 +1,13 @@
 # defaults
-CC = gcc
+CXX = g++
 LEX = flex
 BISON = bison
-CFLAGS = -pipe -g -O2
+CXXFLAGS = -pipe -g -O2
 
 # works on both x86 and x86_64
-override CC += -m32 -std=gnu99
+override CXX += -m32 -std=c++0x
+# for linking
+override CC = ${CXX}
 
-# TODO check if this is actually needed - I don't think it should be
-ifeq ($(findstring CYGWIN,$(shell uname)), CYGWIN)
-  override CFLAGS += -DFD_SETSIZE=4096 -DCYGWIN
-else
-  override CFLAGS += -fstack-protector
-endif
+override CXXFLAGS += -fstack-protector
 
diff --git a/src/char/char.c b/src/char/char.c
deleted file mode 100644
index 2a46283..0000000
--- a/src/char/char.c
+++ /dev/null
@@ -1,4076 +0,0 @@
-// $Id: char.c,v 1.3 2004/09/13 16:52:16 Yor Exp $
-// original : char2.c 2003/03/14 11:58:35 Rev.1.5
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <stdarg.h>
-#include <sys/wait.h>
-
-#include "../common/core.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/mmo.h"
-#include "../common/version.h"
-#include "../common/lock.h"
-#include "char.h"
-
-#include "inter.h"
-#include "int_guild.h"
-#include "int_party.h"
-#include "int_storage.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-struct mmo_map_server server[MAX_MAP_SERVERS];
-int  server_fd[MAX_MAP_SERVERS];
-int  server_freezeflag[MAX_MAP_SERVERS];    // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
-int  anti_freeze_enable = 0;
-int  ANTI_FREEZE_INTERVAL = 6;
-
-int  login_fd, char_fd;
-char userid[24];
-char passwd[24];
-char server_name[20];
-char wisp_server_name[24] = "Server";
-char login_ip_str[16];
-int  login_ip;
-int  login_port = 6900;
-char char_ip_str[16];
-int  char_ip;
-int  char_port = 6121;
-int  char_maintenance;
-int  char_new;
-int  email_creation = 0;        // disabled by default
-char char_txt[1024];
-char backup_txt[1024];          //By zanetheinsane
-char backup_txt_flag = 0;       // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor]
-char unknown_char_name[1024] = "Unknown";
-char char_log_filename[1024] = "log/char.log";
-//Added for lan support
-char lan_map_ip[128];
-int  subneti[4];
-int  subnetmaski[4];
-int  name_ignoring_case = 0;    // Allow or not identical name for characters but with a different case by [Yor]
-int  char_name_option = 0;      // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
-char char_name_letters[1024] = "";  // list of letters/symbols authorised (or not) in a character name. by [Yor]
-
-struct char_session_data
-{
-    int  account_id, login_id1, login_id2, sex;
-    unsigned short packet_tmw_version;
-    int  found_char[9];
-    char email[40];             // e-mail (default: a@a.com) by [Yor]
-    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-};
-
-#define AUTH_FIFO_SIZE 256
-struct
-{
-    int  account_id, char_id, login_id1, login_id2, ip, char_pos, delflag,
-        sex;
-    unsigned short packet_tmw_version;
-    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-} auth_fifo[AUTH_FIFO_SIZE];
-int  auth_fifo_pos = 0;
-
-int  check_ip_flag = 1;         // It's to check IP of a player between char-server and other servers (part of anti-hacking system)
-
-int  char_id_count = 150000;
-struct mmo_charstatus *char_dat;
-int  char_num, char_max;
-int  max_connect_user = 0;
-int  autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-int  start_zeny = 500;
-int  start_weapon = 1201;
-int  start_armor = 1202;
-
-// Initial position (it's possible to set it in conf file)
-struct point start_point = { "new_1-1.gat", 53, 111 };
-
-struct gm_account *gm_account = NULL;
-int  GM_num = 0;
-
-// online players by [Yor]
-char online_txt_filename[1024] = "online.txt";
-char online_html_filename[1024] = "online.html";
-int  online_sorting_option = 0; // sorting option to display online players in online files
-int  online_display_option = 1; // display options: to know which columns must be displayed
-int  online_refresh_html = 20;  // refresh time (in sec) of the html file in the explorer
-int  online_gm_display_min_level = 20;  // minimum GM level to display 'GM' when we want to display it
-
-int *online_chars;              // same size of char_dat, and id value of current server (or -1)
-time_t update_online;           // to update online files when we receiving information from a server (not less than 8 seconds)
-
-pid_t pid = 0;                  // For forked DB writes
-
-//------------------------------
-// Writing function of logs file
-//------------------------------
-int char_log (char *fmt, ...)
-{
-    FILE *logfp;
-    va_list ap;
-    struct timeval tv;
-    char tmpstr[2048];
-
-    va_start (ap, fmt);
-
-    logfp = fopen_ (char_log_filename, "a");
-    if (logfp)
-    {
-        if (fmt[0] == '\0')     // jump a line if no message
-            fprintf (logfp, "\n");
-        else
-        {
-            gettimeofday (&tv, NULL);
-            strftime (tmpstr, 24, "%d-%m-%Y %H:%M:%S", gmtime (&(tv.tv_sec)));
-            sprintf (tmpstr + 19, ".%03d: %s", (int) tv.tv_usec / 1000, fmt);
-            vfprintf (logfp, tmpstr, ap);
-        }
-        fclose_ (logfp);
-    }
-
-    va_end (ap);
-    return 0;
-}
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars (unsigned char *str)
-{
-    int  i;
-    int  change = 0;
-
-    for (i = 0; str[i]; i++)
-    {
-        if (str[i] < 32)
-        {
-            str[i] = '_';
-            change = 1;
-        }
-    }
-
-    return change;
-}
-
-//----------------------------------------------------------------------
-// Determine if an account (id) is a GM account
-// and returns its level (or 0 if it isn't a GM account or if not found)
-//----------------------------------------------------------------------
-int isGM (int account_id)
-{
-    int  i;
-
-    for (i = 0; i < GM_num; i++)
-        if (gm_account[i].account_id == account_id)
-            return gm_account[i].level;
-    return 0;
-}
-
-//----------------------------------------------
-// Search an character id
-//   (return character index or -1 (if not found))
-//   If exact character name is not found,
-//   the function checks without case sensitive
-//   and returns index if only 1 character is found
-//   and similar to the searched name.
-//----------------------------------------------
-int search_character_index (char *character_name)
-{
-    int  i, quantity, index;
-
-    quantity = 0;
-    index = -1;
-    for (i = 0; i < char_num; i++)
-    {
-        // Without case sensitive check (increase the number of similar character names found)
-        if (strcasecmp (char_dat[i].name, character_name) == 0)
-        {
-            // Strict comparison (if found, we finish the function immediatly with correct value)
-            if (strcmp (char_dat[i].name, character_name) == 0)
-                return i;
-            quantity++;
-            index = i;
-        }
-    }
-    // Here, the exact character name is not found
-    // We return the found index of a similar account ONLY if there is 1 similar character
-    if (quantity == 1)
-        return index;
-
-    // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
-    return -1;
-}
-
-//-------------------------------------
-// Return character name with the index
-//-------------------------------------
-char *search_character_name (int index)
-{
-
-    if (index >= 0 && index < char_num)
-        return char_dat[index].name;
-
-    return unknown_char_name;
-}
-
-//-------------------------------------------------
-// Function to create the character line (for save)
-//-------------------------------------------------
-int mmo_char_tostr (char *str, struct mmo_charstatus *p)
-{
-    int  i;
-    char *str_p = str;
-
-    // on multi-map server, sometimes it's posssible that last_point become void. (reason???) We check that to not lost character at restart.
-    if (p->last_point.map[0] == '\0')
-    {
-        memcpy (p->last_point.map, "prontera.gat", 16);
-        p->last_point.x = 273;
-        p->last_point.y = 354;
-    }
-
-    str_p += sprintf (str_p, "%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%s,%d,%d\t%s,%d,%d,%d\t", p->char_id, p->account_id, p->char_num, p->name,  //
-                      p->pc_class, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->hp, p->max_hp, p->sp, p->max_sp, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, p->status_point, p->skill_point, p->option, p->karma, p->manner,    //
-                      p->party_id, p->guild_id, 0, p->hair, p->hair_color, p->clothes_color, 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);
-    for (i = 0; i < 10; i++)
-        if (p->memo_point[i].map[0])
-        {
-            str_p +=
-                sprintf (str_p, "%s,%d,%d", p->memo_point[i].map,
-                         p->memo_point[i].x, p->memo_point[i].y);
-        }
-    *(str_p++) = '\t';
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-        if (p->inventory[i].nameid)
-        {
-            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                              p->inventory[i].id, p->inventory[i].nameid,
-                              p->inventory[i].amount, p->inventory[i].equip,
-                              p->inventory[i].identify,
-                              p->inventory[i].refine,
-                              p->inventory[i].attribute,
-                              p->inventory[i].card[0],
-                              p->inventory[i].card[1],
-                              p->inventory[i].card[2],
-                              p->inventory[i].card[3],
-                              p->inventory[i].broken);
-        }
-    *(str_p++) = '\t';
-
-    for (i = 0; i < MAX_CART; i++)
-        if (p->cart[i].nameid)
-        {
-            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                              p->cart[i].id, p->cart[i].nameid,
-                              p->cart[i].amount, p->cart[i].equip,
-                              p->cart[i].identify, p->cart[i].refine,
-                              p->cart[i].attribute, p->cart[i].card[0],
-                              p->cart[i].card[1], p->cart[i].card[2],
-                              p->cart[i].card[3], p->cart[i].broken);
-        }
-    *(str_p++) = '\t';
-
-    for (i = 0; i < MAX_SKILL; i++)
-        if (p->skill[i].id)
-        {
-            str_p +=
-                sprintf (str_p, "%d,%d ", p->skill[i].id,
-                         p->skill[i].lv | (p->skill[i].flags << 16));
-        }
-    *(str_p++) = '\t';
-
-    for (i = 0; i < p->global_reg_num; i++)
-        if (p->global_reg[i].str[0])
-            str_p +=
-                sprintf (str_p, "%s,%d ", p->global_reg[i].str,
-                         p->global_reg[i].value);
-    *(str_p++) = '\t';
-
-    *str_p = '\0';
-    return 0;
-}
-
-//-------------------------------------------------------------------------
-// Function to set the character from the line (at read of characters file)
-//-------------------------------------------------------------------------
-int mmo_char_fromstr (char *str, struct mmo_charstatus *p)
-{
-    int  tmp_int[256];
-    int  set, next, len, i;
-
-    // initilialise character
-    memset (p, '\0', sizeof (struct mmo_charstatus));
-
-    // If it's not char structure of version 1008 and after
-    if ((set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name,  //
-                       &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36], //
-                       p->save_point.map, &tmp_int[37], &tmp_int[38],
-                       &tmp_int[39], &next)) != 43)
-    {
-        tmp_int[39] = 0;        // partner id
-        // If not char structure from version 384 to 1007
-        if ((set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
-                           &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36], //
-                           p->save_point.map, &tmp_int[37], &tmp_int[38],
-                           &next)) != 42)
-        {
-            // It's char structure of a version before 384
-            tmp_int[26] = 0;    // pet id
-            set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
-                          &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36],    //
-                          p->save_point.map, &tmp_int[37], &tmp_int[38],
-                          &next);
-            set += 2;
-            //printf("char: old char data ver.1\n");
-            // Char structure of version 1007 or older
-        }
-        else
-        {
-            set++;
-            //printf("char: old char data ver.2\n");
-        }
-        // Char structure of version 1008+
-    }
-    else
-    {
-        //printf("char: new char data ver.3\n");
-    }
-    if (set != 43)
-        return 0;
-
-    p->char_id = tmp_int[0];
-    p->account_id = tmp_int[1];
-    p->char_num = tmp_int[2];
-    p->pc_class = tmp_int[3];
-    p->base_level = tmp_int[4];
-    p->job_level = tmp_int[5];
-    p->base_exp = tmp_int[6];
-    p->job_exp = tmp_int[7];
-    p->zeny = tmp_int[8];
-    p->hp = tmp_int[9];
-    p->max_hp = tmp_int[10];
-    p->sp = tmp_int[11];
-    p->max_sp = tmp_int[12];
-    p->str = tmp_int[13];
-    p->agi = tmp_int[14];
-    p->vit = tmp_int[15];
-    p->int_ = tmp_int[16];
-    p->dex = tmp_int[17];
-    p->luk = tmp_int[18];
-    p->status_point = tmp_int[19];
-    p->skill_point = tmp_int[20];
-    p->option = tmp_int[21];
-    p->karma = tmp_int[22];
-    p->manner = tmp_int[23];
-    p->party_id = tmp_int[24];
-    p->guild_id = tmp_int[25];
-//  p->pet_id = tmp_int[26];
-    p->hair = tmp_int[27];
-    p->hair_color = tmp_int[28];
-    p->clothes_color = tmp_int[29];
-    p->weapon = tmp_int[30];
-    p->shield = tmp_int[31];
-    p->head_top = tmp_int[32];
-    p->head_mid = tmp_int[33];
-    p->head_bottom = tmp_int[34];
-    p->last_point.x = tmp_int[35];
-    p->last_point.y = tmp_int[36];
-    p->save_point.x = tmp_int[37];
-    p->save_point.y = tmp_int[38];
-    p->partner_id = tmp_int[39];
-
-    // Some checks
-    for (i = 0; i < char_num; i++)
-    {
-        if (char_dat[i].char_id == p->char_id)
-        {
-            printf
-                ("\033[1;31mmmo_auth_init: ******Error: a character has an identical id to another.\n");
-            printf
-                ("               character id #%d -> new character not readed.\n",
-                 p->char_id);
-            printf ("               Character saved in log file.\033[0m\n");
-            return -1;
-        }
-        else if (strcmp (char_dat[i].name, p->name) == 0)
-        {
-            printf
-                ("\033[1;31mmmo_auth_init: ******Error: character name already exists.\n");
-            printf
-                ("               character name '%s' -> new character not readed.\n",
-                 p->name);
-            printf ("               Character saved in log file.\033[0m\n");
-            return -2;
-        }
-    }
-
-    if (strcasecmp (wisp_server_name, p->name) == 0)
-    {
-        printf
-            ("mmo_auth_init: ******WARNING: character name has wisp server name.\n");
-        printf
-            ("               Character name '%s' = wisp server name '%s'.\n",
-             p->name, wisp_server_name);
-        printf
-            ("               Character readed. Suggestion: change the wisp server name.\n");
-        char_log
-            ("mmo_auth_init: ******WARNING: character name has wisp server name: Character name '%s' = wisp server name '%s'.\n",
-             p->name, wisp_server_name);
-    }
-
-    if (str[next] == '\n' || str[next] == '\r')
-        return 1;               // 新規データ
-
-    next++;
-
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        if (sscanf
-            (str + next, "%[^,],%d,%d%n", p->memo_point[i].map, &tmp_int[0],
-             &tmp_int[1], &len) != 3)
-            return -3;
-        p->memo_point[i].x = tmp_int[0];
-        p->memo_point[i].y = tmp_int[1];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-
-    next++;
-
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                    &tmp_int[11], &len) == 12)
-        {
-            // do nothing, it's ok
-        }
-        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                         &len) == 11)
-        {
-            tmp_int[11] = 0;    // broken doesn't exist in this version -> 0
-        }
-        else                    // invalid structure
-            return -4;
-        p->inventory[i].id = tmp_int[0];
-        p->inventory[i].nameid = tmp_int[1];
-        p->inventory[i].amount = tmp_int[2];
-        p->inventory[i].equip = tmp_int[3];
-        p->inventory[i].identify = tmp_int[4];
-        p->inventory[i].refine = tmp_int[5];
-        p->inventory[i].attribute = tmp_int[6];
-        p->inventory[i].card[0] = tmp_int[7];
-        p->inventory[i].card[1] = tmp_int[8];
-        p->inventory[i].card[2] = tmp_int[9];
-        p->inventory[i].card[3] = tmp_int[10];
-        p->inventory[i].broken = tmp_int[11];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-
-    next++;
-
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                    &tmp_int[11], &len) == 12)
-        {
-            // do nothing, it's ok
-        }
-        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                         &len) == 11)
-        {
-            tmp_int[11] = 0;    // broken doesn't exist in this version -> 0
-        }
-        else                    // invalid structure
-            return -5;
-        p->cart[i].id = tmp_int[0];
-        p->cart[i].nameid = tmp_int[1];
-        p->cart[i].amount = tmp_int[2];
-        p->cart[i].equip = tmp_int[3];
-        p->cart[i].identify = tmp_int[4];
-        p->cart[i].refine = tmp_int[5];
-        p->cart[i].attribute = tmp_int[6];
-        p->cart[i].card[0] = tmp_int[7];
-        p->cart[i].card[1] = tmp_int[8];
-        p->cart[i].card[2] = tmp_int[9];
-        p->cart[i].card[3] = tmp_int[10];
-        p->cart[i].broken = tmp_int[11];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-
-    next++;
-
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        if (sscanf (str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len) !=
-            2)
-            return -6;
-        p->skill[tmp_int[0]].id = tmp_int[0];
-        p->skill[tmp_int[0]].lv = tmp_int[1] & 0xffff;
-        p->skill[tmp_int[0]].flags = ((tmp_int[1] >> 16) & 0xffff);
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-
-    next++;
-
-    for (i = 0;
-         str[next] && str[next] != '\t' && str[next] != '\n'
-         && str[next] != '\r'; i++)
-    {                           // global_reg実装以前のathena.txt互換のため一応'\n'チェック
-        if (sscanf
-            (str + next, "%[^,],%d%n", p->global_reg[i].str,
-             &p->global_reg[i].value, &len) != 2)
-        {
-            // because some scripts are not correct, the str can be "". So, we must check that.
-            // If it's, we must not refuse the character, but just this REG value.
-            // Character line will have something like: nov_2nd_cos,9 ,9 nov_1_2_cos_c,1 (here, ,9 is not good)
-            if (str[next] == ','
-                && sscanf (str + next, ",%d%n", &p->global_reg[i].value,
-                           &len) == 1)
-                i--;
-            else
-                return -7;
-        }
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    p->global_reg_num = i;
-
-    return 1;
-}
-
-//---------------------------------
-// Function to read characters file
-//---------------------------------
-int mmo_char_init (void)
-{
-    char line[65536];
-    int  i;
-    int  ret, line_count;
-    FILE *fp;
-
-    char_max = 256;
-    CREATE (char_dat, struct mmo_charstatus, 256);
-    CREATE (online_chars, int, 256);
-    for (i = 0; i < char_max; i++)
-        online_chars[i] = -1;
-
-    char_num = 0;
-
-    fp = fopen_ (char_txt, "r");
-    if (fp == NULL)
-    {
-        printf ("Characters file not found: %s.\n", char_txt);
-        char_log ("Characters file not found: %s.\n", char_txt);
-        char_log ("Id for the next created character: %d.\n",
-                  char_id_count);
-        return 0;
-    }
-
-    line_count = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        int  i, j;
-        line_count++;
-
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        line[sizeof (line) - 1] = '\0';
-
-        j = 0;
-        if (sscanf (line, "%d\t%%newid%%%n", &i, &j) == 1 && j > 0)
-        {
-            if (char_id_count < i)
-                char_id_count = i;
-            continue;
-        }
-
-        if (char_num >= char_max)
-        {
-            char_max += 256;
-            RECREATE (char_dat, struct mmo_charstatus, char_max);
-            RECREATE (online_chars, int, char_max);
-            for (i = char_max - 256; i < char_max; i++)
-                online_chars[i] = -1;
-        }
-
-        ret = mmo_char_fromstr (line, &char_dat[char_num]);
-        if (ret > 0)
-        {                       // negative value or zero for errors
-            if (char_dat[char_num].char_id >= char_id_count)
-                char_id_count = char_dat[char_num].char_id + 1;
-            char_num++;
-        }
-        else
-        {
-            printf
-                ("mmo_char_init: in characters file, unable to read the line #%d.\n",
-                 line_count);
-            printf ("               -> Character saved in log file.\n");
-            switch (ret)
-            {
-                case -1:
-                    char_log
-                        ("Duplicate character id in the next character line (character not readed):\n");
-                    break;
-                case -2:
-                    char_log
-                        ("Duplicate character name in the next character line (character not readed):\n");
-                    break;
-                case -3:
-                    char_log
-                        ("Invalid memo point structure in the next character line (character not readed):\n");
-                    break;
-                case -4:
-                    char_log
-                        ("Invalid inventory item structure in the next character line (character not readed):\n");
-                    break;
-                case -5:
-                    char_log
-                        ("Invalid cart item structure in the next character line (character not readed):\n");
-                    break;
-                case -6:
-                    char_log
-                        ("Invalid skill structure in the next character line (character not readed):\n");
-                    break;
-                case -7:
-                    char_log
-                        ("Invalid register structure in the next character line (character not readed):\n");
-                    break;
-                default:       // 0
-                    char_log
-                        ("Unabled to get a character in the next line - Basic structure of line (before inventory) is incorrect (character not readed):\n");
-                    break;
-            }
-            char_log ("%s", line);
-        }
-    }
-    fclose_ (fp);
-
-    if (char_num == 0)
-    {
-        printf ("mmo_char_init: No character found in %s.\n", char_txt);
-        char_log ("mmo_char_init: No character found in %s.\n",
-                  char_txt);
-    }
-    else if (char_num == 1)
-    {
-        printf ("mmo_char_init: 1 character read in %s.\n", char_txt);
-        char_log ("mmo_char_init: 1 character read in %s.\n", char_txt);
-    }
-    else
-    {
-        printf ("mmo_char_init: %d characters read in %s.\n", char_num,
-                char_txt);
-        char_log ("mmo_char_init: %d characters read in %s.\n",
-                  char_num, char_txt);
-    }
-
-    char_log ("Id for the next created character: %d.\n",
-              char_id_count);
-
-    return 0;
-}
-
-//---------------------------------------------------------
-// Function to save characters in files (speed up by [Yor])
-//---------------------------------------------------------
-void mmo_char_sync (void)
-{
-    char line[65536];
-    int  i, j, k;
-    int  lock;
-    FILE *fp;
-    int  id[char_num];
-
-    // Sorting before save (by [Yor])
-    for (i = 0; i < char_num; i++)
-    {
-        id[i] = i;
-        for (j = 0; j < i; j++)
-        {
-            if ((char_dat[i].account_id < char_dat[id[j]].account_id) ||
-                // if same account id, we sort by slot.
-                (char_dat[i].account_id == char_dat[id[j]].account_id &&
-                 char_dat[i].char_num < char_dat[id[j]].char_num))
-            {
-                for (k = i; k > j; k--)
-                    id[k] = id[k - 1];
-                id[j] = i;      // id[i]
-                break;
-            }
-        }
-    }
-
-    // Data save
-    fp = lock_fopen (char_txt, &lock);
-    if (fp == NULL)
-    {
-        printf ("WARNING: Server can't not save characters.\n");
-        char_log ("WARNING: Server can't not save characters.\n");
-    }
-    else
-    {
-        for (i = 0; i < char_num; i++)
-        {
-            // create only once the line, and save it in the 2 files (it's speeder than repeat twice the loop and create twice the line)
-            mmo_char_tostr (line, &char_dat[id[i]]);    // use of sorted index
-            fprintf (fp, "%s\n", line);
-        }
-        fprintf (fp, "%d\t%%newid%%\n", char_id_count);
-        lock_fclose (fp, char_txt, &lock);
-    }
-
-    // Data save (backup)
-    if (backup_txt_flag)
-    {                           // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor]
-        fp = lock_fopen (backup_txt, &lock);
-        if (fp == NULL)
-        {
-            printf
-                ("WARNING: Server can't not create backup of characters file.\n");
-            char_log
-                ("WARNING: Server can't not create backup of characters file.\n");
-            return;
-        }
-        for (i = 0; i < char_num; i++)
-        {
-            // create only once the line, and save it in the 2 files (it's speeder than repeat twice the loop and create twice the line)
-            mmo_char_tostr (line, &char_dat[id[i]]);    // use of sorted index
-            fprintf (fp, "%s\n", line);
-        }
-        fprintf (fp, "%d\t%%newid%%\n", char_id_count);
-        lock_fclose (fp, backup_txt, &lock);
-    }
-
-    return;
-}
-
-//----------------------------------------------------
-// Function to save (in a periodic way) datas in files
-//----------------------------------------------------
-void mmo_char_sync_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    if (pid != 0)
-    {
-        int  status;
-        pid_t temp = waitpid (pid, &status, WNOHANG);
-
-        // Need to check status too?
-        if (temp == 0)
-        {
-            return;
-        }
-    }
-
-    // This can take a lot of time. Fork a child to handle the work and return at once
-    // If we're unable to fork just continue running the function normally
-    if ((pid = fork ()) > 0)
-        return;
-
-    mmo_char_sync ();
-    inter_save ();
-
-    // If we're a child we should suicide now.
-    if (pid == 0)
-        _exit (0);
-}
-
-//----------------------------------------------------
-// Remove trailing whitespace from a name
-//----------------------------------------------------
-static void remove_trailing_blanks (char *name)
-{
-    char *tail = name + strlen (name) - 1;
-
-    while (tail > name && *tail == ' ')
-        *tail-- = 0;
-}
-
-//----------------------------------------------------
-// Remove prefix whitespace from a name
-//----------------------------------------------------
-static void remove_prefix_blanks (char *name)
-{
-    char *dst = name;
-    char *src = name;
-
-    while (*src == ' ')         // find first nonblank
-        ++src;
-    while ((*dst++ = *src++));  // `strmove'
-}
-
-//-----------------------------------
-// Function to create a new character
-//-----------------------------------
-int make_new_char (int fd, unsigned char *dat)
-{
-    int  i, j;
-    struct char_session_data *sd = (struct char_session_data *)session[fd]->session_data;
-
-    // remove control characters from the name
-    dat[23] = '\0';
-    if (remove_control_chars (dat))
-    {
-        char_log
-            ("Make new char error (control char received in the name): (connection #%d, account: %d).\n",
-             fd, sd->account_id);
-        return -1;
-    }
-
-    // Eliminate whitespace
-    remove_trailing_blanks ((char *) dat);
-    remove_prefix_blanks ((char *) dat);
-
-    // check lenght of character name
-    if (strlen (dat) < 4)
-    {
-        char_log
-            ("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n",
-             fd, sd->account_id, dat);
-        return -1;
-    }
-
-    // Check Authorised letters/symbols in the name of the character
-    if (char_name_option == 1)
-    {                           // only letters/symbols in char_name_letters are authorised
-        for (i = 0; dat[i]; i++)
-            if (strchr (char_name_letters, dat[i]) == NULL)
-            {
-                char_log
-                    ("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n",
-                     fd, sd->account_id, dat, dat[i]);
-                return -1;
-            }
-    }
-    else if (char_name_option == 2)
-    {                           // letters/symbols in char_name_letters are forbidden
-        for (i = 0; dat[i]; i++)
-            if (strchr (char_name_letters, dat[i]) != NULL)
-            {
-                char_log
-                    ("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n",
-                     fd, sd->account_id, dat, dat[i]);
-                return -1;
-            }
-    }                           // else, all letters/symbols are authorised (except control char removed before)
-
-    if (dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29] != 5 * 6 ||   // stats
-        dat[30] >= 9 ||         // slots (dat[30] can not be negativ)
-        dat[33] < 0 || dat[33] >= 20 || // hair style
-        dat[31] >= 12)
-    {                           // hair color (dat[31] can not be negativ)
-        char_log
-            ("Make new char error (invalid values): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n",
-             fd, sd->account_id, dat[30], dat, dat[24], dat[25],
-             dat[26], dat[27], dat[28], dat[29],
-             dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
-             dat[33], dat[31]);
-        return -1;
-    }
-
-    // check individual stat value
-    for (i = 24; i <= 29; i++)
-    {
-        if (dat[i] < 1 || dat[i] > 9)
-        {
-            char_log
-                ("Make new char error (invalid stat value: not between 1 to 9): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n",
-                 fd, sd->account_id, dat[30], dat, dat[24], dat[25],
-                 dat[26], dat[27], dat[28], dat[29],
-                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
-                 dat[33], dat[31]);
-            return -1;
-        }
-    }
-
-    for (i = 0; i < char_num; i++)
-    {
-        if ((name_ignoring_case != 0 && strcmp (char_dat[i].name, dat) == 0)
-            || (name_ignoring_case == 0
-                && strcasecmp (char_dat[i].name, dat) == 0))
-        {
-            char_log
-                ("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
-                 fd, sd->account_id, dat[30], dat, char_dat[i].name,
-                 dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
-                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
-                 dat[33], dat[31]);
-            return -1;
-        }
-        if (char_dat[i].account_id == sd->account_id
-            && char_dat[i].char_num == dat[30])
-        {
-            char_log
-                ("Make new char error (slot already used): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
-                 fd, sd->account_id, dat[30], dat, char_dat[i].name,
-                 dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
-                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
-                 dat[33], dat[31]);
-            return -1;
-        }
-    }
-
-    if (strcmp (wisp_server_name, dat) == 0)
-    {
-        char_log
-            ("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %d), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
-             fd, sd->account_id, dat[30], dat, char_dat[i].name,
-             dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
-             dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
-             dat[33], dat[31]);
-        return -1;
-    }
-
-    if (char_num >= char_max)
-    {
-        char_max += 256;
-        RECREATE (char_dat, struct mmo_charstatus, char_max);
-        RECREATE (online_chars, int, char_max);
-        for (j = char_max - 256; j < char_max; j++)
-            online_chars[j] = -1;
-    }
-
-    char ip[16];
-    unsigned char *sin_addr =
-        (unsigned char *) &session[fd]->client_addr.sin_addr;
-    sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2],
-             sin_addr[3]);
-
-    char_log
-        ("Creation of New Character: (connection #%d, account: %d) slot %d, character Name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d. [%s]\n",
-         fd, sd->account_id, dat[30], dat, dat[24], dat[25], dat[26],
-         dat[27], dat[28], dat[29],
-         dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], dat[33],
-         dat[31], ip);
-
-    memset (&char_dat[i], 0, sizeof (struct mmo_charstatus));
-
-    char_dat[i].char_id = char_id_count++;
-    char_dat[i].account_id = sd->account_id;
-    char_dat[i].char_num = dat[30];
-    strcpy (char_dat[i].name, dat);
-    char_dat[i].pc_class = 0;
-    char_dat[i].base_level = 1;
-    char_dat[i].job_level = 1;
-    char_dat[i].base_exp = 0;
-    char_dat[i].job_exp = 0;
-    char_dat[i].zeny = start_zeny;
-    char_dat[i].str = dat[24];
-    char_dat[i].agi = dat[25];
-    char_dat[i].vit = dat[26];
-    char_dat[i].int_ = dat[27];
-    char_dat[i].dex = dat[28];
-    char_dat[i].luk = dat[29];
-    char_dat[i].max_hp = 40 * (100 + char_dat[i].vit) / 100;
-    char_dat[i].max_sp = 11 * (100 + char_dat[i].int_) / 100;
-    char_dat[i].hp = char_dat[i].max_hp;
-    char_dat[i].sp = char_dat[i].max_sp;
-    char_dat[i].status_point = 0;
-    char_dat[i].skill_point = 0;
-    char_dat[i].option = 0;
-    char_dat[i].karma = 0;
-    char_dat[i].manner = 0;
-    char_dat[i].party_id = 0;
-    char_dat[i].guild_id = 0;
-    char_dat[i].hair = dat[33];
-    char_dat[i].hair_color = dat[31];
-    char_dat[i].clothes_color = 0;
-    char_dat[i].inventory[0].nameid = start_weapon; // Knife
-    char_dat[i].inventory[0].amount = 1;
-    char_dat[i].inventory[0].equip = 0x02;
-    char_dat[i].inventory[0].identify = 1;
-    char_dat[i].inventory[0].broken = 0;
-    char_dat[i].inventory[1].nameid = start_armor;  // Cotton Shirt
-    char_dat[i].inventory[1].amount = 1;
-    char_dat[i].inventory[1].equip = 0x10;
-    char_dat[i].inventory[1].identify = 1;
-    char_dat[i].inventory[1].broken = 0;
-    char_dat[i].weapon = 1;
-    char_dat[i].shield = 0;
-    char_dat[i].head_top = 0;
-    char_dat[i].head_mid = 0;
-    char_dat[i].head_bottom = 0;
-    memcpy (&char_dat[i].last_point, &start_point, sizeof (start_point));
-    memcpy (&char_dat[i].save_point, &start_point, sizeof (start_point));
-    char_num++;
-
-    return i;
-}
-
-//----------------------------------------------------
-// This function return the name of the job (by [Yor])
-//----------------------------------------------------
-char *job_name (int pc_class)
-{
-    switch (pc_class)
-    {
-        case 0:
-            return "Novice";
-        case 1:
-            return "Swordsman";
-        case 2:
-            return "Mage";
-        case 3:
-            return "Archer";
-        case 4:
-            return "Acolyte";
-        case 5:
-            return "Merchant";
-        case 6:
-            return "Thief";
-        case 7:
-            return "Knight";
-        case 8:
-            return "Priest";
-        case 9:
-            return "Wizard";
-        case 10:
-            return "Blacksmith";
-        case 11:
-            return "Hunter";
-        case 12:
-            return "Assassin";
-        case 13:
-            return "Knight 2";
-        case 14:
-            return "Crusader";
-        case 15:
-            return "Monk";
-        case 16:
-            return "Sage";
-        case 17:
-            return "Rogue";
-        case 18:
-            return "Alchemist";
-        case 19:
-            return "Bard";
-        case 20:
-            return "Dancer";
-        case 21:
-            return "Crusader 2";
-        case 22:
-            return "Wedding";
-        case 23:
-            return "Super Novice";
-        case 4001:
-            return "Novice High";
-        case 4002:
-            return "Swordsman High";
-        case 4003:
-            return "Mage High";
-        case 4004:
-            return "Archer High";
-        case 4005:
-            return "Acolyte High";
-        case 4006:
-            return "Merchant High";
-        case 4007:
-            return "Thief High";
-        case 4008:
-            return "Lord Knight";
-        case 4009:
-            return "High Priest";
-        case 4010:
-            return "High Wizard";
-        case 4011:
-            return "Whitesmith";
-        case 4012:
-            return "Sniper";
-        case 4013:
-            return "Assassin Cross";
-        case 4014:
-            return "Peko Knight";
-        case 4015:
-            return "Paladin";
-        case 4016:
-            return "Champion";
-        case 4017:
-            return "Professor";
-        case 4018:
-            return "Stalker";
-        case 4019:
-            return "Creator";
-        case 4020:
-            return "Clown";
-        case 4021:
-            return "Gypsy";
-        case 4022:
-            return "Peko Paladin";
-        case 4023:
-            return "Baby Novice";
-        case 4024:
-            return "Baby Swordsman";
-        case 4025:
-            return "Baby Mage";
-        case 4026:
-            return "Baby Archer";
-        case 4027:
-            return "Baby Acolyte";
-        case 4028:
-            return "Baby Merchant";
-        case 4029:
-            return "Baby Thief";
-        case 4030:
-            return "Baby Knight";
-        case 4031:
-            return "Baby Priest";
-        case 4032:
-            return "Baby Wizard";
-        case 4033:
-            return "Baby Blacksmith";
-        case 4034:
-            return "Baby Hunter";
-        case 4035:
-            return "Baby Assassin";
-        case 4036:
-            return "Baby Peco Knight";
-        case 4037:
-            return "Baby Crusader";
-        case 4038:
-            return "Baby Monk";
-        case 4039:
-            return "Baby Sage";
-        case 4040:
-            return "Baby Rogue";
-        case 4041:
-            return "Baby Alchemist";
-        case 4042:
-            return "Baby Bard";
-        case 4043:
-            return "Baby Dancer";
-        case 4044:
-            return "Baby Peco Crusader";
-        case 4045:
-            return "Super Baby";
-    }
-    return "Unknown Job";
-}
-
-//-------------------------------------------------------------
-// Function to create the online files (txt and html). by [Yor]
-//-------------------------------------------------------------
-void create_online_files (void)
-{
-    int  i, j, k, l;            // for loops
-    int  players;               // count the number of players
-    FILE *fp;                   // for the txt file
-    FILE *fp2;                  // for the html file
-    char temp[256];             // to prepare what we must display
-    time_t time_server;         // for number of seconds
-    struct tm *datetime;        // variable for time in structure ->tm_mday, ->tm_sec, ...
-    int  id[char_num];
-
-    if (online_display_option == 0) // we display nothing, so return
-        return;
-
-    //char_log("Creation of online players files.\n");
-
-    // Get number of online players, id of each online players
-    players = 0;
-    // sort online characters.
-    for (i = 0; i < char_num; i++)
-    {
-        if (online_chars[i] != -1)
-        {
-            id[players] = i;
-            // use sorting option
-            switch (online_sorting_option)
-            {
-                case 1:        // by name (without case sensitive)
-                {
-                    char *p_name = char_dat[i].name;    //speed up sorting when there are a lot of players. But very rarely players have same name.
-                    for (j = 0; j < players; j++)
-                        if (strcasecmp (p_name, char_dat[id[j]].name) < 0 ||
-                            // if same name, we sort with case sensitive.
-                            (strcasecmp (p_name, char_dat[id[j]].name) == 0 &&
-                             strcmp (p_name, char_dat[id[j]].name) < 0))
-                        {
-                            for (k = players; k > j; k--)
-                                id[k] = id[k - 1];
-                            id[j] = i;  // id[players]
-                            break;
-                        }
-                }
-                    break;
-                case 2:        // by zeny
-                    for (j = 0; j < players; j++)
-                        if (char_dat[i].zeny < char_dat[id[j]].zeny ||
-                            // if same number of zenys, we sort by name.
-                            (char_dat[i].zeny == char_dat[id[j]].zeny &&
-                             strcasecmp (char_dat[i].name,
-                                      char_dat[id[j]].name) < 0))
-                        {
-                            for (k = players; k > j; k--)
-                                id[k] = id[k - 1];
-                            id[j] = i;  // id[players]
-                            break;
-                        }
-                    break;
-                case 3:        // by base level
-                    for (j = 0; j < players; j++)
-                        if (char_dat[i].base_level <
-                            char_dat[id[j]].base_level ||
-                            // if same base level, we sort by base exp.
-                            (char_dat[i].base_level ==
-                             char_dat[id[j]].base_level
-                             && char_dat[i].base_exp <
-                             char_dat[id[j]].base_exp))
-                        {
-                            for (k = players; k > j; k--)
-                                id[k] = id[k - 1];
-                            id[j] = i;  // id[players]
-                            break;
-                        }
-                    break;
-                case 4:        // by job (and job level)
-                    for (j = 0; j < players; j++)
-                        if (char_dat[i].pc_class < char_dat[id[j]].pc_class ||
-                            // if same job, we sort by job level.
-                            (char_dat[i].pc_class == char_dat[id[j]].pc_class &&
-                             char_dat[i].job_level <
-                             char_dat[id[j]].job_level) ||
-                            // if same job and job level, we sort by job exp.
-                            (char_dat[i].pc_class == char_dat[id[j]].pc_class &&
-                             char_dat[i].job_level ==
-                             char_dat[id[j]].job_level
-                             && char_dat[i].job_exp <
-                             char_dat[id[j]].job_exp))
-                        {
-                            for (k = players; k > j; k--)
-                                id[k] = id[k - 1];
-                            id[j] = i;  // id[players]
-                            break;
-                        }
-                    break;
-                case 5:        // by location map name
-                {
-                    int  cpm_result;    // A lot of player maps are identical. So, test if done often twice.
-                    for (j = 0; j < players; j++)
-                        if ((cpm_result = strcmp (char_dat[i].last_point.map, char_dat[id[j]].last_point.map)) < 0 ||   // no map are identical and with upper cases (not use strcasecmp)
-                            // if same map name, we sort by name.
-                            (cpm_result == 0 &&
-                             strcasecmp (char_dat[i].name,
-                                      char_dat[id[j]].name) < 0))
-                        {
-                            for (k = players; k > j; k--)
-                                id[k] = id[k - 1];
-                            id[j] = i;  // id[players]
-                            break;
-                        }
-                }
-                    break;
-                default:       // 0 or invalid value: no sorting
-                    break;
-            }
-            players++;
-        }
-    }
-
-    // write files
-    fp = fopen_ (online_txt_filename, "w");
-    if (fp != NULL)
-    {
-        fp2 = fopen_ (online_html_filename, "w");
-        if (fp2 != NULL)
-        {
-            // get time
-            time (&time_server);    // get time in seconds since 1/1/1970
-            datetime = localtime (&time_server);    // convert seconds in structure
-            strftime (temp, sizeof (temp), "%d %b %Y %X", datetime);    // like sprintf, but only for date/time (05 dec 2003 15:12:52)
-            // write heading
-            fprintf (fp2, "<HTML>\n");
-            fprintf (fp2, "  <META http-equiv=\"Refresh\" content=\"%d\">\n", online_refresh_html); // update on client explorer every x seconds
-            fprintf (fp2, "  <HEAD>\n");
-            fprintf (fp2, "    <TITLE>Online Players on %s</TITLE>\n",
-                     server_name);
-            fprintf (fp2, "  </HEAD>\n");
-            fprintf (fp2, "  <BODY>\n");
-            fprintf (fp2, "    <H3>Online Players on %s (%s):</H3>\n",
-                     server_name, temp);
-            fprintf (fp, "Online Players on %s (%s):\n", server_name, temp);
-            fprintf (fp, "\n");
-
-            // If we display at least 1 player
-            if (players > 0)
-            {
-                j = 0;          // count the number of characters for the txt version and to set the separate line
-                fprintf (fp2, "    <table border=\"1\" cellspacing=\"1\">\n");
-                fprintf (fp2, "      <tr>\n");
-                if ((online_display_option & 1)
-                    || (online_display_option & 64))
-                {
-                    fprintf (fp2, "        <td><b>Name</b></td>\n");
-                    if (online_display_option & 64)
-                    {
-                        fprintf (fp, "Name                          "); // 30
-                        j += 30;
-                    }
-                    else
-                    {
-                        fprintf (fp, "Name                     ");  // 25
-                        j += 25;
-                    }
-                }
-                if ((online_display_option & 6) == 6)
-                {
-                    fprintf (fp2, "        <td><b>Job (levels)</b></td>\n");
-                    fprintf (fp, "Job                 Levels ");    // 27
-                    j += 27;
-                }
-                else if (online_display_option & 2)
-                {
-                    fprintf (fp2, "        <td><b>Job</b></td>\n");
-                    fprintf (fp, "Job                ");    // 19
-                    j += 19;
-                }
-                else if (online_display_option & 4)
-                {
-                    fprintf (fp2, "        <td><b>Levels</b></td>\n");
-                    fprintf (fp, " Levels ");   // 8
-                    j += 8;
-                }
-                if (online_display_option & 24)
-                {               // 8 or 16
-                    fprintf (fp2, "        <td><b>Location</b></td>\n");
-                    if (online_display_option & 16)
-                    {
-                        fprintf (fp, "Location     ( x , y ) ");    // 23
-                        j += 23;
-                    }
-                    else
-                    {
-                        fprintf (fp, "Location     ");  // 13
-                        j += 13;
-                    }
-                }
-                if (online_display_option & 32)
-                {
-                    fprintf (fp2,
-                             "        <td ALIGN=CENTER><b>zenys</b></td>\n");
-                    fprintf (fp, "          Zenys ");   // 16
-                    j += 16;
-                }
-                fprintf (fp2, "      </tr>\n");
-                fprintf (fp, "\n");
-                for (k = 0; k < j; k++)
-                    fprintf (fp, "-");
-                fprintf (fp, "\n");
-
-                // display each player.
-                for (i = 0; i < players; i++)
-                {
-                    // get id of the character (more speed)
-                    j = id[i];
-                    fprintf (fp2, "      <tr>\n");
-                    // displaying the character name
-                    if ((online_display_option & 1)
-                        || (online_display_option & 64))
-                    {           // without/with 'GM' display
-                        strcpy (temp, char_dat[j].name);
-                        l = isGM (char_dat[j].account_id);
-                        if (online_display_option & 64)
-                        {
-                            if (l >= online_gm_display_min_level)
-                                fprintf (fp, "%-24s (GM) ", temp);
-                            else
-                                fprintf (fp, "%-24s      ", temp);
-                        }
-                        else
-                            fprintf (fp, "%-24s ", temp);
-                        // name of the character in the html (no < >, because that create problem in html code)
-                        fprintf (fp2, "        <td>");
-                        if ((online_display_option & 64)
-                            && l >= online_gm_display_min_level)
-                            fprintf (fp2, "<b>");
-                        for (k = 0; temp[k]; k++)
-                        {
-                            switch (temp[k])
-                            {
-                                case '<':  // <
-                                    fprintf (fp2, "&lt;");
-                                    break;
-                                case '>':  // >
-                                    fprintf (fp2, "&gt;");
-                                    break;
-                                default:
-                                    fprintf (fp2, "%c", temp[k]);
-                                    break;
-                            };
-                        }
-                        if ((online_display_option & 64)
-                            && l >= online_gm_display_min_level)
-                            fprintf (fp2, "</b> (GM)");
-                        fprintf (fp2, "</td>\n");
-                    }
-                    // displaying of the job
-                    if (online_display_option & 6)
-                    {
-                        char *jobname = job_name (char_dat[j].pc_class);
-                        if ((online_display_option & 6) == 6)
-                        {
-                            fprintf (fp2, "        <td>%s %d/%d</td>\n",
-                                     jobname, char_dat[j].base_level,
-                                     char_dat[j].job_level);
-                            fprintf (fp, "%-18s %3d/%3d ", jobname,
-                                     char_dat[j].base_level,
-                                     char_dat[j].job_level);
-                        }
-                        else if (online_display_option & 2)
-                        {
-                            fprintf (fp2, "        <td>%s</td>\n", jobname);
-                            fprintf (fp, "%-18s ", jobname);
-                        }
-                        else if (online_display_option & 4)
-                        {
-                            fprintf (fp2, "        <td>%d/%d</td>\n",
-                                     char_dat[j].base_level,
-                                     char_dat[j].job_level);
-                            fprintf (fp, "%3d/%3d ", char_dat[j].base_level,
-                                     char_dat[j].job_level);
-                        }
-                    }
-                    // displaying of the map
-                    if (online_display_option & 24)
-                    {           // 8 or 16
-                        // prepare map name
-                        memset (temp, 0, sizeof (temp));
-                        strncpy (temp, char_dat[j].last_point.map, 16);
-                        if (strchr (temp, '.') != NULL)
-                            temp[strchr (temp, '.') - temp] = '\0'; // suppress the '.gat'
-                        // write map name
-                        if (online_display_option & 16)
-                        {       // map-name AND coordonates
-                            fprintf (fp2, "        <td>%s (%d, %d)</td>\n",
-                                     temp, char_dat[j].last_point.x,
-                                     char_dat[j].last_point.y);
-                            fprintf (fp, "%-12s (%3d,%3d) ", temp,
-                                     char_dat[j].last_point.x,
-                                     char_dat[j].last_point.y);
-                        }
-                        else
-                        {
-                            fprintf (fp2, "        <td>%s</td>\n", temp);
-                            fprintf (fp, "%-12s ", temp);
-                        }
-                    }
-                    // displaying number of zenys
-                    if (online_display_option & 32)
-                    {
-                        // write number of zenys
-                        if (char_dat[j].zeny == 0)
-                        {       // if no zeny
-                            fprintf (fp2,
-                                     "        <td ALIGN=RIGHT>no zeny</td>\n");
-                            fprintf (fp, "        no zeny ");
-                        }
-                        else
-                        {
-                            fprintf (fp2,
-                                     "        <td ALIGN=RIGHT>%d z</td>\n",
-                                     char_dat[j].zeny);
-                            fprintf (fp, "%13d z ", char_dat[j].zeny);
-                        }
-                    }
-                    fprintf (fp, "\n");
-                    fprintf (fp2, "      </tr>\n");
-                }
-                fprintf (fp2, "    </table>\n");
-                fprintf (fp, "\n");
-            }
-
-            // Displaying number of online players
-            if (players == 0)
-            {
-                fprintf (fp2, "    <p>No user is online.</p>\n");
-                fprintf (fp, "No user is online.\n");
-                // no display if only 1 player
-            }
-            else if (players == 1)
-            {
-            }
-            else
-            {
-                fprintf (fp2, "    <p>%d users are online.</p>\n", players);
-                fprintf (fp, "%d users are online.\n", players);
-            }
-            fprintf (fp2, "  </BODY>\n");
-            fprintf (fp2, "</HTML>\n");
-            fclose_ (fp2);
-        }
-        fclose_ (fp);
-    }
-
-    return;
-}
-
-//---------------------------------------------------------------------
-// This function return the number of online players in all map-servers
-//---------------------------------------------------------------------
-int count_users (void)
-{
-    int  i, users;
-
-    users = 0;
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-        if (server_fd[i] >= 0)
-            users += server[i].users;
-
-    return users;
-}
-
-//----------------------------------------
-// [Fate] Find inventory item based on equipment mask, return view.  ID must match view ID (!).
-//----------------------------------------
-static int find_equip_view (struct mmo_charstatus *p, unsigned int equipmask)
-{
-    int  i;
-    for (i = 0; i < MAX_INVENTORY; i++)
-        if (p->inventory[i].nameid && p->inventory[i].amount
-            && p->inventory[i].equip & equipmask)
-            return p->inventory[i].nameid;
-    return 0;
-}
-
-//----------------------------------------
-// Function to send characters to a player
-//----------------------------------------
-int mmo_char_send006b (int fd, struct char_session_data *sd)
-{
-    int  i, j, found_num;
-    struct mmo_charstatus *p;
-    const int offset = 24;
-
-    found_num = 0;
-    for (i = 0; i < char_num; i++)
-    {
-        if (char_dat[i].account_id == sd->account_id)
-        {
-            sd->found_char[found_num] = i;
-            found_num++;
-            if (found_num == 9)
-                break;
-        }
-    }
-    for (i = found_num; i < 9; i++)
-        sd->found_char[i] = -1;
-
-    memset (WFIFOP (fd, 0), 0, offset + found_num * 106);
-    WFIFOW (fd, 0) = 0x6b;
-    WFIFOW (fd, 2) = offset + found_num * 106;
-
-    for (i = 0; i < found_num; i++)
-    {
-        p = &char_dat[sd->found_char[i]];
-        j = offset + (i * 106); // increase speed of code
-
-        WFIFOL (fd, j) = p->char_id;
-        WFIFOL (fd, j + 4) = p->base_exp;
-        WFIFOL (fd, j + 8) = p->zeny;
-        WFIFOL (fd, j + 12) = p->job_exp;
-        WFIFOL (fd, j + 16) = 0;    //p->job_level; // [Fate] We no longer reveal this to the player, as its meaning is weird.
-
-        WFIFOW (fd, j + 20) = find_equip_view (p, 0x0040);  // 9: shoes
-        WFIFOW (fd, j + 22) = find_equip_view (p, 0x0004);  // 10: gloves
-        WFIFOW (fd, j + 24) = find_equip_view (p, 0x0008);  // 11: cape
-        WFIFOW (fd, j + 26) = find_equip_view (p, 0x0010);  // 12: misc1
-        WFIFOL (fd, j + 28) = p->option;
-
-        WFIFOL (fd, j + 32) = p->karma;
-        WFIFOL (fd, j + 36) = p->manner;
-
-        WFIFOW (fd, j + 40) = p->status_point;
-        WFIFOW (fd, j + 42) = (p->hp > 0x7fff) ? 0x7fff : p->hp;
-        WFIFOW (fd, j + 44) = (p->max_hp > 0x7fff) ? 0x7fff : p->max_hp;
-        WFIFOW (fd, j + 46) = (p->sp > 0x7fff) ? 0x7fff : p->sp;
-        WFIFOW (fd, j + 48) = (p->max_sp > 0x7fff) ? 0x7fff : p->max_sp;
-        WFIFOW (fd, j + 50) = DEFAULT_WALK_SPEED;   // p->speed;
-        WFIFOW (fd, j + 52) = p->pc_class;
-        WFIFOW (fd, j + 54) = p->hair;
-//      WFIFOW(fd,j+56) = p->weapon; // dont send weapon since TMW does not support it
-        WFIFOW (fd, j + 56) = 0;
-        WFIFOW (fd, j + 58) = p->base_level;
-        WFIFOW (fd, j + 60) = p->skill_point;
-        WFIFOW (fd, j + 62) = p->head_bottom;
-        WFIFOW (fd, j + 64) = p->shield;
-        WFIFOW (fd, j + 66) = p->head_top;
-        WFIFOW (fd, j + 68) = p->head_mid;
-        WFIFOW (fd, j + 70) = p->hair_color;
-        WFIFOW (fd, j + 72) = find_equip_view (p, 0x0080);  // 13: misc2
-//      WFIFOW(fd,j+72) = p->clothes_color;
-
-        memcpy (WFIFOP (fd, j + 74), p->name, 24);
-
-        WFIFOB (fd, j + 98) = (p->str > 255) ? 255 : p->str;
-        WFIFOB (fd, j + 99) = (p->agi > 255) ? 255 : p->agi;
-        WFIFOB (fd, j + 100) = (p->vit > 255) ? 255 : p->vit;
-        WFIFOB (fd, j + 101) = (p->int_ > 255) ? 255 : p->int_;
-        WFIFOB (fd, j + 102) = (p->dex > 255) ? 255 : p->dex;
-        WFIFOB (fd, j + 103) = (p->luk > 255) ? 255 : p->luk;
-        WFIFOB (fd, j + 104) = p->char_num;
-    }
-
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-int set_account_reg2 (int acc, int num, struct global_reg *reg)
-{
-    int  i, c;
-
-    c = 0;
-    for (i = 0; i < char_num; i++)
-    {
-        if (char_dat[i].account_id == acc)
-        {
-            memcpy (char_dat[i].account_reg2, reg,
-                    sizeof (char_dat[i].account_reg2));
-            char_dat[i].account_reg2_num = num;
-            c++;
-        }
-    }
-    return c;
-}
-
-// Divorce a character from it's partner and let the map server know
-int char_divorce (struct mmo_charstatus *cs)
-{
-    int  i;
-    char buf[10];
-
-    if (cs == NULL)
-        return 0;
-
-    if (cs->partner_id <= 0)
-    {
-        WBUFW (buf, 0) = 0x2b12;
-        WBUFL (buf, 2) = cs->char_id;
-        WBUFL (buf, 6) = 0;     // partner id 0 means failure
-        mapif_sendall (buf, 10);
-        return 0;
-    }
-
-    WBUFW (buf, 0) = 0x2b12;
-    WBUFL (buf, 2) = cs->char_id;
-
-    for (i = 0; i < char_num; i++)
-    {
-        if (char_dat[i].char_id == cs->partner_id
-            && char_dat[i].partner_id == cs->char_id)
-        {
-            WBUFL (buf, 6) = cs->partner_id;
-            mapif_sendall (buf, 10);
-            cs->partner_id = 0;
-            char_dat[i].partner_id = 0;
-            return 0;
-        }
-        // The other char doesn't have us as their partner, so just clear our partner
-        // Don't worry about this, as the map server should verify itself that the other doesn't have us as a partner, and so won't mess with their marriage
-        else if (char_dat[i].char_id == cs->partner_id)
-        {
-            WBUFL (buf, 6) = cs->partner_id;
-            mapif_sendall (buf, 10);
-            cs->partner_id = 0;
-            return 0;
-        }
-    }
-
-    // Our partner wasn't found, so just clear our marriage
-    WBUFL (buf, 6) = cs->partner_id;
-    cs->partner_id = 0;
-    mapif_sendall (buf, 10);
-
-    return 0;
-}
-
-//------------------------------------------------------------
-// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
-//------------------------------------------------------------
-int e_mail_check (unsigned char *email)
-{
-    char ch;
-    unsigned char *last_arobas;
-
-    // athena limits
-    if (strlen (email) < 3 || strlen (email) > 39)
-        return 0;
-
-    // part of RFC limits (official reference of e-mail description)
-    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
-        return 0;
-
-    if (email[strlen (email) - 1] == '.')
-        return 0;
-
-    last_arobas = strrchr (email, '@');
-
-    if (strstr (last_arobas, "@.") != NULL ||
-        strstr (last_arobas, "..") != NULL)
-        return 0;
-
-    for (ch = 1; ch < 32; ch++)
-    {
-        if (strchr (last_arobas, ch) != NULL)
-        {
-            return 0;
-            break;
-        }
-    }
-
-    if (strchr (last_arobas, ' ') != NULL ||
-        strchr (last_arobas, ';') != NULL)
-        return 0;
-
-    // all correct
-    return 1;
-}
-
-//----------------------------------------------------------------------
-// Force disconnection of an online player (with account value) by [Yor]
-//----------------------------------------------------------------------
-int disconnect_player (int accound_id)
-{
-    int  i;
-    struct char_session_data *sd;
-
-    // disconnect player if online on char-server
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
-        {
-            if (sd->account_id == accound_id)
-            {
-                session[i]->eof = 1;
-                return 1;
-            }
-        }
-    }
-
-    return 0;
-}
-
-// キャラ削除に伴うデータ削除
-static int char_delete (struct mmo_charstatus *cs)
-{
-
-    // ギルド脱退
-    if (cs->guild_id)
-        inter_guild_leave (cs->guild_id, cs->account_id, cs->char_id);
-    // パーティー脱退
-    if (cs->party_id)
-        inter_party_leave (cs->party_id, cs->account_id);
-    // 離婚
-    if (cs->partner_id)
-        char_divorce (cs);
-
-    // Force the character (and all on the same account) to leave all map servers
-    {
-        unsigned char buf[6];
-        WBUFW (buf, 0) = 0x2afe;
-        WBUFL (buf, 2) = cs->account_id;
-        mapif_sendall (buf, 6);
-    }
-
-    return 0;
-}
-
-void parse_tologin (int fd)
-{
-    int  i;
-    struct char_session_data *sd;
-
-    // only login-server can have an access to here.
-    // so, if it isn't the login-server, we disconnect the session (fd != login_fd).
-    if (fd != login_fd || session[fd]->eof)
-    {
-        if (fd == login_fd)
-        {
-            printf
-                ("Char-server can't connect to login-server (connection #%d).\n",
-                 fd);
-            login_fd = -1;
-        }
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    sd = (struct char_session_data*)session[fd]->session_data;
-
-    while (RFIFOREST (fd) >= 2)
-    {
-//      printf("parse_tologin: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
-
-        switch (RFIFOW (fd, 0))
-        {
-            case 0x2711:
-                if (RFIFOREST (fd) < 3)
-                    return;
-                if (RFIFOB (fd, 2))
-                {
-//              printf("connect login server error : %d\n", RFIFOB(fd,2));
-                    printf ("Can not connect to login-server.\n");
-                    printf
-                        ("The server communication passwords (default s1/p1) is probably invalid.\n");
-                    printf
-                        ("Also, please make sure your accounts file (default: accounts.txt) has those values present.\n");
-                    printf
-                        ("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n");
-                    exit (1);
-                }
-                else
-                {
-                    printf ("Connected to login-server (connection #%d).\n",
-                            fd);
-                    // if no map-server already connected, display a message...
-                    for (i = 0; i < MAX_MAP_SERVERS; i++)
-                        if (server_fd[i] >= 0 && server[i].map[0][0])   // if map-server online and at least 1 map
-                            break;
-                    if (i == MAX_MAP_SERVERS)
-                        printf ("Awaiting maps from map-server.\n");
-                }
-                RFIFOSKIP (fd, 3);
-                break;
-
-            case 0x2713:
-                if (RFIFOREST (fd) < 51)
-                    return;
-//          printf("parse_tologin 2713 : %d\n", RFIFOB(fd,6));
-                for (i = 0; i < fd_max; i++)
-                {
-                    if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)
-                        && sd->account_id == RFIFOL (fd, 2))
-                    {
-                        if (RFIFOB (fd, 6) != 0)
-                        {
-                            WFIFOW (i, 0) = 0x6c;
-                            WFIFOB (i, 2) = 0x42;
-                            WFIFOSET (i, 3);
-                        }
-                        else if (max_connect_user == 0
-                                 || count_users () < max_connect_user)
-                        {
-//                      if (max_connect_user == 0)
-//                          printf("max_connect_user (unlimited) -> accepted.\n");
-//                      else
-//                          printf("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user);
-                            memcpy (sd->email, RFIFOP (fd, 7), 40);
-                            if (e_mail_check (sd->email) == 0)
-                                strncpy (sd->email, "a@a.com", 40); // default e-mail
-                            sd->connect_until_time = (time_t) RFIFOL (fd, 47);
-                            // send characters to player
-                            mmo_char_send006b (i, sd);
-                        }
-                        else
-                        {
-                            // refuse connection: too much online players
-//                      printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user);
-                            WFIFOW (i, 0) = 0x6c;
-                            WFIFOW (i, 2) = 0;
-                            WFIFOSET (i, 3);
-                        }
-                        break;
-                    }
-                }
-                RFIFOSKIP (fd, 51);
-                break;
-
-                // Receiving of an e-mail/time limit from the login-server (answer of a request because a player comes back from map-server to char-server) by [Yor]
-            case 0x2717:
-                if (RFIFOREST (fd) < 50)
-                    return;
-                for (i = 0; i < fd_max; i++)
-                {
-                    if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
-                    {
-                        if (sd->account_id == RFIFOL (fd, 2))
-                        {
-                            memcpy (sd->email, RFIFOP (fd, 6), 40);
-                            if (e_mail_check (sd->email) == 0)
-                                strncpy (sd->email, "a@a.com", 40); // default e-mail
-                            sd->connect_until_time = (time_t) RFIFOL (fd, 46);
-                            break;
-                        }
-                    }
-                }
-                RFIFOSKIP (fd, 50);
-                break;
-
-            case 0x2721:       // gm reply
-                if (RFIFOREST (fd) < 10)
-                    return;
-                {
-                    unsigned char buf[10];
-                    WBUFW (buf, 0) = 0x2b0b;
-                    WBUFL (buf, 2) = RFIFOL (fd, 2);    // account
-                    WBUFL (buf, 6) = RFIFOL (fd, 6);    // GM level
-                    mapif_sendall (buf, 10);
-//          printf("parse_tologin: To become GM answer: char -> map.\n");
-                }
-                RFIFOSKIP (fd, 10);
-                break;
-
-            case 0x2723:       // changesex reply (modified by [Yor])
-                if (RFIFOREST (fd) < 7)
-                    return;
-                {
-                    int  acc, sex, i, j;
-                    unsigned char buf[7];
-                    acc = RFIFOL (fd, 2);
-                    sex = RFIFOB (fd, 6);
-                    RFIFOSKIP (fd, 7);
-                    if (acc > 0)
-                    {
-                        for (i = 0; i < char_num; i++)
-                        {
-                            if (char_dat[i].account_id == acc)
-                            {
-                                int  jobclass = char_dat[i].pc_class;
-                                char_dat[i].sex = sex;
-//                      auth_fifo[i].sex = sex;
-                                if (jobclass == 19 || jobclass == 20 ||
-                                    jobclass == 4020 || jobclass == 4021 ||
-                                    jobclass == 4042 || jobclass == 4043)
-                                {
-                                    // job modification
-                                    if (jobclass == 19 || jobclass == 20)
-                                    {
-                                        char_dat[i].pc_class = (sex) ? 19 : 20;
-                                    }
-                                    else if (jobclass == 4020
-                                             || jobclass == 4021)
-                                    {
-                                        char_dat[i].pc_class =
-                                            (sex) ? 4020 : 4021;
-                                    }
-                                    else if (jobclass == 4042
-                                             || jobclass == 4043)
-                                    {
-                                        char_dat[i].pc_class =
-                                            (sex) ? 4042 : 4043;
-                                    }
-                                }
-                                // to avoid any problem with equipment and invalid sex, equipment is unequiped.
-                                for (j = 0; j < MAX_INVENTORY; j++)
-                                {
-                                    if (char_dat[i].inventory[j].nameid
-                                        && char_dat[i].inventory[j].equip)
-                                        char_dat[i].inventory[j].equip = 0;
-                                }
-                                char_dat[i].weapon = 0;
-                                char_dat[i].shield = 0;
-                                char_dat[i].head_top = 0;
-                                char_dat[i].head_mid = 0;
-                                char_dat[i].head_bottom = 0;
-                            }
-                        }
-                        // disconnect player if online on char-server
-                        disconnect_player (acc);
-                    }
-                    WBUFW (buf, 0) = 0x2b0d;
-                    WBUFL (buf, 2) = acc;
-                    WBUFB (buf, 6) = sex;
-                    mapif_sendall (buf, 7);
-                }
-                break;
-
-            case 0x2726:       // Request to send a broadcast message (no answer)
-                if (RFIFOREST (fd) < 8
-                    || RFIFOREST (fd) < (8 + RFIFOL (fd, 4)))
-                    return;
-                if (RFIFOL (fd, 4) < 1)
-                    char_log
-                        ("Receiving a message for broadcast, but message is void.\n");
-                else
-                {
-                    // at least 1 map-server
-                    for (i = 0; i < MAX_MAP_SERVERS; i++)
-                        if (server_fd[i] >= 0)
-                            break;
-                    if (i == MAX_MAP_SERVERS)
-                        char_log
-                            ("'ladmin': Receiving a message for broadcast, but no map-server is online.\n");
-                    else
-                    {
-                        char buf[128];
-                        char message[RFIFOL (fd, 4) + 1];   // +1 to add a null terminated if not exist in the packet
-                        int  lp;
-                        char *p;
-                        memset (message, '\0', sizeof (message));
-                        memcpy (message, RFIFOP (fd, 8), RFIFOL (fd, 4));
-                        message[sizeof (message) - 1] = '\0';
-                        remove_control_chars (message);
-                        // remove all first spaces
-                        p = message;
-                        while (p[0] == ' ')
-                            p++;
-                        // if message is only composed of spaces
-                        if (p[0] == '\0')
-                            char_log
-                                ("Receiving a message for broadcast, but message is only a lot of spaces.\n");
-                        // else send message to all map-servers
-                        else
-                        {
-                            if (RFIFOW (fd, 2) == 0)
-                            {
-                                char_log
-                                    ("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n",
-                                     message);
-                                lp = 4;
-                            }
-                            else
-                            {
-                                char_log
-                                    ("'ladmin': Receiving a message for broadcast (message (in blue): %s)\n",
-                                     message);
-                                lp = 8;
-                            }
-                            // split message to max 80 char
-                            while (p[0] != '\0')
-                            {   // if not finish
-                                if (p[0] == ' ')    // jump if first char is a space
-                                    p++;
-                                else
-                                {
-                                    char split[80];
-                                    char *last_space;
-                                    sscanf (p, "%79[^\t]", split);  // max 79 char, any char (\t is control char and control char was removed before)
-                                    split[sizeof (split) - 1] = '\0';   // last char always \0
-                                    if ((last_space =
-                                         strrchr (split, ' ')) != NULL)
-                                    {   // searching space from end of the string
-                                        last_space[0] = '\0';   // replace it by NULL to have correct length of split
-                                        p++;    // to jump the new NULL
-                                    }
-                                    p += strlen (split);
-                                    // send broadcast to all map-servers
-                                    WBUFW (buf, 0) = 0x3800;
-                                    WBUFW (buf, 2) = lp + strlen (split) + 1;
-                                    WBUFL (buf, 4) = 0x65756c62;    // only write if in blue (lp = 8)
-                                    memcpy (WBUFP (buf, lp), split,
-                                            strlen (split) + 1);
-                                    mapif_sendall (buf, WBUFW (buf, 2));
-                                }
-                            }
-                        }
-                    }
-                }
-                RFIFOSKIP (fd, 8 + RFIFOL (fd, 4));
-                break;
-
-                // account_reg2変更通知
-            case 0x2729:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    struct global_reg reg[ACCOUNT_REG2_NUM];
-                    unsigned char buf[4096];
-                    int  j, p, acc;
-                    acc = RFIFOL (fd, 4);
-                    for (p = 8, j = 0;
-                         p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
-                         p += 36, j++)
-                    {
-                        memcpy (reg[j].str, RFIFOP (fd, p), 32);
-                        reg[j].value = RFIFOL (fd, p + 32);
-                    }
-                    set_account_reg2 (acc, j, reg);
-                    // 同垢ログインを禁止していれば送る必要は無い
-                    memcpy (buf, RFIFOP (fd, 0), RFIFOW (fd, 2));
-                    WBUFW (buf, 0) = 0x2b11;
-                    mapif_sendall (buf, WBUFW (buf, 2));
-                    RFIFOSKIP (fd, RFIFOW (fd, 2));
-//          printf("char: save_account_reg_reply\n");
-                }
-                break;
-
-            case 0x7924:
-            {                   // [Fate] Itemfrob package: forwarded from login-server
-                if (RFIFOREST (fd) < 10)
-                    return;
-                int  source_id = RFIFOL (fd, 2);
-                int  dest_id = RFIFOL (fd, 6);
-                unsigned char buf[10];
-
-                WBUFW (buf, 0) = 0x2afa;
-                WBUFL (buf, 2) = source_id;
-                WBUFL (buf, 6) = dest_id;
-
-                mapif_sendall (buf, 10);    // forward package to map servers
-                for (i = 0; i < char_num; i++)
-                {
-                    struct mmo_charstatus *c = char_dat + i;
-                    struct storage *s = account2storage (c->account_id);
-                    int  changes = 0;
-                    int  j;
-#define FIX(v) if (v == source_id) {v = dest_id; ++changes; }
-                    for (j = 0; j < MAX_INVENTORY; j++)
-                        FIX (c->inventory[j].nameid);
-                    for (j = 0; j < MAX_CART; j++)
-                        FIX (c->cart[j].nameid);
-                    FIX (c->weapon);
-                    FIX (c->shield);
-                    FIX (c->head_top);
-                    FIX (c->head_mid);
-                    FIX (c->head_bottom);
-
-                    if (s)
-                        for (j = 0; j < s->storage_amount; j++)
-                            FIX (s->storage_[j].nameid);
-#undef FIX
-                    if (changes)
-                        char_log
-                            ("itemfrob(%d -> %d):  `%s'(%d, account %d): changed %d times\n",
-                             source_id, dest_id, c->name, c->char_id,
-                             c->account_id, changes);
-
-                }
-
-                mmo_char_sync ();
-                inter_storage_save ();
-                RFIFOSKIP (fd, 10);
-                break;
-            }
-
-                // Account deletion notification (from login-server)
-            case 0x2730:
-                if (RFIFOREST (fd) < 6)
-                    return;
-                // Deletion of all characters of the account
-                for (i = 0; i < char_num; i++)
-                {
-                    if (char_dat[i].account_id == RFIFOL (fd, 2))
-                    {
-                        char_delete (&char_dat[i]);
-                        if (i < char_num - 1)
-                        {
-                            memcpy (&char_dat[i], &char_dat[char_num - 1],
-                                    sizeof (struct mmo_charstatus));
-                            // if moved character owns to deleted account, check again it's character
-                            if (char_dat[i].account_id == RFIFOL (fd, 2))
-                            {
-                                i--;
-                                // Correct moved character reference in the character's owner by [Yor]
-                            }
-                            else
-                            {
-                                int  j, k;
-                                struct char_session_data *sd2;
-                                for (j = 0; j < fd_max; j++)
-                                {
-                                    if (session[j]
-                                        && (sd2 = (struct char_session_data*)session[j]->session_data)
-                                        && sd2->account_id ==
-                                        char_dat[char_num - 1].account_id)
-                                    {
-                                        for (k = 0; k < 9; k++)
-                                        {
-                                            if (sd2->found_char[k] ==
-                                                char_num - 1)
-                                            {
-                                                sd2->found_char[k] = i;
-                                                break;
-                                            }
-                                        }
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                        char_num--;
-                    }
-                }
-                // Deletion of the storage
-                inter_storage_delete (RFIFOL (fd, 2));
-                // send to all map-servers to disconnect the player
-                {
-                    unsigned char buf[6];
-                    WBUFW (buf, 0) = 0x2b13;
-                    WBUFL (buf, 2) = RFIFOL (fd, 2);
-                    mapif_sendall (buf, 6);
-                }
-                // disconnect player if online on char-server
-                disconnect_player (RFIFOL (fd, 2));
-                RFIFOSKIP (fd, 6);
-                break;
-
-                // State change of account/ban notification (from login-server) by [Yor]
-            case 0x2731:
-                if (RFIFOREST (fd) < 11)
-                    return;
-                // send to all map-servers to disconnect the player
-                {
-                    unsigned char buf[11];
-                    WBUFW (buf, 0) = 0x2b14;
-                    WBUFL (buf, 2) = RFIFOL (fd, 2);
-                    WBUFB (buf, 6) = RFIFOB (fd, 6);    // 0: change of statut, 1: ban
-                    WBUFL (buf, 7) = RFIFOL (fd, 7);    // status or final date of a banishment
-                    mapif_sendall (buf, 11);
-                }
-                // disconnect player if online on char-server
-                disconnect_player (RFIFOL (fd, 2));
-                RFIFOSKIP (fd, 11);
-                break;
-
-                // Receiving GM acounts info from login-server (by [Yor])
-            case 0x2732:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    char buf[32000];
-                    if (gm_account != NULL)
-                        free (gm_account);
-                    CREATE (gm_account, struct gm_account, (RFIFOW (fd, 2) - 4) / 5);
-                    GM_num = 0;
-                    for (i = 4; i < RFIFOW (fd, 2); i = i + 5)
-                    {
-                        gm_account[GM_num].account_id = RFIFOL (fd, i);
-                        gm_account[GM_num].level = (int) RFIFOB (fd, i + 4);
-                        //printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
-                        GM_num++;
-                    }
-                    printf
-                        ("From login-server: receiving of %d GM accounts information.\n",
-                         GM_num);
-                    char_log
-                        ("From login-server: receiving of %d GM accounts information.\n",
-                         GM_num);
-                    create_online_files (); // update online players files (perhaps some online players change of GM level)
-                    // send new gm acccounts level to map-servers
-                    memcpy (buf, RFIFOP (fd, 0), RFIFOW (fd, 2));
-                    WBUFW (buf, 0) = 0x2b15;
-                    mapif_sendall (buf, RFIFOW (fd, 2));
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-            case 0x2741:       // change password reply
-                if (RFIFOREST (fd) < 7)
-                    return;
-                {
-                    int  acc, status, i;
-                    acc = RFIFOL (fd, 2);
-                    status = RFIFOB (fd, 6);
-
-                    for (i = 0; i < fd_max; i++)
-                    {
-                        if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
-                        {
-                            if (sd->account_id == acc)
-                            {
-                                WFIFOW (i, 0) = 0x62;
-                                WFIFOB (i, 2) = status;
-                                WFIFOSET (i, 3);
-                                break;
-                            }
-                        }
-                    }
-                }
-                RFIFOSKIP (fd, 7);
-                break;
-
-            default:
-                session[fd]->eof = 1;
-                return;
-        }
-    }
-    RFIFOFLUSH (fd);
-}
-
-//--------------------------------
-// Map-server anti-freeze system
-//--------------------------------
-void map_anti_freeze_system (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  i;
-
-    //printf("Entering in map_anti_freeze_system function to check freeze of servers.\n");
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-    {
-        if (server_fd[i] >= 0)
-        {                       // if map-server is online
-            //printf("map_anti_freeze_system: server #%d, flag: %d.\n", i, server_freezeflag[i]);
-            if (server_freezeflag[i]-- < 1)
-            {                   // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
-                printf
-                    ("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n",
-                     i);
-                char_log
-                    ("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n",
-                     i);
-                session[server_fd[i]]->eof = 1;
-            }
-        }
-    }
-}
-
-void parse_frommap (int fd)
-{
-    int  i, j;
-    int  id;
-
-    for (id = 0; id < MAX_MAP_SERVERS; id++)
-        if (server_fd[id] == fd)
-            break;
-    if (id == MAX_MAP_SERVERS || session[fd]->eof)
-    {
-        if (id < MAX_MAP_SERVERS)
-        {
-            printf ("Map-server %d (session #%d) has disconnected.\n", id,
-                    fd);
-            memset (&server[id], 0, sizeof (struct mmo_map_server));
-            server_fd[id] = -1;
-            for (j = 0; j < char_num; j++)
-                if (online_chars[j] == fd)
-                    online_chars[j] = -1;
-            create_online_files (); // update online players files (to remove all online players of this server)
-        }
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    while (RFIFOREST (fd) >= 2)
-    {
-//      printf("parse_frommap: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
-
-        switch (RFIFOW (fd, 0))
-        {
-                // request from map-server to reload GM accounts. Transmission to login-server (by Yor)
-            case 0x2af7:
-                if (login_fd > 0)
-                {               // don't send request if no login-server
-                    WFIFOW (login_fd, 0) = 0x2709;
-                    WFIFOSET (login_fd, 2);
-//              printf("char : request from map-server to reload GM accounts -> login-server.\n");
-                }
-                RFIFOSKIP (fd, 2);
-                break;
-
-                // Receiving map names list from the map-server
-            case 0x2afa:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                memset (server[id].map, 0, sizeof (server[id].map));
-                j = 0;
-                for (i = 4; i < RFIFOW (fd, 2); i += 16)
-                {
-                    memcpy (server[id].map[j], RFIFOP (fd, i), 16);
-//              printf("set map %d.%d : %s\n", id, j, server[id].map[j]);
-                    j++;
-                }
-                {
-                    unsigned char *p = (unsigned char *) &server[id].ip;
-                    printf
-                        ("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
-                         id, j, p[0], p[1], p[2], p[3], server[id].port);
-                    printf ("Map-server %d loading complete.\n", id);
-                    char_log
-                        ("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d. Map-server %d loading complete.\n",
-                         id, j, p[0], p[1], p[2], p[3],
-                         server[id].port, id);
-                }
-                WFIFOW (fd, 0) = 0x2afb;
-                WFIFOB (fd, 2) = 0;
-                memcpy (WFIFOP (fd, 3), wisp_server_name, 24);  // name for wisp to player
-                WFIFOSET (fd, 27);
-                {
-                    unsigned char buf[16384];
-                    int  x;
-                    if (j == 0)
-                    {
-                        printf ("WARNING: Map-Server %d have NO map.\n", id);
-                        char_log ("WARNING: Map-Server %d have NO map.\n",
-                                  id);
-                        // Transmitting maps information to the other map-servers
-                    }
-                    else
-                    {
-                        WBUFW (buf, 0) = 0x2b04;
-                        WBUFW (buf, 2) = j * 16 + 10;
-                        WBUFL (buf, 4) = server[id].ip;
-                        WBUFW (buf, 8) = server[id].port;
-                        memcpy (WBUFP (buf, 10), RFIFOP (fd, 4), j * 16);
-                        mapif_sendallwos (fd, buf, WBUFW (buf, 2));
-                    }
-                    // Transmitting the maps of the other map-servers to the new map-server
-                    for (x = 0; x < MAX_MAP_SERVERS; x++)
-                    {
-                        if (server_fd[x] >= 0 && x != id)
-                        {
-                            WFIFOW (fd, 0) = 0x2b04;
-                            WFIFOL (fd, 4) = server[x].ip;
-                            WFIFOW (fd, 8) = server[x].port;
-                            j = 0;
-                            for (i = 0; i < MAX_MAP_PER_SERVER; i++)
-                                if (server[x].map[i][0])
-                                    memcpy (WFIFOP (fd, 10 + (j++) * 16),
-                                            server[x].map[i], 16);
-                            if (j > 0)
-                            {
-                                WFIFOW (fd, 2) = j * 16 + 10;
-                                WFIFOSET (fd, WFIFOW (fd, 2));
-                            }
-                        }
-                    }
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-                // 認証要求
-            case 0x2afc:
-                if (RFIFOREST (fd) < 22)
-                    return;
-                //printf("auth_fifo search: account: %d, char: %d, secure: %08x-%08x\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14));
-                for (i = 0; i < AUTH_FIFO_SIZE; i++)
-                {
-                    if (auth_fifo[i].account_id == RFIFOL (fd, 2) &&
-                        auth_fifo[i].char_id == RFIFOL (fd, 6) &&
-                        auth_fifo[i].login_id1 == RFIFOL (fd, 10) &&
-#if CMP_AUTHFIFO_LOGIN2 != 0
-                        // here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value)
-                        (auth_fifo[i].login_id2 == RFIFOL (fd, 14) || RFIFOL (fd, 14) == 0) &&  // relate to the versions higher than 18
-#endif
-                        (!check_ip_flag || auth_fifo[i].ip == RFIFOL (fd, 18))
-                        && !auth_fifo[i].delflag)
-                    {
-                        auth_fifo[i].delflag = 1;
-                        WFIFOW (fd, 0) = 0x2afd;
-                        WFIFOW (fd, 2) = 18 + sizeof (struct mmo_charstatus);
-                        WFIFOL (fd, 4) = RFIFOL (fd, 2);
-                        WFIFOL (fd, 8) = auth_fifo[i].login_id2;
-                        WFIFOL (fd, 12) =
-                            (unsigned long) auth_fifo[i].connect_until_time;
-                        char_dat[auth_fifo[i].char_pos].sex =
-                            auth_fifo[i].sex;
-                        WFIFOW (fd, 16) = auth_fifo[i].packet_tmw_version;
-                        fprintf (stderr,
-                                 "From queue index %d: recalling packet version %d\n",
-                                 i, auth_fifo[i].packet_tmw_version);
-                        memcpy (WFIFOP (fd, 18),
-                                &char_dat[auth_fifo[i].char_pos],
-                                sizeof (struct mmo_charstatus));
-                        WFIFOSET (fd, WFIFOW (fd, 2));
-                        //printf("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6));
-                        break;
-                    }
-                }
-                if (i == AUTH_FIFO_SIZE)
-                {
-                    WFIFOW (fd, 0) = 0x2afe;
-                    WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                    WFIFOSET (fd, 6);
-                    printf
-                        ("auth_fifo search error! account %d not authentified.\n",
-                         RFIFOL (fd, 2));
-                }
-                RFIFOSKIP (fd, 22);
-                break;
-
-                // MAPサーバー上のユーザー数受信
-            case 0x2aff:
-                if (RFIFOREST (fd) < 6 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                server[id].users = RFIFOW (fd, 4);
-                if (anti_freeze_enable)
-                    server_freezeflag[id] = 5;  // Map anti-freeze system. Counter. 5 ok, 4...0 freezed
-                // remove all previously online players of the server
-                for (i = 0; i < char_num; i++)
-                    if (online_chars[i] == id)
-                        online_chars[i] = -1;
-                // add online players in the list by [Yor]
-                for (i = 0; i < server[id].users; i++)
-                {
-                    int  char_id = RFIFOL (fd, 6 + i * 4);
-                    for (j = 0; j < char_num; j++)
-                        if (char_dat[j].char_id == char_id)
-                        {
-                            online_chars[j] = id;
-                            //printf("%d\n", char_id);
-                            break;
-                        }
-                }
-                if (update_online < time (NULL))
-                {               // Time is done
-                    update_online = time (NULL) + 8;
-                    create_online_files (); // only every 8 sec. (normally, 1 server send users every 5 sec.) Don't update every time, because that takes time, but only every 2 connection.
-                    // it set to 8 sec because is more than 5 (sec) and if we have more than 1 map-server, informations can be received in shifted.
-                }
-                RFIFOSKIP (fd, 6 + i * 4);
-                break;
-
-                // キャラデータ保存
-            case 0x2b01:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                for (i = 0; i < char_num; i++)
-                {
-                    if (char_dat[i].account_id == RFIFOL (fd, 4) &&
-                        char_dat[i].char_id == RFIFOL (fd, 8))
-                        break;
-                }
-                if (i != char_num)
-                    memcpy (&char_dat[i], RFIFOP (fd, 12),
-                            sizeof (struct mmo_charstatus));
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-                // キャラセレ要求
-            case 0x2b02:
-                if (RFIFOREST (fd) < 18)
-                    return;
-                if (auth_fifo_pos >= AUTH_FIFO_SIZE)
-                    auth_fifo_pos = 0;
-                //printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", auth_fifo_pos, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
-                auth_fifo[auth_fifo_pos].account_id = RFIFOL (fd, 2);
-                auth_fifo[auth_fifo_pos].char_id = 0;
-                auth_fifo[auth_fifo_pos].login_id1 = RFIFOL (fd, 6);
-                auth_fifo[auth_fifo_pos].login_id2 = RFIFOL (fd, 10);
-                auth_fifo[auth_fifo_pos].delflag = 2;
-                auth_fifo[auth_fifo_pos].char_pos = 0;
-                auth_fifo[auth_fifo_pos].connect_until_time = 0;    // unlimited/unknown time by default (not display in map-server)
-                auth_fifo[auth_fifo_pos].ip = RFIFOL (fd, 14);
-                auth_fifo_pos++;
-                WFIFOW (fd, 0) = 0x2b03;
-                WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                WFIFOB (fd, 6) = 0;
-                WFIFOSET (fd, 7);
-                RFIFOSKIP (fd, 18);
-                break;
-
-                // マップサーバー間移動要求
-            case 0x2b05:
-                if (RFIFOREST (fd) < 49)
-                    return;
-                if (auth_fifo_pos >= AUTH_FIFO_SIZE)
-                    auth_fifo_pos = 0;
-                WFIFOW (fd, 0) = 0x2b06;
-                memcpy (WFIFOP (fd, 2), RFIFOP (fd, 2), 42);
-                //printf("auth_fifo set (auth#%d) - account: %d, secure: 0x%08x-0x%08x\n", auth_fifo_pos, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
-                auth_fifo[auth_fifo_pos].account_id = RFIFOL (fd, 2);
-                auth_fifo[auth_fifo_pos].char_id = RFIFOL (fd, 14);
-                auth_fifo[auth_fifo_pos].login_id1 = RFIFOL (fd, 6);
-                auth_fifo[auth_fifo_pos].login_id2 = RFIFOL (fd, 10);
-                auth_fifo[auth_fifo_pos].delflag = 0;
-                auth_fifo[auth_fifo_pos].sex = RFIFOB (fd, 44);
-                auth_fifo[auth_fifo_pos].connect_until_time = 0;    // unlimited/unknown time by default (not display in map-server)
-                auth_fifo[auth_fifo_pos].ip = RFIFOL (fd, 45);
-                for (i = 0; i < char_num; i++)
-                    if (char_dat[i].account_id == RFIFOL (fd, 2) &&
-                        char_dat[i].char_id == RFIFOL (fd, 14))
-                    {
-                        auth_fifo[auth_fifo_pos].char_pos = i;
-                        auth_fifo_pos++;
-                        WFIFOL (fd, 6) = 0;
-                        break;
-                    }
-                if (i == char_num)
-                    WFIFOW (fd, 6) = 1;
-                WFIFOSET (fd, 44);
-                RFIFOSKIP (fd, 49);
-                break;
-
-                // キャラ名検索
-            case 0x2b08:
-                if (RFIFOREST (fd) < 6)
-                    return;
-                for (i = 0; i < char_num; i++)
-                {
-                    if (char_dat[i].char_id == RFIFOL (fd, 2))
-                        break;
-                }
-                WFIFOW (fd, 0) = 0x2b09;
-                WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                if (i != char_num)
-                    memcpy (WFIFOP (fd, 6), char_dat[i].name, 24);
-                else
-                    memcpy (WFIFOP (fd, 6), unknown_char_name, 24);
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 6);
-                break;
-
-                // it is a request to become GM
-            case 0x2b0a:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-//          printf("parse_frommap: change gm -> login, account: %d, pass: '%s'.\n", RFIFOL(fd,4), RFIFOP(fd,8));
-                if (login_fd > 0)
-                {               // don't send request if no login-server
-                    WFIFOW (login_fd, 0) = 0x2720;
-                    memcpy (WFIFOP (login_fd, 2), RFIFOP (fd, 2),
-                            RFIFOW (fd, 2) - 2);
-                    WFIFOSET (login_fd, RFIFOW (fd, 2));
-                }
-                else
-                {
-                    WFIFOW (fd, 0) = 0x2b0b;
-                    WFIFOL (fd, 2) = RFIFOL (fd, 4);
-                    WFIFOL (fd, 6) = 0;
-                    WFIFOSET (fd, 10);
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-                // Map server send information to change an email of an account -> login-server
-            case 0x2b0c:
-                if (RFIFOREST (fd) < 86)
-                    return;
-                if (login_fd > 0)
-                {               // don't send request if no login-server
-                    memcpy (WFIFOP (login_fd, 0), RFIFOP (fd, 0), 86);  // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
-                    WFIFOW (login_fd, 0) = 0x2722;
-                    WFIFOSET (login_fd, 86);
-                }
-                RFIFOSKIP (fd, 86);
-                break;
-
-                // Map server ask char-server about a character name to do some operations (all operations are transmitted to login-server)
-            case 0x2b0e:
-                if (RFIFOREST (fd) < 44)
-                    return;
-                {
-                    char character_name[24];
-                    int  acc = RFIFOL (fd, 2);  // account_id of who ask (-1 if nobody)
-                    memcpy (character_name, RFIFOP (fd, 6), 24);
-                    character_name[sizeof (character_name) - 1] = '\0';
-                    // prepare answer
-                    WFIFOW (fd, 0) = 0x2b0f;    // answer
-                    WFIFOL (fd, 2) = acc;   // who want do operation
-                    WFIFOW (fd, 30) = RFIFOW (fd, 30);  // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex
-                    // search character
-                    i = search_character_index (character_name);
-                    if (i >= 0)
-                    {
-                        memcpy (WFIFOP (fd, 6), search_character_name (i), 24); // put correct name if found
-                        WFIFOW (fd, 32) = 0;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                        switch (RFIFOW (fd, 30))
-                        {
-                            case 1:    // block
-                                if (acc == -1
-                                    || isGM (acc) >=
-                                    isGM (char_dat[i].account_id))
-                                {
-                                    if (login_fd > 0)
-                                    {   // don't send request if no login-server
-                                        WFIFOW (login_fd, 0) = 0x2724;
-                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
-                                        WFIFOL (login_fd, 6) = 5;   // status of the account
-                                        WFIFOSET (login_fd, 10);
-//                          printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 5);
-                                    }
-                                    else
-                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                }
-                                else
-                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                break;
-                            case 2:    // ban
-                                if (acc == -1
-                                    || isGM (acc) >=
-                                    isGM (char_dat[i].account_id))
-                                {
-                                    if (login_fd > 0)
-                                    {   // don't send request if no login-server
-                                        WFIFOW (login_fd, 0) = 0x2725;
-                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
-                                        WFIFOW (login_fd, 6) = RFIFOW (fd, 32); // year
-                                        WFIFOW (login_fd, 8) = RFIFOW (fd, 34); // month
-                                        WFIFOW (login_fd, 10) = RFIFOW (fd, 36);    // day
-                                        WFIFOW (login_fd, 12) = RFIFOW (fd, 38);    // hour
-                                        WFIFOW (login_fd, 14) = RFIFOW (fd, 40);    // minute
-                                        WFIFOW (login_fd, 16) = RFIFOW (fd, 42);    // second
-                                        WFIFOSET (login_fd, 18);
-//                          printf("char : status -> login: account %d, ban: %dy %dm %dd %dh %dmn %ds\n",
-//                                 char_dat[i].account_id, (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), (short)RFIFOW(fd,38), (short)RFIFOW(fd,40), (short)RFIFOW(fd,42));
-                                    }
-                                    else
-                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                }
-                                else
-                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                break;
-                            case 3:    // unblock
-                                if (acc == -1
-                                    || isGM (acc) >=
-                                    isGM (char_dat[i].account_id))
-                                {
-                                    if (login_fd > 0)
-                                    {   // don't send request if no login-server
-                                        WFIFOW (login_fd, 0) = 0x2724;
-                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
-                                        WFIFOL (login_fd, 6) = 0;   // status of the account
-                                        WFIFOSET (login_fd, 10);
-//                          printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 0);
-                                    }
-                                    else
-                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                }
-                                else
-                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                break;
-                            case 4:    // unban
-                                if (acc == -1
-                                    || isGM (acc) >=
-                                    isGM (char_dat[i].account_id))
-                                {
-                                    if (login_fd > 0)
-                                    {   // don't send request if no login-server
-                                        WFIFOW (login_fd, 0) = 0x272a;
-                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
-                                        WFIFOSET (login_fd, 6);
-//                          printf("char : status -> login: account %d, unban request\n", char_dat[i].account_id);
-                                    }
-                                    else
-                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                }
-                                else
-                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                break;
-                            case 5:    // changesex
-                                if (acc == -1
-                                    || isGM (acc) >=
-                                    isGM (char_dat[i].account_id))
-                                {
-                                    if (login_fd > 0)
-                                    {   // don't send request if no login-server
-                                        WFIFOW (login_fd, 0) = 0x2727;
-                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
-                                        WFIFOSET (login_fd, 6);
-//                          printf("char : status -> login: account %d, change sex request\n", char_dat[i].account_id);
-                                    }
-                                    else
-                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                }
-                                else
-                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                                break;
-                        }
-                    }
-                    else
-                    {
-                        // character name not found
-                        memcpy (WFIFOP (fd, 6), character_name, 24);
-                        WFIFOW (fd, 32) = 1;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
-                    }
-                    // send answer if a player ask, not if the server ask
-                    if (acc != -1)
-                    {
-                        WFIFOSET (fd, 34);
-                    }
-                    RFIFOSKIP (fd, 44);
-                    break;
-                }
-
-//      case 0x2b0f: not more used (available for futur usage)
-
-                // account_reg保存要求
-            case 0x2b10:
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    struct global_reg reg[ACCOUNT_REG2_NUM];
-                    int  p, acc;
-                    acc = RFIFOL (fd, 4);
-                    for (p = 8, j = 0;
-                         p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
-                         p += 36, j++)
-                    {
-                        memcpy (reg[j].str, RFIFOP (fd, p), 32);
-                        reg[j].value = RFIFOL (fd, p + 32);
-                    }
-                    set_account_reg2 (acc, j, reg);
-                    // loginサーバーへ送る
-                    if (login_fd > 0)
-                    {           // don't send request if no login-server
-                        memcpy (WFIFOP (login_fd, 0), RFIFOP (fd, 0),
-                                RFIFOW (fd, 2));
-                        WFIFOW (login_fd, 0) = 0x2728;
-                        WFIFOSET (login_fd, WFIFOW (login_fd, 2));
-                    }
-                    // ワールドへの同垢ログインがなければmapサーバーに送る必要はない
-                    //memcpy(buf, RFIFOP(fd,0), RFIFOW(fd,2));
-                    //WBUFW(buf,0) = 0x2b11;
-                    //mapif_sendall(buf, WBUFW(buf,2));
-                    RFIFOSKIP (fd, RFIFOW (fd, 2));
-//          printf("char: save_account_reg (from map)\n");
-                    break;
-                }
-
-                // Map server is requesting a divorce
-            case 0x2b16:
-                if (RFIFOREST (fd) < 4)
-                    return;
-                {
-                    for (i = 0; i < char_num; i++)
-                        if (char_dat[i].char_id == RFIFOL (fd, 2))
-                            break;
-
-                    if (i != char_num)
-                        char_divorce (&char_dat[i]);
-
-                    RFIFOSKIP (fd, 6);
-                    break;
-
-                }
-
-            default:
-                // inter server処理に渡す
-            {
-                int  r = inter_parse_frommap (fd);
-                if (r == 1)     // 処理できた
-                    break;
-                if (r == 2)     // パケット長が足りない
-                    return;
-            }
-                // inter server処理でもない場合は切断
-                printf
-                    ("char: unknown packet 0x%04x (%d bytes to read in buffer)! (from map).\n",
-                     RFIFOW (fd, 0), RFIFOREST (fd));
-                session[fd]->eof = 1;
-                return;
-        }
-    }
-}
-
-int search_mapserver (char *map)
-{
-    int  i, j;
-    char temp_map[16];
-    int  temp_map_len;
-
-//  printf("Searching the map-server for map '%s'... ", map);
-    strncpy (temp_map, map, sizeof (temp_map));
-    temp_map[sizeof (temp_map) - 1] = '\0';
-    if (strchr (temp_map, '.') != NULL)
-        temp_map[strchr (temp_map, '.') - temp_map + 1] = '\0'; // suppress the '.gat', but conserve the '.' to be sure of the name of the map
-
-    temp_map_len = strlen (temp_map);
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-        if (server_fd[i] >= 0)
-            for (j = 0; server[i].map[j][0]; j++)
-                //printf("%s : %s = %d\n", server[i].map[j], map, strncmp(server[i].map[j], temp_map, temp_map_len));
-                if (strncmp (server[i].map[j], temp_map, temp_map_len) == 0)
-                {
-//                  printf("found -> server #%d.\n", i);
-                    return i;
-                }
-
-//  printf("not found.\n");
-    return -1;
-}
-
-// char_mapifの初期化処理(現在はinter_mapif初期化のみ)
-static int char_mapif_init (int fd)
-{
-    return inter_mapif_init (fd);
-}
-
-//-----------------------------------------------------
-// Test to know if an IP come from LAN or WAN. by [Yor]
-//-----------------------------------------------------
-int lan_ip_check (unsigned char *p)
-{
-    int  i;
-    int  lancheck = 1;
-
-//  printf("lan_ip_check: to compare: %d.%d.%d.%d, network: %d.%d.%d.%d/%d.%d.%d.%d\n",
-//         p[0], p[1], p[2], p[3],
-//         subneti[0], subneti[1], subneti[2], subneti[3],
-//         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
-    for (i = 0; i < 4; i++)
-    {
-        if ((subneti[i] & subnetmaski[i]) != (p[i] & subnetmaski[i]))
-        {
-            lancheck = 0;
-            break;
-        }
-    }
-    printf ("LAN test (result): %s source\033[0m.\n",
-            (lancheck) ? "\033[1;36mLAN" : "\033[1;32mWAN");
-    return lancheck;
-}
-
-void parse_char (int fd)
-{
-    int  i, ch;
-    char email[40];
-    struct char_session_data *sd;
-    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
-
-    if (login_fd < 0 || session[fd]->eof)
-    {                           // disconnect any player (already connected to char-server or coming back from map-server) if login-server is diconnected.
-        if (fd == login_fd)
-            login_fd = -1;
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    sd = (struct char_session_data*)session[fd]->session_data;
-
-    while (RFIFOREST (fd) >= 2)
-    {
-//      if (RFIFOW(fd,0) < 30000)
-//          printf("parse_char: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
-
-        switch (RFIFOW (fd, 0))
-        {
-            case 0x20b:        //20040622暗号化ragexe対応
-                if (RFIFOREST (fd) < 19)
-                    return;
-                RFIFOSKIP (fd, 19);
-                break;
-
-            case 0x61:         // change password request
-                if (RFIFOREST (fd) < 50)
-                    return;
-                {
-                    WFIFOW (login_fd, 0) = 0x2740;
-                    WFIFOL (login_fd, 2) = sd->account_id;
-                    memcpy (WFIFOP (login_fd, 6), RFIFOP (fd, 2), 24);
-                    memcpy (WFIFOP (login_fd, 30), RFIFOP (fd, 26), 24);
-                    WFIFOSET (login_fd, 54);
-                }
-                RFIFOSKIP (fd, 50);
-                break;
-
-            case 0x65:         // 接続要求
-                if (RFIFOREST (fd) < 17)
-                    return;
-                {
-                    int  GM_value;
-                    if ((GM_value = isGM (RFIFOL (fd, 2))))
-                        printf
-                            ("Account Logged On; Account ID: %d (GM level %d).\n",
-                             RFIFOL (fd, 2), GM_value);
-                    else
-                        printf ("Account Logged On; Account ID: %d.\n",
-                                RFIFOL (fd, 2));
-                    if (sd == NULL)
-                    {
-                        CREATE (sd, struct char_session_data, 1);
-                        session[fd]->session_data = sd;
-                        memcpy (sd->email, "no mail", 40);  // put here a mail without '@' to refuse deletion if we don't receive the e-mail
-                        sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server)
-                    }
-                    sd->account_id = RFIFOL (fd, 2);
-                    sd->login_id1 = RFIFOL (fd, 6);
-                    sd->login_id2 = RFIFOL (fd, 10);
-                    sd->packet_tmw_version = RFIFOW (fd, 14);
-                    sd->sex = RFIFOB (fd, 16);
-                    // send back account_id
-                    WFIFOL (fd, 0) = RFIFOL (fd, 2);
-                    WFIFOSET (fd, 4);
-                    // search authentification
-                    for (i = 0; i < AUTH_FIFO_SIZE; i++)
-                    {
-                        if (auth_fifo[i].account_id == sd->account_id &&
-                            auth_fifo[i].login_id1 == sd->login_id1 &&
-#if CMP_AUTHFIFO_LOGIN2 != 0
-                            auth_fifo[i].login_id2 == sd->login_id2 &&  // relate to the versions higher than 18
-#endif
-                            (!check_ip_flag
-                             || auth_fifo[i].ip ==
-                             session[fd]->client_addr.sin_addr.s_addr)
-                            && auth_fifo[i].delflag == 2)
-                        {
-                            auth_fifo[i].delflag = 1;
-                            if (max_connect_user == 0
-                                || count_users () < max_connect_user)
-                            {
-                                if (login_fd > 0)
-                                {   // don't send request if no login-server
-                                    // request to login-server to obtain e-mail/time limit
-                                    WFIFOW (login_fd, 0) = 0x2716;
-                                    WFIFOL (login_fd, 2) = sd->account_id;
-                                    WFIFOSET (login_fd, 6);
-                                }
-                                // Record client version
-                                auth_fifo[i].packet_tmw_version =
-                                    sd->packet_tmw_version;
-                                // send characters to player
-                                mmo_char_send006b (fd, sd);
-                            }
-                            else
-                            {
-                                // refuse connection (over populated)
-                                WFIFOW (fd, 0) = 0x6c;
-                                WFIFOW (fd, 2) = 0;
-                                WFIFOSET (fd, 3);
-                            }
-                            break;
-                        }
-                    }
-                    // authentification not found
-                    if (i == AUTH_FIFO_SIZE)
-                    {
-                        if (login_fd > 0)
-                        {       // don't send request if no login-server
-                            WFIFOW (login_fd, 0) = 0x2712;  // ask login-server to authentify an account
-                            WFIFOL (login_fd, 2) = sd->account_id;
-                            WFIFOL (login_fd, 6) = sd->login_id1;
-                            WFIFOL (login_fd, 10) = sd->login_id2;  // relate to the versions higher than 18
-                            WFIFOB (login_fd, 14) = sd->sex;
-                            WFIFOL (login_fd, 15) =
-                                session[fd]->client_addr.sin_addr.s_addr;
-                            WFIFOSET (login_fd, 19);
-                        }
-                        else
-                        {       // if no login-server, we must refuse connection
-                            WFIFOW (fd, 0) = 0x6c;
-                            WFIFOW (fd, 2) = 0;
-                            WFIFOSET (fd, 3);
-                        }
-                    }
-                }
-                RFIFOSKIP (fd, 17);
-                break;
-
-            case 0x66:         // キャラ選択
-                if (!sd || RFIFOREST (fd) < 3)
-                    return;
-
-                char ip[16];
-                unsigned char *sin_addr =
-                    (unsigned char *) &session[fd]->client_addr.sin_addr;
-                sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1],
-                         sin_addr[2], sin_addr[3]);
-
-                // if we activated email creation and email is default email
-                if (email_creation != 0 && strcmp (sd->email, "a@a.com") == 0
-                    && login_fd > 0)
-                {               // to modify an e-mail, login-server must be online
-                    WFIFOW (fd, 0) = 0x70;
-                    WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
-                    WFIFOSET (fd, 3);
-
-                    // otherwise, load the character
-                }
-                else
-                {
-                    for (ch = 0; ch < 9; ch++)
-                        if (sd->found_char[ch] >= 0
-                            && char_dat[sd->found_char[ch]].char_num ==
-                            RFIFOB (fd, 2))
-                            break;
-                    if (ch != 9)
-                    {
-                        char_log
-                            ("Character Selected, Account ID: %d, Character Slot: %d, Character Name: %s [%s]\n",
-                             sd->account_id, RFIFOB (fd, 2),
-                             char_dat[sd->found_char[ch]].name, ip);
-                        // searching map server
-                        i = search_mapserver (char_dat
-                                              [sd->found_char[ch]].last_point.
-                                              map);
-                        // if map is not found, we check major cities
-                        if (i < 0)
-                        {
-                            if ((i = search_mapserver ("prontera.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "prontera.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 273;    // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    354;
-                            }
-                            else if ((i =
-                                      search_mapserver ("geffen.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "geffen.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 120;    // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    100;
-                            }
-                            else if ((i =
-                                      search_mapserver ("morocc.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "morocc.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 160;    // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    94;
-                            }
-                            else if ((i =
-                                      search_mapserver ("alberta.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "alberta.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 116;    // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    57;
-                            }
-                            else if ((i =
-                                      search_mapserver ("payon.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "payon.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 87; // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    117;
-                            }
-                            else if ((i =
-                                      search_mapserver ("izlude.gat")) >= 0)
-                            {   // check is done without 'gat'.
-                                memcpy (char_dat
-                                        [sd->found_char[ch]].last_point.map,
-                                        "izlude.gat", 16);
-                                char_dat[sd->found_char[ch]].last_point.x = 94; // savepoint coordonates
-                                char_dat[sd->found_char[ch]].last_point.y =
-                                    103;
-                            }
-                            else
-                            {
-                                int  j;
-                                // get first online server (with a map)
-                                i = 0;
-                                for (j = 0; j < MAX_MAP_SERVERS; j++)
-                                    if (server_fd[j] >= 0
-                                        && server[j].map[0][0])
-                                    {   // change save point to one of map found on the server (the first)
-                                        i = j;
-                                        memcpy (char_dat
-                                                [sd->
-                                                 found_char[ch]].last_point.
-                                                map, server[j].map[0], 16);
-                                        printf
-                                            ("Map-server #%d found with a map: '%s'.\n",
-                                             j, server[j].map[0]);
-                                        // coordonates are unknown
-                                        break;
-                                    }
-                                // if no map-server is connected, we send: server closed
-                                if (j == MAX_MAP_SERVERS)
-                                {
-                                    WFIFOW (fd, 0) = 0x81;
-                                    WFIFOL (fd, 2) = 1; // 01 = Server closed
-                                    WFIFOSET (fd, 3);
-                                    RFIFOSKIP (fd, 3);
-                                    break;
-                                }
-                            }
-                        }
-                        WFIFOW (fd, 0) = 0x71;
-                        WFIFOL (fd, 2) = char_dat[sd->found_char[ch]].char_id;
-                        memcpy (WFIFOP (fd, 6),
-                                char_dat[sd->found_char[ch]].last_point.map,
-                                16);
-                        printf
-                            ("Character selection '%s' (account: %d, slot: %d) [%s]\n",
-                             char_dat[sd->found_char[ch]].name,
-                             sd->account_id, ch, ip);
-                        printf ("--Send IP of map-server. ");
-                        if (lan_ip_check (p))
-                            WFIFOL (fd, 22) = inet_addr (lan_map_ip);
-                        else
-                            WFIFOL (fd, 22) = server[i].ip;
-                        WFIFOW (fd, 26) = server[i].port;
-                        WFIFOSET (fd, 28);
-                        if (auth_fifo_pos >= AUTH_FIFO_SIZE)
-                            auth_fifo_pos = 0;
-                        //printf("auth_fifo set #%d - account %d, char: %d, secure: %08x-%08x\n", auth_fifo_pos, sd->account_id, char_dat[sd->found_char[ch]].char_id, sd->login_id1, sd->login_id2);
-                        auth_fifo[auth_fifo_pos].account_id = sd->account_id;
-                        auth_fifo[auth_fifo_pos].char_id =
-                            char_dat[sd->found_char[ch]].char_id;
-                        auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1;
-                        auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2;
-                        auth_fifo[auth_fifo_pos].delflag = 0;
-                        auth_fifo[auth_fifo_pos].char_pos =
-                            sd->found_char[ch];
-                        auth_fifo[auth_fifo_pos].sex = sd->sex;
-                        auth_fifo[auth_fifo_pos].connect_until_time =
-                            sd->connect_until_time;
-                        auth_fifo[auth_fifo_pos].ip =
-                            session[fd]->client_addr.sin_addr.s_addr;
-                        auth_fifo[auth_fifo_pos].packet_tmw_version =
-                            sd->packet_tmw_version;
-                        auth_fifo_pos++;
-                    }
-                }
-                RFIFOSKIP (fd, 3);
-                break;
-
-            case 0x67:         // 作成
-                if (!sd || RFIFOREST (fd) < 37)
-                    return;
-                i = make_new_char (fd, RFIFOP (fd, 2));
-                if (i < 0)
-                {
-                    WFIFOW (fd, 0) = 0x6e;
-                    WFIFOB (fd, 2) = 0x00;
-                    WFIFOSET (fd, 3);
-                    RFIFOSKIP (fd, 37);
-                    break;
-                }
-
-                WFIFOW (fd, 0) = 0x6d;
-                memset (WFIFOP (fd, 2), 0, 106);
-
-                WFIFOL (fd, 2) = char_dat[i].char_id;
-                WFIFOL (fd, 2 + 4) = char_dat[i].base_exp;
-                WFIFOL (fd, 2 + 8) = char_dat[i].zeny;
-                WFIFOL (fd, 2 + 12) = char_dat[i].job_exp;
-                WFIFOL (fd, 2 + 16) = char_dat[i].job_level;
-
-                WFIFOL (fd, 2 + 28) = char_dat[i].karma;
-                WFIFOL (fd, 2 + 32) = char_dat[i].manner;
-
-                WFIFOW (fd, 2 + 40) = 0x30;
-                WFIFOW (fd, 2 + 42) =
-                    (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp;
-                WFIFOW (fd, 2 + 44) =
-                    (char_dat[i].max_hp >
-                     0x7fff) ? 0x7fff : char_dat[i].max_hp;
-                WFIFOW (fd, 2 + 46) =
-                    (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp;
-                WFIFOW (fd, 2 + 48) =
-                    (char_dat[i].max_sp >
-                     0x7fff) ? 0x7fff : char_dat[i].max_sp;
-                WFIFOW (fd, 2 + 50) = DEFAULT_WALK_SPEED;   // char_dat[i].speed;
-                WFIFOW (fd, 2 + 52) = char_dat[i].pc_class;
-                WFIFOW (fd, 2 + 54) = char_dat[i].hair;
-
-                WFIFOW (fd, 2 + 58) = char_dat[i].base_level;
-                WFIFOW (fd, 2 + 60) = char_dat[i].skill_point;
-
-                WFIFOW (fd, 2 + 64) = char_dat[i].shield;
-                WFIFOW (fd, 2 + 66) = char_dat[i].head_top;
-                WFIFOW (fd, 2 + 68) = char_dat[i].head_mid;
-                WFIFOW (fd, 2 + 70) = char_dat[i].hair_color;
-
-                memcpy (WFIFOP (fd, 2 + 74), char_dat[i].name, 24);
-
-                WFIFOB (fd, 2 + 98) =
-                    (char_dat[i].str > 255) ? 255 : char_dat[i].str;
-                WFIFOB (fd, 2 + 99) =
-                    (char_dat[i].agi > 255) ? 255 : char_dat[i].agi;
-                WFIFOB (fd, 2 + 100) =
-                    (char_dat[i].vit > 255) ? 255 : char_dat[i].vit;
-                WFIFOB (fd, 2 + 101) =
-                    (char_dat[i].int_ > 255) ? 255 : char_dat[i].int_;
-                WFIFOB (fd, 2 + 102) =
-                    (char_dat[i].dex > 255) ? 255 : char_dat[i].dex;
-                WFIFOB (fd, 2 + 103) =
-                    (char_dat[i].luk > 255) ? 255 : char_dat[i].luk;
-                WFIFOB (fd, 2 + 104) = char_dat[i].char_num;
-
-                WFIFOSET (fd, 108);
-                RFIFOSKIP (fd, 37);
-                for (ch = 0; ch < 9; ch++)
-                {
-                    if (sd->found_char[ch] == -1)
-                    {
-                        sd->found_char[ch] = i;
-                        break;
-                    }
-                }
-
-            case 0x68:         // delete char //Yor's Fix
-                if (!sd || RFIFOREST (fd) < 46)
-                    return;
-                memcpy (email, RFIFOP (fd, 6), 40);
-                if (e_mail_check (email) == 0)
-                    strncpy (email, "a@a.com", 40); // default e-mail
-
-                // if we activated email creation and email is default email
-                if (email_creation != 0 && strcmp (sd->email, "a@a.com") == 0
-                    && login_fd > 0)
-                {               // to modify an e-mail, login-server must be online
-                    // if sended email is incorrect e-mail
-                    if (strcmp (email, "a@a.com") == 0)
-                    {
-                        WFIFOW (fd, 0) = 0x70;
-                        WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
-                        WFIFOSET (fd, 3);
-                        RFIFOSKIP (fd, 46);
-                        // we act like we have selected a character
-                    }
-                    else
-                    {
-                        // we change the packet to set it like selection.
-                        for (i = 0; i < 9; i++)
-                            if (char_dat[sd->found_char[i]].char_id ==
-                                RFIFOL (fd, 2))
-                            {
-                                // we save new e-mail
-                                memcpy (sd->email, email, 40);
-                                // we send new e-mail to login-server ('online' login-server is checked before)
-                                WFIFOW (login_fd, 0) = 0x2715;
-                                WFIFOL (login_fd, 2) = sd->account_id;
-                                memcpy (WFIFOP (login_fd, 6), email, 40);
-                                WFIFOSET (login_fd, 46);
-                                // skip part of the packet! (46, but leave the size of select packet: 3)
-                                RFIFOSKIP (fd, 43);
-                                // change value to put new packet (char selection)
-                                RFIFOW (fd, 0) = 0x66;
-                                RFIFOB (fd, 2) =
-                                    char_dat[sd->found_char[i]].char_num;
-                                // not send packet, it's modify of actual packet
-                                break;
-                            }
-                        if (i == 9)
-                        {
-                            WFIFOW (fd, 0) = 0x70;
-                            WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
-                            WFIFOSET (fd, 3);
-                            RFIFOSKIP (fd, 46);
-                        }
-                    }
-
-                    // otherwise, we delete the character
-                }
-                else
-                {
-                    /*if (strcasecmp(email, sd->email) != 0) { // if it's an invalid email
-                     * WFIFOW(fd, 0) = 0x70;
-                     * WFIFOB(fd, 2) = 0; // 00 = Incorrect Email address
-                     * WFIFOSET(fd, 3);
-                     * // if mail is correct
-                     * } else { */
-                    for (i = 0; i < 9; i++)
-                    {
-                        struct mmo_charstatus *cs = NULL;
-                        if (sd->found_char[i] >= 0
-                            && (cs =
-                                &char_dat[sd->found_char[i]])->char_id ==
-                            RFIFOL (fd, 2))
-                        {
-                            char_delete (cs);   // deletion process
-
-                            if (sd->found_char[i] != char_num - 1)
-                            {
-                                memcpy (&char_dat[sd->found_char[i]],
-                                        &char_dat[char_num - 1],
-                                        sizeof (struct mmo_charstatus));
-                                // Correct moved character reference in the character's owner
-                                {
-                                    int  j, k;
-                                    struct char_session_data *sd2;
-                                    for (j = 0; j < fd_max; j++)
-                                    {
-                                        if (session[j]
-                                            && (sd2 = (struct char_session_data*)
-                                                session[j]->session_data)
-                                            && sd2->account_id ==
-                                            char_dat[char_num - 1].account_id)
-                                        {
-                                            for (k = 0; k < 9; k++)
-                                            {
-                                                if (sd2->found_char[k] ==
-                                                    char_num - 1)
-                                                {
-                                                    sd2->found_char[k] =
-                                                        sd->found_char[i];
-                                                    break;
-                                                }
-                                            }
-                                            break;
-                                        }
-                                    }
-                                }
-                            }
-
-                            char_num--;
-                            for (ch = i; ch < 9 - 1; ch++)
-                                sd->found_char[ch] = sd->found_char[ch + 1];
-                            sd->found_char[8] = -1;
-                            WFIFOW (fd, 0) = 0x6f;
-                            WFIFOSET (fd, 2);
-                            break;
-                        }
-                    }
-
-                    if (i == 9)
-                    {
-                        WFIFOW (fd, 0) = 0x70;
-                        WFIFOB (fd, 2) = 0;
-                        WFIFOSET (fd, 3);
-                    }
-                    //}
-                    RFIFOSKIP (fd, 46);
-                }
-                break;
-
-            case 0x2af8:       // マップサーバーログイン
-                if (RFIFOREST (fd) < 60)
-                    return;
-                WFIFOW (fd, 0) = 0x2af9;
-                for (i = 0; i < MAX_MAP_SERVERS; i++)
-                {
-                    if (server_fd[i] < 0)
-                        break;
-                }
-                if (i == MAX_MAP_SERVERS || strcmp (RFIFOP (fd, 2), userid)
-                    || strcmp (RFIFOP (fd, 26), passwd))
-                {
-                    WFIFOB (fd, 2) = 3;
-                    WFIFOSET (fd, 3);
-                    RFIFOSKIP (fd, 60);
-                }
-                else
-                {
-                    int  len;
-                    WFIFOB (fd, 2) = 0;
-                    session[fd]->func_parse = parse_frommap;
-                    server_fd[i] = fd;
-                    if (anti_freeze_enable)
-                        server_freezeflag[i] = 5;   // Map anti-freeze system. Counter. 5 ok, 4...0 freezed
-                    server[i].ip = RFIFOL (fd, 54);
-                    server[i].port = RFIFOW (fd, 58);
-                    server[i].users = 0;
-                    memset (server[i].map, 0, sizeof (server[i].map));
-                    WFIFOSET (fd, 3);
-                    RFIFOSKIP (fd, 60);
-                    realloc_fifo (fd, FIFOSIZE_SERVERLINK,
-                                  FIFOSIZE_SERVERLINK);
-                    char_mapif_init (fd);
-                    // send gm acccounts level to map-servers
-                    len = 4;
-                    WFIFOW (fd, 0) = 0x2b15;
-                    for (i = 0; i < GM_num; i++)
-                    {
-                        WFIFOL (fd, len) = gm_account[i].account_id;
-                        WFIFOB (fd, len + 4) =
-                            (unsigned char) gm_account[i].level;
-                        len += 5;
-                    }
-                    WFIFOW (fd, 2) = len;
-                    WFIFOSET (fd, len);
-                    return;
-                }
-                break;
-
-            case 0x187:        // Alive信号?
-                if (RFIFOREST (fd) < 6)
-                    return;
-                RFIFOSKIP (fd, 6);
-                break;
-
-            case 0x7530:       // Athena情報所得
-                WFIFOW (fd, 0) = 0x7531;
-                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
-                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
-                WFIFOB (fd, 4) = ATHENA_REVISION;
-                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
-                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
-                WFIFOB (fd, 7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR;
-                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
-                WFIFOSET (fd, 10);
-                RFIFOSKIP (fd, 2);
-                return;
-
-            case 0x7532:       // 接続の切断(defaultと処理は一緒だが明示的にするため)
-                session[fd]->eof = 1;
-                return;
-
-            default:
-                session[fd]->eof = 1;
-                return;
-        }
-    }
-}
-
-// 全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す)
-int mapif_sendall (char *buf, unsigned int len)
-{
-    int  i, c;
-
-    c = 0;
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-    {
-        int  fd;
-        if ((fd = server_fd[i]) >= 0)
-        {
-            memcpy (WFIFOP (fd, 0), buf, len);
-            WFIFOSET (fd, len);
-            c++;
-        }
-    }
-    return c;
-}
-
-// 自分以外の全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す)
-int mapif_sendallwos (int sfd, unsigned char *buf, unsigned int len)
-{
-    int  i, c;
-
-    c = 0;
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-    {
-        int  fd;
-        if ((fd = server_fd[i]) >= 0 && fd != sfd)
-        {
-            memcpy (WFIFOP (fd, 0), buf, len);
-            WFIFOSET (fd, len);
-            c++;
-        }
-    }
-    return c;
-}
-
-// MAPサーバーにデータ送信(map鯖生存確認有り)
-int mapif_send (int fd, unsigned char *buf, unsigned int len)
-{
-    int  i;
-
-    if (fd >= 0)
-    {
-        for (i = 0; i < MAX_MAP_SERVERS; i++)
-        {
-            if (fd == server_fd[i])
-            {
-                memcpy (WFIFOP (fd, 0), buf, len);
-                WFIFOSET (fd, len);
-                return 1;
-            }
-        }
-    }
-    return 0;
-}
-
-void send_users_tologin (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  users = count_users ();
-    char buf[16];
-
-    if (login_fd > 0 && session[login_fd])
-    {
-        // send number of user to login server
-        WFIFOW (login_fd, 0) = 0x2714;
-        WFIFOL (login_fd, 2) = users;
-        WFIFOSET (login_fd, 6);
-    }
-    // send number of players to all map-servers
-    WBUFW (buf, 0) = 0x2b00;
-    WBUFL (buf, 2) = users;
-    mapif_sendall (buf, 6);
-}
-
-void check_connect_login_server (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    if (login_fd <= 0 || session[login_fd] == NULL)
-    {
-        printf ("Attempt to connect to login-server...\n");
-        if ((login_fd = make_connection (login_ip, login_port)) < 0)
-            return;
-        session[login_fd]->func_parse = parse_tologin;
-        realloc_fifo (login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-        WFIFOW (login_fd, 0) = 0x2710;
-        memset (WFIFOP (login_fd, 2), 0, 24);
-        memcpy (WFIFOP (login_fd, 2), userid,
-                strlen (userid) < 24 ? strlen (userid) : 24);
-        memset (WFIFOP (login_fd, 26), 0, 24);
-        memcpy (WFIFOP (login_fd, 26), passwd,
-                strlen (passwd) < 24 ? strlen (passwd) : 24);
-        WFIFOL (login_fd, 50) = 0;
-        WFIFOL (login_fd, 54) = char_ip;
-        WFIFOL (login_fd, 58) = char_port;
-        memset (WFIFOP (login_fd, 60), 0, 20);
-        memcpy (WFIFOP (login_fd, 60), server_name,
-                strlen (server_name) < 20 ? strlen (server_name) : 20);
-        WFIFOW (login_fd, 80) = 0;
-        WFIFOW (login_fd, 82) = char_maintenance;
-        WFIFOW (login_fd, 84) = char_new;
-        WFIFOSET (login_fd, 86);
-    }
-}
-
-//----------------------------------------------------------
-// Return numerical value of a switch configuration by [Yor]
-// on/off, english, français, deutsch, español
-//----------------------------------------------------------
-int config_switch (const char *str)
-{
-    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
-        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
-        || strcasecmp (str, "si") == 0)
-        return 1;
-    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
-        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
-        return 0;
-
-    return atoi (str);
-}
-
-//-------------------------------------------
-// Reading Lan Support configuration by [Yor]
-//-------------------------------------------
-int lan_config_read (const char *lancfgName)
-{
-    int  j;
-    struct hostent *h = NULL;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    // set default configuration
-    strncpy (lan_map_ip, "127.0.0.1", sizeof (lan_map_ip));
-    subneti[0] = 127;
-    subneti[1] = 0;
-    subneti[2] = 0;
-    subneti[3] = 1;
-    for (j = 0; j < 4; j++)
-        subnetmaski[j] = 255;
-
-    fp = fopen_ (lancfgName, "r");
-
-    if (fp == NULL)
-    {
-        printf ("LAN support configuration file not found: %s\n", lancfgName);
-        return 1;
-    }
-
-    printf ("---start reading of Lan Support configuration...\n");
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        line[sizeof (line) - 1] = '\0';
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
-            continue;
-
-        remove_control_chars (w1);
-        remove_control_chars (w2);
-        if (strcasecmp (w1, "lan_map_ip") == 0)
-        {                       // Read map-server Lan IP Address
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                sprintf (lan_map_ip, "%d.%d.%d.%d",
-                         (unsigned char) h->h_addr[0],
-                         (unsigned char) h->h_addr[1],
-                         (unsigned char) h->h_addr[2],
-                         (unsigned char) h->h_addr[3]);
-            }
-            else
-            {
-                strncpy (lan_map_ip, w2, sizeof (lan_map_ip));
-                lan_map_ip[sizeof (lan_map_ip) - 1] = 0;
-            }
-            printf ("LAN IP of map-server: %s.\n", lan_map_ip);
-        }
-        else if (strcasecmp (w1, "subnet") == 0)
-        {                       // Read Subnetwork
-            for (j = 0; j < 4; j++)
-                subneti[j] = 0;
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                for (j = 0; j < 4; j++)
-                    subneti[j] = (unsigned char) h->h_addr[j];
-            }
-            else
-            {
-                sscanf (w2, "%d.%d.%d.%d", &subneti[0], &subneti[1],
-                        &subneti[2], &subneti[3]);
-            }
-            printf ("Sub-network of the map-server: %d.%d.%d.%d.\n",
-                    subneti[0], subneti[1], subneti[2], subneti[3]);
-        }
-        else if (strcasecmp (w1, "subnetmask") == 0)
-        {                       // Read Subnetwork Mask
-            for (j = 0; j < 4; j++)
-                subnetmaski[j] = 255;
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                for (j = 0; j < 4; j++)
-                    subnetmaski[j] = (unsigned char) h->h_addr[j];
-            }
-            else
-            {
-                sscanf (w2, "%d.%d.%d.%d", &subnetmaski[0], &subnetmaski[1],
-                        &subnetmaski[2], &subnetmaski[3]);
-            }
-            printf ("Sub-network mask of the map-server: %d.%d.%d.%d.\n",
-                    subnetmaski[0], subnetmaski[1], subnetmaski[2],
-                    subnetmaski[3]);
-        }
-    }
-    fclose_ (fp);
-
-    // sub-network check of the map-server
-    {
-        unsigned int a0, a1, a2, a3;
-        unsigned char p[4];
-        sscanf (lan_map_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
-        p[0] = a0;
-        p[1] = a1;
-        p[2] = a2;
-        p[3] = a3;
-        printf ("LAN test of LAN IP of the map-server: ");
-        if (lan_ip_check (p) == 0)
-        {
-            printf
-                ("\033[1;31m***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network.\033[0m\n");
-        }
-    }
-
-    printf ("---End reading of Lan Support configuration...\n");
-
-    return 0;
-}
-
-int char_config_read (const char *cfgName)
-{
-    struct hostent *h = NULL;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp = fopen_ (cfgName, "r");
-
-    if (fp == NULL)
-    {
-        printf ("Configuration file not found: %s.\n", cfgName);
-        exit (1);
-    }
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        line[sizeof (line) - 1] = '\0';
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
-            continue;
-
-        remove_control_chars (w1);
-        remove_control_chars (w2);
-        if (strcasecmp (w1, "userid") == 0)
-        {
-            memcpy (userid, w2, 24);
-        }
-        else if (strcasecmp (w1, "passwd") == 0)
-        {
-            memcpy (passwd, w2, 24);
-        }
-        else if (strcasecmp (w1, "server_name") == 0)
-        {
-            memcpy (server_name, w2, sizeof (server_name));
-            server_name[sizeof (server_name) - 1] = '\0';
-            printf ("%s server has been intialized\n", w2);
-        }
-        else if (strcasecmp (w1, "wisp_server_name") == 0)
-        {
-            if (strlen (w2) >= 4)
-            {
-                strncpy (wisp_server_name, w2, sizeof (wisp_server_name));
-                wisp_server_name[sizeof (wisp_server_name) - 1] = '\0';
-            }
-        }
-        else if (strcasecmp (w1, "login_ip") == 0)
-        {
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                printf ("Login server IP address : %s -> %d.%d.%d.%d\n", w2,
-                        (unsigned char) h->h_addr[0],
-                        (unsigned char) h->h_addr[1],
-                        (unsigned char) h->h_addr[2],
-                        (unsigned char) h->h_addr[3]);
-                sprintf (login_ip_str, "%d.%d.%d.%d",
-                         (unsigned char) h->h_addr[0],
-                         (unsigned char) h->h_addr[1],
-                         (unsigned char) h->h_addr[2],
-                         (unsigned char) h->h_addr[3]);
-            }
-            else
-                memcpy (login_ip_str, w2, 16);
-        }
-        else if (strcasecmp (w1, "login_port") == 0)
-        {
-            login_port = atoi (w2);
-        }
-        else if (strcasecmp (w1, "char_ip") == 0)
-        {
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                printf ("Character server IP address : %s -> %d.%d.%d.%d\n",
-                        w2, (unsigned char) h->h_addr[0],
-                        (unsigned char) h->h_addr[1],
-                        (unsigned char) h->h_addr[2],
-                        (unsigned char) h->h_addr[3]);
-                sprintf (char_ip_str, "%d.%d.%d.%d",
-                         (unsigned char) h->h_addr[0],
-                         (unsigned char) h->h_addr[1],
-                         (unsigned char) h->h_addr[2],
-                         (unsigned char) h->h_addr[3]);
-            }
-            else
-                memcpy (char_ip_str, w2, 16);
-        }
-        else if (strcasecmp (w1, "char_port") == 0)
-        {
-            char_port = atoi (w2);
-        }
-        else if (strcasecmp (w1, "char_maintenance") == 0)
-        {
-            char_maintenance = atoi (w2);
-        }
-        else if (strcasecmp (w1, "char_new") == 0)
-        {
-            char_new = atoi (w2);
-        }
-        else if (strcasecmp (w1, "email_creation") == 0)
-        {
-            email_creation = config_switch (w2);
-        }
-        else if (strcasecmp (w1, "char_txt") == 0)
-        {
-            strcpy (char_txt, w2);
-        }
-        else if (strcasecmp (w1, "backup_txt") == 0)
-        {                       //By zanetheinsane
-            strcpy (backup_txt, w2);
-        }
-        else if (strcasecmp (w1, "backup_txt_flag") == 0)
-        {                       // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. By [Yor]
-            backup_txt_flag = config_switch (w2);
-        }
-        else if (strcasecmp (w1, "max_connect_user") == 0)
-        {
-            max_connect_user = atoi (w2);
-            if (max_connect_user < 0)
-                max_connect_user = 0;   // unlimited online players
-        }
-        else if (strcasecmp (w1, "check_ip_flag") == 0)
-        {
-            check_ip_flag = config_switch (w2);
-        }
-        else if (strcasecmp (w1, "autosave_time") == 0)
-        {
-            autosave_interval = atoi (w2) * 1000;
-            if (autosave_interval <= 0)
-                autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-        }
-        else if (strcasecmp (w1, "start_point") == 0)
-        {
-            char map[32];
-            int  x, y;
-            if (sscanf (w2, "%[^,],%d,%d", map, &x, &y) < 3)
-                continue;
-            if (strstr (map, ".gat") != NULL)
-            {                   // Verify at least if '.gat' is in the map name
-                memcpy (start_point.map, map, 16);
-                start_point.x = x;
-                start_point.y = y;
-            }
-        }
-        else if (strcasecmp (w1, "start_zeny") == 0)
-        {
-            start_zeny = atoi (w2);
-            if (start_zeny < 0)
-                start_zeny = 0;
-        }
-        else if (strcasecmp (w1, "start_weapon") == 0)
-        {
-            start_weapon = atoi (w2);
-            if (start_weapon < 0)
-                start_weapon = 0;
-        }
-        else if (strcasecmp (w1, "start_armor") == 0)
-        {
-            start_armor = atoi (w2);
-            if (start_armor < 0)
-                start_armor = 0;
-        }
-        else if (strcasecmp (w1, "unknown_char_name") == 0)
-        {
-            strcpy (unknown_char_name, w2);
-            unknown_char_name[24] = 0;
-        }
-        else if (strcasecmp (w1, "char_log_filename") == 0)
-        {
-            strcpy (char_log_filename, w2);
-        }
-        else if (strcasecmp (w1, "name_ignoring_case") == 0)
-        {
-            name_ignoring_case = config_switch (w2);
-        }
-        else if (strcasecmp (w1, "char_name_option") == 0)
-        {
-            char_name_option = atoi (w2);
-        }
-        else if (strcasecmp (w1, "char_name_letters") == 0)
-        {
-            strcpy (char_name_letters, w2);
-// online files options
-        }
-        else if (strcasecmp (w1, "online_txt_filename") == 0)
-        {
-            strcpy (online_txt_filename, w2);
-        }
-        else if (strcasecmp (w1, "online_html_filename") == 0)
-        {
-            strcpy (online_html_filename, w2);
-        }
-        else if (strcasecmp (w1, "online_sorting_option") == 0)
-        {
-            online_sorting_option = atoi (w2);
-        }
-        else if (strcasecmp (w1, "online_display_option") == 0)
-        {
-            online_display_option = atoi (w2);
-        }
-        else if (strcasecmp (w1, "online_gm_display_min_level") == 0)
-        {                       // minimum GM level to display 'GM' when we want to display it
-            online_gm_display_min_level = atoi (w2);
-            if (online_gm_display_min_level < 5)    // send online file every 5 seconds to player is enough
-                online_gm_display_min_level = 5;
-        }
-        else if (strcasecmp (w1, "online_refresh_html") == 0)
-        {
-            online_refresh_html = atoi (w2);
-            if (online_refresh_html < 1)
-                online_refresh_html = 1;
-        }
-        else if (strcasecmp (w1, "anti_freeze_enable") == 0)
-        {
-            anti_freeze_enable = config_switch (w2);
-        }
-        else if (strcasecmp (w1, "anti_freeze_interval") == 0)
-        {
-            ANTI_FREEZE_INTERVAL = atoi (w2);
-            if (ANTI_FREEZE_INTERVAL < 5)
-                ANTI_FREEZE_INTERVAL = 5;   // minimum 5 seconds
-        }
-        else if (strcasecmp (w1, "import") == 0)
-        {
-            char_config_read (w2);
-        }
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-void term_func (void)
-{
-    int  i;
-
-    // write online players files with no player
-    for (i = 0; i < char_num; i++)
-        online_chars[i] = -1;
-    create_online_files ();
-    free (online_chars);
-
-    mmo_char_sync ();
-    inter_save ();
-
-    if (gm_account != NULL)
-        free (gm_account);
-
-    free (char_dat);
-    delete_session (login_fd);
-    delete_session (char_fd);
-
-    char_log ("----End of char-server (normal end with closing of all files).\n");
-}
-
-int do_init (int argc, char **argv)
-{
-    int  i;
-
-    // a newline in the log...
-    char_log ("");
-    char_log ("The char-server starting...\n");
-
-    char_config_read ((argc < 2) ? CHAR_CONF_NAME : argv[1]);
-    lan_config_read ((argc > 1) ? argv[1] : LOGIN_LAN_CONF_NAME);
-
-    login_ip = inet_addr (login_ip_str);
-    char_ip = inet_addr (char_ip_str);
-
-    for (i = 0; i < MAX_MAP_SERVERS; i++)
-    {
-        memset (&server[i], 0, sizeof (struct mmo_map_server));
-        server_fd[i] = -1;
-    }
-
-    mmo_char_init ();
-
-    update_online = time (NULL);
-    create_online_files ();     // update online players files at start of the server
-
-    inter_init ((argc > 2) ? argv[2] : inter_cfgName);  // inter server 初期化
-
-//    set_termfunc (do_final);
-    set_defaultparse (parse_char);
-
-    char_fd = make_listen_port (char_port);
-
-//    add_timer_func_list (check_connect_login_server, "check_connect_login_server");
-//    add_timer_func_list (send_users_tologin, "send_users_tologin");
-//    add_timer_func_list (mmo_char_sync_timer, "mmo_char_sync_timer");
-
-    i = add_timer_interval (gettick () + 1000, check_connect_login_server, 0,
-                            0, 10 * 1000);
-    i = add_timer_interval (gettick () + 1000, send_users_tologin, 0, 0,
-                            5 * 1000);
-    i = add_timer_interval (gettick () + autosave_interval,
-                            mmo_char_sync_timer, 0, 0, autosave_interval);
-
-    if (anti_freeze_enable > 0)
-    {
-//        add_timer_func_list (map_anti_freeze_system, "map_anti_freeze_system");
-        i = add_timer_interval (gettick () + 1000, map_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000);  // checks every X seconds user specifies
-    }
-
-    char_log ("The char-server is ready (Server is listening on the port %d).\n",
-              char_port);
-
-    printf
-        ("The char-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
-         char_port);
-
-    return 0;
-}
diff --git a/src/char/char.cpp b/src/char/char.cpp
new file mode 100644
index 0000000..a57520b
--- /dev/null
+++ b/src/char/char.cpp
@@ -0,0 +1,4076 @@
+// $Id: char.c,v 1.3 2004/09/13 16:52:16 Yor Exp $
+// original : char2.c 2003/03/14 11:58:35 Rev.1.5
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <sys/wait.h>
+
+#include "../common/core.hpp"
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/mmo.hpp"
+#include "../common/version.hpp"
+#include "../common/lock.hpp"
+#include "char.hpp"
+
+#include "inter.hpp"
+#include "int_guild.hpp"
+#include "int_party.hpp"
+#include "int_storage.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+struct mmo_map_server server[MAX_MAP_SERVERS];
+int  server_fd[MAX_MAP_SERVERS];
+int  server_freezeflag[MAX_MAP_SERVERS];    // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+int  anti_freeze_enable = 0;
+int  ANTI_FREEZE_INTERVAL = 6;
+
+int  login_fd, char_fd;
+char userid[24];
+char passwd[24];
+char server_name[20];
+char wisp_server_name[24] = "Server";
+char login_ip_str[16];
+int  login_ip;
+int  login_port = 6900;
+char char_ip_str[16];
+int  char_ip;
+int  char_port = 6121;
+int  char_maintenance;
+int  char_new;
+int  email_creation = 0;        // disabled by default
+char char_txt[1024];
+char backup_txt[1024];          //By zanetheinsane
+char backup_txt_flag = 0;       // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor]
+char unknown_char_name[1024] = "Unknown";
+char char_log_filename[1024] = "log/char.log";
+//Added for lan support
+char lan_map_ip[128];
+int  subneti[4];
+int  subnetmaski[4];
+int  name_ignoring_case = 0;    // Allow or not identical name for characters but with a different case by [Yor]
+int  char_name_option = 0;      // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
+char char_name_letters[1024] = "";  // list of letters/symbols authorised (or not) in a character name. by [Yor]
+
+struct char_session_data
+{
+    int  account_id, login_id1, login_id2, sex;
+    unsigned short packet_tmw_version;
+    int  found_char[9];
+    char email[40];             // e-mail (default: a@a.com) by [Yor]
+    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+};
+
+#define AUTH_FIFO_SIZE 256
+struct
+{
+    int  account_id, char_id, login_id1, login_id2, ip, char_pos, delflag,
+        sex;
+    unsigned short packet_tmw_version;
+    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+} auth_fifo[AUTH_FIFO_SIZE];
+int  auth_fifo_pos = 0;
+
+int  check_ip_flag = 1;         // It's to check IP of a player between char-server and other servers (part of anti-hacking system)
+
+int  char_id_count = 150000;
+struct mmo_charstatus *char_dat;
+int  char_num, char_max;
+int  max_connect_user = 0;
+int  autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+int  start_zeny = 500;
+int  start_weapon = 1201;
+int  start_armor = 1202;
+
+// Initial position (it's possible to set it in conf file)
+struct point start_point = { "new_1-1.gat", 53, 111 };
+
+struct gm_account *gm_account = NULL;
+int  GM_num = 0;
+
+// online players by [Yor]
+char online_txt_filename[1024] = "online.txt";
+char online_html_filename[1024] = "online.html";
+int  online_sorting_option = 0; // sorting option to display online players in online files
+int  online_display_option = 1; // display options: to know which columns must be displayed
+int  online_refresh_html = 20;  // refresh time (in sec) of the html file in the explorer
+int  online_gm_display_min_level = 20;  // minimum GM level to display 'GM' when we want to display it
+
+int *online_chars;              // same size of char_dat, and id value of current server (or -1)
+time_t update_online;           // to update online files when we receiving information from a server (not less than 8 seconds)
+
+pid_t pid = 0;                  // For forked DB writes
+
+//------------------------------
+// Writing function of logs file
+//------------------------------
+int char_log (char *fmt, ...)
+{
+    FILE *logfp;
+    va_list ap;
+    struct timeval tv;
+    char tmpstr[2048];
+
+    va_start (ap, fmt);
+
+    logfp = fopen_ (char_log_filename, "a");
+    if (logfp)
+    {
+        if (fmt[0] == '\0')     // jump a line if no message
+            fprintf (logfp, "\n");
+        else
+        {
+            gettimeofday (&tv, NULL);
+            strftime (tmpstr, 24, "%d-%m-%Y %H:%M:%S", gmtime (&(tv.tv_sec)));
+            sprintf (tmpstr + 19, ".%03d: %s", (int) tv.tv_usec / 1000, fmt);
+            vfprintf (logfp, tmpstr, ap);
+        }
+        fclose_ (logfp);
+    }
+
+    va_end (ap);
+    return 0;
+}
+
+//-----------------------------------------------------
+// Function to suppress control characters in a string.
+//-----------------------------------------------------
+int remove_control_chars (unsigned char *str)
+{
+    int  i;
+    int  change = 0;
+
+    for (i = 0; str[i]; i++)
+    {
+        if (str[i] < 32)
+        {
+            str[i] = '_';
+            change = 1;
+        }
+    }
+
+    return change;
+}
+
+//----------------------------------------------------------------------
+// Determine if an account (id) is a GM account
+// and returns its level (or 0 if it isn't a GM account or if not found)
+//----------------------------------------------------------------------
+int isGM (int account_id)
+{
+    int  i;
+
+    for (i = 0; i < GM_num; i++)
+        if (gm_account[i].account_id == account_id)
+            return gm_account[i].level;
+    return 0;
+}
+
+//----------------------------------------------
+// Search an character id
+//   (return character index or -1 (if not found))
+//   If exact character name is not found,
+//   the function checks without case sensitive
+//   and returns index if only 1 character is found
+//   and similar to the searched name.
+//----------------------------------------------
+int search_character_index (char *character_name)
+{
+    int  i, quantity, index;
+
+    quantity = 0;
+    index = -1;
+    for (i = 0; i < char_num; i++)
+    {
+        // Without case sensitive check (increase the number of similar character names found)
+        if (strcasecmp (char_dat[i].name, character_name) == 0)
+        {
+            // Strict comparison (if found, we finish the function immediatly with correct value)
+            if (strcmp (char_dat[i].name, character_name) == 0)
+                return i;
+            quantity++;
+            index = i;
+        }
+    }
+    // Here, the exact character name is not found
+    // We return the found index of a similar account ONLY if there is 1 similar character
+    if (quantity == 1)
+        return index;
+
+    // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
+    return -1;
+}
+
+//-------------------------------------
+// Return character name with the index
+//-------------------------------------
+char *search_character_name (int index)
+{
+
+    if (index >= 0 && index < char_num)
+        return char_dat[index].name;
+
+    return unknown_char_name;
+}
+
+//-------------------------------------------------
+// Function to create the character line (for save)
+//-------------------------------------------------
+int mmo_char_tostr (char *str, struct mmo_charstatus *p)
+{
+    int  i;
+    char *str_p = str;
+
+    // on multi-map server, sometimes it's posssible that last_point become void. (reason???) We check that to not lost character at restart.
+    if (p->last_point.map[0] == '\0')
+    {
+        memcpy (p->last_point.map, "prontera.gat", 16);
+        p->last_point.x = 273;
+        p->last_point.y = 354;
+    }
+
+    str_p += sprintf (str_p, "%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%s,%d,%d\t%s,%d,%d,%d\t", p->char_id, p->account_id, p->char_num, p->name,  //
+                      p->pc_class, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->hp, p->max_hp, p->sp, p->max_sp, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, p->status_point, p->skill_point, p->option, p->karma, p->manner,    //
+                      p->party_id, p->guild_id, 0, p->hair, p->hair_color, p->clothes_color, 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);
+    for (i = 0; i < 10; i++)
+        if (p->memo_point[i].map[0])
+        {
+            str_p +=
+                sprintf (str_p, "%s,%d,%d", p->memo_point[i].map,
+                         p->memo_point[i].x, p->memo_point[i].y);
+        }
+    *(str_p++) = '\t';
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+        if (p->inventory[i].nameid)
+        {
+            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                              p->inventory[i].id, p->inventory[i].nameid,
+                              p->inventory[i].amount, p->inventory[i].equip,
+                              p->inventory[i].identify,
+                              p->inventory[i].refine,
+                              p->inventory[i].attribute,
+                              p->inventory[i].card[0],
+                              p->inventory[i].card[1],
+                              p->inventory[i].card[2],
+                              p->inventory[i].card[3],
+                              p->inventory[i].broken);
+        }
+    *(str_p++) = '\t';
+
+    for (i = 0; i < MAX_CART; i++)
+        if (p->cart[i].nameid)
+        {
+            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                              p->cart[i].id, p->cart[i].nameid,
+                              p->cart[i].amount, p->cart[i].equip,
+                              p->cart[i].identify, p->cart[i].refine,
+                              p->cart[i].attribute, p->cart[i].card[0],
+                              p->cart[i].card[1], p->cart[i].card[2],
+                              p->cart[i].card[3], p->cart[i].broken);
+        }
+    *(str_p++) = '\t';
+
+    for (i = 0; i < MAX_SKILL; i++)
+        if (p->skill[i].id)
+        {
+            str_p +=
+                sprintf (str_p, "%d,%d ", p->skill[i].id,
+                         p->skill[i].lv | (p->skill[i].flags << 16));
+        }
+    *(str_p++) = '\t';
+
+    for (i = 0; i < p->global_reg_num; i++)
+        if (p->global_reg[i].str[0])
+            str_p +=
+                sprintf (str_p, "%s,%d ", p->global_reg[i].str,
+                         p->global_reg[i].value);
+    *(str_p++) = '\t';
+
+    *str_p = '\0';
+    return 0;
+}
+
+//-------------------------------------------------------------------------
+// Function to set the character from the line (at read of characters file)
+//-------------------------------------------------------------------------
+int mmo_char_fromstr (char *str, struct mmo_charstatus *p)
+{
+    int  tmp_int[256];
+    int  set, next, len, i;
+
+    // initilialise character
+    memset (p, '\0', sizeof (struct mmo_charstatus));
+
+    // If it's not char structure of version 1008 and after
+    if ((set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name,  //
+                       &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36], //
+                       p->save_point.map, &tmp_int[37], &tmp_int[38],
+                       &tmp_int[39], &next)) != 43)
+    {
+        tmp_int[39] = 0;        // partner id
+        // If not char structure from version 384 to 1007
+        if ((set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
+                           &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36], //
+                           p->save_point.map, &tmp_int[37], &tmp_int[38],
+                           &next)) != 42)
+        {
+            // It's char structure of a version before 384
+            tmp_int[26] = 0;    // pet id
+            set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
+                          &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], &tmp_int[34], p->last_point.map, &tmp_int[35], &tmp_int[36],    //
+                          p->save_point.map, &tmp_int[37], &tmp_int[38],
+                          &next);
+            set += 2;
+            //printf("char: old char data ver.1\n");
+            // Char structure of version 1007 or older
+        }
+        else
+        {
+            set++;
+            //printf("char: old char data ver.2\n");
+        }
+        // Char structure of version 1008+
+    }
+    else
+    {
+        //printf("char: new char data ver.3\n");
+    }
+    if (set != 43)
+        return 0;
+
+    p->char_id = tmp_int[0];
+    p->account_id = tmp_int[1];
+    p->char_num = tmp_int[2];
+    p->pc_class = tmp_int[3];
+    p->base_level = tmp_int[4];
+    p->job_level = tmp_int[5];
+    p->base_exp = tmp_int[6];
+    p->job_exp = tmp_int[7];
+    p->zeny = tmp_int[8];
+    p->hp = tmp_int[9];
+    p->max_hp = tmp_int[10];
+    p->sp = tmp_int[11];
+    p->max_sp = tmp_int[12];
+    p->str = tmp_int[13];
+    p->agi = tmp_int[14];
+    p->vit = tmp_int[15];
+    p->int_ = tmp_int[16];
+    p->dex = tmp_int[17];
+    p->luk = tmp_int[18];
+    p->status_point = tmp_int[19];
+    p->skill_point = tmp_int[20];
+    p->option = tmp_int[21];
+    p->karma = tmp_int[22];
+    p->manner = tmp_int[23];
+    p->party_id = tmp_int[24];
+    p->guild_id = tmp_int[25];
+//  p->pet_id = tmp_int[26];
+    p->hair = tmp_int[27];
+    p->hair_color = tmp_int[28];
+    p->clothes_color = tmp_int[29];
+    p->weapon = tmp_int[30];
+    p->shield = tmp_int[31];
+    p->head_top = tmp_int[32];
+    p->head_mid = tmp_int[33];
+    p->head_bottom = tmp_int[34];
+    p->last_point.x = tmp_int[35];
+    p->last_point.y = tmp_int[36];
+    p->save_point.x = tmp_int[37];
+    p->save_point.y = tmp_int[38];
+    p->partner_id = tmp_int[39];
+
+    // Some checks
+    for (i = 0; i < char_num; i++)
+    {
+        if (char_dat[i].char_id == p->char_id)
+        {
+            printf
+                ("\033[1;31mmmo_auth_init: ******Error: a character has an identical id to another.\n");
+            printf
+                ("               character id #%d -> new character not readed.\n",
+                 p->char_id);
+            printf ("               Character saved in log file.\033[0m\n");
+            return -1;
+        }
+        else if (strcmp (char_dat[i].name, p->name) == 0)
+        {
+            printf
+                ("\033[1;31mmmo_auth_init: ******Error: character name already exists.\n");
+            printf
+                ("               character name '%s' -> new character not readed.\n",
+                 p->name);
+            printf ("               Character saved in log file.\033[0m\n");
+            return -2;
+        }
+    }
+
+    if (strcasecmp (wisp_server_name, p->name) == 0)
+    {
+        printf
+            ("mmo_auth_init: ******WARNING: character name has wisp server name.\n");
+        printf
+            ("               Character name '%s' = wisp server name '%s'.\n",
+             p->name, wisp_server_name);
+        printf
+            ("               Character readed. Suggestion: change the wisp server name.\n");
+        char_log
+            ("mmo_auth_init: ******WARNING: character name has wisp server name: Character name '%s' = wisp server name '%s'.\n",
+             p->name, wisp_server_name);
+    }
+
+    if (str[next] == '\n' || str[next] == '\r')
+        return 1;               // 新規データ
+
+    next++;
+
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        if (sscanf
+            (str + next, "%[^,],%d,%d%n", p->memo_point[i].map, &tmp_int[0],
+             &tmp_int[1], &len) != 3)
+            return -3;
+        p->memo_point[i].x = tmp_int[0];
+        p->memo_point[i].y = tmp_int[1];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+
+    next++;
+
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                    &tmp_int[11], &len) == 12)
+        {
+            // do nothing, it's ok
+        }
+        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                         &len) == 11)
+        {
+            tmp_int[11] = 0;    // broken doesn't exist in this version -> 0
+        }
+        else                    // invalid structure
+            return -4;
+        p->inventory[i].id = tmp_int[0];
+        p->inventory[i].nameid = tmp_int[1];
+        p->inventory[i].amount = tmp_int[2];
+        p->inventory[i].equip = tmp_int[3];
+        p->inventory[i].identify = tmp_int[4];
+        p->inventory[i].refine = tmp_int[5];
+        p->inventory[i].attribute = tmp_int[6];
+        p->inventory[i].card[0] = tmp_int[7];
+        p->inventory[i].card[1] = tmp_int[8];
+        p->inventory[i].card[2] = tmp_int[9];
+        p->inventory[i].card[3] = tmp_int[10];
+        p->inventory[i].broken = tmp_int[11];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+
+    next++;
+
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                    &tmp_int[11], &len) == 12)
+        {
+            // do nothing, it's ok
+        }
+        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                         &len) == 11)
+        {
+            tmp_int[11] = 0;    // broken doesn't exist in this version -> 0
+        }
+        else                    // invalid structure
+            return -5;
+        p->cart[i].id = tmp_int[0];
+        p->cart[i].nameid = tmp_int[1];
+        p->cart[i].amount = tmp_int[2];
+        p->cart[i].equip = tmp_int[3];
+        p->cart[i].identify = tmp_int[4];
+        p->cart[i].refine = tmp_int[5];
+        p->cart[i].attribute = tmp_int[6];
+        p->cart[i].card[0] = tmp_int[7];
+        p->cart[i].card[1] = tmp_int[8];
+        p->cart[i].card[2] = tmp_int[9];
+        p->cart[i].card[3] = tmp_int[10];
+        p->cart[i].broken = tmp_int[11];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+
+    next++;
+
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        if (sscanf (str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len) !=
+            2)
+            return -6;
+        p->skill[tmp_int[0]].id = tmp_int[0];
+        p->skill[tmp_int[0]].lv = tmp_int[1] & 0xffff;
+        p->skill[tmp_int[0]].flags = ((tmp_int[1] >> 16) & 0xffff);
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+
+    next++;
+
+    for (i = 0;
+         str[next] && str[next] != '\t' && str[next] != '\n'
+         && str[next] != '\r'; i++)
+    {                           // global_reg実装以前のathena.txt互換のため一応'\n'チェック
+        if (sscanf
+            (str + next, "%[^,],%d%n", p->global_reg[i].str,
+             &p->global_reg[i].value, &len) != 2)
+        {
+            // because some scripts are not correct, the str can be "". So, we must check that.
+            // If it's, we must not refuse the character, but just this REG value.
+            // Character line will have something like: nov_2nd_cos,9 ,9 nov_1_2_cos_c,1 (here, ,9 is not good)
+            if (str[next] == ','
+                && sscanf (str + next, ",%d%n", &p->global_reg[i].value,
+                           &len) == 1)
+                i--;
+            else
+                return -7;
+        }
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    p->global_reg_num = i;
+
+    return 1;
+}
+
+//---------------------------------
+// Function to read characters file
+//---------------------------------
+int mmo_char_init (void)
+{
+    char line[65536];
+    int  i;
+    int  ret, line_count;
+    FILE *fp;
+
+    char_max = 256;
+    CREATE (char_dat, struct mmo_charstatus, 256);
+    CREATE (online_chars, int, 256);
+    for (i = 0; i < char_max; i++)
+        online_chars[i] = -1;
+
+    char_num = 0;
+
+    fp = fopen_ (char_txt, "r");
+    if (fp == NULL)
+    {
+        printf ("Characters file not found: %s.\n", char_txt);
+        char_log ("Characters file not found: %s.\n", char_txt);
+        char_log ("Id for the next created character: %d.\n",
+                  char_id_count);
+        return 0;
+    }
+
+    line_count = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        int  i, j;
+        line_count++;
+
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        line[sizeof (line) - 1] = '\0';
+
+        j = 0;
+        if (sscanf (line, "%d\t%%newid%%%n", &i, &j) == 1 && j > 0)
+        {
+            if (char_id_count < i)
+                char_id_count = i;
+            continue;
+        }
+
+        if (char_num >= char_max)
+        {
+            char_max += 256;
+            RECREATE (char_dat, struct mmo_charstatus, char_max);
+            RECREATE (online_chars, int, char_max);
+            for (i = char_max - 256; i < char_max; i++)
+                online_chars[i] = -1;
+        }
+
+        ret = mmo_char_fromstr (line, &char_dat[char_num]);
+        if (ret > 0)
+        {                       // negative value or zero for errors
+            if (char_dat[char_num].char_id >= char_id_count)
+                char_id_count = char_dat[char_num].char_id + 1;
+            char_num++;
+        }
+        else
+        {
+            printf
+                ("mmo_char_init: in characters file, unable to read the line #%d.\n",
+                 line_count);
+            printf ("               -> Character saved in log file.\n");
+            switch (ret)
+            {
+                case -1:
+                    char_log
+                        ("Duplicate character id in the next character line (character not readed):\n");
+                    break;
+                case -2:
+                    char_log
+                        ("Duplicate character name in the next character line (character not readed):\n");
+                    break;
+                case -3:
+                    char_log
+                        ("Invalid memo point structure in the next character line (character not readed):\n");
+                    break;
+                case -4:
+                    char_log
+                        ("Invalid inventory item structure in the next character line (character not readed):\n");
+                    break;
+                case -5:
+                    char_log
+                        ("Invalid cart item structure in the next character line (character not readed):\n");
+                    break;
+                case -6:
+                    char_log
+                        ("Invalid skill structure in the next character line (character not readed):\n");
+                    break;
+                case -7:
+                    char_log
+                        ("Invalid register structure in the next character line (character not readed):\n");
+                    break;
+                default:       // 0
+                    char_log
+                        ("Unabled to get a character in the next line - Basic structure of line (before inventory) is incorrect (character not readed):\n");
+                    break;
+            }
+            char_log ("%s", line);
+        }
+    }
+    fclose_ (fp);
+
+    if (char_num == 0)
+    {
+        printf ("mmo_char_init: No character found in %s.\n", char_txt);
+        char_log ("mmo_char_init: No character found in %s.\n",
+                  char_txt);
+    }
+    else if (char_num == 1)
+    {
+        printf ("mmo_char_init: 1 character read in %s.\n", char_txt);
+        char_log ("mmo_char_init: 1 character read in %s.\n", char_txt);
+    }
+    else
+    {
+        printf ("mmo_char_init: %d characters read in %s.\n", char_num,
+                char_txt);
+        char_log ("mmo_char_init: %d characters read in %s.\n",
+                  char_num, char_txt);
+    }
+
+    char_log ("Id for the next created character: %d.\n",
+              char_id_count);
+
+    return 0;
+}
+
+//---------------------------------------------------------
+// Function to save characters in files (speed up by [Yor])
+//---------------------------------------------------------
+void mmo_char_sync (void)
+{
+    char line[65536];
+    int  i, j, k;
+    int  lock;
+    FILE *fp;
+    int  id[char_num];
+
+    // Sorting before save (by [Yor])
+    for (i = 0; i < char_num; i++)
+    {
+        id[i] = i;
+        for (j = 0; j < i; j++)
+        {
+            if ((char_dat[i].account_id < char_dat[id[j]].account_id) ||
+                // if same account id, we sort by slot.
+                (char_dat[i].account_id == char_dat[id[j]].account_id &&
+                 char_dat[i].char_num < char_dat[id[j]].char_num))
+            {
+                for (k = i; k > j; k--)
+                    id[k] = id[k - 1];
+                id[j] = i;      // id[i]
+                break;
+            }
+        }
+    }
+
+    // Data save
+    fp = lock_fopen (char_txt, &lock);
+    if (fp == NULL)
+    {
+        printf ("WARNING: Server can't not save characters.\n");
+        char_log ("WARNING: Server can't not save characters.\n");
+    }
+    else
+    {
+        for (i = 0; i < char_num; i++)
+        {
+            // create only once the line, and save it in the 2 files (it's speeder than repeat twice the loop and create twice the line)
+            mmo_char_tostr (line, &char_dat[id[i]]);    // use of sorted index
+            fprintf (fp, "%s\n", line);
+        }
+        fprintf (fp, "%d\t%%newid%%\n", char_id_count);
+        lock_fclose (fp, char_txt, &lock);
+    }
+
+    // Data save (backup)
+    if (backup_txt_flag)
+    {                           // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. => option By [Yor]
+        fp = lock_fopen (backup_txt, &lock);
+        if (fp == NULL)
+        {
+            printf
+                ("WARNING: Server can't not create backup of characters file.\n");
+            char_log
+                ("WARNING: Server can't not create backup of characters file.\n");
+            return;
+        }
+        for (i = 0; i < char_num; i++)
+        {
+            // create only once the line, and save it in the 2 files (it's speeder than repeat twice the loop and create twice the line)
+            mmo_char_tostr (line, &char_dat[id[i]]);    // use of sorted index
+            fprintf (fp, "%s\n", line);
+        }
+        fprintf (fp, "%d\t%%newid%%\n", char_id_count);
+        lock_fclose (fp, backup_txt, &lock);
+    }
+
+    return;
+}
+
+//----------------------------------------------------
+// Function to save (in a periodic way) datas in files
+//----------------------------------------------------
+void mmo_char_sync_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    if (pid != 0)
+    {
+        int  status;
+        pid_t temp = waitpid (pid, &status, WNOHANG);
+
+        // Need to check status too?
+        if (temp == 0)
+        {
+            return;
+        }
+    }
+
+    // This can take a lot of time. Fork a child to handle the work and return at once
+    // If we're unable to fork just continue running the function normally
+    if ((pid = fork ()) > 0)
+        return;
+
+    mmo_char_sync ();
+    inter_save ();
+
+    // If we're a child we should suicide now.
+    if (pid == 0)
+        _exit (0);
+}
+
+//----------------------------------------------------
+// Remove trailing whitespace from a name
+//----------------------------------------------------
+static void remove_trailing_blanks (char *name)
+{
+    char *tail = name + strlen (name) - 1;
+
+    while (tail > name && *tail == ' ')
+        *tail-- = 0;
+}
+
+//----------------------------------------------------
+// Remove prefix whitespace from a name
+//----------------------------------------------------
+static void remove_prefix_blanks (char *name)
+{
+    char *dst = name;
+    char *src = name;
+
+    while (*src == ' ')         // find first nonblank
+        ++src;
+    while ((*dst++ = *src++));  // `strmove'
+}
+
+//-----------------------------------
+// Function to create a new character
+//-----------------------------------
+int make_new_char (int fd, unsigned char *dat)
+{
+    int  i, j;
+    struct char_session_data *sd = (struct char_session_data *)session[fd]->session_data;
+
+    // remove control characters from the name
+    dat[23] = '\0';
+    if (remove_control_chars (dat))
+    {
+        char_log
+            ("Make new char error (control char received in the name): (connection #%d, account: %d).\n",
+             fd, sd->account_id);
+        return -1;
+    }
+
+    // Eliminate whitespace
+    remove_trailing_blanks ((char *) dat);
+    remove_prefix_blanks ((char *) dat);
+
+    // check lenght of character name
+    if (strlen (dat) < 4)
+    {
+        char_log
+            ("Make new char error (character name too small): (connection #%d, account: %d, name: '%s').\n",
+             fd, sd->account_id, dat);
+        return -1;
+    }
+
+    // Check Authorised letters/symbols in the name of the character
+    if (char_name_option == 1)
+    {                           // only letters/symbols in char_name_letters are authorised
+        for (i = 0; dat[i]; i++)
+            if (strchr (char_name_letters, dat[i]) == NULL)
+            {
+                char_log
+                    ("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n",
+                     fd, sd->account_id, dat, dat[i]);
+                return -1;
+            }
+    }
+    else if (char_name_option == 2)
+    {                           // letters/symbols in char_name_letters are forbidden
+        for (i = 0; dat[i]; i++)
+            if (strchr (char_name_letters, dat[i]) != NULL)
+            {
+                char_log
+                    ("Make new char error (invalid letter in the name): (connection #%d, account: %d), name: %s, invalid letter: %c.\n",
+                     fd, sd->account_id, dat, dat[i]);
+                return -1;
+            }
+    }                           // else, all letters/symbols are authorised (except control char removed before)
+
+    if (dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29] != 5 * 6 ||   // stats
+        dat[30] >= 9 ||         // slots (dat[30] can not be negativ)
+        dat[33] < 0 || dat[33] >= 20 || // hair style
+        dat[31] >= 12)
+    {                           // hair color (dat[31] can not be negativ)
+        char_log
+            ("Make new char error (invalid values): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n",
+             fd, sd->account_id, dat[30], dat, dat[24], dat[25],
+             dat[26], dat[27], dat[28], dat[29],
+             dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
+             dat[33], dat[31]);
+        return -1;
+    }
+
+    // check individual stat value
+    for (i = 24; i <= 29; i++)
+    {
+        if (dat[i] < 1 || dat[i] > 9)
+        {
+            char_log
+                ("Make new char error (invalid stat value: not between 1 to 9): (connection #%d, account: %d) slot %d, name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d\n",
+                 fd, sd->account_id, dat[30], dat, dat[24], dat[25],
+                 dat[26], dat[27], dat[28], dat[29],
+                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
+                 dat[33], dat[31]);
+            return -1;
+        }
+    }
+
+    for (i = 0; i < char_num; i++)
+    {
+        if ((name_ignoring_case != 0 && strcmp (char_dat[i].name, dat) == 0)
+            || (name_ignoring_case == 0
+                && strcasecmp (char_dat[i].name, dat) == 0))
+        {
+            char_log
+                ("Make new char error (name already exists): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
+                 fd, sd->account_id, dat[30], dat, char_dat[i].name,
+                 dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
+                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
+                 dat[33], dat[31]);
+            return -1;
+        }
+        if (char_dat[i].account_id == sd->account_id
+            && char_dat[i].char_num == dat[30])
+        {
+            char_log
+                ("Make new char error (slot already used): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %s), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
+                 fd, sd->account_id, dat[30], dat, char_dat[i].name,
+                 dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
+                 dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
+                 dat[33], dat[31]);
+            return -1;
+        }
+    }
+
+    if (strcmp (wisp_server_name, dat) == 0)
+    {
+        char_log
+            ("Make new char error (name used is wisp name for server): (connection #%d, account: %d) slot %d, name: %s (actual name of other char: %d), stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d.\n",
+             fd, sd->account_id, dat[30], dat, char_dat[i].name,
+             dat[24], dat[25], dat[26], dat[27], dat[28], dat[29],
+             dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29],
+             dat[33], dat[31]);
+        return -1;
+    }
+
+    if (char_num >= char_max)
+    {
+        char_max += 256;
+        RECREATE (char_dat, struct mmo_charstatus, char_max);
+        RECREATE (online_chars, int, char_max);
+        for (j = char_max - 256; j < char_max; j++)
+            online_chars[j] = -1;
+    }
+
+    char ip[16];
+    unsigned char *sin_addr =
+        (unsigned char *) &session[fd]->client_addr.sin_addr;
+    sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2],
+             sin_addr[3]);
+
+    char_log
+        ("Creation of New Character: (connection #%d, account: %d) slot %d, character Name: %s, stats: %d+%d+%d+%d+%d+%d=%d, hair: %d, hair color: %d. [%s]\n",
+         fd, sd->account_id, dat[30], dat, dat[24], dat[25], dat[26],
+         dat[27], dat[28], dat[29],
+         dat[24] + dat[25] + dat[26] + dat[27] + dat[28] + dat[29], dat[33],
+         dat[31], ip);
+
+    memset (&char_dat[i], 0, sizeof (struct mmo_charstatus));
+
+    char_dat[i].char_id = char_id_count++;
+    char_dat[i].account_id = sd->account_id;
+    char_dat[i].char_num = dat[30];
+    strcpy (char_dat[i].name, dat);
+    char_dat[i].pc_class = 0;
+    char_dat[i].base_level = 1;
+    char_dat[i].job_level = 1;
+    char_dat[i].base_exp = 0;
+    char_dat[i].job_exp = 0;
+    char_dat[i].zeny = start_zeny;
+    char_dat[i].str = dat[24];
+    char_dat[i].agi = dat[25];
+    char_dat[i].vit = dat[26];
+    char_dat[i].int_ = dat[27];
+    char_dat[i].dex = dat[28];
+    char_dat[i].luk = dat[29];
+    char_dat[i].max_hp = 40 * (100 + char_dat[i].vit) / 100;
+    char_dat[i].max_sp = 11 * (100 + char_dat[i].int_) / 100;
+    char_dat[i].hp = char_dat[i].max_hp;
+    char_dat[i].sp = char_dat[i].max_sp;
+    char_dat[i].status_point = 0;
+    char_dat[i].skill_point = 0;
+    char_dat[i].option = 0;
+    char_dat[i].karma = 0;
+    char_dat[i].manner = 0;
+    char_dat[i].party_id = 0;
+    char_dat[i].guild_id = 0;
+    char_dat[i].hair = dat[33];
+    char_dat[i].hair_color = dat[31];
+    char_dat[i].clothes_color = 0;
+    char_dat[i].inventory[0].nameid = start_weapon; // Knife
+    char_dat[i].inventory[0].amount = 1;
+    char_dat[i].inventory[0].equip = 0x02;
+    char_dat[i].inventory[0].identify = 1;
+    char_dat[i].inventory[0].broken = 0;
+    char_dat[i].inventory[1].nameid = start_armor;  // Cotton Shirt
+    char_dat[i].inventory[1].amount = 1;
+    char_dat[i].inventory[1].equip = 0x10;
+    char_dat[i].inventory[1].identify = 1;
+    char_dat[i].inventory[1].broken = 0;
+    char_dat[i].weapon = 1;
+    char_dat[i].shield = 0;
+    char_dat[i].head_top = 0;
+    char_dat[i].head_mid = 0;
+    char_dat[i].head_bottom = 0;
+    memcpy (&char_dat[i].last_point, &start_point, sizeof (start_point));
+    memcpy (&char_dat[i].save_point, &start_point, sizeof (start_point));
+    char_num++;
+
+    return i;
+}
+
+//----------------------------------------------------
+// This function return the name of the job (by [Yor])
+//----------------------------------------------------
+char *job_name (int pc_class)
+{
+    switch (pc_class)
+    {
+        case 0:
+            return "Novice";
+        case 1:
+            return "Swordsman";
+        case 2:
+            return "Mage";
+        case 3:
+            return "Archer";
+        case 4:
+            return "Acolyte";
+        case 5:
+            return "Merchant";
+        case 6:
+            return "Thief";
+        case 7:
+            return "Knight";
+        case 8:
+            return "Priest";
+        case 9:
+            return "Wizard";
+        case 10:
+            return "Blacksmith";
+        case 11:
+            return "Hunter";
+        case 12:
+            return "Assassin";
+        case 13:
+            return "Knight 2";
+        case 14:
+            return "Crusader";
+        case 15:
+            return "Monk";
+        case 16:
+            return "Sage";
+        case 17:
+            return "Rogue";
+        case 18:
+            return "Alchemist";
+        case 19:
+            return "Bard";
+        case 20:
+            return "Dancer";
+        case 21:
+            return "Crusader 2";
+        case 22:
+            return "Wedding";
+        case 23:
+            return "Super Novice";
+        case 4001:
+            return "Novice High";
+        case 4002:
+            return "Swordsman High";
+        case 4003:
+            return "Mage High";
+        case 4004:
+            return "Archer High";
+        case 4005:
+            return "Acolyte High";
+        case 4006:
+            return "Merchant High";
+        case 4007:
+            return "Thief High";
+        case 4008:
+            return "Lord Knight";
+        case 4009:
+            return "High Priest";
+        case 4010:
+            return "High Wizard";
+        case 4011:
+            return "Whitesmith";
+        case 4012:
+            return "Sniper";
+        case 4013:
+            return "Assassin Cross";
+        case 4014:
+            return "Peko Knight";
+        case 4015:
+            return "Paladin";
+        case 4016:
+            return "Champion";
+        case 4017:
+            return "Professor";
+        case 4018:
+            return "Stalker";
+        case 4019:
+            return "Creator";
+        case 4020:
+            return "Clown";
+        case 4021:
+            return "Gypsy";
+        case 4022:
+            return "Peko Paladin";
+        case 4023:
+            return "Baby Novice";
+        case 4024:
+            return "Baby Swordsman";
+        case 4025:
+            return "Baby Mage";
+        case 4026:
+            return "Baby Archer";
+        case 4027:
+            return "Baby Acolyte";
+        case 4028:
+            return "Baby Merchant";
+        case 4029:
+            return "Baby Thief";
+        case 4030:
+            return "Baby Knight";
+        case 4031:
+            return "Baby Priest";
+        case 4032:
+            return "Baby Wizard";
+        case 4033:
+            return "Baby Blacksmith";
+        case 4034:
+            return "Baby Hunter";
+        case 4035:
+            return "Baby Assassin";
+        case 4036:
+            return "Baby Peco Knight";
+        case 4037:
+            return "Baby Crusader";
+        case 4038:
+            return "Baby Monk";
+        case 4039:
+            return "Baby Sage";
+        case 4040:
+            return "Baby Rogue";
+        case 4041:
+            return "Baby Alchemist";
+        case 4042:
+            return "Baby Bard";
+        case 4043:
+            return "Baby Dancer";
+        case 4044:
+            return "Baby Peco Crusader";
+        case 4045:
+            return "Super Baby";
+    }
+    return "Unknown Job";
+}
+
+//-------------------------------------------------------------
+// Function to create the online files (txt and html). by [Yor]
+//-------------------------------------------------------------
+void create_online_files (void)
+{
+    int  i, j, k, l;            // for loops
+    int  players;               // count the number of players
+    FILE *fp;                   // for the txt file
+    FILE *fp2;                  // for the html file
+    char temp[256];             // to prepare what we must display
+    time_t time_server;         // for number of seconds
+    struct tm *datetime;        // variable for time in structure ->tm_mday, ->tm_sec, ...
+    int  id[char_num];
+
+    if (online_display_option == 0) // we display nothing, so return
+        return;
+
+    //char_log("Creation of online players files.\n");
+
+    // Get number of online players, id of each online players
+    players = 0;
+    // sort online characters.
+    for (i = 0; i < char_num; i++)
+    {
+        if (online_chars[i] != -1)
+        {
+            id[players] = i;
+            // use sorting option
+            switch (online_sorting_option)
+            {
+                case 1:        // by name (without case sensitive)
+                {
+                    char *p_name = char_dat[i].name;    //speed up sorting when there are a lot of players. But very rarely players have same name.
+                    for (j = 0; j < players; j++)
+                        if (strcasecmp (p_name, char_dat[id[j]].name) < 0 ||
+                            // if same name, we sort with case sensitive.
+                            (strcasecmp (p_name, char_dat[id[j]].name) == 0 &&
+                             strcmp (p_name, char_dat[id[j]].name) < 0))
+                        {
+                            for (k = players; k > j; k--)
+                                id[k] = id[k - 1];
+                            id[j] = i;  // id[players]
+                            break;
+                        }
+                }
+                    break;
+                case 2:        // by zeny
+                    for (j = 0; j < players; j++)
+                        if (char_dat[i].zeny < char_dat[id[j]].zeny ||
+                            // if same number of zenys, we sort by name.
+                            (char_dat[i].zeny == char_dat[id[j]].zeny &&
+                             strcasecmp (char_dat[i].name,
+                                      char_dat[id[j]].name) < 0))
+                        {
+                            for (k = players; k > j; k--)
+                                id[k] = id[k - 1];
+                            id[j] = i;  // id[players]
+                            break;
+                        }
+                    break;
+                case 3:        // by base level
+                    for (j = 0; j < players; j++)
+                        if (char_dat[i].base_level <
+                            char_dat[id[j]].base_level ||
+                            // if same base level, we sort by base exp.
+                            (char_dat[i].base_level ==
+                             char_dat[id[j]].base_level
+                             && char_dat[i].base_exp <
+                             char_dat[id[j]].base_exp))
+                        {
+                            for (k = players; k > j; k--)
+                                id[k] = id[k - 1];
+                            id[j] = i;  // id[players]
+                            break;
+                        }
+                    break;
+                case 4:        // by job (and job level)
+                    for (j = 0; j < players; j++)
+                        if (char_dat[i].pc_class < char_dat[id[j]].pc_class ||
+                            // if same job, we sort by job level.
+                            (char_dat[i].pc_class == char_dat[id[j]].pc_class &&
+                             char_dat[i].job_level <
+                             char_dat[id[j]].job_level) ||
+                            // if same job and job level, we sort by job exp.
+                            (char_dat[i].pc_class == char_dat[id[j]].pc_class &&
+                             char_dat[i].job_level ==
+                             char_dat[id[j]].job_level
+                             && char_dat[i].job_exp <
+                             char_dat[id[j]].job_exp))
+                        {
+                            for (k = players; k > j; k--)
+                                id[k] = id[k - 1];
+                            id[j] = i;  // id[players]
+                            break;
+                        }
+                    break;
+                case 5:        // by location map name
+                {
+                    int  cpm_result;    // A lot of player maps are identical. So, test if done often twice.
+                    for (j = 0; j < players; j++)
+                        if ((cpm_result = strcmp (char_dat[i].last_point.map, char_dat[id[j]].last_point.map)) < 0 ||   // no map are identical and with upper cases (not use strcasecmp)
+                            // if same map name, we sort by name.
+                            (cpm_result == 0 &&
+                             strcasecmp (char_dat[i].name,
+                                      char_dat[id[j]].name) < 0))
+                        {
+                            for (k = players; k > j; k--)
+                                id[k] = id[k - 1];
+                            id[j] = i;  // id[players]
+                            break;
+                        }
+                }
+                    break;
+                default:       // 0 or invalid value: no sorting
+                    break;
+            }
+            players++;
+        }
+    }
+
+    // write files
+    fp = fopen_ (online_txt_filename, "w");
+    if (fp != NULL)
+    {
+        fp2 = fopen_ (online_html_filename, "w");
+        if (fp2 != NULL)
+        {
+            // get time
+            time (&time_server);    // get time in seconds since 1/1/1970
+            datetime = localtime (&time_server);    // convert seconds in structure
+            strftime (temp, sizeof (temp), "%d %b %Y %X", datetime);    // like sprintf, but only for date/time (05 dec 2003 15:12:52)
+            // write heading
+            fprintf (fp2, "<HTML>\n");
+            fprintf (fp2, "  <META http-equiv=\"Refresh\" content=\"%d\">\n", online_refresh_html); // update on client explorer every x seconds
+            fprintf (fp2, "  <HEAD>\n");
+            fprintf (fp2, "    <TITLE>Online Players on %s</TITLE>\n",
+                     server_name);
+            fprintf (fp2, "  </HEAD>\n");
+            fprintf (fp2, "  <BODY>\n");
+            fprintf (fp2, "    <H3>Online Players on %s (%s):</H3>\n",
+                     server_name, temp);
+            fprintf (fp, "Online Players on %s (%s):\n", server_name, temp);
+            fprintf (fp, "\n");
+
+            // If we display at least 1 player
+            if (players > 0)
+            {
+                j = 0;          // count the number of characters for the txt version and to set the separate line
+                fprintf (fp2, "    <table border=\"1\" cellspacing=\"1\">\n");
+                fprintf (fp2, "      <tr>\n");
+                if ((online_display_option & 1)
+                    || (online_display_option & 64))
+                {
+                    fprintf (fp2, "        <td><b>Name</b></td>\n");
+                    if (online_display_option & 64)
+                    {
+                        fprintf (fp, "Name                          "); // 30
+                        j += 30;
+                    }
+                    else
+                    {
+                        fprintf (fp, "Name                     ");  // 25
+                        j += 25;
+                    }
+                }
+                if ((online_display_option & 6) == 6)
+                {
+                    fprintf (fp2, "        <td><b>Job (levels)</b></td>\n");
+                    fprintf (fp, "Job                 Levels ");    // 27
+                    j += 27;
+                }
+                else if (online_display_option & 2)
+                {
+                    fprintf (fp2, "        <td><b>Job</b></td>\n");
+                    fprintf (fp, "Job                ");    // 19
+                    j += 19;
+                }
+                else if (online_display_option & 4)
+                {
+                    fprintf (fp2, "        <td><b>Levels</b></td>\n");
+                    fprintf (fp, " Levels ");   // 8
+                    j += 8;
+                }
+                if (online_display_option & 24)
+                {               // 8 or 16
+                    fprintf (fp2, "        <td><b>Location</b></td>\n");
+                    if (online_display_option & 16)
+                    {
+                        fprintf (fp, "Location     ( x , y ) ");    // 23
+                        j += 23;
+                    }
+                    else
+                    {
+                        fprintf (fp, "Location     ");  // 13
+                        j += 13;
+                    }
+                }
+                if (online_display_option & 32)
+                {
+                    fprintf (fp2,
+                             "        <td ALIGN=CENTER><b>zenys</b></td>\n");
+                    fprintf (fp, "          Zenys ");   // 16
+                    j += 16;
+                }
+                fprintf (fp2, "      </tr>\n");
+                fprintf (fp, "\n");
+                for (k = 0; k < j; k++)
+                    fprintf (fp, "-");
+                fprintf (fp, "\n");
+
+                // display each player.
+                for (i = 0; i < players; i++)
+                {
+                    // get id of the character (more speed)
+                    j = id[i];
+                    fprintf (fp2, "      <tr>\n");
+                    // displaying the character name
+                    if ((online_display_option & 1)
+                        || (online_display_option & 64))
+                    {           // without/with 'GM' display
+                        strcpy (temp, char_dat[j].name);
+                        l = isGM (char_dat[j].account_id);
+                        if (online_display_option & 64)
+                        {
+                            if (l >= online_gm_display_min_level)
+                                fprintf (fp, "%-24s (GM) ", temp);
+                            else
+                                fprintf (fp, "%-24s      ", temp);
+                        }
+                        else
+                            fprintf (fp, "%-24s ", temp);
+                        // name of the character in the html (no < >, because that create problem in html code)
+                        fprintf (fp2, "        <td>");
+                        if ((online_display_option & 64)
+                            && l >= online_gm_display_min_level)
+                            fprintf (fp2, "<b>");
+                        for (k = 0; temp[k]; k++)
+                        {
+                            switch (temp[k])
+                            {
+                                case '<':  // <
+                                    fprintf (fp2, "&lt;");
+                                    break;
+                                case '>':  // >
+                                    fprintf (fp2, "&gt;");
+                                    break;
+                                default:
+                                    fprintf (fp2, "%c", temp[k]);
+                                    break;
+                            };
+                        }
+                        if ((online_display_option & 64)
+                            && l >= online_gm_display_min_level)
+                            fprintf (fp2, "</b> (GM)");
+                        fprintf (fp2, "</td>\n");
+                    }
+                    // displaying of the job
+                    if (online_display_option & 6)
+                    {
+                        char *jobname = job_name (char_dat[j].pc_class);
+                        if ((online_display_option & 6) == 6)
+                        {
+                            fprintf (fp2, "        <td>%s %d/%d</td>\n",
+                                     jobname, char_dat[j].base_level,
+                                     char_dat[j].job_level);
+                            fprintf (fp, "%-18s %3d/%3d ", jobname,
+                                     char_dat[j].base_level,
+                                     char_dat[j].job_level);
+                        }
+                        else if (online_display_option & 2)
+                        {
+                            fprintf (fp2, "        <td>%s</td>\n", jobname);
+                            fprintf (fp, "%-18s ", jobname);
+                        }
+                        else if (online_display_option & 4)
+                        {
+                            fprintf (fp2, "        <td>%d/%d</td>\n",
+                                     char_dat[j].base_level,
+                                     char_dat[j].job_level);
+                            fprintf (fp, "%3d/%3d ", char_dat[j].base_level,
+                                     char_dat[j].job_level);
+                        }
+                    }
+                    // displaying of the map
+                    if (online_display_option & 24)
+                    {           // 8 or 16
+                        // prepare map name
+                        memset (temp, 0, sizeof (temp));
+                        strncpy (temp, char_dat[j].last_point.map, 16);
+                        if (strchr (temp, '.') != NULL)
+                            temp[strchr (temp, '.') - temp] = '\0'; // suppress the '.gat'
+                        // write map name
+                        if (online_display_option & 16)
+                        {       // map-name AND coordonates
+                            fprintf (fp2, "        <td>%s (%d, %d)</td>\n",
+                                     temp, char_dat[j].last_point.x,
+                                     char_dat[j].last_point.y);
+                            fprintf (fp, "%-12s (%3d,%3d) ", temp,
+                                     char_dat[j].last_point.x,
+                                     char_dat[j].last_point.y);
+                        }
+                        else
+                        {
+                            fprintf (fp2, "        <td>%s</td>\n", temp);
+                            fprintf (fp, "%-12s ", temp);
+                        }
+                    }
+                    // displaying number of zenys
+                    if (online_display_option & 32)
+                    {
+                        // write number of zenys
+                        if (char_dat[j].zeny == 0)
+                        {       // if no zeny
+                            fprintf (fp2,
+                                     "        <td ALIGN=RIGHT>no zeny</td>\n");
+                            fprintf (fp, "        no zeny ");
+                        }
+                        else
+                        {
+                            fprintf (fp2,
+                                     "        <td ALIGN=RIGHT>%d z</td>\n",
+                                     char_dat[j].zeny);
+                            fprintf (fp, "%13d z ", char_dat[j].zeny);
+                        }
+                    }
+                    fprintf (fp, "\n");
+                    fprintf (fp2, "      </tr>\n");
+                }
+                fprintf (fp2, "    </table>\n");
+                fprintf (fp, "\n");
+            }
+
+            // Displaying number of online players
+            if (players == 0)
+            {
+                fprintf (fp2, "    <p>No user is online.</p>\n");
+                fprintf (fp, "No user is online.\n");
+                // no display if only 1 player
+            }
+            else if (players == 1)
+            {
+            }
+            else
+            {
+                fprintf (fp2, "    <p>%d users are online.</p>\n", players);
+                fprintf (fp, "%d users are online.\n", players);
+            }
+            fprintf (fp2, "  </BODY>\n");
+            fprintf (fp2, "</HTML>\n");
+            fclose_ (fp2);
+        }
+        fclose_ (fp);
+    }
+
+    return;
+}
+
+//---------------------------------------------------------------------
+// This function return the number of online players in all map-servers
+//---------------------------------------------------------------------
+int count_users (void)
+{
+    int  i, users;
+
+    users = 0;
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+        if (server_fd[i] >= 0)
+            users += server[i].users;
+
+    return users;
+}
+
+//----------------------------------------
+// [Fate] Find inventory item based on equipment mask, return view.  ID must match view ID (!).
+//----------------------------------------
+static int find_equip_view (struct mmo_charstatus *p, unsigned int equipmask)
+{
+    int  i;
+    for (i = 0; i < MAX_INVENTORY; i++)
+        if (p->inventory[i].nameid && p->inventory[i].amount
+            && p->inventory[i].equip & equipmask)
+            return p->inventory[i].nameid;
+    return 0;
+}
+
+//----------------------------------------
+// Function to send characters to a player
+//----------------------------------------
+int mmo_char_send006b (int fd, struct char_session_data *sd)
+{
+    int  i, j, found_num;
+    struct mmo_charstatus *p;
+    const int offset = 24;
+
+    found_num = 0;
+    for (i = 0; i < char_num; i++)
+    {
+        if (char_dat[i].account_id == sd->account_id)
+        {
+            sd->found_char[found_num] = i;
+            found_num++;
+            if (found_num == 9)
+                break;
+        }
+    }
+    for (i = found_num; i < 9; i++)
+        sd->found_char[i] = -1;
+
+    memset (WFIFOP (fd, 0), 0, offset + found_num * 106);
+    WFIFOW (fd, 0) = 0x6b;
+    WFIFOW (fd, 2) = offset + found_num * 106;
+
+    for (i = 0; i < found_num; i++)
+    {
+        p = &char_dat[sd->found_char[i]];
+        j = offset + (i * 106); // increase speed of code
+
+        WFIFOL (fd, j) = p->char_id;
+        WFIFOL (fd, j + 4) = p->base_exp;
+        WFIFOL (fd, j + 8) = p->zeny;
+        WFIFOL (fd, j + 12) = p->job_exp;
+        WFIFOL (fd, j + 16) = 0;    //p->job_level; // [Fate] We no longer reveal this to the player, as its meaning is weird.
+
+        WFIFOW (fd, j + 20) = find_equip_view (p, 0x0040);  // 9: shoes
+        WFIFOW (fd, j + 22) = find_equip_view (p, 0x0004);  // 10: gloves
+        WFIFOW (fd, j + 24) = find_equip_view (p, 0x0008);  // 11: cape
+        WFIFOW (fd, j + 26) = find_equip_view (p, 0x0010);  // 12: misc1
+        WFIFOL (fd, j + 28) = p->option;
+
+        WFIFOL (fd, j + 32) = p->karma;
+        WFIFOL (fd, j + 36) = p->manner;
+
+        WFIFOW (fd, j + 40) = p->status_point;
+        WFIFOW (fd, j + 42) = (p->hp > 0x7fff) ? 0x7fff : p->hp;
+        WFIFOW (fd, j + 44) = (p->max_hp > 0x7fff) ? 0x7fff : p->max_hp;
+        WFIFOW (fd, j + 46) = (p->sp > 0x7fff) ? 0x7fff : p->sp;
+        WFIFOW (fd, j + 48) = (p->max_sp > 0x7fff) ? 0x7fff : p->max_sp;
+        WFIFOW (fd, j + 50) = DEFAULT_WALK_SPEED;   // p->speed;
+        WFIFOW (fd, j + 52) = p->pc_class;
+        WFIFOW (fd, j + 54) = p->hair;
+//      WFIFOW(fd,j+56) = p->weapon; // dont send weapon since TMW does not support it
+        WFIFOW (fd, j + 56) = 0;
+        WFIFOW (fd, j + 58) = p->base_level;
+        WFIFOW (fd, j + 60) = p->skill_point;
+        WFIFOW (fd, j + 62) = p->head_bottom;
+        WFIFOW (fd, j + 64) = p->shield;
+        WFIFOW (fd, j + 66) = p->head_top;
+        WFIFOW (fd, j + 68) = p->head_mid;
+        WFIFOW (fd, j + 70) = p->hair_color;
+        WFIFOW (fd, j + 72) = find_equip_view (p, 0x0080);  // 13: misc2
+//      WFIFOW(fd,j+72) = p->clothes_color;
+
+        memcpy (WFIFOP (fd, j + 74), p->name, 24);
+
+        WFIFOB (fd, j + 98) = (p->str > 255) ? 255 : p->str;
+        WFIFOB (fd, j + 99) = (p->agi > 255) ? 255 : p->agi;
+        WFIFOB (fd, j + 100) = (p->vit > 255) ? 255 : p->vit;
+        WFIFOB (fd, j + 101) = (p->int_ > 255) ? 255 : p->int_;
+        WFIFOB (fd, j + 102) = (p->dex > 255) ? 255 : p->dex;
+        WFIFOB (fd, j + 103) = (p->luk > 255) ? 255 : p->luk;
+        WFIFOB (fd, j + 104) = p->char_num;
+    }
+
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+int set_account_reg2 (int acc, int num, struct global_reg *reg)
+{
+    int  i, c;
+
+    c = 0;
+    for (i = 0; i < char_num; i++)
+    {
+        if (char_dat[i].account_id == acc)
+        {
+            memcpy (char_dat[i].account_reg2, reg,
+                    sizeof (char_dat[i].account_reg2));
+            char_dat[i].account_reg2_num = num;
+            c++;
+        }
+    }
+    return c;
+}
+
+// Divorce a character from it's partner and let the map server know
+int char_divorce (struct mmo_charstatus *cs)
+{
+    int  i;
+    char buf[10];
+
+    if (cs == NULL)
+        return 0;
+
+    if (cs->partner_id <= 0)
+    {
+        WBUFW (buf, 0) = 0x2b12;
+        WBUFL (buf, 2) = cs->char_id;
+        WBUFL (buf, 6) = 0;     // partner id 0 means failure
+        mapif_sendall (buf, 10);
+        return 0;
+    }
+
+    WBUFW (buf, 0) = 0x2b12;
+    WBUFL (buf, 2) = cs->char_id;
+
+    for (i = 0; i < char_num; i++)
+    {
+        if (char_dat[i].char_id == cs->partner_id
+            && char_dat[i].partner_id == cs->char_id)
+        {
+            WBUFL (buf, 6) = cs->partner_id;
+            mapif_sendall (buf, 10);
+            cs->partner_id = 0;
+            char_dat[i].partner_id = 0;
+            return 0;
+        }
+        // The other char doesn't have us as their partner, so just clear our partner
+        // Don't worry about this, as the map server should verify itself that the other doesn't have us as a partner, and so won't mess with their marriage
+        else if (char_dat[i].char_id == cs->partner_id)
+        {
+            WBUFL (buf, 6) = cs->partner_id;
+            mapif_sendall (buf, 10);
+            cs->partner_id = 0;
+            return 0;
+        }
+    }
+
+    // Our partner wasn't found, so just clear our marriage
+    WBUFL (buf, 6) = cs->partner_id;
+    cs->partner_id = 0;
+    mapif_sendall (buf, 10);
+
+    return 0;
+}
+
+//------------------------------------------------------------
+// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
+//------------------------------------------------------------
+int e_mail_check (unsigned char *email)
+{
+    char ch;
+    unsigned char *last_arobas;
+
+    // athena limits
+    if (strlen (email) < 3 || strlen (email) > 39)
+        return 0;
+
+    // part of RFC limits (official reference of e-mail description)
+    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
+        return 0;
+
+    if (email[strlen (email) - 1] == '.')
+        return 0;
+
+    last_arobas = strrchr (email, '@');
+
+    if (strstr (last_arobas, "@.") != NULL ||
+        strstr (last_arobas, "..") != NULL)
+        return 0;
+
+    for (ch = 1; ch < 32; ch++)
+    {
+        if (strchr (last_arobas, ch) != NULL)
+        {
+            return 0;
+            break;
+        }
+    }
+
+    if (strchr (last_arobas, ' ') != NULL ||
+        strchr (last_arobas, ';') != NULL)
+        return 0;
+
+    // all correct
+    return 1;
+}
+
+//----------------------------------------------------------------------
+// Force disconnection of an online player (with account value) by [Yor]
+//----------------------------------------------------------------------
+int disconnect_player (int accound_id)
+{
+    int  i;
+    struct char_session_data *sd;
+
+    // disconnect player if online on char-server
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
+        {
+            if (sd->account_id == accound_id)
+            {
+                session[i]->eof = 1;
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+// キャラ削除に伴うデータ削除
+static int char_delete (struct mmo_charstatus *cs)
+{
+
+    // ギルド脱退
+    if (cs->guild_id)
+        inter_guild_leave (cs->guild_id, cs->account_id, cs->char_id);
+    // パーティー脱退
+    if (cs->party_id)
+        inter_party_leave (cs->party_id, cs->account_id);
+    // 離婚
+    if (cs->partner_id)
+        char_divorce (cs);
+
+    // Force the character (and all on the same account) to leave all map servers
+    {
+        unsigned char buf[6];
+        WBUFW (buf, 0) = 0x2afe;
+        WBUFL (buf, 2) = cs->account_id;
+        mapif_sendall (buf, 6);
+    }
+
+    return 0;
+}
+
+void parse_tologin (int fd)
+{
+    int  i;
+    struct char_session_data *sd;
+
+    // only login-server can have an access to here.
+    // so, if it isn't the login-server, we disconnect the session (fd != login_fd).
+    if (fd != login_fd || session[fd]->eof)
+    {
+        if (fd == login_fd)
+        {
+            printf
+                ("Char-server can't connect to login-server (connection #%d).\n",
+                 fd);
+            login_fd = -1;
+        }
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    sd = (struct char_session_data*)session[fd]->session_data;
+
+    while (RFIFOREST (fd) >= 2)
+    {
+//      printf("parse_tologin: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
+
+        switch (RFIFOW (fd, 0))
+        {
+            case 0x2711:
+                if (RFIFOREST (fd) < 3)
+                    return;
+                if (RFIFOB (fd, 2))
+                {
+//              printf("connect login server error : %d\n", RFIFOB(fd,2));
+                    printf ("Can not connect to login-server.\n");
+                    printf
+                        ("The server communication passwords (default s1/p1) is probably invalid.\n");
+                    printf
+                        ("Also, please make sure your accounts file (default: accounts.txt) has those values present.\n");
+                    printf
+                        ("If you changed the communication passwords, change them back at map_athena.conf and char_athena.conf\n");
+                    exit (1);
+                }
+                else
+                {
+                    printf ("Connected to login-server (connection #%d).\n",
+                            fd);
+                    // if no map-server already connected, display a message...
+                    for (i = 0; i < MAX_MAP_SERVERS; i++)
+                        if (server_fd[i] >= 0 && server[i].map[0][0])   // if map-server online and at least 1 map
+                            break;
+                    if (i == MAX_MAP_SERVERS)
+                        printf ("Awaiting maps from map-server.\n");
+                }
+                RFIFOSKIP (fd, 3);
+                break;
+
+            case 0x2713:
+                if (RFIFOREST (fd) < 51)
+                    return;
+//          printf("parse_tologin 2713 : %d\n", RFIFOB(fd,6));
+                for (i = 0; i < fd_max; i++)
+                {
+                    if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)
+                        && sd->account_id == RFIFOL (fd, 2))
+                    {
+                        if (RFIFOB (fd, 6) != 0)
+                        {
+                            WFIFOW (i, 0) = 0x6c;
+                            WFIFOB (i, 2) = 0x42;
+                            WFIFOSET (i, 3);
+                        }
+                        else if (max_connect_user == 0
+                                 || count_users () < max_connect_user)
+                        {
+//                      if (max_connect_user == 0)
+//                          printf("max_connect_user (unlimited) -> accepted.\n");
+//                      else
+//                          printf("count_users(): %d < max_connect_user (%d) -> accepted.\n", count_users(), max_connect_user);
+                            memcpy (sd->email, RFIFOP (fd, 7), 40);
+                            if (e_mail_check (sd->email) == 0)
+                                strncpy (sd->email, "a@a.com", 40); // default e-mail
+                            sd->connect_until_time = (time_t) RFIFOL (fd, 47);
+                            // send characters to player
+                            mmo_char_send006b (i, sd);
+                        }
+                        else
+                        {
+                            // refuse connection: too much online players
+//                      printf("count_users(): %d < max_connect_use (%d) -> fail...\n", count_users(), max_connect_user);
+                            WFIFOW (i, 0) = 0x6c;
+                            WFIFOW (i, 2) = 0;
+                            WFIFOSET (i, 3);
+                        }
+                        break;
+                    }
+                }
+                RFIFOSKIP (fd, 51);
+                break;
+
+                // Receiving of an e-mail/time limit from the login-server (answer of a request because a player comes back from map-server to char-server) by [Yor]
+            case 0x2717:
+                if (RFIFOREST (fd) < 50)
+                    return;
+                for (i = 0; i < fd_max; i++)
+                {
+                    if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
+                    {
+                        if (sd->account_id == RFIFOL (fd, 2))
+                        {
+                            memcpy (sd->email, RFIFOP (fd, 6), 40);
+                            if (e_mail_check (sd->email) == 0)
+                                strncpy (sd->email, "a@a.com", 40); // default e-mail
+                            sd->connect_until_time = (time_t) RFIFOL (fd, 46);
+                            break;
+                        }
+                    }
+                }
+                RFIFOSKIP (fd, 50);
+                break;
+
+            case 0x2721:       // gm reply
+                if (RFIFOREST (fd) < 10)
+                    return;
+                {
+                    unsigned char buf[10];
+                    WBUFW (buf, 0) = 0x2b0b;
+                    WBUFL (buf, 2) = RFIFOL (fd, 2);    // account
+                    WBUFL (buf, 6) = RFIFOL (fd, 6);    // GM level
+                    mapif_sendall (buf, 10);
+//          printf("parse_tologin: To become GM answer: char -> map.\n");
+                }
+                RFIFOSKIP (fd, 10);
+                break;
+
+            case 0x2723:       // changesex reply (modified by [Yor])
+                if (RFIFOREST (fd) < 7)
+                    return;
+                {
+                    int  acc, sex, i, j;
+                    unsigned char buf[7];
+                    acc = RFIFOL (fd, 2);
+                    sex = RFIFOB (fd, 6);
+                    RFIFOSKIP (fd, 7);
+                    if (acc > 0)
+                    {
+                        for (i = 0; i < char_num; i++)
+                        {
+                            if (char_dat[i].account_id == acc)
+                            {
+                                int  jobclass = char_dat[i].pc_class;
+                                char_dat[i].sex = sex;
+//                      auth_fifo[i].sex = sex;
+                                if (jobclass == 19 || jobclass == 20 ||
+                                    jobclass == 4020 || jobclass == 4021 ||
+                                    jobclass == 4042 || jobclass == 4043)
+                                {
+                                    // job modification
+                                    if (jobclass == 19 || jobclass == 20)
+                                    {
+                                        char_dat[i].pc_class = (sex) ? 19 : 20;
+                                    }
+                                    else if (jobclass == 4020
+                                             || jobclass == 4021)
+                                    {
+                                        char_dat[i].pc_class =
+                                            (sex) ? 4020 : 4021;
+                                    }
+                                    else if (jobclass == 4042
+                                             || jobclass == 4043)
+                                    {
+                                        char_dat[i].pc_class =
+                                            (sex) ? 4042 : 4043;
+                                    }
+                                }
+                                // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+                                for (j = 0; j < MAX_INVENTORY; j++)
+                                {
+                                    if (char_dat[i].inventory[j].nameid
+                                        && char_dat[i].inventory[j].equip)
+                                        char_dat[i].inventory[j].equip = 0;
+                                }
+                                char_dat[i].weapon = 0;
+                                char_dat[i].shield = 0;
+                                char_dat[i].head_top = 0;
+                                char_dat[i].head_mid = 0;
+                                char_dat[i].head_bottom = 0;
+                            }
+                        }
+                        // disconnect player if online on char-server
+                        disconnect_player (acc);
+                    }
+                    WBUFW (buf, 0) = 0x2b0d;
+                    WBUFL (buf, 2) = acc;
+                    WBUFB (buf, 6) = sex;
+                    mapif_sendall (buf, 7);
+                }
+                break;
+
+            case 0x2726:       // Request to send a broadcast message (no answer)
+                if (RFIFOREST (fd) < 8
+                    || RFIFOREST (fd) < (8 + RFIFOL (fd, 4)))
+                    return;
+                if (RFIFOL (fd, 4) < 1)
+                    char_log
+                        ("Receiving a message for broadcast, but message is void.\n");
+                else
+                {
+                    // at least 1 map-server
+                    for (i = 0; i < MAX_MAP_SERVERS; i++)
+                        if (server_fd[i] >= 0)
+                            break;
+                    if (i == MAX_MAP_SERVERS)
+                        char_log
+                            ("'ladmin': Receiving a message for broadcast, but no map-server is online.\n");
+                    else
+                    {
+                        char buf[128];
+                        char message[RFIFOL (fd, 4) + 1];   // +1 to add a null terminated if not exist in the packet
+                        int  lp;
+                        char *p;
+                        memset (message, '\0', sizeof (message));
+                        memcpy (message, RFIFOP (fd, 8), RFIFOL (fd, 4));
+                        message[sizeof (message) - 1] = '\0';
+                        remove_control_chars (message);
+                        // remove all first spaces
+                        p = message;
+                        while (p[0] == ' ')
+                            p++;
+                        // if message is only composed of spaces
+                        if (p[0] == '\0')
+                            char_log
+                                ("Receiving a message for broadcast, but message is only a lot of spaces.\n");
+                        // else send message to all map-servers
+                        else
+                        {
+                            if (RFIFOW (fd, 2) == 0)
+                            {
+                                char_log
+                                    ("'ladmin': Receiving a message for broadcast (message (in yellow): %s)\n",
+                                     message);
+                                lp = 4;
+                            }
+                            else
+                            {
+                                char_log
+                                    ("'ladmin': Receiving a message for broadcast (message (in blue): %s)\n",
+                                     message);
+                                lp = 8;
+                            }
+                            // split message to max 80 char
+                            while (p[0] != '\0')
+                            {   // if not finish
+                                if (p[0] == ' ')    // jump if first char is a space
+                                    p++;
+                                else
+                                {
+                                    char split[80];
+                                    char *last_space;
+                                    sscanf (p, "%79[^\t]", split);  // max 79 char, any char (\t is control char and control char was removed before)
+                                    split[sizeof (split) - 1] = '\0';   // last char always \0
+                                    if ((last_space =
+                                         strrchr (split, ' ')) != NULL)
+                                    {   // searching space from end of the string
+                                        last_space[0] = '\0';   // replace it by NULL to have correct length of split
+                                        p++;    // to jump the new NULL
+                                    }
+                                    p += strlen (split);
+                                    // send broadcast to all map-servers
+                                    WBUFW (buf, 0) = 0x3800;
+                                    WBUFW (buf, 2) = lp + strlen (split) + 1;
+                                    WBUFL (buf, 4) = 0x65756c62;    // only write if in blue (lp = 8)
+                                    memcpy (WBUFP (buf, lp), split,
+                                            strlen (split) + 1);
+                                    mapif_sendall (buf, WBUFW (buf, 2));
+                                }
+                            }
+                        }
+                    }
+                }
+                RFIFOSKIP (fd, 8 + RFIFOL (fd, 4));
+                break;
+
+                // account_reg2変更通知
+            case 0x2729:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    struct global_reg reg[ACCOUNT_REG2_NUM];
+                    unsigned char buf[4096];
+                    int  j, p, acc;
+                    acc = RFIFOL (fd, 4);
+                    for (p = 8, j = 0;
+                         p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
+                         p += 36, j++)
+                    {
+                        memcpy (reg[j].str, RFIFOP (fd, p), 32);
+                        reg[j].value = RFIFOL (fd, p + 32);
+                    }
+                    set_account_reg2 (acc, j, reg);
+                    // 同垢ログインを禁止していれば送る必要は無い
+                    memcpy (buf, RFIFOP (fd, 0), RFIFOW (fd, 2));
+                    WBUFW (buf, 0) = 0x2b11;
+                    mapif_sendall (buf, WBUFW (buf, 2));
+                    RFIFOSKIP (fd, RFIFOW (fd, 2));
+//          printf("char: save_account_reg_reply\n");
+                }
+                break;
+
+            case 0x7924:
+            {                   // [Fate] Itemfrob package: forwarded from login-server
+                if (RFIFOREST (fd) < 10)
+                    return;
+                int  source_id = RFIFOL (fd, 2);
+                int  dest_id = RFIFOL (fd, 6);
+                unsigned char buf[10];
+
+                WBUFW (buf, 0) = 0x2afa;
+                WBUFL (buf, 2) = source_id;
+                WBUFL (buf, 6) = dest_id;
+
+                mapif_sendall (buf, 10);    // forward package to map servers
+                for (i = 0; i < char_num; i++)
+                {
+                    struct mmo_charstatus *c = char_dat + i;
+                    struct storage *s = account2storage (c->account_id);
+                    int  changes = 0;
+                    int  j;
+#define FIX(v) if (v == source_id) {v = dest_id; ++changes; }
+                    for (j = 0; j < MAX_INVENTORY; j++)
+                        FIX (c->inventory[j].nameid);
+                    for (j = 0; j < MAX_CART; j++)
+                        FIX (c->cart[j].nameid);
+                    FIX (c->weapon);
+                    FIX (c->shield);
+                    FIX (c->head_top);
+                    FIX (c->head_mid);
+                    FIX (c->head_bottom);
+
+                    if (s)
+                        for (j = 0; j < s->storage_amount; j++)
+                            FIX (s->storage_[j].nameid);
+#undef FIX
+                    if (changes)
+                        char_log
+                            ("itemfrob(%d -> %d):  `%s'(%d, account %d): changed %d times\n",
+                             source_id, dest_id, c->name, c->char_id,
+                             c->account_id, changes);
+
+                }
+
+                mmo_char_sync ();
+                inter_storage_save ();
+                RFIFOSKIP (fd, 10);
+                break;
+            }
+
+                // Account deletion notification (from login-server)
+            case 0x2730:
+                if (RFIFOREST (fd) < 6)
+                    return;
+                // Deletion of all characters of the account
+                for (i = 0; i < char_num; i++)
+                {
+                    if (char_dat[i].account_id == RFIFOL (fd, 2))
+                    {
+                        char_delete (&char_dat[i]);
+                        if (i < char_num - 1)
+                        {
+                            memcpy (&char_dat[i], &char_dat[char_num - 1],
+                                    sizeof (struct mmo_charstatus));
+                            // if moved character owns to deleted account, check again it's character
+                            if (char_dat[i].account_id == RFIFOL (fd, 2))
+                            {
+                                i--;
+                                // Correct moved character reference in the character's owner by [Yor]
+                            }
+                            else
+                            {
+                                int  j, k;
+                                struct char_session_data *sd2;
+                                for (j = 0; j < fd_max; j++)
+                                {
+                                    if (session[j]
+                                        && (sd2 = (struct char_session_data*)session[j]->session_data)
+                                        && sd2->account_id ==
+                                        char_dat[char_num - 1].account_id)
+                                    {
+                                        for (k = 0; k < 9; k++)
+                                        {
+                                            if (sd2->found_char[k] ==
+                                                char_num - 1)
+                                            {
+                                                sd2->found_char[k] = i;
+                                                break;
+                                            }
+                                        }
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        char_num--;
+                    }
+                }
+                // Deletion of the storage
+                inter_storage_delete (RFIFOL (fd, 2));
+                // send to all map-servers to disconnect the player
+                {
+                    unsigned char buf[6];
+                    WBUFW (buf, 0) = 0x2b13;
+                    WBUFL (buf, 2) = RFIFOL (fd, 2);
+                    mapif_sendall (buf, 6);
+                }
+                // disconnect player if online on char-server
+                disconnect_player (RFIFOL (fd, 2));
+                RFIFOSKIP (fd, 6);
+                break;
+
+                // State change of account/ban notification (from login-server) by [Yor]
+            case 0x2731:
+                if (RFIFOREST (fd) < 11)
+                    return;
+                // send to all map-servers to disconnect the player
+                {
+                    unsigned char buf[11];
+                    WBUFW (buf, 0) = 0x2b14;
+                    WBUFL (buf, 2) = RFIFOL (fd, 2);
+                    WBUFB (buf, 6) = RFIFOB (fd, 6);    // 0: change of statut, 1: ban
+                    WBUFL (buf, 7) = RFIFOL (fd, 7);    // status or final date of a banishment
+                    mapif_sendall (buf, 11);
+                }
+                // disconnect player if online on char-server
+                disconnect_player (RFIFOL (fd, 2));
+                RFIFOSKIP (fd, 11);
+                break;
+
+                // Receiving GM acounts info from login-server (by [Yor])
+            case 0x2732:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    char buf[32000];
+                    if (gm_account != NULL)
+                        free (gm_account);
+                    CREATE (gm_account, struct gm_account, (RFIFOW (fd, 2) - 4) / 5);
+                    GM_num = 0;
+                    for (i = 4; i < RFIFOW (fd, 2); i = i + 5)
+                    {
+                        gm_account[GM_num].account_id = RFIFOL (fd, i);
+                        gm_account[GM_num].level = (int) RFIFOB (fd, i + 4);
+                        //printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
+                        GM_num++;
+                    }
+                    printf
+                        ("From login-server: receiving of %d GM accounts information.\n",
+                         GM_num);
+                    char_log
+                        ("From login-server: receiving of %d GM accounts information.\n",
+                         GM_num);
+                    create_online_files (); // update online players files (perhaps some online players change of GM level)
+                    // send new gm acccounts level to map-servers
+                    memcpy (buf, RFIFOP (fd, 0), RFIFOW (fd, 2));
+                    WBUFW (buf, 0) = 0x2b15;
+                    mapif_sendall (buf, RFIFOW (fd, 2));
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+            case 0x2741:       // change password reply
+                if (RFIFOREST (fd) < 7)
+                    return;
+                {
+                    int  acc, status, i;
+                    acc = RFIFOL (fd, 2);
+                    status = RFIFOB (fd, 6);
+
+                    for (i = 0; i < fd_max; i++)
+                    {
+                        if (session[i] && (sd = (struct char_session_data*)session[i]->session_data))
+                        {
+                            if (sd->account_id == acc)
+                            {
+                                WFIFOW (i, 0) = 0x62;
+                                WFIFOB (i, 2) = status;
+                                WFIFOSET (i, 3);
+                                break;
+                            }
+                        }
+                    }
+                }
+                RFIFOSKIP (fd, 7);
+                break;
+
+            default:
+                session[fd]->eof = 1;
+                return;
+        }
+    }
+    RFIFOFLUSH (fd);
+}
+
+//--------------------------------
+// Map-server anti-freeze system
+//--------------------------------
+void map_anti_freeze_system (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  i;
+
+    //printf("Entering in map_anti_freeze_system function to check freeze of servers.\n");
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+    {
+        if (server_fd[i] >= 0)
+        {                       // if map-server is online
+            //printf("map_anti_freeze_system: server #%d, flag: %d.\n", i, server_freezeflag[i]);
+            if (server_freezeflag[i]-- < 1)
+            {                   // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+                printf
+                    ("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n",
+                     i);
+                char_log
+                    ("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n",
+                     i);
+                session[server_fd[i]]->eof = 1;
+            }
+        }
+    }
+}
+
+void parse_frommap (int fd)
+{
+    int  i, j;
+    int  id;
+
+    for (id = 0; id < MAX_MAP_SERVERS; id++)
+        if (server_fd[id] == fd)
+            break;
+    if (id == MAX_MAP_SERVERS || session[fd]->eof)
+    {
+        if (id < MAX_MAP_SERVERS)
+        {
+            printf ("Map-server %d (session #%d) has disconnected.\n", id,
+                    fd);
+            memset (&server[id], 0, sizeof (struct mmo_map_server));
+            server_fd[id] = -1;
+            for (j = 0; j < char_num; j++)
+                if (online_chars[j] == fd)
+                    online_chars[j] = -1;
+            create_online_files (); // update online players files (to remove all online players of this server)
+        }
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    while (RFIFOREST (fd) >= 2)
+    {
+//      printf("parse_frommap: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
+
+        switch (RFIFOW (fd, 0))
+        {
+                // request from map-server to reload GM accounts. Transmission to login-server (by Yor)
+            case 0x2af7:
+                if (login_fd > 0)
+                {               // don't send request if no login-server
+                    WFIFOW (login_fd, 0) = 0x2709;
+                    WFIFOSET (login_fd, 2);
+//              printf("char : request from map-server to reload GM accounts -> login-server.\n");
+                }
+                RFIFOSKIP (fd, 2);
+                break;
+
+                // Receiving map names list from the map-server
+            case 0x2afa:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                memset (server[id].map, 0, sizeof (server[id].map));
+                j = 0;
+                for (i = 4; i < RFIFOW (fd, 2); i += 16)
+                {
+                    memcpy (server[id].map[j], RFIFOP (fd, i), 16);
+//              printf("set map %d.%d : %s\n", id, j, server[id].map[j]);
+                    j++;
+                }
+                {
+                    unsigned char *p = (unsigned char *) &server[id].ip;
+                    printf
+                        ("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
+                         id, j, p[0], p[1], p[2], p[3], server[id].port);
+                    printf ("Map-server %d loading complete.\n", id);
+                    char_log
+                        ("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d. Map-server %d loading complete.\n",
+                         id, j, p[0], p[1], p[2], p[3],
+                         server[id].port, id);
+                }
+                WFIFOW (fd, 0) = 0x2afb;
+                WFIFOB (fd, 2) = 0;
+                memcpy (WFIFOP (fd, 3), wisp_server_name, 24);  // name for wisp to player
+                WFIFOSET (fd, 27);
+                {
+                    unsigned char buf[16384];
+                    int  x;
+                    if (j == 0)
+                    {
+                        printf ("WARNING: Map-Server %d have NO map.\n", id);
+                        char_log ("WARNING: Map-Server %d have NO map.\n",
+                                  id);
+                        // Transmitting maps information to the other map-servers
+                    }
+                    else
+                    {
+                        WBUFW (buf, 0) = 0x2b04;
+                        WBUFW (buf, 2) = j * 16 + 10;
+                        WBUFL (buf, 4) = server[id].ip;
+                        WBUFW (buf, 8) = server[id].port;
+                        memcpy (WBUFP (buf, 10), RFIFOP (fd, 4), j * 16);
+                        mapif_sendallwos (fd, buf, WBUFW (buf, 2));
+                    }
+                    // Transmitting the maps of the other map-servers to the new map-server
+                    for (x = 0; x < MAX_MAP_SERVERS; x++)
+                    {
+                        if (server_fd[x] >= 0 && x != id)
+                        {
+                            WFIFOW (fd, 0) = 0x2b04;
+                            WFIFOL (fd, 4) = server[x].ip;
+                            WFIFOW (fd, 8) = server[x].port;
+                            j = 0;
+                            for (i = 0; i < MAX_MAP_PER_SERVER; i++)
+                                if (server[x].map[i][0])
+                                    memcpy (WFIFOP (fd, 10 + (j++) * 16),
+                                            server[x].map[i], 16);
+                            if (j > 0)
+                            {
+                                WFIFOW (fd, 2) = j * 16 + 10;
+                                WFIFOSET (fd, WFIFOW (fd, 2));
+                            }
+                        }
+                    }
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+                // 認証要求
+            case 0x2afc:
+                if (RFIFOREST (fd) < 22)
+                    return;
+                //printf("auth_fifo search: account: %d, char: %d, secure: %08x-%08x\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14));
+                for (i = 0; i < AUTH_FIFO_SIZE; i++)
+                {
+                    if (auth_fifo[i].account_id == RFIFOL (fd, 2) &&
+                        auth_fifo[i].char_id == RFIFOL (fd, 6) &&
+                        auth_fifo[i].login_id1 == RFIFOL (fd, 10) &&
+#if CMP_AUTHFIFO_LOGIN2 != 0
+                        // here, it's the only area where it's possible that we doesn't know login_id2 (map-server asks just after 0x72 packet, that doesn't given the value)
+                        (auth_fifo[i].login_id2 == RFIFOL (fd, 14) || RFIFOL (fd, 14) == 0) &&  // relate to the versions higher than 18
+#endif
+                        (!check_ip_flag || auth_fifo[i].ip == RFIFOL (fd, 18))
+                        && !auth_fifo[i].delflag)
+                    {
+                        auth_fifo[i].delflag = 1;
+                        WFIFOW (fd, 0) = 0x2afd;
+                        WFIFOW (fd, 2) = 18 + sizeof (struct mmo_charstatus);
+                        WFIFOL (fd, 4) = RFIFOL (fd, 2);
+                        WFIFOL (fd, 8) = auth_fifo[i].login_id2;
+                        WFIFOL (fd, 12) =
+                            (unsigned long) auth_fifo[i].connect_until_time;
+                        char_dat[auth_fifo[i].char_pos].sex =
+                            auth_fifo[i].sex;
+                        WFIFOW (fd, 16) = auth_fifo[i].packet_tmw_version;
+                        fprintf (stderr,
+                                 "From queue index %d: recalling packet version %d\n",
+                                 i, auth_fifo[i].packet_tmw_version);
+                        memcpy (WFIFOP (fd, 18),
+                                &char_dat[auth_fifo[i].char_pos],
+                                sizeof (struct mmo_charstatus));
+                        WFIFOSET (fd, WFIFOW (fd, 2));
+                        //printf("auth_fifo search success (auth #%d, account %d, character: %d).\n", i, RFIFOL(fd,2), RFIFOL(fd,6));
+                        break;
+                    }
+                }
+                if (i == AUTH_FIFO_SIZE)
+                {
+                    WFIFOW (fd, 0) = 0x2afe;
+                    WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                    WFIFOSET (fd, 6);
+                    printf
+                        ("auth_fifo search error! account %d not authentified.\n",
+                         RFIFOL (fd, 2));
+                }
+                RFIFOSKIP (fd, 22);
+                break;
+
+                // MAPサーバー上のユーザー数受信
+            case 0x2aff:
+                if (RFIFOREST (fd) < 6 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                server[id].users = RFIFOW (fd, 4);
+                if (anti_freeze_enable)
+                    server_freezeflag[id] = 5;  // Map anti-freeze system. Counter. 5 ok, 4...0 freezed
+                // remove all previously online players of the server
+                for (i = 0; i < char_num; i++)
+                    if (online_chars[i] == id)
+                        online_chars[i] = -1;
+                // add online players in the list by [Yor]
+                for (i = 0; i < server[id].users; i++)
+                {
+                    int  char_id = RFIFOL (fd, 6 + i * 4);
+                    for (j = 0; j < char_num; j++)
+                        if (char_dat[j].char_id == char_id)
+                        {
+                            online_chars[j] = id;
+                            //printf("%d\n", char_id);
+                            break;
+                        }
+                }
+                if (update_online < time (NULL))
+                {               // Time is done
+                    update_online = time (NULL) + 8;
+                    create_online_files (); // only every 8 sec. (normally, 1 server send users every 5 sec.) Don't update every time, because that takes time, but only every 2 connection.
+                    // it set to 8 sec because is more than 5 (sec) and if we have more than 1 map-server, informations can be received in shifted.
+                }
+                RFIFOSKIP (fd, 6 + i * 4);
+                break;
+
+                // キャラデータ保存
+            case 0x2b01:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                for (i = 0; i < char_num; i++)
+                {
+                    if (char_dat[i].account_id == RFIFOL (fd, 4) &&
+                        char_dat[i].char_id == RFIFOL (fd, 8))
+                        break;
+                }
+                if (i != char_num)
+                    memcpy (&char_dat[i], RFIFOP (fd, 12),
+                            sizeof (struct mmo_charstatus));
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+                // キャラセレ要求
+            case 0x2b02:
+                if (RFIFOREST (fd) < 18)
+                    return;
+                if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+                    auth_fifo_pos = 0;
+                //printf("auth_fifo set (auth #%d) - account: %d, secure: %08x-%08x\n", auth_fifo_pos, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
+                auth_fifo[auth_fifo_pos].account_id = RFIFOL (fd, 2);
+                auth_fifo[auth_fifo_pos].char_id = 0;
+                auth_fifo[auth_fifo_pos].login_id1 = RFIFOL (fd, 6);
+                auth_fifo[auth_fifo_pos].login_id2 = RFIFOL (fd, 10);
+                auth_fifo[auth_fifo_pos].delflag = 2;
+                auth_fifo[auth_fifo_pos].char_pos = 0;
+                auth_fifo[auth_fifo_pos].connect_until_time = 0;    // unlimited/unknown time by default (not display in map-server)
+                auth_fifo[auth_fifo_pos].ip = RFIFOL (fd, 14);
+                auth_fifo_pos++;
+                WFIFOW (fd, 0) = 0x2b03;
+                WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                WFIFOB (fd, 6) = 0;
+                WFIFOSET (fd, 7);
+                RFIFOSKIP (fd, 18);
+                break;
+
+                // マップサーバー間移動要求
+            case 0x2b05:
+                if (RFIFOREST (fd) < 49)
+                    return;
+                if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+                    auth_fifo_pos = 0;
+                WFIFOW (fd, 0) = 0x2b06;
+                memcpy (WFIFOP (fd, 2), RFIFOP (fd, 2), 42);
+                //printf("auth_fifo set (auth#%d) - account: %d, secure: 0x%08x-0x%08x\n", auth_fifo_pos, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10));
+                auth_fifo[auth_fifo_pos].account_id = RFIFOL (fd, 2);
+                auth_fifo[auth_fifo_pos].char_id = RFIFOL (fd, 14);
+                auth_fifo[auth_fifo_pos].login_id1 = RFIFOL (fd, 6);
+                auth_fifo[auth_fifo_pos].login_id2 = RFIFOL (fd, 10);
+                auth_fifo[auth_fifo_pos].delflag = 0;
+                auth_fifo[auth_fifo_pos].sex = RFIFOB (fd, 44);
+                auth_fifo[auth_fifo_pos].connect_until_time = 0;    // unlimited/unknown time by default (not display in map-server)
+                auth_fifo[auth_fifo_pos].ip = RFIFOL (fd, 45);
+                for (i = 0; i < char_num; i++)
+                    if (char_dat[i].account_id == RFIFOL (fd, 2) &&
+                        char_dat[i].char_id == RFIFOL (fd, 14))
+                    {
+                        auth_fifo[auth_fifo_pos].char_pos = i;
+                        auth_fifo_pos++;
+                        WFIFOL (fd, 6) = 0;
+                        break;
+                    }
+                if (i == char_num)
+                    WFIFOW (fd, 6) = 1;
+                WFIFOSET (fd, 44);
+                RFIFOSKIP (fd, 49);
+                break;
+
+                // キャラ名検索
+            case 0x2b08:
+                if (RFIFOREST (fd) < 6)
+                    return;
+                for (i = 0; i < char_num; i++)
+                {
+                    if (char_dat[i].char_id == RFIFOL (fd, 2))
+                        break;
+                }
+                WFIFOW (fd, 0) = 0x2b09;
+                WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                if (i != char_num)
+                    memcpy (WFIFOP (fd, 6), char_dat[i].name, 24);
+                else
+                    memcpy (WFIFOP (fd, 6), unknown_char_name, 24);
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 6);
+                break;
+
+                // it is a request to become GM
+            case 0x2b0a:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+//          printf("parse_frommap: change gm -> login, account: %d, pass: '%s'.\n", RFIFOL(fd,4), RFIFOP(fd,8));
+                if (login_fd > 0)
+                {               // don't send request if no login-server
+                    WFIFOW (login_fd, 0) = 0x2720;
+                    memcpy (WFIFOP (login_fd, 2), RFIFOP (fd, 2),
+                            RFIFOW (fd, 2) - 2);
+                    WFIFOSET (login_fd, RFIFOW (fd, 2));
+                }
+                else
+                {
+                    WFIFOW (fd, 0) = 0x2b0b;
+                    WFIFOL (fd, 2) = RFIFOL (fd, 4);
+                    WFIFOL (fd, 6) = 0;
+                    WFIFOSET (fd, 10);
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+                // Map server send information to change an email of an account -> login-server
+            case 0x2b0c:
+                if (RFIFOREST (fd) < 86)
+                    return;
+                if (login_fd > 0)
+                {               // don't send request if no login-server
+                    memcpy (WFIFOP (login_fd, 0), RFIFOP (fd, 0), 86);  // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
+                    WFIFOW (login_fd, 0) = 0x2722;
+                    WFIFOSET (login_fd, 86);
+                }
+                RFIFOSKIP (fd, 86);
+                break;
+
+                // Map server ask char-server about a character name to do some operations (all operations are transmitted to login-server)
+            case 0x2b0e:
+                if (RFIFOREST (fd) < 44)
+                    return;
+                {
+                    char character_name[24];
+                    int  acc = RFIFOL (fd, 2);  // account_id of who ask (-1 if nobody)
+                    memcpy (character_name, RFIFOP (fd, 6), 24);
+                    character_name[sizeof (character_name) - 1] = '\0';
+                    // prepare answer
+                    WFIFOW (fd, 0) = 0x2b0f;    // answer
+                    WFIFOL (fd, 2) = acc;   // who want do operation
+                    WFIFOW (fd, 30) = RFIFOW (fd, 30);  // type of operation: 1-block, 2-ban, 3-unblock, 4-unban, 5-changesex
+                    // search character
+                    i = search_character_index (character_name);
+                    if (i >= 0)
+                    {
+                        memcpy (WFIFOP (fd, 6), search_character_name (i), 24); // put correct name if found
+                        WFIFOW (fd, 32) = 0;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                        switch (RFIFOW (fd, 30))
+                        {
+                            case 1:    // block
+                                if (acc == -1
+                                    || isGM (acc) >=
+                                    isGM (char_dat[i].account_id))
+                                {
+                                    if (login_fd > 0)
+                                    {   // don't send request if no login-server
+                                        WFIFOW (login_fd, 0) = 0x2724;
+                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
+                                        WFIFOL (login_fd, 6) = 5;   // status of the account
+                                        WFIFOSET (login_fd, 10);
+//                          printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 5);
+                                    }
+                                    else
+                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                }
+                                else
+                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                break;
+                            case 2:    // ban
+                                if (acc == -1
+                                    || isGM (acc) >=
+                                    isGM (char_dat[i].account_id))
+                                {
+                                    if (login_fd > 0)
+                                    {   // don't send request if no login-server
+                                        WFIFOW (login_fd, 0) = 0x2725;
+                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
+                                        WFIFOW (login_fd, 6) = RFIFOW (fd, 32); // year
+                                        WFIFOW (login_fd, 8) = RFIFOW (fd, 34); // month
+                                        WFIFOW (login_fd, 10) = RFIFOW (fd, 36);    // day
+                                        WFIFOW (login_fd, 12) = RFIFOW (fd, 38);    // hour
+                                        WFIFOW (login_fd, 14) = RFIFOW (fd, 40);    // minute
+                                        WFIFOW (login_fd, 16) = RFIFOW (fd, 42);    // second
+                                        WFIFOSET (login_fd, 18);
+//                          printf("char : status -> login: account %d, ban: %dy %dm %dd %dh %dmn %ds\n",
+//                                 char_dat[i].account_id, (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), (short)RFIFOW(fd,38), (short)RFIFOW(fd,40), (short)RFIFOW(fd,42));
+                                    }
+                                    else
+                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                }
+                                else
+                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                break;
+                            case 3:    // unblock
+                                if (acc == -1
+                                    || isGM (acc) >=
+                                    isGM (char_dat[i].account_id))
+                                {
+                                    if (login_fd > 0)
+                                    {   // don't send request if no login-server
+                                        WFIFOW (login_fd, 0) = 0x2724;
+                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
+                                        WFIFOL (login_fd, 6) = 0;   // status of the account
+                                        WFIFOSET (login_fd, 10);
+//                          printf("char : status -> login: account %d, status: %d \n", char_dat[i].account_id, 0);
+                                    }
+                                    else
+                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                }
+                                else
+                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                break;
+                            case 4:    // unban
+                                if (acc == -1
+                                    || isGM (acc) >=
+                                    isGM (char_dat[i].account_id))
+                                {
+                                    if (login_fd > 0)
+                                    {   // don't send request if no login-server
+                                        WFIFOW (login_fd, 0) = 0x272a;
+                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
+                                        WFIFOSET (login_fd, 6);
+//                          printf("char : status -> login: account %d, unban request\n", char_dat[i].account_id);
+                                    }
+                                    else
+                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                }
+                                else
+                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                break;
+                            case 5:    // changesex
+                                if (acc == -1
+                                    || isGM (acc) >=
+                                    isGM (char_dat[i].account_id))
+                                {
+                                    if (login_fd > 0)
+                                    {   // don't send request if no login-server
+                                        WFIFOW (login_fd, 0) = 0x2727;
+                                        WFIFOL (login_fd, 2) = char_dat[i].account_id;  // account value
+                                        WFIFOSET (login_fd, 6);
+//                          printf("char : status -> login: account %d, change sex request\n", char_dat[i].account_id);
+                                    }
+                                    else
+                                        WFIFOW (fd, 32) = 3;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                }
+                                else
+                                    WFIFOW (fd, 32) = 2;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                                break;
+                        }
+                    }
+                    else
+                    {
+                        // character name not found
+                        memcpy (WFIFOP (fd, 6), character_name, 24);
+                        WFIFOW (fd, 32) = 1;    // answer: 0-login-server resquest done, 1-player not found, 2-gm level too low, 3-login-server offline
+                    }
+                    // send answer if a player ask, not if the server ask
+                    if (acc != -1)
+                    {
+                        WFIFOSET (fd, 34);
+                    }
+                    RFIFOSKIP (fd, 44);
+                    break;
+                }
+
+//      case 0x2b0f: not more used (available for futur usage)
+
+                // account_reg保存要求
+            case 0x2b10:
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    struct global_reg reg[ACCOUNT_REG2_NUM];
+                    int  p, acc;
+                    acc = RFIFOL (fd, 4);
+                    for (p = 8, j = 0;
+                         p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
+                         p += 36, j++)
+                    {
+                        memcpy (reg[j].str, RFIFOP (fd, p), 32);
+                        reg[j].value = RFIFOL (fd, p + 32);
+                    }
+                    set_account_reg2 (acc, j, reg);
+                    // loginサーバーへ送る
+                    if (login_fd > 0)
+                    {           // don't send request if no login-server
+                        memcpy (WFIFOP (login_fd, 0), RFIFOP (fd, 0),
+                                RFIFOW (fd, 2));
+                        WFIFOW (login_fd, 0) = 0x2728;
+                        WFIFOSET (login_fd, WFIFOW (login_fd, 2));
+                    }
+                    // ワールドへの同垢ログインがなければmapサーバーに送る必要はない
+                    //memcpy(buf, RFIFOP(fd,0), RFIFOW(fd,2));
+                    //WBUFW(buf,0) = 0x2b11;
+                    //mapif_sendall(buf, WBUFW(buf,2));
+                    RFIFOSKIP (fd, RFIFOW (fd, 2));
+//          printf("char: save_account_reg (from map)\n");
+                    break;
+                }
+
+                // Map server is requesting a divorce
+            case 0x2b16:
+                if (RFIFOREST (fd) < 4)
+                    return;
+                {
+                    for (i = 0; i < char_num; i++)
+                        if (char_dat[i].char_id == RFIFOL (fd, 2))
+                            break;
+
+                    if (i != char_num)
+                        char_divorce (&char_dat[i]);
+
+                    RFIFOSKIP (fd, 6);
+                    break;
+
+                }
+
+            default:
+                // inter server処理に渡す
+            {
+                int  r = inter_parse_frommap (fd);
+                if (r == 1)     // 処理できた
+                    break;
+                if (r == 2)     // パケット長が足りない
+                    return;
+            }
+                // inter server処理でもない場合は切断
+                printf
+                    ("char: unknown packet 0x%04x (%d bytes to read in buffer)! (from map).\n",
+                     RFIFOW (fd, 0), RFIFOREST (fd));
+                session[fd]->eof = 1;
+                return;
+        }
+    }
+}
+
+int search_mapserver (char *map)
+{
+    int  i, j;
+    char temp_map[16];
+    int  temp_map_len;
+
+//  printf("Searching the map-server for map '%s'... ", map);
+    strncpy (temp_map, map, sizeof (temp_map));
+    temp_map[sizeof (temp_map) - 1] = '\0';
+    if (strchr (temp_map, '.') != NULL)
+        temp_map[strchr (temp_map, '.') - temp_map + 1] = '\0'; // suppress the '.gat', but conserve the '.' to be sure of the name of the map
+
+    temp_map_len = strlen (temp_map);
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+        if (server_fd[i] >= 0)
+            for (j = 0; server[i].map[j][0]; j++)
+                //printf("%s : %s = %d\n", server[i].map[j], map, strncmp(server[i].map[j], temp_map, temp_map_len));
+                if (strncmp (server[i].map[j], temp_map, temp_map_len) == 0)
+                {
+//                  printf("found -> server #%d.\n", i);
+                    return i;
+                }
+
+//  printf("not found.\n");
+    return -1;
+}
+
+// char_mapifの初期化処理(現在はinter_mapif初期化のみ)
+static int char_mapif_init (int fd)
+{
+    return inter_mapif_init (fd);
+}
+
+//-----------------------------------------------------
+// Test to know if an IP come from LAN or WAN. by [Yor]
+//-----------------------------------------------------
+int lan_ip_check (unsigned char *p)
+{
+    int  i;
+    int  lancheck = 1;
+
+//  printf("lan_ip_check: to compare: %d.%d.%d.%d, network: %d.%d.%d.%d/%d.%d.%d.%d\n",
+//         p[0], p[1], p[2], p[3],
+//         subneti[0], subneti[1], subneti[2], subneti[3],
+//         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
+    for (i = 0; i < 4; i++)
+    {
+        if ((subneti[i] & subnetmaski[i]) != (p[i] & subnetmaski[i]))
+        {
+            lancheck = 0;
+            break;
+        }
+    }
+    printf ("LAN test (result): %s source\033[0m.\n",
+            (lancheck) ? "\033[1;36mLAN" : "\033[1;32mWAN");
+    return lancheck;
+}
+
+void parse_char (int fd)
+{
+    int  i, ch;
+    char email[40];
+    struct char_session_data *sd;
+    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+
+    if (login_fd < 0 || session[fd]->eof)
+    {                           // disconnect any player (already connected to char-server or coming back from map-server) if login-server is diconnected.
+        if (fd == login_fd)
+            login_fd = -1;
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    sd = (struct char_session_data*)session[fd]->session_data;
+
+    while (RFIFOREST (fd) >= 2)
+    {
+//      if (RFIFOW(fd,0) < 30000)
+//          printf("parse_char: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
+
+        switch (RFIFOW (fd, 0))
+        {
+            case 0x20b:        //20040622暗号化ragexe対応
+                if (RFIFOREST (fd) < 19)
+                    return;
+                RFIFOSKIP (fd, 19);
+                break;
+
+            case 0x61:         // change password request
+                if (RFIFOREST (fd) < 50)
+                    return;
+                {
+                    WFIFOW (login_fd, 0) = 0x2740;
+                    WFIFOL (login_fd, 2) = sd->account_id;
+                    memcpy (WFIFOP (login_fd, 6), RFIFOP (fd, 2), 24);
+                    memcpy (WFIFOP (login_fd, 30), RFIFOP (fd, 26), 24);
+                    WFIFOSET (login_fd, 54);
+                }
+                RFIFOSKIP (fd, 50);
+                break;
+
+            case 0x65:         // 接続要求
+                if (RFIFOREST (fd) < 17)
+                    return;
+                {
+                    int  GM_value;
+                    if ((GM_value = isGM (RFIFOL (fd, 2))))
+                        printf
+                            ("Account Logged On; Account ID: %d (GM level %d).\n",
+                             RFIFOL (fd, 2), GM_value);
+                    else
+                        printf ("Account Logged On; Account ID: %d.\n",
+                                RFIFOL (fd, 2));
+                    if (sd == NULL)
+                    {
+                        CREATE (sd, struct char_session_data, 1);
+                        session[fd]->session_data = sd;
+                        memcpy (sd->email, "no mail", 40);  // put here a mail without '@' to refuse deletion if we don't receive the e-mail
+                        sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server)
+                    }
+                    sd->account_id = RFIFOL (fd, 2);
+                    sd->login_id1 = RFIFOL (fd, 6);
+                    sd->login_id2 = RFIFOL (fd, 10);
+                    sd->packet_tmw_version = RFIFOW (fd, 14);
+                    sd->sex = RFIFOB (fd, 16);
+                    // send back account_id
+                    WFIFOL (fd, 0) = RFIFOL (fd, 2);
+                    WFIFOSET (fd, 4);
+                    // search authentification
+                    for (i = 0; i < AUTH_FIFO_SIZE; i++)
+                    {
+                        if (auth_fifo[i].account_id == sd->account_id &&
+                            auth_fifo[i].login_id1 == sd->login_id1 &&
+#if CMP_AUTHFIFO_LOGIN2 != 0
+                            auth_fifo[i].login_id2 == sd->login_id2 &&  // relate to the versions higher than 18
+#endif
+                            (!check_ip_flag
+                             || auth_fifo[i].ip ==
+                             session[fd]->client_addr.sin_addr.s_addr)
+                            && auth_fifo[i].delflag == 2)
+                        {
+                            auth_fifo[i].delflag = 1;
+                            if (max_connect_user == 0
+                                || count_users () < max_connect_user)
+                            {
+                                if (login_fd > 0)
+                                {   // don't send request if no login-server
+                                    // request to login-server to obtain e-mail/time limit
+                                    WFIFOW (login_fd, 0) = 0x2716;
+                                    WFIFOL (login_fd, 2) = sd->account_id;
+                                    WFIFOSET (login_fd, 6);
+                                }
+                                // Record client version
+                                auth_fifo[i].packet_tmw_version =
+                                    sd->packet_tmw_version;
+                                // send characters to player
+                                mmo_char_send006b (fd, sd);
+                            }
+                            else
+                            {
+                                // refuse connection (over populated)
+                                WFIFOW (fd, 0) = 0x6c;
+                                WFIFOW (fd, 2) = 0;
+                                WFIFOSET (fd, 3);
+                            }
+                            break;
+                        }
+                    }
+                    // authentification not found
+                    if (i == AUTH_FIFO_SIZE)
+                    {
+                        if (login_fd > 0)
+                        {       // don't send request if no login-server
+                            WFIFOW (login_fd, 0) = 0x2712;  // ask login-server to authentify an account
+                            WFIFOL (login_fd, 2) = sd->account_id;
+                            WFIFOL (login_fd, 6) = sd->login_id1;
+                            WFIFOL (login_fd, 10) = sd->login_id2;  // relate to the versions higher than 18
+                            WFIFOB (login_fd, 14) = sd->sex;
+                            WFIFOL (login_fd, 15) =
+                                session[fd]->client_addr.sin_addr.s_addr;
+                            WFIFOSET (login_fd, 19);
+                        }
+                        else
+                        {       // if no login-server, we must refuse connection
+                            WFIFOW (fd, 0) = 0x6c;
+                            WFIFOW (fd, 2) = 0;
+                            WFIFOSET (fd, 3);
+                        }
+                    }
+                }
+                RFIFOSKIP (fd, 17);
+                break;
+
+            case 0x66:         // キャラ選択
+                if (!sd || RFIFOREST (fd) < 3)
+                    return;
+
+                char ip[16];
+                unsigned char *sin_addr =
+                    (unsigned char *) &session[fd]->client_addr.sin_addr;
+                sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1],
+                         sin_addr[2], sin_addr[3]);
+
+                // if we activated email creation and email is default email
+                if (email_creation != 0 && strcmp (sd->email, "a@a.com") == 0
+                    && login_fd > 0)
+                {               // to modify an e-mail, login-server must be online
+                    WFIFOW (fd, 0) = 0x70;
+                    WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
+                    WFIFOSET (fd, 3);
+
+                    // otherwise, load the character
+                }
+                else
+                {
+                    for (ch = 0; ch < 9; ch++)
+                        if (sd->found_char[ch] >= 0
+                            && char_dat[sd->found_char[ch]].char_num ==
+                            RFIFOB (fd, 2))
+                            break;
+                    if (ch != 9)
+                    {
+                        char_log
+                            ("Character Selected, Account ID: %d, Character Slot: %d, Character Name: %s [%s]\n",
+                             sd->account_id, RFIFOB (fd, 2),
+                             char_dat[sd->found_char[ch]].name, ip);
+                        // searching map server
+                        i = search_mapserver (char_dat
+                                              [sd->found_char[ch]].last_point.
+                                              map);
+                        // if map is not found, we check major cities
+                        if (i < 0)
+                        {
+                            if ((i = search_mapserver ("prontera.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "prontera.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 273;    // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    354;
+                            }
+                            else if ((i =
+                                      search_mapserver ("geffen.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "geffen.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 120;    // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    100;
+                            }
+                            else if ((i =
+                                      search_mapserver ("morocc.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "morocc.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 160;    // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    94;
+                            }
+                            else if ((i =
+                                      search_mapserver ("alberta.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "alberta.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 116;    // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    57;
+                            }
+                            else if ((i =
+                                      search_mapserver ("payon.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "payon.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 87; // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    117;
+                            }
+                            else if ((i =
+                                      search_mapserver ("izlude.gat")) >= 0)
+                            {   // check is done without 'gat'.
+                                memcpy (char_dat
+                                        [sd->found_char[ch]].last_point.map,
+                                        "izlude.gat", 16);
+                                char_dat[sd->found_char[ch]].last_point.x = 94; // savepoint coordonates
+                                char_dat[sd->found_char[ch]].last_point.y =
+                                    103;
+                            }
+                            else
+                            {
+                                int  j;
+                                // get first online server (with a map)
+                                i = 0;
+                                for (j = 0; j < MAX_MAP_SERVERS; j++)
+                                    if (server_fd[j] >= 0
+                                        && server[j].map[0][0])
+                                    {   // change save point to one of map found on the server (the first)
+                                        i = j;
+                                        memcpy (char_dat
+                                                [sd->
+                                                 found_char[ch]].last_point.
+                                                map, server[j].map[0], 16);
+                                        printf
+                                            ("Map-server #%d found with a map: '%s'.\n",
+                                             j, server[j].map[0]);
+                                        // coordonates are unknown
+                                        break;
+                                    }
+                                // if no map-server is connected, we send: server closed
+                                if (j == MAX_MAP_SERVERS)
+                                {
+                                    WFIFOW (fd, 0) = 0x81;
+                                    WFIFOL (fd, 2) = 1; // 01 = Server closed
+                                    WFIFOSET (fd, 3);
+                                    RFIFOSKIP (fd, 3);
+                                    break;
+                                }
+                            }
+                        }
+                        WFIFOW (fd, 0) = 0x71;
+                        WFIFOL (fd, 2) = char_dat[sd->found_char[ch]].char_id;
+                        memcpy (WFIFOP (fd, 6),
+                                char_dat[sd->found_char[ch]].last_point.map,
+                                16);
+                        printf
+                            ("Character selection '%s' (account: %d, slot: %d) [%s]\n",
+                             char_dat[sd->found_char[ch]].name,
+                             sd->account_id, ch, ip);
+                        printf ("--Send IP of map-server. ");
+                        if (lan_ip_check (p))
+                            WFIFOL (fd, 22) = inet_addr (lan_map_ip);
+                        else
+                            WFIFOL (fd, 22) = server[i].ip;
+                        WFIFOW (fd, 26) = server[i].port;
+                        WFIFOSET (fd, 28);
+                        if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+                            auth_fifo_pos = 0;
+                        //printf("auth_fifo set #%d - account %d, char: %d, secure: %08x-%08x\n", auth_fifo_pos, sd->account_id, char_dat[sd->found_char[ch]].char_id, sd->login_id1, sd->login_id2);
+                        auth_fifo[auth_fifo_pos].account_id = sd->account_id;
+                        auth_fifo[auth_fifo_pos].char_id =
+                            char_dat[sd->found_char[ch]].char_id;
+                        auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1;
+                        auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2;
+                        auth_fifo[auth_fifo_pos].delflag = 0;
+                        auth_fifo[auth_fifo_pos].char_pos =
+                            sd->found_char[ch];
+                        auth_fifo[auth_fifo_pos].sex = sd->sex;
+                        auth_fifo[auth_fifo_pos].connect_until_time =
+                            sd->connect_until_time;
+                        auth_fifo[auth_fifo_pos].ip =
+                            session[fd]->client_addr.sin_addr.s_addr;
+                        auth_fifo[auth_fifo_pos].packet_tmw_version =
+                            sd->packet_tmw_version;
+                        auth_fifo_pos++;
+                    }
+                }
+                RFIFOSKIP (fd, 3);
+                break;
+
+            case 0x67:         // 作成
+                if (!sd || RFIFOREST (fd) < 37)
+                    return;
+                i = make_new_char (fd, RFIFOP (fd, 2));
+                if (i < 0)
+                {
+                    WFIFOW (fd, 0) = 0x6e;
+                    WFIFOB (fd, 2) = 0x00;
+                    WFIFOSET (fd, 3);
+                    RFIFOSKIP (fd, 37);
+                    break;
+                }
+
+                WFIFOW (fd, 0) = 0x6d;
+                memset (WFIFOP (fd, 2), 0, 106);
+
+                WFIFOL (fd, 2) = char_dat[i].char_id;
+                WFIFOL (fd, 2 + 4) = char_dat[i].base_exp;
+                WFIFOL (fd, 2 + 8) = char_dat[i].zeny;
+                WFIFOL (fd, 2 + 12) = char_dat[i].job_exp;
+                WFIFOL (fd, 2 + 16) = char_dat[i].job_level;
+
+                WFIFOL (fd, 2 + 28) = char_dat[i].karma;
+                WFIFOL (fd, 2 + 32) = char_dat[i].manner;
+
+                WFIFOW (fd, 2 + 40) = 0x30;
+                WFIFOW (fd, 2 + 42) =
+                    (char_dat[i].hp > 0x7fff) ? 0x7fff : char_dat[i].hp;
+                WFIFOW (fd, 2 + 44) =
+                    (char_dat[i].max_hp >
+                     0x7fff) ? 0x7fff : char_dat[i].max_hp;
+                WFIFOW (fd, 2 + 46) =
+                    (char_dat[i].sp > 0x7fff) ? 0x7fff : char_dat[i].sp;
+                WFIFOW (fd, 2 + 48) =
+                    (char_dat[i].max_sp >
+                     0x7fff) ? 0x7fff : char_dat[i].max_sp;
+                WFIFOW (fd, 2 + 50) = DEFAULT_WALK_SPEED;   // char_dat[i].speed;
+                WFIFOW (fd, 2 + 52) = char_dat[i].pc_class;
+                WFIFOW (fd, 2 + 54) = char_dat[i].hair;
+
+                WFIFOW (fd, 2 + 58) = char_dat[i].base_level;
+                WFIFOW (fd, 2 + 60) = char_dat[i].skill_point;
+
+                WFIFOW (fd, 2 + 64) = char_dat[i].shield;
+                WFIFOW (fd, 2 + 66) = char_dat[i].head_top;
+                WFIFOW (fd, 2 + 68) = char_dat[i].head_mid;
+                WFIFOW (fd, 2 + 70) = char_dat[i].hair_color;
+
+                memcpy (WFIFOP (fd, 2 + 74), char_dat[i].name, 24);
+
+                WFIFOB (fd, 2 + 98) =
+                    (char_dat[i].str > 255) ? 255 : char_dat[i].str;
+                WFIFOB (fd, 2 + 99) =
+                    (char_dat[i].agi > 255) ? 255 : char_dat[i].agi;
+                WFIFOB (fd, 2 + 100) =
+                    (char_dat[i].vit > 255) ? 255 : char_dat[i].vit;
+                WFIFOB (fd, 2 + 101) =
+                    (char_dat[i].int_ > 255) ? 255 : char_dat[i].int_;
+                WFIFOB (fd, 2 + 102) =
+                    (char_dat[i].dex > 255) ? 255 : char_dat[i].dex;
+                WFIFOB (fd, 2 + 103) =
+                    (char_dat[i].luk > 255) ? 255 : char_dat[i].luk;
+                WFIFOB (fd, 2 + 104) = char_dat[i].char_num;
+
+                WFIFOSET (fd, 108);
+                RFIFOSKIP (fd, 37);
+                for (ch = 0; ch < 9; ch++)
+                {
+                    if (sd->found_char[ch] == -1)
+                    {
+                        sd->found_char[ch] = i;
+                        break;
+                    }
+                }
+
+            case 0x68:         // delete char //Yor's Fix
+                if (!sd || RFIFOREST (fd) < 46)
+                    return;
+                memcpy (email, RFIFOP (fd, 6), 40);
+                if (e_mail_check (email) == 0)
+                    strncpy (email, "a@a.com", 40); // default e-mail
+
+                // if we activated email creation and email is default email
+                if (email_creation != 0 && strcmp (sd->email, "a@a.com") == 0
+                    && login_fd > 0)
+                {               // to modify an e-mail, login-server must be online
+                    // if sended email is incorrect e-mail
+                    if (strcmp (email, "a@a.com") == 0)
+                    {
+                        WFIFOW (fd, 0) = 0x70;
+                        WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
+                        WFIFOSET (fd, 3);
+                        RFIFOSKIP (fd, 46);
+                        // we act like we have selected a character
+                    }
+                    else
+                    {
+                        // we change the packet to set it like selection.
+                        for (i = 0; i < 9; i++)
+                            if (char_dat[sd->found_char[i]].char_id ==
+                                RFIFOL (fd, 2))
+                            {
+                                // we save new e-mail
+                                memcpy (sd->email, email, 40);
+                                // we send new e-mail to login-server ('online' login-server is checked before)
+                                WFIFOW (login_fd, 0) = 0x2715;
+                                WFIFOL (login_fd, 2) = sd->account_id;
+                                memcpy (WFIFOP (login_fd, 6), email, 40);
+                                WFIFOSET (login_fd, 46);
+                                // skip part of the packet! (46, but leave the size of select packet: 3)
+                                RFIFOSKIP (fd, 43);
+                                // change value to put new packet (char selection)
+                                RFIFOW (fd, 0) = 0x66;
+                                RFIFOB (fd, 2) =
+                                    char_dat[sd->found_char[i]].char_num;
+                                // not send packet, it's modify of actual packet
+                                break;
+                            }
+                        if (i == 9)
+                        {
+                            WFIFOW (fd, 0) = 0x70;
+                            WFIFOB (fd, 2) = 0; // 00 = Incorrect Email address
+                            WFIFOSET (fd, 3);
+                            RFIFOSKIP (fd, 46);
+                        }
+                    }
+
+                    // otherwise, we delete the character
+                }
+                else
+                {
+                    /*if (strcasecmp(email, sd->email) != 0) { // if it's an invalid email
+                     * WFIFOW(fd, 0) = 0x70;
+                     * WFIFOB(fd, 2) = 0; // 00 = Incorrect Email address
+                     * WFIFOSET(fd, 3);
+                     * // if mail is correct
+                     * } else { */
+                    for (i = 0; i < 9; i++)
+                    {
+                        struct mmo_charstatus *cs = NULL;
+                        if (sd->found_char[i] >= 0
+                            && (cs =
+                                &char_dat[sd->found_char[i]])->char_id ==
+                            RFIFOL (fd, 2))
+                        {
+                            char_delete (cs);   // deletion process
+
+                            if (sd->found_char[i] != char_num - 1)
+                            {
+                                memcpy (&char_dat[sd->found_char[i]],
+                                        &char_dat[char_num - 1],
+                                        sizeof (struct mmo_charstatus));
+                                // Correct moved character reference in the character's owner
+                                {
+                                    int  j, k;
+                                    struct char_session_data *sd2;
+                                    for (j = 0; j < fd_max; j++)
+                                    {
+                                        if (session[j]
+                                            && (sd2 = (struct char_session_data*)
+                                                session[j]->session_data)
+                                            && sd2->account_id ==
+                                            char_dat[char_num - 1].account_id)
+                                        {
+                                            for (k = 0; k < 9; k++)
+                                            {
+                                                if (sd2->found_char[k] ==
+                                                    char_num - 1)
+                                                {
+                                                    sd2->found_char[k] =
+                                                        sd->found_char[i];
+                                                    break;
+                                                }
+                                            }
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+
+                            char_num--;
+                            for (ch = i; ch < 9 - 1; ch++)
+                                sd->found_char[ch] = sd->found_char[ch + 1];
+                            sd->found_char[8] = -1;
+                            WFIFOW (fd, 0) = 0x6f;
+                            WFIFOSET (fd, 2);
+                            break;
+                        }
+                    }
+
+                    if (i == 9)
+                    {
+                        WFIFOW (fd, 0) = 0x70;
+                        WFIFOB (fd, 2) = 0;
+                        WFIFOSET (fd, 3);
+                    }
+                    //}
+                    RFIFOSKIP (fd, 46);
+                }
+                break;
+
+            case 0x2af8:       // マップサーバーログイン
+                if (RFIFOREST (fd) < 60)
+                    return;
+                WFIFOW (fd, 0) = 0x2af9;
+                for (i = 0; i < MAX_MAP_SERVERS; i++)
+                {
+                    if (server_fd[i] < 0)
+                        break;
+                }
+                if (i == MAX_MAP_SERVERS || strcmp (RFIFOP (fd, 2), userid)
+                    || strcmp (RFIFOP (fd, 26), passwd))
+                {
+                    WFIFOB (fd, 2) = 3;
+                    WFIFOSET (fd, 3);
+                    RFIFOSKIP (fd, 60);
+                }
+                else
+                {
+                    int  len;
+                    WFIFOB (fd, 2) = 0;
+                    session[fd]->func_parse = parse_frommap;
+                    server_fd[i] = fd;
+                    if (anti_freeze_enable)
+                        server_freezeflag[i] = 5;   // Map anti-freeze system. Counter. 5 ok, 4...0 freezed
+                    server[i].ip = RFIFOL (fd, 54);
+                    server[i].port = RFIFOW (fd, 58);
+                    server[i].users = 0;
+                    memset (server[i].map, 0, sizeof (server[i].map));
+                    WFIFOSET (fd, 3);
+                    RFIFOSKIP (fd, 60);
+                    realloc_fifo (fd, FIFOSIZE_SERVERLINK,
+                                  FIFOSIZE_SERVERLINK);
+                    char_mapif_init (fd);
+                    // send gm acccounts level to map-servers
+                    len = 4;
+                    WFIFOW (fd, 0) = 0x2b15;
+                    for (i = 0; i < GM_num; i++)
+                    {
+                        WFIFOL (fd, len) = gm_account[i].account_id;
+                        WFIFOB (fd, len + 4) =
+                            (unsigned char) gm_account[i].level;
+                        len += 5;
+                    }
+                    WFIFOW (fd, 2) = len;
+                    WFIFOSET (fd, len);
+                    return;
+                }
+                break;
+
+            case 0x187:        // Alive信号?
+                if (RFIFOREST (fd) < 6)
+                    return;
+                RFIFOSKIP (fd, 6);
+                break;
+
+            case 0x7530:       // Athena情報所得
+                WFIFOW (fd, 0) = 0x7531;
+                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
+                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
+                WFIFOB (fd, 4) = ATHENA_REVISION;
+                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
+                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
+                WFIFOB (fd, 7) = ATHENA_SERVER_INTER | ATHENA_SERVER_CHAR;
+                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
+                WFIFOSET (fd, 10);
+                RFIFOSKIP (fd, 2);
+                return;
+
+            case 0x7532:       // 接続の切断(defaultと処理は一緒だが明示的にするため)
+                session[fd]->eof = 1;
+                return;
+
+            default:
+                session[fd]->eof = 1;
+                return;
+        }
+    }
+}
+
+// 全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す)
+int mapif_sendall (char *buf, unsigned int len)
+{
+    int  i, c;
+
+    c = 0;
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+    {
+        int  fd;
+        if ((fd = server_fd[i]) >= 0)
+        {
+            memcpy (WFIFOP (fd, 0), buf, len);
+            WFIFOSET (fd, len);
+            c++;
+        }
+    }
+    return c;
+}
+
+// 自分以外の全てのMAPサーバーにデータ送信(送信したmap鯖の数を返す)
+int mapif_sendallwos (int sfd, unsigned char *buf, unsigned int len)
+{
+    int  i, c;
+
+    c = 0;
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+    {
+        int  fd;
+        if ((fd = server_fd[i]) >= 0 && fd != sfd)
+        {
+            memcpy (WFIFOP (fd, 0), buf, len);
+            WFIFOSET (fd, len);
+            c++;
+        }
+    }
+    return c;
+}
+
+// MAPサーバーにデータ送信(map鯖生存確認有り)
+int mapif_send (int fd, unsigned char *buf, unsigned int len)
+{
+    int  i;
+
+    if (fd >= 0)
+    {
+        for (i = 0; i < MAX_MAP_SERVERS; i++)
+        {
+            if (fd == server_fd[i])
+            {
+                memcpy (WFIFOP (fd, 0), buf, len);
+                WFIFOSET (fd, len);
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+void send_users_tologin (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  users = count_users ();
+    char buf[16];
+
+    if (login_fd > 0 && session[login_fd])
+    {
+        // send number of user to login server
+        WFIFOW (login_fd, 0) = 0x2714;
+        WFIFOL (login_fd, 2) = users;
+        WFIFOSET (login_fd, 6);
+    }
+    // send number of players to all map-servers
+    WBUFW (buf, 0) = 0x2b00;
+    WBUFL (buf, 2) = users;
+    mapif_sendall (buf, 6);
+}
+
+void check_connect_login_server (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    if (login_fd <= 0 || session[login_fd] == NULL)
+    {
+        printf ("Attempt to connect to login-server...\n");
+        if ((login_fd = make_connection (login_ip, login_port)) < 0)
+            return;
+        session[login_fd]->func_parse = parse_tologin;
+        realloc_fifo (login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+        WFIFOW (login_fd, 0) = 0x2710;
+        memset (WFIFOP (login_fd, 2), 0, 24);
+        memcpy (WFIFOP (login_fd, 2), userid,
+                strlen (userid) < 24 ? strlen (userid) : 24);
+        memset (WFIFOP (login_fd, 26), 0, 24);
+        memcpy (WFIFOP (login_fd, 26), passwd,
+                strlen (passwd) < 24 ? strlen (passwd) : 24);
+        WFIFOL (login_fd, 50) = 0;
+        WFIFOL (login_fd, 54) = char_ip;
+        WFIFOL (login_fd, 58) = char_port;
+        memset (WFIFOP (login_fd, 60), 0, 20);
+        memcpy (WFIFOP (login_fd, 60), server_name,
+                strlen (server_name) < 20 ? strlen (server_name) : 20);
+        WFIFOW (login_fd, 80) = 0;
+        WFIFOW (login_fd, 82) = char_maintenance;
+        WFIFOW (login_fd, 84) = char_new;
+        WFIFOSET (login_fd, 86);
+    }
+}
+
+//----------------------------------------------------------
+// Return numerical value of a switch configuration by [Yor]
+// on/off, english, français, deutsch, español
+//----------------------------------------------------------
+int config_switch (const char *str)
+{
+    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
+        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
+        || strcasecmp (str, "si") == 0)
+        return 1;
+    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
+        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
+        return 0;
+
+    return atoi (str);
+}
+
+//-------------------------------------------
+// Reading Lan Support configuration by [Yor]
+//-------------------------------------------
+int lan_config_read (const char *lancfgName)
+{
+    int  j;
+    struct hostent *h = NULL;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    // set default configuration
+    strncpy (lan_map_ip, "127.0.0.1", sizeof (lan_map_ip));
+    subneti[0] = 127;
+    subneti[1] = 0;
+    subneti[2] = 0;
+    subneti[3] = 1;
+    for (j = 0; j < 4; j++)
+        subnetmaski[j] = 255;
+
+    fp = fopen_ (lancfgName, "r");
+
+    if (fp == NULL)
+    {
+        printf ("LAN support configuration file not found: %s\n", lancfgName);
+        return 1;
+    }
+
+    printf ("---start reading of Lan Support configuration...\n");
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        line[sizeof (line) - 1] = '\0';
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+            continue;
+
+        remove_control_chars (w1);
+        remove_control_chars (w2);
+        if (strcasecmp (w1, "lan_map_ip") == 0)
+        {                       // Read map-server Lan IP Address
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                sprintf (lan_map_ip, "%d.%d.%d.%d",
+                         (unsigned char) h->h_addr[0],
+                         (unsigned char) h->h_addr[1],
+                         (unsigned char) h->h_addr[2],
+                         (unsigned char) h->h_addr[3]);
+            }
+            else
+            {
+                strncpy (lan_map_ip, w2, sizeof (lan_map_ip));
+                lan_map_ip[sizeof (lan_map_ip) - 1] = 0;
+            }
+            printf ("LAN IP of map-server: %s.\n", lan_map_ip);
+        }
+        else if (strcasecmp (w1, "subnet") == 0)
+        {                       // Read Subnetwork
+            for (j = 0; j < 4; j++)
+                subneti[j] = 0;
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                for (j = 0; j < 4; j++)
+                    subneti[j] = (unsigned char) h->h_addr[j];
+            }
+            else
+            {
+                sscanf (w2, "%d.%d.%d.%d", &subneti[0], &subneti[1],
+                        &subneti[2], &subneti[3]);
+            }
+            printf ("Sub-network of the map-server: %d.%d.%d.%d.\n",
+                    subneti[0], subneti[1], subneti[2], subneti[3]);
+        }
+        else if (strcasecmp (w1, "subnetmask") == 0)
+        {                       // Read Subnetwork Mask
+            for (j = 0; j < 4; j++)
+                subnetmaski[j] = 255;
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                for (j = 0; j < 4; j++)
+                    subnetmaski[j] = (unsigned char) h->h_addr[j];
+            }
+            else
+            {
+                sscanf (w2, "%d.%d.%d.%d", &subnetmaski[0], &subnetmaski[1],
+                        &subnetmaski[2], &subnetmaski[3]);
+            }
+            printf ("Sub-network mask of the map-server: %d.%d.%d.%d.\n",
+                    subnetmaski[0], subnetmaski[1], subnetmaski[2],
+                    subnetmaski[3]);
+        }
+    }
+    fclose_ (fp);
+
+    // sub-network check of the map-server
+    {
+        unsigned int a0, a1, a2, a3;
+        unsigned char p[4];
+        sscanf (lan_map_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
+        p[0] = a0;
+        p[1] = a1;
+        p[2] = a2;
+        p[3] = a3;
+        printf ("LAN test of LAN IP of the map-server: ");
+        if (lan_ip_check (p) == 0)
+        {
+            printf
+                ("\033[1;31m***ERROR: LAN IP of the map-server doesn't belong to the specified Sub-network.\033[0m\n");
+        }
+    }
+
+    printf ("---End reading of Lan Support configuration...\n");
+
+    return 0;
+}
+
+int char_config_read (const char *cfgName)
+{
+    struct hostent *h = NULL;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp = fopen_ (cfgName, "r");
+
+    if (fp == NULL)
+    {
+        printf ("Configuration file not found: %s.\n", cfgName);
+        exit (1);
+    }
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        line[sizeof (line) - 1] = '\0';
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+            continue;
+
+        remove_control_chars (w1);
+        remove_control_chars (w2);
+        if (strcasecmp (w1, "userid") == 0)
+        {
+            memcpy (userid, w2, 24);
+        }
+        else if (strcasecmp (w1, "passwd") == 0)
+        {
+            memcpy (passwd, w2, 24);
+        }
+        else if (strcasecmp (w1, "server_name") == 0)
+        {
+            memcpy (server_name, w2, sizeof (server_name));
+            server_name[sizeof (server_name) - 1] = '\0';
+            printf ("%s server has been intialized\n", w2);
+        }
+        else if (strcasecmp (w1, "wisp_server_name") == 0)
+        {
+            if (strlen (w2) >= 4)
+            {
+                strncpy (wisp_server_name, w2, sizeof (wisp_server_name));
+                wisp_server_name[sizeof (wisp_server_name) - 1] = '\0';
+            }
+        }
+        else if (strcasecmp (w1, "login_ip") == 0)
+        {
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                printf ("Login server IP address : %s -> %d.%d.%d.%d\n", w2,
+                        (unsigned char) h->h_addr[0],
+                        (unsigned char) h->h_addr[1],
+                        (unsigned char) h->h_addr[2],
+                        (unsigned char) h->h_addr[3]);
+                sprintf (login_ip_str, "%d.%d.%d.%d",
+                         (unsigned char) h->h_addr[0],
+                         (unsigned char) h->h_addr[1],
+                         (unsigned char) h->h_addr[2],
+                         (unsigned char) h->h_addr[3]);
+            }
+            else
+                memcpy (login_ip_str, w2, 16);
+        }
+        else if (strcasecmp (w1, "login_port") == 0)
+        {
+            login_port = atoi (w2);
+        }
+        else if (strcasecmp (w1, "char_ip") == 0)
+        {
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                printf ("Character server IP address : %s -> %d.%d.%d.%d\n",
+                        w2, (unsigned char) h->h_addr[0],
+                        (unsigned char) h->h_addr[1],
+                        (unsigned char) h->h_addr[2],
+                        (unsigned char) h->h_addr[3]);
+                sprintf (char_ip_str, "%d.%d.%d.%d",
+                         (unsigned char) h->h_addr[0],
+                         (unsigned char) h->h_addr[1],
+                         (unsigned char) h->h_addr[2],
+                         (unsigned char) h->h_addr[3]);
+            }
+            else
+                memcpy (char_ip_str, w2, 16);
+        }
+        else if (strcasecmp (w1, "char_port") == 0)
+        {
+            char_port = atoi (w2);
+        }
+        else if (strcasecmp (w1, "char_maintenance") == 0)
+        {
+            char_maintenance = atoi (w2);
+        }
+        else if (strcasecmp (w1, "char_new") == 0)
+        {
+            char_new = atoi (w2);
+        }
+        else if (strcasecmp (w1, "email_creation") == 0)
+        {
+            email_creation = config_switch (w2);
+        }
+        else if (strcasecmp (w1, "char_txt") == 0)
+        {
+            strcpy (char_txt, w2);
+        }
+        else if (strcasecmp (w1, "backup_txt") == 0)
+        {                       //By zanetheinsane
+            strcpy (backup_txt, w2);
+        }
+        else if (strcasecmp (w1, "backup_txt_flag") == 0)
+        {                       // The backup_txt file was created because char deletion bug existed. Now it's finish and that take a lot of time to create a second file when there are a lot of characters. By [Yor]
+            backup_txt_flag = config_switch (w2);
+        }
+        else if (strcasecmp (w1, "max_connect_user") == 0)
+        {
+            max_connect_user = atoi (w2);
+            if (max_connect_user < 0)
+                max_connect_user = 0;   // unlimited online players
+        }
+        else if (strcasecmp (w1, "check_ip_flag") == 0)
+        {
+            check_ip_flag = config_switch (w2);
+        }
+        else if (strcasecmp (w1, "autosave_time") == 0)
+        {
+            autosave_interval = atoi (w2) * 1000;
+            if (autosave_interval <= 0)
+                autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+        }
+        else if (strcasecmp (w1, "start_point") == 0)
+        {
+            char map[32];
+            int  x, y;
+            if (sscanf (w2, "%[^,],%d,%d", map, &x, &y) < 3)
+                continue;
+            if (strstr (map, ".gat") != NULL)
+            {                   // Verify at least if '.gat' is in the map name
+                memcpy (start_point.map, map, 16);
+                start_point.x = x;
+                start_point.y = y;
+            }
+        }
+        else if (strcasecmp (w1, "start_zeny") == 0)
+        {
+            start_zeny = atoi (w2);
+            if (start_zeny < 0)
+                start_zeny = 0;
+        }
+        else if (strcasecmp (w1, "start_weapon") == 0)
+        {
+            start_weapon = atoi (w2);
+            if (start_weapon < 0)
+                start_weapon = 0;
+        }
+        else if (strcasecmp (w1, "start_armor") == 0)
+        {
+            start_armor = atoi (w2);
+            if (start_armor < 0)
+                start_armor = 0;
+        }
+        else if (strcasecmp (w1, "unknown_char_name") == 0)
+        {
+            strcpy (unknown_char_name, w2);
+            unknown_char_name[24] = 0;
+        }
+        else if (strcasecmp (w1, "char_log_filename") == 0)
+        {
+            strcpy (char_log_filename, w2);
+        }
+        else if (strcasecmp (w1, "name_ignoring_case") == 0)
+        {
+            name_ignoring_case = config_switch (w2);
+        }
+        else if (strcasecmp (w1, "char_name_option") == 0)
+        {
+            char_name_option = atoi (w2);
+        }
+        else if (strcasecmp (w1, "char_name_letters") == 0)
+        {
+            strcpy (char_name_letters, w2);
+// online files options
+        }
+        else if (strcasecmp (w1, "online_txt_filename") == 0)
+        {
+            strcpy (online_txt_filename, w2);
+        }
+        else if (strcasecmp (w1, "online_html_filename") == 0)
+        {
+            strcpy (online_html_filename, w2);
+        }
+        else if (strcasecmp (w1, "online_sorting_option") == 0)
+        {
+            online_sorting_option = atoi (w2);
+        }
+        else if (strcasecmp (w1, "online_display_option") == 0)
+        {
+            online_display_option = atoi (w2);
+        }
+        else if (strcasecmp (w1, "online_gm_display_min_level") == 0)
+        {                       // minimum GM level to display 'GM' when we want to display it
+            online_gm_display_min_level = atoi (w2);
+            if (online_gm_display_min_level < 5)    // send online file every 5 seconds to player is enough
+                online_gm_display_min_level = 5;
+        }
+        else if (strcasecmp (w1, "online_refresh_html") == 0)
+        {
+            online_refresh_html = atoi (w2);
+            if (online_refresh_html < 1)
+                online_refresh_html = 1;
+        }
+        else if (strcasecmp (w1, "anti_freeze_enable") == 0)
+        {
+            anti_freeze_enable = config_switch (w2);
+        }
+        else if (strcasecmp (w1, "anti_freeze_interval") == 0)
+        {
+            ANTI_FREEZE_INTERVAL = atoi (w2);
+            if (ANTI_FREEZE_INTERVAL < 5)
+                ANTI_FREEZE_INTERVAL = 5;   // minimum 5 seconds
+        }
+        else if (strcasecmp (w1, "import") == 0)
+        {
+            char_config_read (w2);
+        }
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+void term_func (void)
+{
+    int  i;
+
+    // write online players files with no player
+    for (i = 0; i < char_num; i++)
+        online_chars[i] = -1;
+    create_online_files ();
+    free (online_chars);
+
+    mmo_char_sync ();
+    inter_save ();
+
+    if (gm_account != NULL)
+        free (gm_account);
+
+    free (char_dat);
+    delete_session (login_fd);
+    delete_session (char_fd);
+
+    char_log ("----End of char-server (normal end with closing of all files).\n");
+}
+
+int do_init (int argc, char **argv)
+{
+    int  i;
+
+    // a newline in the log...
+    char_log ("");
+    char_log ("The char-server starting...\n");
+
+    char_config_read ((argc < 2) ? CHAR_CONF_NAME : argv[1]);
+    lan_config_read ((argc > 1) ? argv[1] : LOGIN_LAN_CONF_NAME);
+
+    login_ip = inet_addr (login_ip_str);
+    char_ip = inet_addr (char_ip_str);
+
+    for (i = 0; i < MAX_MAP_SERVERS; i++)
+    {
+        memset (&server[i], 0, sizeof (struct mmo_map_server));
+        server_fd[i] = -1;
+    }
+
+    mmo_char_init ();
+
+    update_online = time (NULL);
+    create_online_files ();     // update online players files at start of the server
+
+    inter_init ((argc > 2) ? argv[2] : inter_cfgName);  // inter server 初期化
+
+//    set_termfunc (do_final);
+    set_defaultparse (parse_char);
+
+    char_fd = make_listen_port (char_port);
+
+//    add_timer_func_list (check_connect_login_server, "check_connect_login_server");
+//    add_timer_func_list (send_users_tologin, "send_users_tologin");
+//    add_timer_func_list (mmo_char_sync_timer, "mmo_char_sync_timer");
+
+    i = add_timer_interval (gettick () + 1000, check_connect_login_server, 0,
+                            0, 10 * 1000);
+    i = add_timer_interval (gettick () + 1000, send_users_tologin, 0, 0,
+                            5 * 1000);
+    i = add_timer_interval (gettick () + autosave_interval,
+                            mmo_char_sync_timer, 0, 0, autosave_interval);
+
+    if (anti_freeze_enable > 0)
+    {
+//        add_timer_func_list (map_anti_freeze_system, "map_anti_freeze_system");
+        i = add_timer_interval (gettick () + 1000, map_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000);  // checks every X seconds user specifies
+    }
+
+    char_log ("The char-server is ready (Server is listening on the port %d).\n",
+              char_port);
+
+    printf
+        ("The char-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
+         char_port);
+
+    return 0;
+}
diff --git a/src/char/char.h b/src/char/char.h
deleted file mode 100644
index cc64024..0000000
--- a/src/char/char.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// $Id: char.h,v 1.1.1.1 2004/09/10 17:26:50 MagicalTux Exp $
-#ifndef _CHAR_H_
-#define _CHAR_H_
-
-#define MAX_MAP_SERVERS 30
-
-#define CHAR_CONF_NAME	"conf/char_athena.conf"
-
-#define LOGIN_LAN_CONF_NAME	"conf/lan_support.conf"
-
-#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
-
-struct mmo_map_server
-{
-    long ip;
-    short port;
-    int  users;
-    char map[MAX_MAP_PER_SERVER][16];
-};
-
-int  search_character_index (char *character_name);
-char *search_character_name (int index);
-
-int  mapif_sendall (char *buf, unsigned int len);
-int  mapif_sendallwos (int fd, unsigned char *buf, unsigned int len);
-int  mapif_send (int fd, unsigned char *buf, unsigned int len);
-
-int  char_log (char *fmt, ...);
-
-extern int autosave_interval;
-
-#endif
diff --git a/src/char/char.hpp b/src/char/char.hpp
new file mode 100644
index 0000000..22b7678
--- /dev/null
+++ b/src/char/char.hpp
@@ -0,0 +1,32 @@
+// $Id: char.h,v 1.1.1.1 2004/09/10 17:26:50 MagicalTux Exp $
+#ifndef CHAR_HPP
+#define CHAR_HPP
+
+#define MAX_MAP_SERVERS 30
+
+#define CHAR_CONF_NAME	"conf/char_athena.conf"
+
+#define LOGIN_LAN_CONF_NAME	"conf/lan_support.conf"
+
+#define DEFAULT_AUTOSAVE_INTERVAL 300*1000
+
+struct mmo_map_server
+{
+    long ip;
+    short port;
+    int  users;
+    char map[MAX_MAP_PER_SERVER][16];
+};
+
+int  search_character_index (char *character_name);
+char *search_character_name (int index);
+
+int  mapif_sendall (char *buf, unsigned int len);
+int  mapif_sendallwos (int fd, unsigned char *buf, unsigned int len);
+int  mapif_send (int fd, unsigned char *buf, unsigned int len);
+
+int  char_log (char *fmt, ...);
+
+extern int autosave_interval;
+
+#endif
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
deleted file mode 100644
index 05aae6b..0000000
--- a/src/char/int_guild.c
+++ /dev/null
@@ -1,1757 +0,0 @@
-// $Id: int_guild.c,v 1.2 2004/09/25 19:36:53 Akitasha Exp $
-#include "inter.h"
-#include "int_guild.h"
-#include "int_storage.h"
-#include "../common/mmo.h"
-#include "char.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/lock.h"
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-char guild_txt[1024] = "save/guild.txt";
-char castle_txt[1024] = "save/castle.txt";
-
-static struct dbt *guild_db;
-static struct dbt *castle_db;
-
-static int guild_newid = 10000;
-
-static int guild_exp[100];
-
-int  mapif_parse_GuildLeave (int fd, int guild_id, int account_id,
-                             int char_id, int flag, const char *mes);
-int  mapif_guild_broken (int guild_id, int flag);
-int  guild_check_empty (struct guild *g);
-int  guild_calcinfo (struct guild *g);
-int  mapif_guild_basicinfochanged (int guild_id, int type, const void *data,
-                                   int len);
-int  mapif_guild_info (int fd, struct guild *g);
-void guild_break_sub (db_key_t key, db_val_t data, va_list ap);
-
-// ギルドデータの文字列への変換
-int inter_guild_tostr (char *str, struct guild *g)
-{
-    int  i, c, len;
-
-    // 基本データ
-    len = sprintf (str, "%d\t%s\t%s\t%d,%d,%d,%d,%d\t%s#\t%s#\t",
-                   g->guild_id, g->name, g->master,
-                   g->guild_lv, g->max_member, g->exp, g->skill_point,
-                   g->castle_id, g->mes1, g->mes2);
-    // メンバー
-    for (i = 0; i < g->max_member; i++)
-    {
-        struct guild_member *m = &g->member[i];
-        len += sprintf (str + len, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\t%s\t",
-                        m->account_id, m->char_id,
-                        m->hair, m->hair_color, m->gender,
-                        m->pc_class, m->lv, m->exp, m->exp_payper, m->position,
-                        ((m->account_id > 0) ? m->name : "-"));
-    }
-    // 役職
-    for (i = 0; i < MAX_GUILDPOSITION; i++)
-    {
-        struct guild_position *p = &g->position[i];
-        len +=
-            sprintf (str + len, "%d,%d\t%s#\t", p->mode, p->exp_mode,
-                     p->name);
-    }
-    // エンブレム
-    len += sprintf (str + len, "%d,%d,", g->emblem_len, g->emblem_id);
-    for (i = 0; i < g->emblem_len; i++)
-    {
-        len +=
-            sprintf (str + len, "%02x", (unsigned char) (g->emblem_data[i]));
-    }
-    len += sprintf (str + len, "$\t");
-    // 同盟リスト
-    c = 0;
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-        if (g->alliance[i].guild_id > 0)
-            c++;
-    len += sprintf (str + len, "%d\t", c);
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-    {
-        struct guild_alliance *a = &g->alliance[i];
-        if (a->guild_id > 0)
-            len +=
-                sprintf (str + len, "%d,%d\t%s\t", a->guild_id, a->opposition,
-                         a->name);
-    }
-    // 追放リスト
-    c = 0;
-    for (i = 0; i < MAX_GUILDEXPLUSION; i++)
-        if (g->explusion[i].account_id > 0)
-            c++;
-    len += sprintf (str + len, "%d\t", c);
-    for (i = 0; i < MAX_GUILDEXPLUSION; i++)
-    {
-        struct guild_explusion *e = &g->explusion[i];
-        if (e->account_id > 0)
-            len += sprintf (str + len, "%d,%d,%d,%d\t%s\t%s\t%s#\t",
-                            e->account_id, e->rsv1, e->rsv2, e->rsv3,
-                            e->name, e->acc, e->mes);
-    }
-    // ギルドスキル
-    for (i = 0; i < MAX_GUILDSKILL; i++)
-    {
-        len += sprintf (str + len, "%d,%d ", g->skill[i].id, g->skill[i].lv);
-    }
-    len += sprintf (str + len, "\t");
-
-    return 0;
-}
-
-// ギルドデータの文字列からの変換
-int inter_guild_fromstr (char *str, struct guild *g)
-{
-    int  i, j, c;
-    int  tmp_int[16];
-    char tmp_str[4][256];
-    char tmp_str2[4096];
-    char *pstr;
-
-    // 基本データ
-    memset (g, 0, sizeof (struct guild));
-    if (sscanf
-        (str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%d,%d,%d\t%[^\t]\t%[^\t]\t",
-         &tmp_int[0], tmp_str[0], tmp_str[1], &tmp_int[1], &tmp_int[2],
-         &tmp_int[3], &tmp_int[4], &tmp_int[5], tmp_str[2], tmp_str[3]) < 8)
-        return 1;
-
-    g->guild_id = tmp_int[0];
-    g->guild_lv = tmp_int[1];
-    g->max_member = tmp_int[2];
-    g->exp = tmp_int[3];
-    g->skill_point = tmp_int[4];
-    g->castle_id = tmp_int[5];
-    memcpy (g->name, tmp_str[0], 24);
-    memcpy (g->master, tmp_str[1], 24);
-    memcpy (g->mes1, tmp_str[2], 60);
-    memcpy (g->mes2, tmp_str[3], 120);
-    g->mes1[strlen (g->mes1) - 1] = 0;
-    g->mes2[strlen (g->mes2) - 1] = 0;
-
-    for (j = 0; j < 6 && str != NULL; j++)  // 位置スキップ
-        str = strchr (str + 1, '\t');
-//  printf("GuildBaseInfo OK\n");
-
-    // メンバー
-    for (i = 0; i < g->max_member; i++)
-    {
-        struct guild_member *m = &g->member[i];
-        if (sscanf (str + 1, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\t%[^\t]\t",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7],
-                    &tmp_int[8], &tmp_int[9], tmp_str[0]) < 11)
-            return 1;
-        m->account_id = tmp_int[0];
-        m->char_id = 0 /*tmp_int[1]*/;
-        m->hair = tmp_int[2];
-        m->hair_color = tmp_int[3];
-        m->gender = tmp_int[4];
-        m->pc_class = tmp_int[5];
-        m->lv = tmp_int[6];
-        m->exp = tmp_int[7];
-        m->exp_payper = tmp_int[8];
-        m->position = tmp_int[9];
-        memcpy (m->name, tmp_str[0], 24);
-
-        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
-            str = strchr (str + 1, '\t');
-    }
-//  printf("GuildMemberInfo OK\n");
-    // 役職
-    i = 0;
-    while (sscanf (str + 1, "%d,%d%n", &tmp_int[0], &tmp_int[1], &j) == 2
-           && str[1 + j] == '\t')
-    {
-        struct guild_position *p = &g->position[i];
-        if (sscanf
-            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
-             tmp_str[0]) < 3)
-            return 1;
-        p->mode = tmp_int[0];
-        p->exp_mode = tmp_int[1];
-        tmp_str[0][strlen (tmp_str[0]) - 1] = 0;
-        memcpy (p->name, tmp_str[0], 24);
-
-        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
-            str = strchr (str + 1, '\t');
-        i++;
-    }
-//  printf("GuildPositionInfo OK\n");
-    // エンブレム
-    tmp_int[1] = 0;
-    if (sscanf (str + 1, "%d,%d,%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str2)
-        < 3 && sscanf (str + 1, "%d,%[^\t]\t", &tmp_int[0], tmp_str2) < 2)
-        return 1;
-    g->emblem_len = tmp_int[0];
-    g->emblem_id = tmp_int[1];
-    for (i = 0, pstr = tmp_str2; i < g->emblem_len; i++, pstr += 2)
-    {
-        int  c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0;
-        if (c1 >= '0' && c1 <= '9')
-            x1 = c1 - '0';
-        if (c1 >= 'a' && c1 <= 'f')
-            x1 = c1 - 'a' + 10;
-        if (c1 >= 'A' && c1 <= 'F')
-            x1 = c1 - 'A' + 10;
-        if (c2 >= '0' && c2 <= '9')
-            x2 = c2 - '0';
-        if (c2 >= 'a' && c2 <= 'f')
-            x2 = c2 - 'a' + 10;
-        if (c2 >= 'A' && c2 <= 'F')
-            x2 = c2 - 'A' + 10;
-        g->emblem_data[i] = (x1 << 4) | x2;
-    }
-//  printf("GuildEmblemInfo OK\n");
-    str = strchr (str + 1, '\t');   // 位置スキップ
-
-    // 同盟リスト
-    if (sscanf (str + 1, "%d\t", &c) < 1)
-        return 1;
-    str = strchr (str + 1, '\t');   // 位置スキップ
-    for (i = 0; i < c; i++)
-    {
-        struct guild_alliance *a = &g->alliance[i];
-        if (sscanf
-            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
-             tmp_str[0]) < 3)
-            return 1;
-        a->guild_id = tmp_int[0];
-        a->opposition = tmp_int[1];
-        memcpy (a->name, tmp_str[0], 24);
-
-        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
-            str = strchr (str + 1, '\t');
-    }
-//  printf("GuildAllianceInfo OK\n");
-    // 追放リスト
-    if (sscanf (str + 1, "%d\t", &c) < 1)
-        return 1;
-    str = strchr (str + 1, '\t');   // 位置スキップ
-    for (i = 0; i < c; i++)
-    {
-        struct guild_explusion *e = &g->explusion[i];
-        if (sscanf (str + 1, "%d,%d,%d,%d\t%[^\t]\t%[^\t]\t%[^\t]\t",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    tmp_str[0], tmp_str[1], tmp_str[2]) < 6)
-            return 1;
-        e->account_id = tmp_int[0];
-        e->rsv1 = tmp_int[1];
-        e->rsv2 = tmp_int[2];
-        e->rsv3 = tmp_int[3];
-        memcpy (e->name, tmp_str[0], 24);
-        memcpy (e->acc, tmp_str[1], 24);
-        tmp_str[2][strlen (tmp_str[2]) - 1] = 0;
-        memcpy (e->mes, tmp_str[2], 40);
-
-        for (j = 0; j < 4 && str != NULL; j++)  // 位置スキップ
-            str = strchr (str + 1, '\t');
-    }
-//  printf("GuildExplusionInfo OK\n");
-    // ギルドスキル
-    for (i = 0; i < MAX_GUILDSKILL; i++)
-    {
-        if (sscanf (str + 1, "%d,%d ", &tmp_int[0], &tmp_int[1]) < 2)
-            break;
-        g->skill[i].id = tmp_int[0];
-        g->skill[i].lv = tmp_int[1];
-        str = strchr (str + 1, ' ');
-    }
-    str = strchr (str + 1, '\t');
-//  printf("GuildSkillInfo OK\n");
-
-    return 0;
-}
-
-// ギルド城データの文字列への変換
-int inter_guildcastle_tostr (char *str, struct guild_castle *gc)
-{
-    int  len;
-
-    len = sprintf (str, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",    // added Guardian HP [Valaris]
-                   gc->castle_id, gc->guild_id, gc->economy, gc->defense,
-                   gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime,
-                   gc->createTime, gc->visibleC, gc->visibleG0, gc->visibleG1,
-                   gc->visibleG2, gc->visibleG3, gc->visibleG4, gc->visibleG5,
-                   gc->visibleG6, gc->visibleG7, gc->Ghp0, gc->Ghp1, gc->Ghp2,
-                   gc->Ghp3, gc->Ghp4, gc->Ghp5, gc->Ghp6, gc->Ghp7);
-
-    return 0;
-}
-
-// ギルド城データの文字列からの変換
-int inter_guildcastle_fromstr (char *str, struct guild_castle *gc)
-{
-    int  tmp_int[26];
-
-    memset (gc, 0, sizeof (struct guild_castle));
-    // new structure of guild castle
-    if (sscanf
-        (str,
-         "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
-         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4],
-         &tmp_int[5], &tmp_int[6], &tmp_int[7], &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]) == 26)
-    {
-        gc->castle_id = tmp_int[0];
-        gc->guild_id = tmp_int[1];
-        gc->economy = tmp_int[2];
-        gc->defense = tmp_int[3];
-        gc->triggerE = tmp_int[4];
-        gc->triggerD = tmp_int[5];
-        gc->nextTime = tmp_int[6];
-        gc->payTime = tmp_int[7];
-        gc->createTime = tmp_int[8];
-        gc->visibleC = tmp_int[9];
-        gc->visibleG0 = tmp_int[10];
-        gc->visibleG1 = tmp_int[11];
-        gc->visibleG2 = tmp_int[12];
-        gc->visibleG3 = tmp_int[13];
-        gc->visibleG4 = tmp_int[14];
-        gc->visibleG5 = tmp_int[15];
-        gc->visibleG6 = tmp_int[16];
-        gc->visibleG7 = tmp_int[17];
-        gc->Ghp0 = tmp_int[18];
-        gc->Ghp1 = tmp_int[19];
-        gc->Ghp2 = tmp_int[20];
-        gc->Ghp3 = tmp_int[21];
-        gc->Ghp4 = tmp_int[22];
-        gc->Ghp5 = tmp_int[23];
-        gc->Ghp6 = tmp_int[24];
-        gc->Ghp7 = tmp_int[25]; // end additions [Valaris]
-        // old structure of guild castle
-    }
-    else if (sscanf
-             (str, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
-              &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4],
-              &tmp_int[5], &tmp_int[6], &tmp_int[7], &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]) == 18)
-    {
-        gc->castle_id = tmp_int[0];
-        gc->guild_id = tmp_int[1];
-        gc->economy = tmp_int[2];
-        gc->defense = tmp_int[3];
-        gc->triggerE = tmp_int[4];
-        gc->triggerD = tmp_int[5];
-        gc->nextTime = tmp_int[6];
-        gc->payTime = tmp_int[7];
-        gc->createTime = tmp_int[8];
-        gc->visibleC = tmp_int[9];
-        gc->visibleG0 = tmp_int[10];
-        gc->visibleG1 = tmp_int[11];
-        gc->visibleG2 = tmp_int[12];
-        gc->visibleG3 = tmp_int[13];
-        gc->visibleG4 = tmp_int[14];
-        gc->visibleG5 = tmp_int[15];
-        gc->visibleG6 = tmp_int[16];
-        gc->visibleG7 = tmp_int[17];
-        if (gc->visibleG0 == 1)
-            gc->Ghp0 = 15670 + 2000 * gc->defense;
-        else
-            gc->Ghp0 = 0;
-        if (gc->visibleG1 == 1)
-            gc->Ghp1 = 15670 + 2000 * gc->defense;
-        else
-            gc->Ghp1 = 0;
-        if (gc->visibleG2 == 1)
-            gc->Ghp2 = 15670 + 2000 * gc->defense;
-        else
-            gc->Ghp2 = 0;
-        if (gc->visibleG3 == 1)
-            gc->Ghp3 = 30214 + 2000 * gc->defense;
-        else
-            gc->Ghp3 = 0;
-        if (gc->visibleG4 == 1)
-            gc->Ghp4 = 30214 + 2000 * gc->defense;
-        else
-            gc->Ghp4 = 0;
-        if (gc->visibleG5 == 1)
-            gc->Ghp5 = 28634 + 2000 * gc->defense;
-        else
-            gc->Ghp5 = 0;
-        if (gc->visibleG6 == 1)
-            gc->Ghp6 = 28634 + 2000 * gc->defense;
-        else
-            gc->Ghp6 = 0;
-        if (gc->visibleG7 == 1)
-            gc->Ghp7 = 28634 + 2000 * gc->defense;
-        else
-            gc->Ghp7 = 0;
-    }
-    else
-    {
-        return 1;
-    }
-
-    return 0;
-}
-
-// ギルド関連データベース読み込み
-int inter_guild_readdb (void)
-{
-    int  i;
-    FILE *fp;
-    char line[1024];
-
-    fp = fopen_ ("db/exp_guild.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/exp_guild.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp) && i < 100)
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        guild_exp[i] = atoi (line);
-        i++;
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-// ギルドデータの読み込み
-int inter_guild_init (void)
-{
-    char line[16384];
-    struct guild *g;
-    struct guild_castle *gc;
-    FILE *fp;
-    int  i, j, c = 0;
-
-    inter_guild_readdb ();
-
-    guild_db = numdb_init ();
-    castle_db = numdb_init ();
-
-    if ((fp = fopen_ (guild_txt, "r")) == NULL)
-        return 1;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        j = 0;
-        if (sscanf (line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
-            && guild_newid <= i)
-        {
-            guild_newid = i;
-            continue;
-        }
-        CREATE (g, struct guild, 1);
-        if (inter_guild_fromstr (line, g) == 0 && g->guild_id > 0)
-        {
-            if (g->guild_id >= guild_newid)
-                guild_newid = g->guild_id + 1;
-            numdb_insert (guild_db, g->guild_id, g);
-            guild_check_empty (g);
-            guild_calcinfo (g);
-        }
-        else
-        {
-            printf ("int_guild: broken data [%s] line %d\n", guild_txt, c);
-            free (g);
-        }
-        c++;
-    }
-    fclose_ (fp);
-//  printf("int_guild: %s read done (%d guilds)\n", guild_txt, c);
-
-    c = 0;                      //カウンタ初期化
-
-    if ((fp = fopen_ (castle_txt, "r")) == NULL)
-    {
-        return 1;
-    }
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        CREATE (gc, struct guild_castle, 1);
-        if (inter_guildcastle_fromstr (line, gc) == 0)
-        {
-            numdb_insert (castle_db, gc->castle_id, gc);
-        }
-        else
-        {
-            printf ("int_guild: broken data [%s] line %d\n", castle_txt, c);
-            free (gc);
-        }
-        c++;
-    }
-
-    if (!c)
-    {
-        printf (" %s - making Default Data...\n", castle_txt);
-        //デフォルトデータを作成
-        for (i = 0; i < MAX_GUILDCASTLE; i++)
-        {
-            CREATE (gc, struct guild_castle, 1);
-            gc->castle_id = i;
-            gc->guild_id = 0;
-            gc->economy = 0;
-            gc->defense = 0;
-            gc->triggerE = 0;
-            gc->triggerD = 0;
-            gc->nextTime = 0;
-            gc->payTime = 0;
-            gc->createTime = 0;
-            gc->visibleC = 0;
-            gc->visibleG0 = 0;
-            gc->visibleG1 = 0;
-            gc->visibleG2 = 0;
-            gc->visibleG3 = 0;
-            gc->visibleG4 = 0;
-            gc->visibleG5 = 0;
-            gc->visibleG6 = 0;
-            gc->visibleG7 = 0;
-            gc->Ghp0 = 0;       // guardian HP [Valaris]
-            gc->Ghp1 = 0;
-            gc->Ghp2 = 0;
-            gc->Ghp3 = 0;
-            gc->Ghp4 = 0;
-            gc->Ghp5 = 0;
-            gc->Ghp6 = 0;
-            gc->Ghp7 = 0;       // end additions [Valaris]
-            numdb_insert (castle_db, gc->castle_id, gc);
-        }
-        printf (" %s - making done\n", castle_txt);
-        return 0;
-    }
-
-    fclose_ (fp);
-
-    return 0;
-}
-
-struct guild *inter_guild_search (int guild_id)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-
-    return g;
-}
-
-// ギルドデータのセーブ用
-void inter_guild_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[16384];
-    FILE *fp;
-
-    inter_guild_tostr (line, (struct guild *) data);
-    fp = va_arg (ap, FILE *);
-    fprintf (fp, "%s\n", line);
-}
-
-// ギルド城データのセーブ用
-void inter_castle_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[16384];
-    FILE *fp;
-
-    inter_guildcastle_tostr (line, (struct guild_castle *) data);
-    fp = va_arg (ap, FILE *);
-    fprintf (fp, "%s\n", line);
-}
-
-// ギルドデータのセーブ
-int inter_guild_save (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if ((fp = lock_fopen (guild_txt, &lock)) == NULL)
-    {
-        printf ("int_guild: cant write [%s] !!! data is lost !!!\n",
-                guild_txt);
-        return 1;
-    }
-    numdb_foreach (guild_db, inter_guild_save_sub, fp);
-//  fprintf(fp, "%d\t%%newid%%\n", guild_newid);
-    lock_fclose (fp, guild_txt, &lock);
-//  printf("int_guild: %s saved.\n", guild_txt);
-
-    if ((fp = lock_fopen (castle_txt, &lock)) == NULL)
-    {
-        printf ("int_guild: cant write [%s] !!! data is lost !!!\n",
-                castle_txt);
-        return 1;
-    }
-    numdb_foreach (castle_db, inter_castle_save_sub, fp);
-    lock_fclose (fp, castle_txt, &lock);
-
-    return 0;
-}
-
-// ギルド名検索用
-void search_guildname_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild *g = (struct guild *) data, **dst;
-    char *str;
-
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct guild **);
-    if (strcasecmp (g->name, str) == 0)
-        *dst = g;
-}
-
-// ギルド名検索
-struct guild *search_guildname (char *str)
-{
-    struct guild *g = NULL;
-    numdb_foreach (guild_db, search_guildname_sub, str, &g);
-    return g;
-}
-
-// ギルドが空かどうかチェック
-int guild_check_empty (struct guild *g)
-{
-    int  i;
-
-    for (i = 0; i < g->max_member; i++)
-    {
-        if (g->member[i].account_id > 0)
-        {
-            return 0;
-        }
-    }
-    // 誰もいないので解散
-    numdb_foreach (guild_db, guild_break_sub, g->guild_id);
-    numdb_erase (guild_db, g->guild_id);
-    inter_guild_storage_delete (g->guild_id);
-    mapif_guild_broken (g->guild_id, 0);
-    free (g);
-
-    return 1;
-}
-
-// キャラの競合がないかチェック用
-void guild_check_conflict_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild *g = (struct guild *) data;
-    int  guild_id, account_id, char_id, i;
-
-    guild_id = va_arg (ap, int);
-    account_id = va_arg (ap, int);
-    char_id = va_arg (ap, int);
-
-    if (g->guild_id == guild_id)    // 本来の所属なので問題なし
-        return;
-
-    for (i = 0; i < MAX_GUILD; i++)
-    {
-        if (g->member[i].account_id == account_id)
-        {
-            // 別のギルドに偽の所属データがあるので脱退
-            printf ("int_guild: guild conflict! %d,%d %d!=%d\n", account_id,
-                    char_id, guild_id, g->guild_id);
-            mapif_parse_GuildLeave (-1, g->guild_id, account_id, 0 /*char_id*/, 0,
-                                    "**データ競合**");
-        }
-    }
-}
-
-// キャラの競合がないかチェック
-int guild_check_conflict (int guild_id, int account_id, int char_id)
-{
-    numdb_foreach (guild_db, guild_check_conflict_sub, guild_id, account_id,
-                   0 /*char_id*/);
-
-    return 0;
-}
-
-int guild_nextexp (int level)
-{
-    if (level < 100)
-        return guild_exp[level - 1];
-
-    return 0;
-}
-
-// ギルドスキルがあるか確認
-int guild_checkskill (struct guild *g, int id)
-{
-    return g->skill[id - 10000].lv;
-}
-
-// ギルドの情報の再計算
-int guild_calcinfo (struct guild *g)
-{
-    int  i, c, nextexp;
-    struct guild before = *g;
-
-    // スキルIDの設定
-    for (i = 0; i < 5; i++)
-        g->skill[i].id = i + 10000;
-
-    // ギルドレベル
-    if (g->guild_lv <= 0)
-        g->guild_lv = 1;
-    nextexp = guild_nextexp (g->guild_lv);
-    if (nextexp > 0)
-    {
-        while (g->exp >= nextexp)
-        {                       // レベルアップ処理
-            g->exp -= nextexp;
-            g->guild_lv++;
-            g->skill_point++;
-            nextexp = guild_nextexp (g->guild_lv);
-        }
-    }
-
-    // ギルドの次の経験値
-    g->next_exp = guild_nextexp (g->guild_lv);
-
-    // メンバ上限(ギルド拡張適用)
-    g->max_member = 100 + guild_checkskill (g, 10004) * 2;
-
-    // 平均レベルとオンライン人数
-    g->average_lv = 0;
-    g->connect_member = 0;
-    c = 0;
-    for (i = 0; i < g->max_member; i++)
-    {
-        if (g->member[i].account_id > 0)
-        {
-            g->average_lv += g->member[i].lv;
-            c++;
-            if (g->member[i].online > 0)
-                g->connect_member++;
-        }
-    }
-    g->average_lv /= c;
-
-    // 全データを送る必要がありそう
-    if (g->max_member != before.max_member ||
-        g->guild_lv != before.guild_lv ||
-        g->skill_point != before.skill_point)
-    {
-        mapif_guild_info (-1, g);
-        return 1;
-    }
-
-    return 0;
-}
-
-//-------------------------------------------------------------------
-// map serverへの通信
-
-// ギルド作成可否
-int mapif_guild_created (int fd, int account_id, struct guild *g)
-{
-    WFIFOW (fd, 0) = 0x3830;
-    WFIFOL (fd, 2) = account_id;
-    if (g != NULL)
-    {
-        WFIFOL (fd, 6) = g->guild_id;
-        printf ("int_guild: created! %d %s\n", g->guild_id, g->name);
-    }
-    else
-    {
-        WFIFOL (fd, 6) = 0;
-    }
-    WFIFOSET (fd, 10);
-    return 0;
-}
-
-// ギルド情報見つからず
-int mapif_guild_noinfo (int fd, int guild_id)
-{
-    WFIFOW (fd, 0) = 0x3831;
-    WFIFOW (fd, 2) = 8;
-    WFIFOL (fd, 4) = guild_id;
-    WFIFOSET (fd, 8);
-    printf ("int_guild: info not found %d\n", guild_id);
-
-    return 0;
-}
-
-// ギルド情報まとめ送り
-int mapif_guild_info (int fd, struct guild *g)
-{
-    unsigned char buf[4 + sizeof (struct guild)];
-
-    WBUFW (buf, 0) = 0x3831;
-    memcpy (buf + 4, g, sizeof (struct guild));
-    WBUFW (buf, 2) = 4 + sizeof (struct guild);
-//  printf("int_guild: sizeof(guild)=%d\n", sizeof(struct guild));
-    if (fd < 0)
-        mapif_sendall (buf, WBUFW (buf, 2));
-    else
-        mapif_send (fd, buf, WBUFW (buf, 2));
-//  printf("int_guild: info %d %s\n", p->guild_id, p->name);
-
-    return 0;
-}
-
-// メンバ追加可否
-int mapif_guild_memberadded (int fd, int guild_id, int account_id,
-                             int char_id, int flag)
-{
-    WFIFOW (fd, 0) = 0x3832;
-    WFIFOL (fd, 2) = guild_id;
-    WFIFOL (fd, 6) = account_id;
-    WFIFOL (fd, 10) = 0 /*char_id*/;
-    WFIFOB (fd, 14) = flag;
-    WFIFOSET (fd, 15);
-
-    return 0;
-}
-
-// 脱退/追放通知
-int mapif_guild_leaved (int guild_id, int account_id, int char_id, int flag,
-                        const char *name, const char *mes)
-{
-    unsigned char buf[79];
-
-    WBUFW (buf, 0) = 0x3834;
-    WBUFL (buf, 2) = guild_id;
-    WBUFL (buf, 6) = account_id;
-    WBUFL (buf, 10) = 0 /*char_id*/;
-    WBUFB (buf, 14) = flag;
-    memcpy (WBUFP (buf, 15), mes, 40);
-    memcpy (WBUFP (buf, 55), name, 24);
-    mapif_sendall (buf, 79);
-    printf ("int_guild: guild leaved %d %d %s %s\n", guild_id, account_id,
-            name, mes);
-
-    return 0;
-}
-
-// オンライン状態とLv更新通知
-int mapif_guild_memberinfoshort (struct guild *g, int idx)
-{
-    unsigned char buf[19];
-
-    WBUFW (buf, 0) = 0x3835;
-    WBUFL (buf, 2) = g->guild_id;
-    WBUFL (buf, 6) = g->member[idx].account_id;
-    WBUFL (buf, 10) = 0 /*g->member[idx].char_id*/;
-    WBUFB (buf, 14) = g->member[idx].online;
-    WBUFW (buf, 15) = g->member[idx].lv;
-    WBUFW (buf, 17) = g->member[idx].pc_class;
-    mapif_sendall (buf, 19);
-    return 0;
-}
-
-// 解散通知
-int mapif_guild_broken (int guild_id, int flag)
-{
-    unsigned char buf[7];
-
-    WBUFW (buf, 0) = 0x3836;
-    WBUFL (buf, 2) = guild_id;
-    WBUFB (buf, 6) = flag;
-    mapif_sendall (buf, 7);
-    printf ("int_guild: broken %d\n", guild_id);
-
-    return 0;
-}
-
-// ギルド内発言
-int mapif_guild_message (int guild_id, int account_id, char *mes, int len)
-{
-    unsigned char buf[len + 12];
-
-    WBUFW (buf, 0) = 0x3837;
-    WBUFW (buf, 2) = len + 12;
-    WBUFL (buf, 4) = guild_id;
-    WBUFL (buf, 8) = account_id;
-    memcpy (WBUFP (buf, 12), mes, len);
-    mapif_sendall (buf, len + 12);
-
-    return 0;
-}
-
-// ギルド基本情報変更通知
-int mapif_guild_basicinfochanged (int guild_id, int type, const void *data,
-                                  int len)
-{
-    unsigned char buf[2048];
-
-    WBUFW (buf, 0) = 0x3839;
-    WBUFW (buf, 2) = len + 10;
-    WBUFL (buf, 4) = guild_id;
-    WBUFW (buf, 8) = type;
-    memcpy (WBUFP (buf, 10), data, len);
-    mapif_sendall (buf, len + 10);
-    return 0;
-}
-
-// ギルドメンバ情報変更通知
-int mapif_guild_memberinfochanged (int guild_id, int account_id, int char_id,
-                                   int type, const void *data, int len)
-{
-    unsigned char buf[len + 18];
-
-    WBUFW (buf, 0) = 0x383a;
-    WBUFW (buf, 2) = len + 18;
-    WBUFL (buf, 4) = guild_id;
-    WBUFL (buf, 8) = account_id;
-    WBUFL (buf, 12) = 0 /*char_id*/;
-    WBUFW (buf, 16) = type;
-    memcpy (WBUFP (buf, 18), data, len);
-    mapif_sendall (buf, len + 18);
-
-    return 0;
-}
-
-// ギルドスキルアップ通知
-int mapif_guild_skillupack (int guild_id, int skill_num, int account_id)
-{
-    unsigned char buf[14];
-
-    WBUFW (buf, 0) = 0x383c;
-    WBUFL (buf, 2) = guild_id;
-    WBUFL (buf, 6) = skill_num;
-    WBUFL (buf, 10) = account_id;
-    mapif_sendall (buf, 14);
-
-    return 0;
-}
-
-// ギルド同盟/敵対通知
-int mapif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
-                          int account_id2, int flag, const char *name1,
-                          const char *name2)
-{
-    unsigned char buf[67];
-
-    WBUFW (buf, 0) = 0x383d;
-    WBUFL (buf, 2) = guild_id1;
-    WBUFL (buf, 6) = guild_id2;
-    WBUFL (buf, 10) = account_id1;
-    WBUFL (buf, 14) = account_id2;
-    WBUFB (buf, 18) = flag;
-    memcpy (WBUFP (buf, 19), name1, 24);
-    memcpy (WBUFP (buf, 43), name2, 24);
-    mapif_sendall (buf, 67);
-
-    return 0;
-}
-
-// ギルド役職変更通知
-int mapif_guild_position (struct guild *g, int idx)
-{
-    unsigned char buf[sizeof (struct guild_position) + 12];
-
-    WBUFW (buf, 0) = 0x383b;
-    WBUFW (buf, 2) = sizeof (struct guild_position) + 12;
-    WBUFL (buf, 4) = g->guild_id;
-    WBUFL (buf, 8) = idx;
-    memcpy (WBUFP (buf, 12), &g->position[idx],
-            sizeof (struct guild_position));
-    mapif_sendall (buf, WBUFW (buf, 2));
-
-    return 0;
-}
-
-// ギルド告知変更通知
-int mapif_guild_notice (struct guild *g)
-{
-    unsigned char buf[186];
-
-    WBUFW (buf, 0) = 0x383e;
-    WBUFL (buf, 2) = g->guild_id;
-    memcpy (WBUFP (buf, 6), g->mes1, 60);
-    memcpy (WBUFP (buf, 66), g->mes2, 120);
-    mapif_sendall (buf, 186);
-
-    return 0;
-}
-
-// ギルドエンブレム変更通知
-int mapif_guild_emblem (struct guild *g)
-{
-    unsigned char buf[2048];
-
-    WBUFW (buf, 0) = 0x383f;
-    WBUFW (buf, 2) = g->emblem_len + 12;
-    WBUFL (buf, 4) = g->guild_id;
-    WBUFL (buf, 8) = g->emblem_id;
-    memcpy (WBUFP (buf, 12), g->emblem_data, g->emblem_len);
-    mapif_sendall (buf, WBUFW (buf, 2));
-
-    return 0;
-}
-
-int mapif_guild_castle_dataload (int castle_id, int index, int value)
-{
-    unsigned char buf[9];
-
-    WBUFW (buf, 0) = 0x3840;
-    WBUFW (buf, 2) = castle_id;
-    WBUFB (buf, 4) = index;
-    WBUFL (buf, 5) = value;
-    mapif_sendall (buf, 9);
-
-    return 0;
-}
-
-int mapif_guild_castle_datasave (int castle_id, int index, int value)
-{
-    unsigned char buf[9];
-
-    WBUFW (buf, 0) = 0x3841;
-    WBUFW (buf, 2) = castle_id;
-    WBUFB (buf, 4) = index;
-    WBUFL (buf, 5) = value;
-    mapif_sendall (buf, 9);
-
-    return 0;
-}
-
-void mapif_guild_castle_alldataload_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    int  fd = va_arg (ap, int);
-    int *p = va_arg (ap, int *);
-
-    memcpy (WFIFOP (fd, *p), (struct guild_castle *) data,
-            sizeof (struct guild_castle));
-    (*p) += sizeof (struct guild_castle);
-}
-
-int mapif_guild_castle_alldataload (int fd)
-{
-    int  len = 4;
-
-    WFIFOW (fd, 0) = 0x3842;
-    numdb_foreach (castle_db, mapif_guild_castle_alldataload_sub, fd, &len);
-    WFIFOW (fd, 2) = len;
-    WFIFOSET (fd, len);
-
-    return 0;
-}
-
-//-------------------------------------------------------------------
-// map serverからの通信
-
-// ギルド作成要求
-int mapif_parse_CreateGuild (int fd, int account_id, char *name,
-                             struct guild_member *master)
-{
-    struct guild *g;
-    int  i;
-
-    for (i = 0; i < 24 && name[i]; i++)
-    {
-        if (!(name[i] & 0xe0) || name[i] == 0x7f)
-        {
-            printf ("int_guild: illeagal guild name [%s]\n", name);
-            mapif_guild_created (fd, account_id, NULL);
-            return 0;
-        }
-    }
-
-    if ((g = search_guildname (name)) != NULL)
-    {
-        printf ("int_guild: same name guild exists [%s]\n", name);
-        mapif_guild_created (fd, account_id, NULL);
-        return 0;
-    }
-    CREATE (g, struct guild, 1);
-    g->guild_id = guild_newid++;
-    memcpy (g->name, name, 24);
-    memcpy (g->master, master->name, 24);
-    memcpy (&g->member[0], master, sizeof (struct guild_member));
-
-    g->position[0].mode = 0x11;
-    strcpy (g->position[0].name, "GuildMaster");
-    strcpy (g->position[MAX_GUILDPOSITION - 1].name, "Newbie");
-    for (i = 1; i < MAX_GUILDPOSITION - 1; i++)
-        sprintf (g->position[i].name, "Position %d", i + 1);
-
-    // ここでギルド情報計算が必要と思われる
-    g->max_member = 100;
-    g->average_lv = master->lv;
-    for (i = 0; i < 5; i++)
-        g->skill[i].id = i + 10000;
-
-    numdb_insert (guild_db, g->guild_id, g);
-
-    mapif_guild_created (fd, account_id, g);
-    mapif_guild_info (fd, g);
-
-    inter_log ("guild %s (id=%d) created by master %s (id=%d)\n",
-               name, g->guild_id, master->name, master->account_id);
-
-    return 0;
-}
-
-// ギルド情報要求
-int mapif_parse_GuildInfo (int fd, int guild_id)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g != NULL)
-    {
-        guild_calcinfo (g);
-        mapif_guild_info (fd, g);
-    }
-    else
-        mapif_guild_noinfo (fd, guild_id);
-
-    return 0;
-}
-
-// ギルドメンバ追加要求
-int mapif_parse_GuildAddMember (int fd, int guild_id, struct guild_member *m)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-    {
-        mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/, 1);
-        return 0;
-    }
-
-    for (int i = 0; i < g->max_member; i++)
-    {
-        if (g->member[i].account_id == 0)
-        {
-            memcpy (&g->member[i], m, sizeof (struct guild_member));
-            mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/,
-                                     0);
-            guild_calcinfo (g);
-            mapif_guild_info (-1, g);
-
-            return 0;
-        }
-    }
-    mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/, 1);
-
-    return 0;
-}
-
-// ギルド脱退/追放要求
-int mapif_parse_GuildLeave (int fd, int guild_id, int account_id, int char_id,
-                            int flag, const char *mes)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g != NULL)
-    {
-        for (int i = 0; i < MAX_GUILD; i++)
-        {
-            if (g->member[i].account_id == account_id)
-            {
-//              printf("%d %d\n", i, (int)(&g->member[i]));
-//              printf("%d %s\n", i, g->member[i].name);
-
-                if (flag)
-                {
-                    int j;
-                    // 追放の場合追放リストに入れる
-                    for (j = 0; j < MAX_GUILDEXPLUSION; j++)
-                    {
-                        if (g->explusion[j].account_id == 0)
-                            break;
-                    }
-                    if (j == MAX_GUILDEXPLUSION)
-                    {           // 一杯なので古いのを消す
-                        for (j = 0; j < MAX_GUILDEXPLUSION - 1; j++)
-                            g->explusion[j] = g->explusion[j + 1];
-                        j = MAX_GUILDEXPLUSION - 1;
-                    }
-                    g->explusion[j].account_id = account_id;
-                    memcpy (g->explusion[j].acc, "dummy", 24);
-                    memcpy (g->explusion[j].name, g->member[i].name, 24);
-                    memcpy (g->explusion[j].mes, mes, 40);
-                }
-
-                mapif_guild_leaved (guild_id, account_id, 0 /*char_id*/, flag,
-                                    g->member[i].name, mes);
-//              printf("%d %d\n", i, (int)(&g->member[i]));
-//              printf("%d %s\n", i, (&g->member[i])->name);
-                memset (&g->member[i], 0, sizeof (struct guild_member));
-
-                if (guild_check_empty (g) == 0)
-                    mapif_guild_info (-1, g);   // まだ人がいるのでデータ送信
-
-                return 0;
-            }
-        }
-    }
-    return 0;
-}
-
-// オンライン/Lv更新
-int mapif_parse_GuildChangeMemberInfoShort (int fd, int guild_id,
-                                            int account_id, int char_id,
-                                            int online, int lv, int pc_class)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-
-    g->connect_member = 0;
-
-    int alv = 0;
-    int c = 0;
-    for (int i = 0; i < MAX_GUILD; i++)
-    {
-        if (g->member[i].account_id == account_id)
-        {
-            g->member[i].online = online;
-            g->member[i].lv = lv;
-            g->member[i].pc_class = pc_class;
-            mapif_guild_memberinfoshort (g, i);
-        }
-        if (g->member[i].account_id > 0)
-        {
-            alv += g->member[i].lv;
-            c++;
-        }
-        if (g->member[i].online)
-            g->connect_member++;
-    }
-    // 平均レベル
-    g->average_lv = alv / c;
-
-    return 0;
-}
-
-// ギルド解散処理用(同盟/敵対を解除)
-void guild_break_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild *g = (struct guild *) data;
-    int  guild_id = va_arg (ap, int);
-    int  i;
-
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-    {
-        if (g->alliance[i].guild_id == guild_id)
-            g->alliance[i].guild_id = 0;
-    }
-}
-
-// ギルド解散要求
-int mapif_parse_BreakGuild (int fd, int guild_id)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-
-    numdb_foreach (guild_db, guild_break_sub, guild_id);
-    numdb_erase (guild_db, guild_id);
-    inter_guild_storage_delete (guild_id);
-    mapif_guild_broken (guild_id, 0);
-
-    inter_log ("guild %s (id=%d) broken\n", g->name, guild_id);
-    free (g);
-
-    return 0;
-}
-
-// ギルドメッセージ送信
-int mapif_parse_GuildMessage (int fd, int guild_id, int account_id, char *mes,
-                              int len)
-{
-    return mapif_guild_message (guild_id, account_id, mes, len);
-}
-
-// ギルド基本データ変更要求
-int mapif_parse_GuildBasicInfoChange (int fd, int guild_id, int type,
-                                      const char *data, int len)
-{
-    short dw = *((short *) data);
-
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-
-    switch (type)
-    {
-        case GBI_GUILDLV:
-            if (dw > 0 && g->guild_lv + dw <= 50)
-            {
-                g->guild_lv += dw;
-                g->skill_point += dw;
-            }
-            else if (dw < 0 && g->guild_lv + dw >= 1)
-                g->guild_lv += dw;
-            mapif_guild_info (-1, g);
-            return 0;
-        default:
-            printf ("int_guild: GuildBasicInfoChange: Unknown type %d\n",
-                    type);
-            break;
-    }
-    mapif_guild_basicinfochanged (guild_id, type, data, len);
-
-    return 0;
-}
-
-// ギルドメンバデータ変更要求
-int mapif_parse_GuildMemberInfoChange (int fd, int guild_id, int account_id,
-                                       int char_id, int type,
-                                       const char *data, int len)
-{
-    int  i;
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-
-    for (i = 0; i < g->max_member; i++)
-        if (g->member[i].account_id == account_id)
-            break;
-    if (i == g->max_member)
-    {
-        printf ("int_guild: GuildMemberChange: Not found %d,%d in %d[%s]\n",
-                account_id, char_id, guild_id, g->name);
-        return 0;
-    }
-    switch (type)
-    {
-        case GMI_POSITION:     // 役職
-            g->member[i].position = *((int *) data);
-            break;
-        case GMI_EXP:          // EXP
-        {
-            int  exp, oldexp = g->member[i].exp;
-            exp = g->member[i].exp = *((unsigned int *) data);
-            g->exp += (exp - oldexp);
-            guild_calcinfo (g); // Lvアップ判断
-            mapif_guild_basicinfochanged (guild_id, GBI_EXP, &g->exp, 4);
-        }
-            break;
-        default:
-            printf ("int_guild: GuildMemberInfoChange: Unknown type %d\n",
-                    type);
-            break;
-    }
-    mapif_guild_memberinfochanged (guild_id, account_id, char_id, type, data,
-                                   len);
-
-    return 0;
-}
-
-// ギルド役職名変更要求
-int mapif_parse_GuildPosition (int fd, int guild_id, int idx,
-                               struct guild_position *p)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-
-    if (g == NULL || idx < 0 || idx >= MAX_GUILDPOSITION)
-    {
-        return 0;
-    }
-    memcpy (&g->position[idx], p, sizeof (struct guild_position));
-    mapif_guild_position (g, idx);
-    printf ("int_guild: position changed %d\n", idx);
-
-    return 0;
-}
-
-// ギルドスキルアップ要求
-int mapif_parse_GuildSkillUp (int fd, int guild_id, int skill_num,
-                              int account_id)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    int  idx = skill_num - 10000;
-
-    if (g == NULL || skill_num < 10000)
-        return 0;
-
-    if (g->skill_point > 0 && g->skill[idx].id > 0 && g->skill[idx].lv < 10)
-    {
-        g->skill[idx].lv++;
-        g->skill_point--;
-        if (guild_calcinfo (g) == 0)
-            mapif_guild_info (-1, g);
-        mapif_guild_skillupack (guild_id, skill_num, account_id);
-        printf ("int_guild: skill %d up\n", skill_num);
-    }
-
-    return 0;
-}
-
-// ギルド同盟要求
-int mapif_parse_GuildAlliance (int fd, int guild_id1, int guild_id2,
-                               int account_id1, int account_id2, int flag)
-{
-    struct guild *g[2];
-    int  j, i;
-
-    g[0] = (struct guild *)numdb_search (guild_db, guild_id1);
-    g[1] = (struct guild *)numdb_search (guild_db, guild_id2);
-    if (g[0] == NULL || g[1] == NULL)
-        return 0;
-
-    if (!(flag & 0x8))
-    {
-        for (i = 0; i < 2 - (flag & 1); i++)
-        {
-            for (j = 0; j < MAX_GUILDALLIANCE; j++)
-                if (g[i]->alliance[j].guild_id == 0)
-                {
-                    g[i]->alliance[j].guild_id = g[1 - i]->guild_id;
-                    memcpy (g[i]->alliance[j].name, g[1 - i]->name, 24);
-                    g[i]->alliance[j].opposition = flag & 1;
-                    break;
-                }
-        }
-    }
-    else
-    {                           // 関係解消
-        for (i = 0; i < 2 - (flag & 1); i++)
-        {
-            for (j = 0; j < MAX_GUILDALLIANCE; j++)
-                if (g[i]->alliance[j].guild_id == g[1 - i]->guild_id
-                    && g[i]->alliance[j].opposition == (flag & 1))
-                {
-                    g[i]->alliance[j].guild_id = 0;
-                    break;
-                }
-        }
-    }
-    mapif_guild_alliance (guild_id1, guild_id2, account_id1, account_id2,
-                          flag, g[0]->name, g[1]->name);
-
-    return 0;
-}
-
-// ギルド告知変更要求
-int mapif_parse_GuildNotice (int fd, int guild_id, const char *mes1,
-                             const char *mes2)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-    memcpy (g->mes1, mes1, 60);
-    memcpy (g->mes2, mes2, 120);
-
-    return mapif_guild_notice (g);
-}
-
-// ギルドエンブレム変更要求
-int mapif_parse_GuildEmblem (int fd, int len, int guild_id, int dummy,
-                             const char *data)
-{
-    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
-    if (g == NULL)
-        return 0;
-    memcpy (g->emblem_data, data, len);
-    g->emblem_len = len;
-    g->emblem_id++;
-
-    return mapif_guild_emblem (g);
-}
-
-int mapif_parse_GuildCastleDataLoad (int fd, int castle_id, int index)
-{
-    struct guild_castle *gc = (struct guild_castle *)numdb_search (castle_db, castle_id);
-
-    if (gc == NULL)
-    {
-        return mapif_guild_castle_dataload (castle_id, 0, 0);
-    }
-    switch (index)
-    {
-        case 1:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->guild_id);
-        case 2:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->economy);
-        case 3:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->defense);
-        case 4:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->triggerE);
-        case 5:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->triggerD);
-        case 6:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->nextTime);
-        case 7:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->payTime);
-        case 8:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->createTime);
-        case 9:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleC);
-        case 10:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG0);
-        case 11:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG1);
-        case 12:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG2);
-        case 13:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG3);
-        case 14:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG4);
-        case 15:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG5);
-        case 16:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG6);
-        case 17:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->visibleG7);
-        case 18:
-            return mapif_guild_castle_dataload (gc->castle_id, index, gc->Ghp0);    // guardian HP [Valaris]
-        case 19:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp1);
-        case 20:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp2);
-        case 21:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp3);
-        case 22:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp4);
-        case 23:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp5);
-        case 24:
-            return mapif_guild_castle_dataload (gc->castle_id, index,
-                                                gc->Ghp6);
-        case 25:
-            return mapif_guild_castle_dataload (gc->castle_id, index, gc->Ghp7);    // end additions [Valaris]
-
-        default:
-            printf
-                ("mapif_parse_GuildCastleDataLoad ERROR!! (Not found index=%d)\n",
-                 index);
-            return 0;
-    }
-
-    return 0;
-}
-
-int mapif_parse_GuildCastleDataSave (int fd, int castle_id, int index,
-                                     int value)
-{
-    struct guild_castle *gc = (struct guild_castle *)numdb_search (castle_db, castle_id);
-
-    if (gc == NULL)
-    {
-        return mapif_guild_castle_datasave (castle_id, index, value);
-    }
-    switch (index)
-    {
-        case 1:
-            if (gc->guild_id != value)
-            {
-                int  gid = (value) ? value : gc->guild_id;
-                struct guild *g = (struct guild *)numdb_search (guild_db, gid);
-                inter_log ("guild %s (id=%d) %s castle id=%d\n",
-                           (g) ? g->name : "??", gid,
-                           (value) ? "occupy" : "abandon", index);
-            }
-            gc->guild_id = value;
-            break;
-        case 2:
-            gc->economy = value;
-            break;
-        case 3:
-            gc->defense = value;
-            break;
-        case 4:
-            gc->triggerE = value;
-            break;
-        case 5:
-            gc->triggerD = value;
-            break;
-        case 6:
-            gc->nextTime = value;
-            break;
-        case 7:
-            gc->payTime = value;
-            break;
-        case 8:
-            gc->createTime = value;
-            break;
-        case 9:
-            gc->visibleC = value;
-            break;
-        case 10:
-            gc->visibleG0 = value;
-            break;
-        case 11:
-            gc->visibleG1 = value;
-            break;
-        case 12:
-            gc->visibleG2 = value;
-            break;
-        case 13:
-            gc->visibleG3 = value;
-            break;
-        case 14:
-            gc->visibleG4 = value;
-            break;
-        case 15:
-            gc->visibleG5 = value;
-            break;
-        case 16:
-            gc->visibleG6 = value;
-            break;
-        case 17:
-            gc->visibleG7 = value;
-            break;
-        case 18:
-            gc->Ghp0 = value;
-            break;              // guardian HP [Valaris]
-        case 19:
-            gc->Ghp1 = value;
-            break;
-        case 20:
-            gc->Ghp2 = value;
-            break;
-        case 21:
-            gc->Ghp3 = value;
-            break;
-        case 22:
-            gc->Ghp4 = value;
-            break;
-        case 23:
-            gc->Ghp5 = value;
-            break;
-        case 24:
-            gc->Ghp6 = value;
-            break;
-        case 25:
-            gc->Ghp7 = value;
-            break;              // end additions [Valaris]
-        default:
-            printf
-                ("mapif_parse_GuildCastleDataSave ERROR!! (Not found index=%d)\n",
-                 index);
-            return 0;
-    }
-
-    return mapif_guild_castle_datasave (gc->castle_id, index, value);
-}
-
-// ギルドチェック要求
-int mapif_parse_GuildCheck (int fd, int guild_id, int account_id, int char_id)
-{
-    return guild_check_conflict (guild_id, account_id, 0 /*char_id*/);
-}
-
-// map server からの通信
-// ・1パケットのみ解析すること
-// ・パケット長データはinter.cにセットしておくこと
-// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
-// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
-int inter_guild_parse_frommap (int fd)
-{
-    switch (RFIFOW (fd, 0))
-    {
-        case 0x3030:
-            mapif_parse_CreateGuild (fd, RFIFOL (fd, 4), RFIFOP (fd, 8),
-                                     (struct guild_member *) RFIFOP (fd, 32));
-            break;
-        case 0x3031:
-            mapif_parse_GuildInfo (fd, RFIFOL (fd, 2));
-            break;
-        case 0x3032:
-            mapif_parse_GuildAddMember (fd, RFIFOL (fd, 4),
-                                        (struct guild_member *) RFIFOP (fd,
-                                                                        8));
-            break;
-        case 0x3034:
-            mapif_parse_GuildLeave (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                    RFIFOL (fd, 10), RFIFOB (fd, 14),
-                                    RFIFOP (fd, 15));
-            break;
-        case 0x3035:
-            mapif_parse_GuildChangeMemberInfoShort (fd, RFIFOL (fd, 2),
-                                                    RFIFOL (fd, 6),
-                                                    RFIFOL (fd, 10),
-                                                    RFIFOB (fd, 14),
-                                                    RFIFOW (fd, 15),
-                                                    RFIFOW (fd, 17));
-            break;
-        case 0x3036:
-            mapif_parse_BreakGuild (fd, RFIFOL (fd, 2));
-            break;
-        case 0x3037:
-            mapif_parse_GuildMessage (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
-                                      RFIFOP (fd, 12), RFIFOW (fd, 2) - 12);
-            break;
-        case 0x3038:
-            mapif_parse_GuildCheck (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                    RFIFOL (fd, 10));
-            break;
-        case 0x3039:
-            mapif_parse_GuildBasicInfoChange (fd, RFIFOL (fd, 4),
-                                              RFIFOW (fd, 8), RFIFOP (fd, 10),
-                                              RFIFOW (fd, 2) - 10);
-            break;
-        case 0x303A:
-            mapif_parse_GuildMemberInfoChange (fd, RFIFOL (fd, 4),
-                                               RFIFOL (fd, 8), RFIFOL (fd,
-                                                                       12),
-                                               RFIFOW (fd, 16), RFIFOP (fd,
-                                                                        18),
-                                               RFIFOW (fd, 2) - 18);
-            break;
-        case 0x303B:
-            mapif_parse_GuildPosition (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
-                                       (struct guild_position *) RFIFOP (fd,
-                                                                         12));
-            break;
-        case 0x303C:
-            mapif_parse_GuildSkillUp (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                      RFIFOL (fd, 10));
-            break;
-        case 0x303D:
-            mapif_parse_GuildAlliance (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                       RFIFOL (fd, 10), RFIFOL (fd, 14),
-                                       RFIFOB (fd, 18));
-            break;
-        case 0x303E:
-            mapif_parse_GuildNotice (fd, RFIFOL (fd, 2), RFIFOP (fd, 6),
-                                     RFIFOP (fd, 66));
-            break;
-        case 0x303F:
-            mapif_parse_GuildEmblem (fd, RFIFOW (fd, 2) - 12, RFIFOL (fd, 4),
-                                     RFIFOL (fd, 8), RFIFOP (fd, 12));
-            break;
-        case 0x3040:
-            mapif_parse_GuildCastleDataLoad (fd, RFIFOW (fd, 2),
-                                             RFIFOB (fd, 4));
-            break;
-        case 0x3041:
-            mapif_parse_GuildCastleDataSave (fd, RFIFOW (fd, 2),
-                                             RFIFOB (fd, 4), RFIFOL (fd, 5));
-            break;
-
-        default:
-            return 0;
-    }
-
-    return 1;
-}
-
-// マップサーバーの接続時処理
-int inter_guild_mapif_init (int fd)
-{
-    return mapif_guild_castle_alldataload (fd);
-}
-
-// サーバーから脱退要求(キャラ削除用)
-int inter_guild_leave (int guild_id, int account_id, int char_id)
-{
-    return mapif_parse_GuildLeave (-1, guild_id, account_id, 0 /*char_id*/, 0,
-                                   "**サーバー命令**");
-}
diff --git a/src/char/int_guild.cpp b/src/char/int_guild.cpp
new file mode 100644
index 0000000..fe9a95b
--- /dev/null
+++ b/src/char/int_guild.cpp
@@ -0,0 +1,1757 @@
+// $Id: int_guild.c,v 1.2 2004/09/25 19:36:53 Akitasha Exp $
+#include "inter.hpp"
+#include "int_guild.hpp"
+#include "int_storage.hpp"
+#include "../common/mmo.hpp"
+#include "char.hpp"
+#include "../common/socket.hpp"
+#include "../common/db.hpp"
+#include "../common/lock.hpp"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+char guild_txt[1024] = "save/guild.txt";
+char castle_txt[1024] = "save/castle.txt";
+
+static struct dbt *guild_db;
+static struct dbt *castle_db;
+
+static int guild_newid = 10000;
+
+static int guild_exp[100];
+
+int  mapif_parse_GuildLeave (int fd, int guild_id, int account_id,
+                             int char_id, int flag, const char *mes);
+int  mapif_guild_broken (int guild_id, int flag);
+int  guild_check_empty (struct guild *g);
+int  guild_calcinfo (struct guild *g);
+int  mapif_guild_basicinfochanged (int guild_id, int type, const void *data,
+                                   int len);
+int  mapif_guild_info (int fd, struct guild *g);
+void guild_break_sub (db_key_t key, db_val_t data, va_list ap);
+
+// ギルドデータの文字列への変換
+int inter_guild_tostr (char *str, struct guild *g)
+{
+    int  i, c, len;
+
+    // 基本データ
+    len = sprintf (str, "%d\t%s\t%s\t%d,%d,%d,%d,%d\t%s#\t%s#\t",
+                   g->guild_id, g->name, g->master,
+                   g->guild_lv, g->max_member, g->exp, g->skill_point,
+                   g->castle_id, g->mes1, g->mes2);
+    // メンバー
+    for (i = 0; i < g->max_member; i++)
+    {
+        struct guild_member *m = &g->member[i];
+        len += sprintf (str + len, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\t%s\t",
+                        m->account_id, m->char_id,
+                        m->hair, m->hair_color, m->gender,
+                        m->pc_class, m->lv, m->exp, m->exp_payper, m->position,
+                        ((m->account_id > 0) ? m->name : "-"));
+    }
+    // 役職
+    for (i = 0; i < MAX_GUILDPOSITION; i++)
+    {
+        struct guild_position *p = &g->position[i];
+        len +=
+            sprintf (str + len, "%d,%d\t%s#\t", p->mode, p->exp_mode,
+                     p->name);
+    }
+    // エンブレム
+    len += sprintf (str + len, "%d,%d,", g->emblem_len, g->emblem_id);
+    for (i = 0; i < g->emblem_len; i++)
+    {
+        len +=
+            sprintf (str + len, "%02x", (unsigned char) (g->emblem_data[i]));
+    }
+    len += sprintf (str + len, "$\t");
+    // 同盟リスト
+    c = 0;
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+        if (g->alliance[i].guild_id > 0)
+            c++;
+    len += sprintf (str + len, "%d\t", c);
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+    {
+        struct guild_alliance *a = &g->alliance[i];
+        if (a->guild_id > 0)
+            len +=
+                sprintf (str + len, "%d,%d\t%s\t", a->guild_id, a->opposition,
+                         a->name);
+    }
+    // 追放リスト
+    c = 0;
+    for (i = 0; i < MAX_GUILDEXPLUSION; i++)
+        if (g->explusion[i].account_id > 0)
+            c++;
+    len += sprintf (str + len, "%d\t", c);
+    for (i = 0; i < MAX_GUILDEXPLUSION; i++)
+    {
+        struct guild_explusion *e = &g->explusion[i];
+        if (e->account_id > 0)
+            len += sprintf (str + len, "%d,%d,%d,%d\t%s\t%s\t%s#\t",
+                            e->account_id, e->rsv1, e->rsv2, e->rsv3,
+                            e->name, e->acc, e->mes);
+    }
+    // ギルドスキル
+    for (i = 0; i < MAX_GUILDSKILL; i++)
+    {
+        len += sprintf (str + len, "%d,%d ", g->skill[i].id, g->skill[i].lv);
+    }
+    len += sprintf (str + len, "\t");
+
+    return 0;
+}
+
+// ギルドデータの文字列からの変換
+int inter_guild_fromstr (char *str, struct guild *g)
+{
+    int  i, j, c;
+    int  tmp_int[16];
+    char tmp_str[4][256];
+    char tmp_str2[4096];
+    char *pstr;
+
+    // 基本データ
+    memset (g, 0, sizeof (struct guild));
+    if (sscanf
+        (str, "%d\t%[^\t]\t%[^\t]\t%d,%d,%d,%d,%d\t%[^\t]\t%[^\t]\t",
+         &tmp_int[0], tmp_str[0], tmp_str[1], &tmp_int[1], &tmp_int[2],
+         &tmp_int[3], &tmp_int[4], &tmp_int[5], tmp_str[2], tmp_str[3]) < 8)
+        return 1;
+
+    g->guild_id = tmp_int[0];
+    g->guild_lv = tmp_int[1];
+    g->max_member = tmp_int[2];
+    g->exp = tmp_int[3];
+    g->skill_point = tmp_int[4];
+    g->castle_id = tmp_int[5];
+    memcpy (g->name, tmp_str[0], 24);
+    memcpy (g->master, tmp_str[1], 24);
+    memcpy (g->mes1, tmp_str[2], 60);
+    memcpy (g->mes2, tmp_str[3], 120);
+    g->mes1[strlen (g->mes1) - 1] = 0;
+    g->mes2[strlen (g->mes2) - 1] = 0;
+
+    for (j = 0; j < 6 && str != NULL; j++)  // 位置スキップ
+        str = strchr (str + 1, '\t');
+//  printf("GuildBaseInfo OK\n");
+
+    // メンバー
+    for (i = 0; i < g->max_member; i++)
+    {
+        struct guild_member *m = &g->member[i];
+        if (sscanf (str + 1, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\t%[^\t]\t",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7],
+                    &tmp_int[8], &tmp_int[9], tmp_str[0]) < 11)
+            return 1;
+        m->account_id = tmp_int[0];
+        m->char_id = 0 /*tmp_int[1]*/;
+        m->hair = tmp_int[2];
+        m->hair_color = tmp_int[3];
+        m->gender = tmp_int[4];
+        m->pc_class = tmp_int[5];
+        m->lv = tmp_int[6];
+        m->exp = tmp_int[7];
+        m->exp_payper = tmp_int[8];
+        m->position = tmp_int[9];
+        memcpy (m->name, tmp_str[0], 24);
+
+        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
+            str = strchr (str + 1, '\t');
+    }
+//  printf("GuildMemberInfo OK\n");
+    // 役職
+    i = 0;
+    while (sscanf (str + 1, "%d,%d%n", &tmp_int[0], &tmp_int[1], &j) == 2
+           && str[1 + j] == '\t')
+    {
+        struct guild_position *p = &g->position[i];
+        if (sscanf
+            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
+             tmp_str[0]) < 3)
+            return 1;
+        p->mode = tmp_int[0];
+        p->exp_mode = tmp_int[1];
+        tmp_str[0][strlen (tmp_str[0]) - 1] = 0;
+        memcpy (p->name, tmp_str[0], 24);
+
+        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
+            str = strchr (str + 1, '\t');
+        i++;
+    }
+//  printf("GuildPositionInfo OK\n");
+    // エンブレム
+    tmp_int[1] = 0;
+    if (sscanf (str + 1, "%d,%d,%[^\t]\t", &tmp_int[0], &tmp_int[1], tmp_str2)
+        < 3 && sscanf (str + 1, "%d,%[^\t]\t", &tmp_int[0], tmp_str2) < 2)
+        return 1;
+    g->emblem_len = tmp_int[0];
+    g->emblem_id = tmp_int[1];
+    for (i = 0, pstr = tmp_str2; i < g->emblem_len; i++, pstr += 2)
+    {
+        int  c1 = pstr[0], c2 = pstr[1], x1 = 0, x2 = 0;
+        if (c1 >= '0' && c1 <= '9')
+            x1 = c1 - '0';
+        if (c1 >= 'a' && c1 <= 'f')
+            x1 = c1 - 'a' + 10;
+        if (c1 >= 'A' && c1 <= 'F')
+            x1 = c1 - 'A' + 10;
+        if (c2 >= '0' && c2 <= '9')
+            x2 = c2 - '0';
+        if (c2 >= 'a' && c2 <= 'f')
+            x2 = c2 - 'a' + 10;
+        if (c2 >= 'A' && c2 <= 'F')
+            x2 = c2 - 'A' + 10;
+        g->emblem_data[i] = (x1 << 4) | x2;
+    }
+//  printf("GuildEmblemInfo OK\n");
+    str = strchr (str + 1, '\t');   // 位置スキップ
+
+    // 同盟リスト
+    if (sscanf (str + 1, "%d\t", &c) < 1)
+        return 1;
+    str = strchr (str + 1, '\t');   // 位置スキップ
+    for (i = 0; i < c; i++)
+    {
+        struct guild_alliance *a = &g->alliance[i];
+        if (sscanf
+            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
+             tmp_str[0]) < 3)
+            return 1;
+        a->guild_id = tmp_int[0];
+        a->opposition = tmp_int[1];
+        memcpy (a->name, tmp_str[0], 24);
+
+        for (j = 0; j < 2 && str != NULL; j++)  // 位置スキップ
+            str = strchr (str + 1, '\t');
+    }
+//  printf("GuildAllianceInfo OK\n");
+    // 追放リスト
+    if (sscanf (str + 1, "%d\t", &c) < 1)
+        return 1;
+    str = strchr (str + 1, '\t');   // 位置スキップ
+    for (i = 0; i < c; i++)
+    {
+        struct guild_explusion *e = &g->explusion[i];
+        if (sscanf (str + 1, "%d,%d,%d,%d\t%[^\t]\t%[^\t]\t%[^\t]\t",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    tmp_str[0], tmp_str[1], tmp_str[2]) < 6)
+            return 1;
+        e->account_id = tmp_int[0];
+        e->rsv1 = tmp_int[1];
+        e->rsv2 = tmp_int[2];
+        e->rsv3 = tmp_int[3];
+        memcpy (e->name, tmp_str[0], 24);
+        memcpy (e->acc, tmp_str[1], 24);
+        tmp_str[2][strlen (tmp_str[2]) - 1] = 0;
+        memcpy (e->mes, tmp_str[2], 40);
+
+        for (j = 0; j < 4 && str != NULL; j++)  // 位置スキップ
+            str = strchr (str + 1, '\t');
+    }
+//  printf("GuildExplusionInfo OK\n");
+    // ギルドスキル
+    for (i = 0; i < MAX_GUILDSKILL; i++)
+    {
+        if (sscanf (str + 1, "%d,%d ", &tmp_int[0], &tmp_int[1]) < 2)
+            break;
+        g->skill[i].id = tmp_int[0];
+        g->skill[i].lv = tmp_int[1];
+        str = strchr (str + 1, ' ');
+    }
+    str = strchr (str + 1, '\t');
+//  printf("GuildSkillInfo OK\n");
+
+    return 0;
+}
+
+// ギルド城データの文字列への変換
+int inter_guildcastle_tostr (char *str, struct guild_castle *gc)
+{
+    int  len;
+
+    len = sprintf (str, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",    // added Guardian HP [Valaris]
+                   gc->castle_id, gc->guild_id, gc->economy, gc->defense,
+                   gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime,
+                   gc->createTime, gc->visibleC, gc->visibleG0, gc->visibleG1,
+                   gc->visibleG2, gc->visibleG3, gc->visibleG4, gc->visibleG5,
+                   gc->visibleG6, gc->visibleG7, gc->Ghp0, gc->Ghp1, gc->Ghp2,
+                   gc->Ghp3, gc->Ghp4, gc->Ghp5, gc->Ghp6, gc->Ghp7);
+
+    return 0;
+}
+
+// ギルド城データの文字列からの変換
+int inter_guildcastle_fromstr (char *str, struct guild_castle *gc)
+{
+    int  tmp_int[26];
+
+    memset (gc, 0, sizeof (struct guild_castle));
+    // new structure of guild castle
+    if (sscanf
+        (str,
+         "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4],
+         &tmp_int[5], &tmp_int[6], &tmp_int[7], &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]) == 26)
+    {
+        gc->castle_id = tmp_int[0];
+        gc->guild_id = tmp_int[1];
+        gc->economy = tmp_int[2];
+        gc->defense = tmp_int[3];
+        gc->triggerE = tmp_int[4];
+        gc->triggerD = tmp_int[5];
+        gc->nextTime = tmp_int[6];
+        gc->payTime = tmp_int[7];
+        gc->createTime = tmp_int[8];
+        gc->visibleC = tmp_int[9];
+        gc->visibleG0 = tmp_int[10];
+        gc->visibleG1 = tmp_int[11];
+        gc->visibleG2 = tmp_int[12];
+        gc->visibleG3 = tmp_int[13];
+        gc->visibleG4 = tmp_int[14];
+        gc->visibleG5 = tmp_int[15];
+        gc->visibleG6 = tmp_int[16];
+        gc->visibleG7 = tmp_int[17];
+        gc->Ghp0 = tmp_int[18];
+        gc->Ghp1 = tmp_int[19];
+        gc->Ghp2 = tmp_int[20];
+        gc->Ghp3 = tmp_int[21];
+        gc->Ghp4 = tmp_int[22];
+        gc->Ghp5 = tmp_int[23];
+        gc->Ghp6 = tmp_int[24];
+        gc->Ghp7 = tmp_int[25]; // end additions [Valaris]
+        // old structure of guild castle
+    }
+    else if (sscanf
+             (str, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
+              &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3], &tmp_int[4],
+              &tmp_int[5], &tmp_int[6], &tmp_int[7], &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]) == 18)
+    {
+        gc->castle_id = tmp_int[0];
+        gc->guild_id = tmp_int[1];
+        gc->economy = tmp_int[2];
+        gc->defense = tmp_int[3];
+        gc->triggerE = tmp_int[4];
+        gc->triggerD = tmp_int[5];
+        gc->nextTime = tmp_int[6];
+        gc->payTime = tmp_int[7];
+        gc->createTime = tmp_int[8];
+        gc->visibleC = tmp_int[9];
+        gc->visibleG0 = tmp_int[10];
+        gc->visibleG1 = tmp_int[11];
+        gc->visibleG2 = tmp_int[12];
+        gc->visibleG3 = tmp_int[13];
+        gc->visibleG4 = tmp_int[14];
+        gc->visibleG5 = tmp_int[15];
+        gc->visibleG6 = tmp_int[16];
+        gc->visibleG7 = tmp_int[17];
+        if (gc->visibleG0 == 1)
+            gc->Ghp0 = 15670 + 2000 * gc->defense;
+        else
+            gc->Ghp0 = 0;
+        if (gc->visibleG1 == 1)
+            gc->Ghp1 = 15670 + 2000 * gc->defense;
+        else
+            gc->Ghp1 = 0;
+        if (gc->visibleG2 == 1)
+            gc->Ghp2 = 15670 + 2000 * gc->defense;
+        else
+            gc->Ghp2 = 0;
+        if (gc->visibleG3 == 1)
+            gc->Ghp3 = 30214 + 2000 * gc->defense;
+        else
+            gc->Ghp3 = 0;
+        if (gc->visibleG4 == 1)
+            gc->Ghp4 = 30214 + 2000 * gc->defense;
+        else
+            gc->Ghp4 = 0;
+        if (gc->visibleG5 == 1)
+            gc->Ghp5 = 28634 + 2000 * gc->defense;
+        else
+            gc->Ghp5 = 0;
+        if (gc->visibleG6 == 1)
+            gc->Ghp6 = 28634 + 2000 * gc->defense;
+        else
+            gc->Ghp6 = 0;
+        if (gc->visibleG7 == 1)
+            gc->Ghp7 = 28634 + 2000 * gc->defense;
+        else
+            gc->Ghp7 = 0;
+    }
+    else
+    {
+        return 1;
+    }
+
+    return 0;
+}
+
+// ギルド関連データベース読み込み
+int inter_guild_readdb (void)
+{
+    int  i;
+    FILE *fp;
+    char line[1024];
+
+    fp = fopen_ ("db/exp_guild.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/exp_guild.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp) && i < 100)
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        guild_exp[i] = atoi (line);
+        i++;
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+// ギルドデータの読み込み
+int inter_guild_init (void)
+{
+    char line[16384];
+    struct guild *g;
+    struct guild_castle *gc;
+    FILE *fp;
+    int  i, j, c = 0;
+
+    inter_guild_readdb ();
+
+    guild_db = numdb_init ();
+    castle_db = numdb_init ();
+
+    if ((fp = fopen_ (guild_txt, "r")) == NULL)
+        return 1;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        j = 0;
+        if (sscanf (line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
+            && guild_newid <= i)
+        {
+            guild_newid = i;
+            continue;
+        }
+        CREATE (g, struct guild, 1);
+        if (inter_guild_fromstr (line, g) == 0 && g->guild_id > 0)
+        {
+            if (g->guild_id >= guild_newid)
+                guild_newid = g->guild_id + 1;
+            numdb_insert (guild_db, g->guild_id, g);
+            guild_check_empty (g);
+            guild_calcinfo (g);
+        }
+        else
+        {
+            printf ("int_guild: broken data [%s] line %d\n", guild_txt, c);
+            free (g);
+        }
+        c++;
+    }
+    fclose_ (fp);
+//  printf("int_guild: %s read done (%d guilds)\n", guild_txt, c);
+
+    c = 0;                      //カウンタ初期化
+
+    if ((fp = fopen_ (castle_txt, "r")) == NULL)
+    {
+        return 1;
+    }
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        CREATE (gc, struct guild_castle, 1);
+        if (inter_guildcastle_fromstr (line, gc) == 0)
+        {
+            numdb_insert (castle_db, gc->castle_id, gc);
+        }
+        else
+        {
+            printf ("int_guild: broken data [%s] line %d\n", castle_txt, c);
+            free (gc);
+        }
+        c++;
+    }
+
+    if (!c)
+    {
+        printf (" %s - making Default Data...\n", castle_txt);
+        //デフォルトデータを作成
+        for (i = 0; i < MAX_GUILDCASTLE; i++)
+        {
+            CREATE (gc, struct guild_castle, 1);
+            gc->castle_id = i;
+            gc->guild_id = 0;
+            gc->economy = 0;
+            gc->defense = 0;
+            gc->triggerE = 0;
+            gc->triggerD = 0;
+            gc->nextTime = 0;
+            gc->payTime = 0;
+            gc->createTime = 0;
+            gc->visibleC = 0;
+            gc->visibleG0 = 0;
+            gc->visibleG1 = 0;
+            gc->visibleG2 = 0;
+            gc->visibleG3 = 0;
+            gc->visibleG4 = 0;
+            gc->visibleG5 = 0;
+            gc->visibleG6 = 0;
+            gc->visibleG7 = 0;
+            gc->Ghp0 = 0;       // guardian HP [Valaris]
+            gc->Ghp1 = 0;
+            gc->Ghp2 = 0;
+            gc->Ghp3 = 0;
+            gc->Ghp4 = 0;
+            gc->Ghp5 = 0;
+            gc->Ghp6 = 0;
+            gc->Ghp7 = 0;       // end additions [Valaris]
+            numdb_insert (castle_db, gc->castle_id, gc);
+        }
+        printf (" %s - making done\n", castle_txt);
+        return 0;
+    }
+
+    fclose_ (fp);
+
+    return 0;
+}
+
+struct guild *inter_guild_search (int guild_id)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+
+    return g;
+}
+
+// ギルドデータのセーブ用
+void inter_guild_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[16384];
+    FILE *fp;
+
+    inter_guild_tostr (line, (struct guild *) data);
+    fp = va_arg (ap, FILE *);
+    fprintf (fp, "%s\n", line);
+}
+
+// ギルド城データのセーブ用
+void inter_castle_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[16384];
+    FILE *fp;
+
+    inter_guildcastle_tostr (line, (struct guild_castle *) data);
+    fp = va_arg (ap, FILE *);
+    fprintf (fp, "%s\n", line);
+}
+
+// ギルドデータのセーブ
+int inter_guild_save (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if ((fp = lock_fopen (guild_txt, &lock)) == NULL)
+    {
+        printf ("int_guild: cant write [%s] !!! data is lost !!!\n",
+                guild_txt);
+        return 1;
+    }
+    numdb_foreach (guild_db, inter_guild_save_sub, fp);
+//  fprintf(fp, "%d\t%%newid%%\n", guild_newid);
+    lock_fclose (fp, guild_txt, &lock);
+//  printf("int_guild: %s saved.\n", guild_txt);
+
+    if ((fp = lock_fopen (castle_txt, &lock)) == NULL)
+    {
+        printf ("int_guild: cant write [%s] !!! data is lost !!!\n",
+                castle_txt);
+        return 1;
+    }
+    numdb_foreach (castle_db, inter_castle_save_sub, fp);
+    lock_fclose (fp, castle_txt, &lock);
+
+    return 0;
+}
+
+// ギルド名検索用
+void search_guildname_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild *g = (struct guild *) data, **dst;
+    char *str;
+
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct guild **);
+    if (strcasecmp (g->name, str) == 0)
+        *dst = g;
+}
+
+// ギルド名検索
+struct guild *search_guildname (char *str)
+{
+    struct guild *g = NULL;
+    numdb_foreach (guild_db, search_guildname_sub, str, &g);
+    return g;
+}
+
+// ギルドが空かどうかチェック
+int guild_check_empty (struct guild *g)
+{
+    int  i;
+
+    for (i = 0; i < g->max_member; i++)
+    {
+        if (g->member[i].account_id > 0)
+        {
+            return 0;
+        }
+    }
+    // 誰もいないので解散
+    numdb_foreach (guild_db, guild_break_sub, g->guild_id);
+    numdb_erase (guild_db, g->guild_id);
+    inter_guild_storage_delete (g->guild_id);
+    mapif_guild_broken (g->guild_id, 0);
+    free (g);
+
+    return 1;
+}
+
+// キャラの競合がないかチェック用
+void guild_check_conflict_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild *g = (struct guild *) data;
+    int  guild_id, account_id, char_id, i;
+
+    guild_id = va_arg (ap, int);
+    account_id = va_arg (ap, int);
+    char_id = va_arg (ap, int);
+
+    if (g->guild_id == guild_id)    // 本来の所属なので問題なし
+        return;
+
+    for (i = 0; i < MAX_GUILD; i++)
+    {
+        if (g->member[i].account_id == account_id)
+        {
+            // 別のギルドに偽の所属データがあるので脱退
+            printf ("int_guild: guild conflict! %d,%d %d!=%d\n", account_id,
+                    char_id, guild_id, g->guild_id);
+            mapif_parse_GuildLeave (-1, g->guild_id, account_id, 0 /*char_id*/, 0,
+                                    "**データ競合**");
+        }
+    }
+}
+
+// キャラの競合がないかチェック
+int guild_check_conflict (int guild_id, int account_id, int char_id)
+{
+    numdb_foreach (guild_db, guild_check_conflict_sub, guild_id, account_id,
+                   0 /*char_id*/);
+
+    return 0;
+}
+
+int guild_nextexp (int level)
+{
+    if (level < 100)
+        return guild_exp[level - 1];
+
+    return 0;
+}
+
+// ギルドスキルがあるか確認
+int guild_checkskill (struct guild *g, int id)
+{
+    return g->skill[id - 10000].lv;
+}
+
+// ギルドの情報の再計算
+int guild_calcinfo (struct guild *g)
+{
+    int  i, c, nextexp;
+    struct guild before = *g;
+
+    // スキルIDの設定
+    for (i = 0; i < 5; i++)
+        g->skill[i].id = i + 10000;
+
+    // ギルドレベル
+    if (g->guild_lv <= 0)
+        g->guild_lv = 1;
+    nextexp = guild_nextexp (g->guild_lv);
+    if (nextexp > 0)
+    {
+        while (g->exp >= nextexp)
+        {                       // レベルアップ処理
+            g->exp -= nextexp;
+            g->guild_lv++;
+            g->skill_point++;
+            nextexp = guild_nextexp (g->guild_lv);
+        }
+    }
+
+    // ギルドの次の経験値
+    g->next_exp = guild_nextexp (g->guild_lv);
+
+    // メンバ上限(ギルド拡張適用)
+    g->max_member = 100 + guild_checkskill (g, 10004) * 2;
+
+    // 平均レベルとオンライン人数
+    g->average_lv = 0;
+    g->connect_member = 0;
+    c = 0;
+    for (i = 0; i < g->max_member; i++)
+    {
+        if (g->member[i].account_id > 0)
+        {
+            g->average_lv += g->member[i].lv;
+            c++;
+            if (g->member[i].online > 0)
+                g->connect_member++;
+        }
+    }
+    g->average_lv /= c;
+
+    // 全データを送る必要がありそう
+    if (g->max_member != before.max_member ||
+        g->guild_lv != before.guild_lv ||
+        g->skill_point != before.skill_point)
+    {
+        mapif_guild_info (-1, g);
+        return 1;
+    }
+
+    return 0;
+}
+
+//-------------------------------------------------------------------
+// map serverへの通信
+
+// ギルド作成可否
+int mapif_guild_created (int fd, int account_id, struct guild *g)
+{
+    WFIFOW (fd, 0) = 0x3830;
+    WFIFOL (fd, 2) = account_id;
+    if (g != NULL)
+    {
+        WFIFOL (fd, 6) = g->guild_id;
+        printf ("int_guild: created! %d %s\n", g->guild_id, g->name);
+    }
+    else
+    {
+        WFIFOL (fd, 6) = 0;
+    }
+    WFIFOSET (fd, 10);
+    return 0;
+}
+
+// ギルド情報見つからず
+int mapif_guild_noinfo (int fd, int guild_id)
+{
+    WFIFOW (fd, 0) = 0x3831;
+    WFIFOW (fd, 2) = 8;
+    WFIFOL (fd, 4) = guild_id;
+    WFIFOSET (fd, 8);
+    printf ("int_guild: info not found %d\n", guild_id);
+
+    return 0;
+}
+
+// ギルド情報まとめ送り
+int mapif_guild_info (int fd, struct guild *g)
+{
+    unsigned char buf[4 + sizeof (struct guild)];
+
+    WBUFW (buf, 0) = 0x3831;
+    memcpy (buf + 4, g, sizeof (struct guild));
+    WBUFW (buf, 2) = 4 + sizeof (struct guild);
+//  printf("int_guild: sizeof(guild)=%d\n", sizeof(struct guild));
+    if (fd < 0)
+        mapif_sendall (buf, WBUFW (buf, 2));
+    else
+        mapif_send (fd, buf, WBUFW (buf, 2));
+//  printf("int_guild: info %d %s\n", p->guild_id, p->name);
+
+    return 0;
+}
+
+// メンバ追加可否
+int mapif_guild_memberadded (int fd, int guild_id, int account_id,
+                             int char_id, int flag)
+{
+    WFIFOW (fd, 0) = 0x3832;
+    WFIFOL (fd, 2) = guild_id;
+    WFIFOL (fd, 6) = account_id;
+    WFIFOL (fd, 10) = 0 /*char_id*/;
+    WFIFOB (fd, 14) = flag;
+    WFIFOSET (fd, 15);
+
+    return 0;
+}
+
+// 脱退/追放通知
+int mapif_guild_leaved (int guild_id, int account_id, int char_id, int flag,
+                        const char *name, const char *mes)
+{
+    unsigned char buf[79];
+
+    WBUFW (buf, 0) = 0x3834;
+    WBUFL (buf, 2) = guild_id;
+    WBUFL (buf, 6) = account_id;
+    WBUFL (buf, 10) = 0 /*char_id*/;
+    WBUFB (buf, 14) = flag;
+    memcpy (WBUFP (buf, 15), mes, 40);
+    memcpy (WBUFP (buf, 55), name, 24);
+    mapif_sendall (buf, 79);
+    printf ("int_guild: guild leaved %d %d %s %s\n", guild_id, account_id,
+            name, mes);
+
+    return 0;
+}
+
+// オンライン状態とLv更新通知
+int mapif_guild_memberinfoshort (struct guild *g, int idx)
+{
+    unsigned char buf[19];
+
+    WBUFW (buf, 0) = 0x3835;
+    WBUFL (buf, 2) = g->guild_id;
+    WBUFL (buf, 6) = g->member[idx].account_id;
+    WBUFL (buf, 10) = 0 /*g->member[idx].char_id*/;
+    WBUFB (buf, 14) = g->member[idx].online;
+    WBUFW (buf, 15) = g->member[idx].lv;
+    WBUFW (buf, 17) = g->member[idx].pc_class;
+    mapif_sendall (buf, 19);
+    return 0;
+}
+
+// 解散通知
+int mapif_guild_broken (int guild_id, int flag)
+{
+    unsigned char buf[7];
+
+    WBUFW (buf, 0) = 0x3836;
+    WBUFL (buf, 2) = guild_id;
+    WBUFB (buf, 6) = flag;
+    mapif_sendall (buf, 7);
+    printf ("int_guild: broken %d\n", guild_id);
+
+    return 0;
+}
+
+// ギルド内発言
+int mapif_guild_message (int guild_id, int account_id, char *mes, int len)
+{
+    unsigned char buf[len + 12];
+
+    WBUFW (buf, 0) = 0x3837;
+    WBUFW (buf, 2) = len + 12;
+    WBUFL (buf, 4) = guild_id;
+    WBUFL (buf, 8) = account_id;
+    memcpy (WBUFP (buf, 12), mes, len);
+    mapif_sendall (buf, len + 12);
+
+    return 0;
+}
+
+// ギルド基本情報変更通知
+int mapif_guild_basicinfochanged (int guild_id, int type, const void *data,
+                                  int len)
+{
+    unsigned char buf[2048];
+
+    WBUFW (buf, 0) = 0x3839;
+    WBUFW (buf, 2) = len + 10;
+    WBUFL (buf, 4) = guild_id;
+    WBUFW (buf, 8) = type;
+    memcpy (WBUFP (buf, 10), data, len);
+    mapif_sendall (buf, len + 10);
+    return 0;
+}
+
+// ギルドメンバ情報変更通知
+int mapif_guild_memberinfochanged (int guild_id, int account_id, int char_id,
+                                   int type, const void *data, int len)
+{
+    unsigned char buf[len + 18];
+
+    WBUFW (buf, 0) = 0x383a;
+    WBUFW (buf, 2) = len + 18;
+    WBUFL (buf, 4) = guild_id;
+    WBUFL (buf, 8) = account_id;
+    WBUFL (buf, 12) = 0 /*char_id*/;
+    WBUFW (buf, 16) = type;
+    memcpy (WBUFP (buf, 18), data, len);
+    mapif_sendall (buf, len + 18);
+
+    return 0;
+}
+
+// ギルドスキルアップ通知
+int mapif_guild_skillupack (int guild_id, int skill_num, int account_id)
+{
+    unsigned char buf[14];
+
+    WBUFW (buf, 0) = 0x383c;
+    WBUFL (buf, 2) = guild_id;
+    WBUFL (buf, 6) = skill_num;
+    WBUFL (buf, 10) = account_id;
+    mapif_sendall (buf, 14);
+
+    return 0;
+}
+
+// ギルド同盟/敵対通知
+int mapif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
+                          int account_id2, int flag, const char *name1,
+                          const char *name2)
+{
+    unsigned char buf[67];
+
+    WBUFW (buf, 0) = 0x383d;
+    WBUFL (buf, 2) = guild_id1;
+    WBUFL (buf, 6) = guild_id2;
+    WBUFL (buf, 10) = account_id1;
+    WBUFL (buf, 14) = account_id2;
+    WBUFB (buf, 18) = flag;
+    memcpy (WBUFP (buf, 19), name1, 24);
+    memcpy (WBUFP (buf, 43), name2, 24);
+    mapif_sendall (buf, 67);
+
+    return 0;
+}
+
+// ギルド役職変更通知
+int mapif_guild_position (struct guild *g, int idx)
+{
+    unsigned char buf[sizeof (struct guild_position) + 12];
+
+    WBUFW (buf, 0) = 0x383b;
+    WBUFW (buf, 2) = sizeof (struct guild_position) + 12;
+    WBUFL (buf, 4) = g->guild_id;
+    WBUFL (buf, 8) = idx;
+    memcpy (WBUFP (buf, 12), &g->position[idx],
+            sizeof (struct guild_position));
+    mapif_sendall (buf, WBUFW (buf, 2));
+
+    return 0;
+}
+
+// ギルド告知変更通知
+int mapif_guild_notice (struct guild *g)
+{
+    unsigned char buf[186];
+
+    WBUFW (buf, 0) = 0x383e;
+    WBUFL (buf, 2) = g->guild_id;
+    memcpy (WBUFP (buf, 6), g->mes1, 60);
+    memcpy (WBUFP (buf, 66), g->mes2, 120);
+    mapif_sendall (buf, 186);
+
+    return 0;
+}
+
+// ギルドエンブレム変更通知
+int mapif_guild_emblem (struct guild *g)
+{
+    unsigned char buf[2048];
+
+    WBUFW (buf, 0) = 0x383f;
+    WBUFW (buf, 2) = g->emblem_len + 12;
+    WBUFL (buf, 4) = g->guild_id;
+    WBUFL (buf, 8) = g->emblem_id;
+    memcpy (WBUFP (buf, 12), g->emblem_data, g->emblem_len);
+    mapif_sendall (buf, WBUFW (buf, 2));
+
+    return 0;
+}
+
+int mapif_guild_castle_dataload (int castle_id, int index, int value)
+{
+    unsigned char buf[9];
+
+    WBUFW (buf, 0) = 0x3840;
+    WBUFW (buf, 2) = castle_id;
+    WBUFB (buf, 4) = index;
+    WBUFL (buf, 5) = value;
+    mapif_sendall (buf, 9);
+
+    return 0;
+}
+
+int mapif_guild_castle_datasave (int castle_id, int index, int value)
+{
+    unsigned char buf[9];
+
+    WBUFW (buf, 0) = 0x3841;
+    WBUFW (buf, 2) = castle_id;
+    WBUFB (buf, 4) = index;
+    WBUFL (buf, 5) = value;
+    mapif_sendall (buf, 9);
+
+    return 0;
+}
+
+void mapif_guild_castle_alldataload_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    int  fd = va_arg (ap, int);
+    int *p = va_arg (ap, int *);
+
+    memcpy (WFIFOP (fd, *p), (struct guild_castle *) data,
+            sizeof (struct guild_castle));
+    (*p) += sizeof (struct guild_castle);
+}
+
+int mapif_guild_castle_alldataload (int fd)
+{
+    int  len = 4;
+
+    WFIFOW (fd, 0) = 0x3842;
+    numdb_foreach (castle_db, mapif_guild_castle_alldataload_sub, fd, &len);
+    WFIFOW (fd, 2) = len;
+    WFIFOSET (fd, len);
+
+    return 0;
+}
+
+//-------------------------------------------------------------------
+// map serverからの通信
+
+// ギルド作成要求
+int mapif_parse_CreateGuild (int fd, int account_id, char *name,
+                             struct guild_member *master)
+{
+    struct guild *g;
+    int  i;
+
+    for (i = 0; i < 24 && name[i]; i++)
+    {
+        if (!(name[i] & 0xe0) || name[i] == 0x7f)
+        {
+            printf ("int_guild: illeagal guild name [%s]\n", name);
+            mapif_guild_created (fd, account_id, NULL);
+            return 0;
+        }
+    }
+
+    if ((g = search_guildname (name)) != NULL)
+    {
+        printf ("int_guild: same name guild exists [%s]\n", name);
+        mapif_guild_created (fd, account_id, NULL);
+        return 0;
+    }
+    CREATE (g, struct guild, 1);
+    g->guild_id = guild_newid++;
+    memcpy (g->name, name, 24);
+    memcpy (g->master, master->name, 24);
+    memcpy (&g->member[0], master, sizeof (struct guild_member));
+
+    g->position[0].mode = 0x11;
+    strcpy (g->position[0].name, "GuildMaster");
+    strcpy (g->position[MAX_GUILDPOSITION - 1].name, "Newbie");
+    for (i = 1; i < MAX_GUILDPOSITION - 1; i++)
+        sprintf (g->position[i].name, "Position %d", i + 1);
+
+    // ここでギルド情報計算が必要と思われる
+    g->max_member = 100;
+    g->average_lv = master->lv;
+    for (i = 0; i < 5; i++)
+        g->skill[i].id = i + 10000;
+
+    numdb_insert (guild_db, g->guild_id, g);
+
+    mapif_guild_created (fd, account_id, g);
+    mapif_guild_info (fd, g);
+
+    inter_log ("guild %s (id=%d) created by master %s (id=%d)\n",
+               name, g->guild_id, master->name, master->account_id);
+
+    return 0;
+}
+
+// ギルド情報要求
+int mapif_parse_GuildInfo (int fd, int guild_id)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g != NULL)
+    {
+        guild_calcinfo (g);
+        mapif_guild_info (fd, g);
+    }
+    else
+        mapif_guild_noinfo (fd, guild_id);
+
+    return 0;
+}
+
+// ギルドメンバ追加要求
+int mapif_parse_GuildAddMember (int fd, int guild_id, struct guild_member *m)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+    {
+        mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/, 1);
+        return 0;
+    }
+
+    for (int i = 0; i < g->max_member; i++)
+    {
+        if (g->member[i].account_id == 0)
+        {
+            memcpy (&g->member[i], m, sizeof (struct guild_member));
+            mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/,
+                                     0);
+            guild_calcinfo (g);
+            mapif_guild_info (-1, g);
+
+            return 0;
+        }
+    }
+    mapif_guild_memberadded (fd, guild_id, m->account_id, 0 /*char_id*/, 1);
+
+    return 0;
+}
+
+// ギルド脱退/追放要求
+int mapif_parse_GuildLeave (int fd, int guild_id, int account_id, int char_id,
+                            int flag, const char *mes)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g != NULL)
+    {
+        for (int i = 0; i < MAX_GUILD; i++)
+        {
+            if (g->member[i].account_id == account_id)
+            {
+//              printf("%d %d\n", i, (int)(&g->member[i]));
+//              printf("%d %s\n", i, g->member[i].name);
+
+                if (flag)
+                {
+                    int j;
+                    // 追放の場合追放リストに入れる
+                    for (j = 0; j < MAX_GUILDEXPLUSION; j++)
+                    {
+                        if (g->explusion[j].account_id == 0)
+                            break;
+                    }
+                    if (j == MAX_GUILDEXPLUSION)
+                    {           // 一杯なので古いのを消す
+                        for (j = 0; j < MAX_GUILDEXPLUSION - 1; j++)
+                            g->explusion[j] = g->explusion[j + 1];
+                        j = MAX_GUILDEXPLUSION - 1;
+                    }
+                    g->explusion[j].account_id = account_id;
+                    memcpy (g->explusion[j].acc, "dummy", 24);
+                    memcpy (g->explusion[j].name, g->member[i].name, 24);
+                    memcpy (g->explusion[j].mes, mes, 40);
+                }
+
+                mapif_guild_leaved (guild_id, account_id, 0 /*char_id*/, flag,
+                                    g->member[i].name, mes);
+//              printf("%d %d\n", i, (int)(&g->member[i]));
+//              printf("%d %s\n", i, (&g->member[i])->name);
+                memset (&g->member[i], 0, sizeof (struct guild_member));
+
+                if (guild_check_empty (g) == 0)
+                    mapif_guild_info (-1, g);   // まだ人がいるのでデータ送信
+
+                return 0;
+            }
+        }
+    }
+    return 0;
+}
+
+// オンライン/Lv更新
+int mapif_parse_GuildChangeMemberInfoShort (int fd, int guild_id,
+                                            int account_id, int char_id,
+                                            int online, int lv, int pc_class)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+
+    g->connect_member = 0;
+
+    int alv = 0;
+    int c = 0;
+    for (int i = 0; i < MAX_GUILD; i++)
+    {
+        if (g->member[i].account_id == account_id)
+        {
+            g->member[i].online = online;
+            g->member[i].lv = lv;
+            g->member[i].pc_class = pc_class;
+            mapif_guild_memberinfoshort (g, i);
+        }
+        if (g->member[i].account_id > 0)
+        {
+            alv += g->member[i].lv;
+            c++;
+        }
+        if (g->member[i].online)
+            g->connect_member++;
+    }
+    // 平均レベル
+    g->average_lv = alv / c;
+
+    return 0;
+}
+
+// ギルド解散処理用(同盟/敵対を解除)
+void guild_break_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild *g = (struct guild *) data;
+    int  guild_id = va_arg (ap, int);
+    int  i;
+
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+    {
+        if (g->alliance[i].guild_id == guild_id)
+            g->alliance[i].guild_id = 0;
+    }
+}
+
+// ギルド解散要求
+int mapif_parse_BreakGuild (int fd, int guild_id)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+
+    numdb_foreach (guild_db, guild_break_sub, guild_id);
+    numdb_erase (guild_db, guild_id);
+    inter_guild_storage_delete (guild_id);
+    mapif_guild_broken (guild_id, 0);
+
+    inter_log ("guild %s (id=%d) broken\n", g->name, guild_id);
+    free (g);
+
+    return 0;
+}
+
+// ギルドメッセージ送信
+int mapif_parse_GuildMessage (int fd, int guild_id, int account_id, char *mes,
+                              int len)
+{
+    return mapif_guild_message (guild_id, account_id, mes, len);
+}
+
+// ギルド基本データ変更要求
+int mapif_parse_GuildBasicInfoChange (int fd, int guild_id, int type,
+                                      const char *data, int len)
+{
+    short dw = *((short *) data);
+
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+
+    switch (type)
+    {
+        case GBI_GUILDLV:
+            if (dw > 0 && g->guild_lv + dw <= 50)
+            {
+                g->guild_lv += dw;
+                g->skill_point += dw;
+            }
+            else if (dw < 0 && g->guild_lv + dw >= 1)
+                g->guild_lv += dw;
+            mapif_guild_info (-1, g);
+            return 0;
+        default:
+            printf ("int_guild: GuildBasicInfoChange: Unknown type %d\n",
+                    type);
+            break;
+    }
+    mapif_guild_basicinfochanged (guild_id, type, data, len);
+
+    return 0;
+}
+
+// ギルドメンバデータ変更要求
+int mapif_parse_GuildMemberInfoChange (int fd, int guild_id, int account_id,
+                                       int char_id, int type,
+                                       const char *data, int len)
+{
+    int  i;
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+
+    for (i = 0; i < g->max_member; i++)
+        if (g->member[i].account_id == account_id)
+            break;
+    if (i == g->max_member)
+    {
+        printf ("int_guild: GuildMemberChange: Not found %d,%d in %d[%s]\n",
+                account_id, char_id, guild_id, g->name);
+        return 0;
+    }
+    switch (type)
+    {
+        case GMI_POSITION:     // 役職
+            g->member[i].position = *((int *) data);
+            break;
+        case GMI_EXP:          // EXP
+        {
+            int  exp, oldexp = g->member[i].exp;
+            exp = g->member[i].exp = *((unsigned int *) data);
+            g->exp += (exp - oldexp);
+            guild_calcinfo (g); // Lvアップ判断
+            mapif_guild_basicinfochanged (guild_id, GBI_EXP, &g->exp, 4);
+        }
+            break;
+        default:
+            printf ("int_guild: GuildMemberInfoChange: Unknown type %d\n",
+                    type);
+            break;
+    }
+    mapif_guild_memberinfochanged (guild_id, account_id, char_id, type, data,
+                                   len);
+
+    return 0;
+}
+
+// ギルド役職名変更要求
+int mapif_parse_GuildPosition (int fd, int guild_id, int idx,
+                               struct guild_position *p)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+
+    if (g == NULL || idx < 0 || idx >= MAX_GUILDPOSITION)
+    {
+        return 0;
+    }
+    memcpy (&g->position[idx], p, sizeof (struct guild_position));
+    mapif_guild_position (g, idx);
+    printf ("int_guild: position changed %d\n", idx);
+
+    return 0;
+}
+
+// ギルドスキルアップ要求
+int mapif_parse_GuildSkillUp (int fd, int guild_id, int skill_num,
+                              int account_id)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    int  idx = skill_num - 10000;
+
+    if (g == NULL || skill_num < 10000)
+        return 0;
+
+    if (g->skill_point > 0 && g->skill[idx].id > 0 && g->skill[idx].lv < 10)
+    {
+        g->skill[idx].lv++;
+        g->skill_point--;
+        if (guild_calcinfo (g) == 0)
+            mapif_guild_info (-1, g);
+        mapif_guild_skillupack (guild_id, skill_num, account_id);
+        printf ("int_guild: skill %d up\n", skill_num);
+    }
+
+    return 0;
+}
+
+// ギルド同盟要求
+int mapif_parse_GuildAlliance (int fd, int guild_id1, int guild_id2,
+                               int account_id1, int account_id2, int flag)
+{
+    struct guild *g[2];
+    int  j, i;
+
+    g[0] = (struct guild *)numdb_search (guild_db, guild_id1);
+    g[1] = (struct guild *)numdb_search (guild_db, guild_id2);
+    if (g[0] == NULL || g[1] == NULL)
+        return 0;
+
+    if (!(flag & 0x8))
+    {
+        for (i = 0; i < 2 - (flag & 1); i++)
+        {
+            for (j = 0; j < MAX_GUILDALLIANCE; j++)
+                if (g[i]->alliance[j].guild_id == 0)
+                {
+                    g[i]->alliance[j].guild_id = g[1 - i]->guild_id;
+                    memcpy (g[i]->alliance[j].name, g[1 - i]->name, 24);
+                    g[i]->alliance[j].opposition = flag & 1;
+                    break;
+                }
+        }
+    }
+    else
+    {                           // 関係解消
+        for (i = 0; i < 2 - (flag & 1); i++)
+        {
+            for (j = 0; j < MAX_GUILDALLIANCE; j++)
+                if (g[i]->alliance[j].guild_id == g[1 - i]->guild_id
+                    && g[i]->alliance[j].opposition == (flag & 1))
+                {
+                    g[i]->alliance[j].guild_id = 0;
+                    break;
+                }
+        }
+    }
+    mapif_guild_alliance (guild_id1, guild_id2, account_id1, account_id2,
+                          flag, g[0]->name, g[1]->name);
+
+    return 0;
+}
+
+// ギルド告知変更要求
+int mapif_parse_GuildNotice (int fd, int guild_id, const char *mes1,
+                             const char *mes2)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+    memcpy (g->mes1, mes1, 60);
+    memcpy (g->mes2, mes2, 120);
+
+    return mapif_guild_notice (g);
+}
+
+// ギルドエンブレム変更要求
+int mapif_parse_GuildEmblem (int fd, int len, int guild_id, int dummy,
+                             const char *data)
+{
+    struct guild *g = (struct guild *)numdb_search (guild_db, guild_id);
+    if (g == NULL)
+        return 0;
+    memcpy (g->emblem_data, data, len);
+    g->emblem_len = len;
+    g->emblem_id++;
+
+    return mapif_guild_emblem (g);
+}
+
+int mapif_parse_GuildCastleDataLoad (int fd, int castle_id, int index)
+{
+    struct guild_castle *gc = (struct guild_castle *)numdb_search (castle_db, castle_id);
+
+    if (gc == NULL)
+    {
+        return mapif_guild_castle_dataload (castle_id, 0, 0);
+    }
+    switch (index)
+    {
+        case 1:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->guild_id);
+        case 2:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->economy);
+        case 3:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->defense);
+        case 4:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->triggerE);
+        case 5:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->triggerD);
+        case 6:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->nextTime);
+        case 7:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->payTime);
+        case 8:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->createTime);
+        case 9:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleC);
+        case 10:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG0);
+        case 11:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG1);
+        case 12:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG2);
+        case 13:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG3);
+        case 14:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG4);
+        case 15:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG5);
+        case 16:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG6);
+        case 17:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->visibleG7);
+        case 18:
+            return mapif_guild_castle_dataload (gc->castle_id, index, gc->Ghp0);    // guardian HP [Valaris]
+        case 19:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp1);
+        case 20:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp2);
+        case 21:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp3);
+        case 22:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp4);
+        case 23:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp5);
+        case 24:
+            return mapif_guild_castle_dataload (gc->castle_id, index,
+                                                gc->Ghp6);
+        case 25:
+            return mapif_guild_castle_dataload (gc->castle_id, index, gc->Ghp7);    // end additions [Valaris]
+
+        default:
+            printf
+                ("mapif_parse_GuildCastleDataLoad ERROR!! (Not found index=%d)\n",
+                 index);
+            return 0;
+    }
+
+    return 0;
+}
+
+int mapif_parse_GuildCastleDataSave (int fd, int castle_id, int index,
+                                     int value)
+{
+    struct guild_castle *gc = (struct guild_castle *)numdb_search (castle_db, castle_id);
+
+    if (gc == NULL)
+    {
+        return mapif_guild_castle_datasave (castle_id, index, value);
+    }
+    switch (index)
+    {
+        case 1:
+            if (gc->guild_id != value)
+            {
+                int  gid = (value) ? value : gc->guild_id;
+                struct guild *g = (struct guild *)numdb_search (guild_db, gid);
+                inter_log ("guild %s (id=%d) %s castle id=%d\n",
+                           (g) ? g->name : "??", gid,
+                           (value) ? "occupy" : "abandon", index);
+            }
+            gc->guild_id = value;
+            break;
+        case 2:
+            gc->economy = value;
+            break;
+        case 3:
+            gc->defense = value;
+            break;
+        case 4:
+            gc->triggerE = value;
+            break;
+        case 5:
+            gc->triggerD = value;
+            break;
+        case 6:
+            gc->nextTime = value;
+            break;
+        case 7:
+            gc->payTime = value;
+            break;
+        case 8:
+            gc->createTime = value;
+            break;
+        case 9:
+            gc->visibleC = value;
+            break;
+        case 10:
+            gc->visibleG0 = value;
+            break;
+        case 11:
+            gc->visibleG1 = value;
+            break;
+        case 12:
+            gc->visibleG2 = value;
+            break;
+        case 13:
+            gc->visibleG3 = value;
+            break;
+        case 14:
+            gc->visibleG4 = value;
+            break;
+        case 15:
+            gc->visibleG5 = value;
+            break;
+        case 16:
+            gc->visibleG6 = value;
+            break;
+        case 17:
+            gc->visibleG7 = value;
+            break;
+        case 18:
+            gc->Ghp0 = value;
+            break;              // guardian HP [Valaris]
+        case 19:
+            gc->Ghp1 = value;
+            break;
+        case 20:
+            gc->Ghp2 = value;
+            break;
+        case 21:
+            gc->Ghp3 = value;
+            break;
+        case 22:
+            gc->Ghp4 = value;
+            break;
+        case 23:
+            gc->Ghp5 = value;
+            break;
+        case 24:
+            gc->Ghp6 = value;
+            break;
+        case 25:
+            gc->Ghp7 = value;
+            break;              // end additions [Valaris]
+        default:
+            printf
+                ("mapif_parse_GuildCastleDataSave ERROR!! (Not found index=%d)\n",
+                 index);
+            return 0;
+    }
+
+    return mapif_guild_castle_datasave (gc->castle_id, index, value);
+}
+
+// ギルドチェック要求
+int mapif_parse_GuildCheck (int fd, int guild_id, int account_id, int char_id)
+{
+    return guild_check_conflict (guild_id, account_id, 0 /*char_id*/);
+}
+
+// map server からの通信
+// ・1パケットのみ解析すること
+// ・パケット長データはinter.cにセットしておくこと
+// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
+// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
+int inter_guild_parse_frommap (int fd)
+{
+    switch (RFIFOW (fd, 0))
+    {
+        case 0x3030:
+            mapif_parse_CreateGuild (fd, RFIFOL (fd, 4), RFIFOP (fd, 8),
+                                     (struct guild_member *) RFIFOP (fd, 32));
+            break;
+        case 0x3031:
+            mapif_parse_GuildInfo (fd, RFIFOL (fd, 2));
+            break;
+        case 0x3032:
+            mapif_parse_GuildAddMember (fd, RFIFOL (fd, 4),
+                                        (struct guild_member *) RFIFOP (fd,
+                                                                        8));
+            break;
+        case 0x3034:
+            mapif_parse_GuildLeave (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                    RFIFOL (fd, 10), RFIFOB (fd, 14),
+                                    RFIFOP (fd, 15));
+            break;
+        case 0x3035:
+            mapif_parse_GuildChangeMemberInfoShort (fd, RFIFOL (fd, 2),
+                                                    RFIFOL (fd, 6),
+                                                    RFIFOL (fd, 10),
+                                                    RFIFOB (fd, 14),
+                                                    RFIFOW (fd, 15),
+                                                    RFIFOW (fd, 17));
+            break;
+        case 0x3036:
+            mapif_parse_BreakGuild (fd, RFIFOL (fd, 2));
+            break;
+        case 0x3037:
+            mapif_parse_GuildMessage (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
+                                      RFIFOP (fd, 12), RFIFOW (fd, 2) - 12);
+            break;
+        case 0x3038:
+            mapif_parse_GuildCheck (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                    RFIFOL (fd, 10));
+            break;
+        case 0x3039:
+            mapif_parse_GuildBasicInfoChange (fd, RFIFOL (fd, 4),
+                                              RFIFOW (fd, 8), RFIFOP (fd, 10),
+                                              RFIFOW (fd, 2) - 10);
+            break;
+        case 0x303A:
+            mapif_parse_GuildMemberInfoChange (fd, RFIFOL (fd, 4),
+                                               RFIFOL (fd, 8), RFIFOL (fd,
+                                                                       12),
+                                               RFIFOW (fd, 16), RFIFOP (fd,
+                                                                        18),
+                                               RFIFOW (fd, 2) - 18);
+            break;
+        case 0x303B:
+            mapif_parse_GuildPosition (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
+                                       (struct guild_position *) RFIFOP (fd,
+                                                                         12));
+            break;
+        case 0x303C:
+            mapif_parse_GuildSkillUp (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                      RFIFOL (fd, 10));
+            break;
+        case 0x303D:
+            mapif_parse_GuildAlliance (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                       RFIFOL (fd, 10), RFIFOL (fd, 14),
+                                       RFIFOB (fd, 18));
+            break;
+        case 0x303E:
+            mapif_parse_GuildNotice (fd, RFIFOL (fd, 2), RFIFOP (fd, 6),
+                                     RFIFOP (fd, 66));
+            break;
+        case 0x303F:
+            mapif_parse_GuildEmblem (fd, RFIFOW (fd, 2) - 12, RFIFOL (fd, 4),
+                                     RFIFOL (fd, 8), RFIFOP (fd, 12));
+            break;
+        case 0x3040:
+            mapif_parse_GuildCastleDataLoad (fd, RFIFOW (fd, 2),
+                                             RFIFOB (fd, 4));
+            break;
+        case 0x3041:
+            mapif_parse_GuildCastleDataSave (fd, RFIFOW (fd, 2),
+                                             RFIFOB (fd, 4), RFIFOL (fd, 5));
+            break;
+
+        default:
+            return 0;
+    }
+
+    return 1;
+}
+
+// マップサーバーの接続時処理
+int inter_guild_mapif_init (int fd)
+{
+    return mapif_guild_castle_alldataload (fd);
+}
+
+// サーバーから脱退要求(キャラ削除用)
+int inter_guild_leave (int guild_id, int account_id, int char_id)
+{
+    return mapif_parse_GuildLeave (-1, guild_id, account_id, 0 /*char_id*/, 0,
+                                   "**サーバー命令**");
+}
diff --git a/src/char/int_guild.h b/src/char/int_guild.h
deleted file mode 100644
index 5ac9a51..0000000
--- a/src/char/int_guild.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// $Id: int_guild.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#ifndef _INT_GUILD_H_
-#define _INT_GUILD_H_
-
-int  inter_guild_init (void);
-int  inter_guild_save (void);
-int  inter_guild_parse_frommap (int fd);
-struct guild *inter_guild_search (int guild_id);
-int  inter_guild_mapif_init (int fd);
-
-int  inter_guild_leave (int guild_id, int account_id, int char_id);
-
-extern char guild_txt[1024];
-extern char castle_txt[1024];
-
-#endif
diff --git a/src/char/int_guild.hpp b/src/char/int_guild.hpp
new file mode 100644
index 0000000..2833e2d
--- /dev/null
+++ b/src/char/int_guild.hpp
@@ -0,0 +1,16 @@
+// $Id: int_guild.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#ifndef INT_GUILD_HPP
+#define INT_GUILD_HPP
+
+int  inter_guild_init (void);
+int  inter_guild_save (void);
+int  inter_guild_parse_frommap (int fd);
+struct guild *inter_guild_search (int guild_id);
+int  inter_guild_mapif_init (int fd);
+
+int  inter_guild_leave (int guild_id, int account_id, int char_id);
+
+extern char guild_txt[1024];
+extern char castle_txt[1024];
+
+#endif
diff --git a/src/char/int_party.c b/src/char/int_party.c
deleted file mode 100644
index 6f8d023..0000000
--- a/src/char/int_party.c
+++ /dev/null
@@ -1,673 +0,0 @@
-// $Id: int_party.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#include "inter.h"
-#include "int_party.h"
-#include "../common/mmo.h"
-#include "char.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/lock.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char party_txt[1024] = "save/party.txt";
-
-static struct dbt *party_db;
-static int party_newid = 100;
-
-int  mapif_party_broken (int party_id, int flag);
-int  party_check_empty (struct party *p);
-int  mapif_parse_PartyLeave (int fd, int party_id, int account_id);
-
-// パーティデータの文字列への変換
-int inter_party_tostr (char *str, struct party *p)
-{
-    int  i, len;
-
-    len =
-        sprintf (str, "%d\t%s\t%d,%d\t", p->party_id, p->name, p->exp,
-                 p->item);
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct party_member *m = &p->member[i];
-        len +=
-            sprintf (str + len, "%d,%d\t%s\t", m->account_id, m->leader,
-                     ((m->account_id > 0) ? m->name : "NoMember"));
-    }
-
-    return 0;
-}
-
-// パーティデータの文字列からの変換
-int inter_party_fromstr (char *str, struct party *p)
-{
-    int  i, j;
-    int  tmp_int[16];
-    char tmp_str[256];
-
-    memset (p, 0, sizeof (struct party));
-
-//  printf("sscanf party main info\n");
-    if (sscanf
-        (str, "%d\t%[^\t]\t%d,%d\t", &tmp_int[0], tmp_str, &tmp_int[1],
-         &tmp_int[2]) != 4)
-        return 1;
-
-    p->party_id = tmp_int[0];
-    strcpy (p->name, tmp_str);
-    p->exp = tmp_int[1];
-    p->item = tmp_int[2];
-//  printf("%d [%s] %d %d\n", tmp_int[0], tmp_str[0], tmp_int[1], tmp_int[2]);
-
-    for (j = 0; j < 3 && str != NULL; j++)
-        str = strchr (str + 1, '\t');
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct party_member *m = &p->member[i];
-        if (str == NULL)
-            return 1;
-//      printf("sscanf party member info %d\n", i);
-
-        if (sscanf
-            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
-             tmp_str) != 3)
-            return 1;
-
-        m->account_id = tmp_int[0];
-        m->leader = tmp_int[1];
-        strncpy (m->name, tmp_str, sizeof (m->name));
-//      printf(" %d %d [%s]\n", tmp_int[0], tmp_int[1], tmp_str);
-
-        for (j = 0; j < 2 && str != NULL; j++)
-            str = strchr (str + 1, '\t');
-    }
-
-    return 0;
-}
-
-// パーティデータのロード
-int inter_party_init (void)
-{
-    char line[8192];
-    struct party *p;
-    FILE *fp;
-    int  c = 0;
-    int  i, j;
-
-    party_db = numdb_init ();
-
-    if ((fp = fopen_ (party_txt, "r")) == NULL)
-        return 1;
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        j = 0;
-        if (sscanf (line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
-            && party_newid <= i)
-        {
-            party_newid = i;
-            continue;
-        }
-
-        CREATE (p, struct party, 1);
-        if (inter_party_fromstr (line, p) == 0 && p->party_id > 0)
-        {
-            if (p->party_id >= party_newid)
-                party_newid = p->party_id + 1;
-            numdb_insert (party_db, p->party_id, p);
-            party_check_empty (p);
-        }
-        else
-        {
-            printf ("int_party: broken data [%s] line %d\n", party_txt,
-                    c + 1);
-            free (p);
-        }
-        c++;
-    }
-    fclose_ (fp);
-//  printf("int_party: %s read done (%d parties)\n", party_txt, c);
-
-    return 0;
-}
-
-// パーティーデータのセーブ用
-void inter_party_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[8192];
-    FILE *fp;
-
-    inter_party_tostr (line, (struct party *) data);
-    fp = va_arg (ap, FILE *);
-    fprintf (fp, "%s\n", line);
-}
-
-// パーティーデータのセーブ
-int inter_party_save (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if ((fp = lock_fopen (party_txt, &lock)) == NULL)
-    {
-        printf ("int_party: cant write [%s] !!! data is lost !!!\n",
-                party_txt);
-        return 1;
-    }
-    numdb_foreach (party_db, inter_party_save_sub, fp);
-//  fprintf(fp, "%d\t%%newid%%\n", party_newid);
-    lock_fclose (fp, party_txt, &lock);
-//  printf("int_party: %s saved.\n", party_txt);
-
-    return 0;
-}
-
-// パーティ名検索用
-void search_partyname_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct party *p = (struct party *) data, **dst;
-    char *str;
-
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct party **);
-    if (strcasecmp (p->name, str) == 0)
-        *dst = p;
-}
-
-// パーティ名検索
-struct party *search_partyname (char *str)
-{
-    struct party *p = NULL;
-    numdb_foreach (party_db, search_partyname_sub, str, &p);
-
-    return p;
-}
-
-// EXP公平分配できるかチェック
-int party_check_exp_share (struct party *p)
-{
-    int  i;
-    int  maxlv = 0, minlv = 0x7fffffff;
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        int  lv = p->member[i].lv;
-        if (p->member[i].online)
-        {
-            if (lv < minlv)
-                minlv = lv;
-            if (maxlv < lv)
-                maxlv = lv;
-        }
-    }
-
-    return (maxlv == 0 || maxlv - minlv <= party_share_level);
-}
-
-// パーティが空かどうかチェック
-int party_check_empty (struct party *p)
-{
-    int  i;
-
-//  printf("party check empty %08X\n", (int)p);
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-//      printf("%d acc=%d\n", i, p->member[i].account_id);
-        if (p->member[i].account_id > 0)
-        {
-            return 0;
-        }
-    }
-    // 誰もいないので解散
-    mapif_party_broken (p->party_id, 0);
-    numdb_erase (party_db, p->party_id);
-    free (p);
-
-    return 1;
-}
-
-// キャラの競合がないかチェック用
-void party_check_conflict_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct party *p = (struct party *) data;
-    int  party_id, account_id, i;
-    char *nick;
-
-    party_id = va_arg (ap, int);
-    account_id = va_arg (ap, int);
-    nick = va_arg (ap, char *);
-
-    if (p->party_id == party_id)    // 本来の所属なので問題なし
-        return;
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        if (p->member[i].account_id == account_id
-            && strcmp (p->member[i].name, nick) == 0)
-        {
-            // 別のパーティに偽の所属データがあるので脱退
-            printf ("int_party: party conflict! %d %d %d\n", account_id,
-                    party_id, p->party_id);
-            mapif_parse_PartyLeave (-1, p->party_id, account_id);
-        }
-    }
-}
-
-// キャラの競合がないかチェック
-int party_check_conflict (int party_id, int account_id, char *nick)
-{
-    numdb_foreach (party_db, party_check_conflict_sub, party_id, account_id,
-                   nick);
-
-    return 0;
-}
-
-//-------------------------------------------------------------------
-// map serverへの通信
-
-// パーティ作成可否
-int mapif_party_created (int fd, int account_id, struct party *p)
-{
-    WFIFOW (fd, 0) = 0x3820;
-    WFIFOL (fd, 2) = account_id;
-    if (p != NULL)
-    {
-        WFIFOB (fd, 6) = 0;
-        WFIFOL (fd, 7) = p->party_id;
-        memcpy (WFIFOP (fd, 11), p->name, 24);
-        printf ("int_party: created! %d %s\n", p->party_id, p->name);
-    }
-    else
-    {
-        WFIFOB (fd, 6) = 1;
-        WFIFOL (fd, 7) = 0;
-        memcpy (WFIFOP (fd, 11), "error", 24);
-    }
-    WFIFOSET (fd, 35);
-
-    return 0;
-}
-
-// パーティ情報見つからず
-int mapif_party_noinfo (int fd, int party_id)
-{
-    WFIFOW (fd, 0) = 0x3821;
-    WFIFOW (fd, 2) = 8;
-    WFIFOL (fd, 4) = party_id;
-    WFIFOSET (fd, 8);
-    printf ("int_party: info not found %d\n", party_id);
-
-    return 0;
-}
-
-// パーティ情報まとめ送り
-int mapif_party_info (int fd, struct party *p)
-{
-    unsigned char buf[4 + sizeof (struct party)];
-
-    WBUFW (buf, 0) = 0x3821;
-    memcpy (buf + 4, p, sizeof (struct party));
-    WBUFW (buf, 2) = 4 + sizeof (struct party);
-    if (fd < 0)
-        mapif_sendall (buf, WBUFW (buf, 2));
-    else
-        mapif_send (fd, buf, WBUFW (buf, 2));
-//  printf("int_party: info %d %s\n", p->party_id, p->name);
-
-    return 0;
-}
-
-// パーティメンバ追加可否
-int mapif_party_memberadded (int fd, int party_id, int account_id, int flag)
-{
-    WFIFOW (fd, 0) = 0x3822;
-    WFIFOL (fd, 2) = party_id;
-    WFIFOL (fd, 6) = account_id;
-    WFIFOB (fd, 10) = flag;
-    WFIFOSET (fd, 11);
-
-    return 0;
-}
-
-// パーティ設定変更通知
-int mapif_party_optionchanged (int fd, struct party *p, int account_id,
-                               int flag)
-{
-    unsigned char buf[15];
-
-    WBUFW (buf, 0) = 0x3823;
-    WBUFL (buf, 2) = p->party_id;
-    WBUFL (buf, 6) = account_id;
-    WBUFW (buf, 10) = p->exp;
-    WBUFW (buf, 12) = p->item;
-    WBUFB (buf, 14) = flag;
-    if (flag == 0)
-        mapif_sendall (buf, 15);
-    else
-        mapif_send (fd, buf, 15);
-    printf ("int_party: option changed %d %d %d %d %d\n", p->party_id,
-            account_id, p->exp, p->item, flag);
-
-    return 0;
-}
-
-// パーティ脱退通知
-int mapif_party_leaved (int party_id, int account_id, char *name)
-{
-    unsigned char buf[34];
-
-    WBUFW (buf, 0) = 0x3824;
-    WBUFL (buf, 2) = party_id;
-    WBUFL (buf, 6) = account_id;
-    memcpy (WBUFP (buf, 10), name, 24);
-    mapif_sendall (buf, 34);
-    printf ("int_party: party leaved %d %d %s\n", party_id, account_id, name);
-
-    return 0;
-}
-
-// パーティマップ更新通知
-int mapif_party_membermoved (struct party *p, int idx)
-{
-    unsigned char buf[29];
-
-    WBUFW (buf, 0) = 0x3825;
-    WBUFL (buf, 2) = p->party_id;
-    WBUFL (buf, 6) = p->member[idx].account_id;
-    memcpy (WBUFP (buf, 10), p->member[idx].map, 16);
-    WBUFB (buf, 26) = p->member[idx].online;
-    WBUFW (buf, 27) = p->member[idx].lv;
-    mapif_sendall (buf, 29);
-
-    return 0;
-}
-
-// パーティ解散通知
-int mapif_party_broken (int party_id, int flag)
-{
-    unsigned char buf[7];
-    WBUFW (buf, 0) = 0x3826;
-    WBUFL (buf, 2) = party_id;
-    WBUFB (buf, 6) = flag;
-    mapif_sendall (buf, 7);
-    printf ("int_party: broken %d\n", party_id);
-
-    return 0;
-}
-
-// パーティ内発言
-int mapif_party_message (int party_id, int account_id, char *mes, int len)
-{
-    unsigned char buf[len + 12];
-
-    WBUFW (buf, 0) = 0x3827;
-    WBUFW (buf, 2) = len + 12;
-    WBUFL (buf, 4) = party_id;
-    WBUFL (buf, 8) = account_id;
-    memcpy (WBUFP (buf, 12), mes, len);
-    mapif_sendall (buf, len + 12);
-
-    return 0;
-}
-
-//-------------------------------------------------------------------
-// map serverからの通信
-
-// パーティ
-int mapif_parse_CreateParty (int fd, int account_id, char *name, char *nick,
-                             char *map, int lv)
-{
-    struct party *p;
-    int  i;
-
-    for (i = 0; i < 24 && name[i]; i++)
-    {
-        if (!(name[i] & 0xe0) || name[i] == 0x7f)
-        {
-            printf ("int_party: illegal party name [%s]\n", name);
-            mapif_party_created (fd, account_id, NULL);
-            return 0;
-        }
-    }
-
-    if ((p = search_partyname (name)) != NULL)
-    {
-        printf ("int_party: same name party exists [%s]\n", name);
-        mapif_party_created (fd, account_id, NULL);
-        return 0;
-    }
-    CREATE (p, struct party, 1);
-    p->party_id = party_newid++;
-    memcpy (p->name, name, 24);
-    p->exp = 0;
-    p->item = 0;
-    p->member[0].account_id = account_id;
-    memcpy (p->member[0].name, nick, 24);
-    memcpy (p->member[0].map, map, 16);
-    p->member[0].leader = 1;
-    p->member[0].online = 1;
-    p->member[0].lv = lv;
-
-    numdb_insert (party_db, p->party_id, p);
-
-    mapif_party_created (fd, account_id, p);
-    mapif_party_info (fd, p);
-
-    return 0;
-}
-
-// パーティ情報要求
-int mapif_parse_PartyInfo (int fd, int party_id)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p != NULL)
-        mapif_party_info (fd, p);
-    else
-        mapif_party_noinfo (fd, party_id);
-
-    return 0;
-}
-
-// パーティ追加要求
-int mapif_parse_PartyAddMember (int fd, int party_id, int account_id,
-                                char *nick, char *map, int lv)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p == NULL)
-    {
-        mapif_party_memberadded (fd, party_id, account_id, 1);
-        return 0;
-    }
-
-    for (int i = 0; i < MAX_PARTY; i++)
-    {
-        if (p->member[i].account_id == 0)
-        {
-            int  flag = 0;
-
-            p->member[i].account_id = account_id;
-            memcpy (p->member[i].name, nick, 24);
-            memcpy (p->member[i].map, map, 16);
-            p->member[i].leader = 0;
-            p->member[i].online = 1;
-            p->member[i].lv = lv;
-            mapif_party_memberadded (fd, party_id, account_id, 0);
-            mapif_party_info (-1, p);
-
-            if (p->exp > 0 && !party_check_exp_share (p))
-            {
-                p->exp = 0;
-                flag = 0x01;
-            }
-            if (flag)
-                mapif_party_optionchanged (fd, p, 0, 0);
-            return 0;
-        }
-    }
-    mapif_party_memberadded (fd, party_id, account_id, 1);
-
-    return 0;
-}
-
-// パーティー設定変更要求
-int mapif_parse_PartyChangeOption (int fd, int party_id, int account_id,
-                                   int exp, int item)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p == NULL)
-        return 0;
-
-    p->exp = exp;
-    int  flag = 0;
-    if (exp > 0 && !party_check_exp_share (p))
-    {
-        flag |= 0x01;
-        p->exp = 0;
-    }
-
-    p->item = item;
-
-    mapif_party_optionchanged (fd, p, account_id, flag);
-    return 0;
-}
-
-// パーティ脱退要求
-int mapif_parse_PartyLeave (int fd, int party_id, int account_id)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p != NULL)
-    {
-        for (int i = 0; i < MAX_PARTY; i++)
-        {
-            if (p->member[i].account_id == account_id)
-            {
-                mapif_party_leaved (party_id, account_id, p->member[i].name);
-
-                memset (&p->member[i], 0, sizeof (struct party_member));
-                if (party_check_empty (p) == 0)
-                    mapif_party_info (-1, p);   // まだ人がいるのでデータ送信
-                return 0;
-            }
-        }
-    }
-
-    return 0;
-}
-
-// パーティマップ更新要求
-int mapif_parse_PartyChangeMap (int fd, int party_id, int account_id,
-                                char *map, int online, int lv)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p == NULL)
-        return 0;
-
-    for (int i = 0; i < MAX_PARTY; i++)
-    {
-        if (p->member[i].account_id == account_id)
-        {
-            int  flag = 0;
-
-            memcpy (p->member[i].map, map, 16);
-            p->member[i].online = online;
-            p->member[i].lv = lv;
-            mapif_party_membermoved (p, i);
-
-            if (p->exp > 0 && !party_check_exp_share (p))
-            {
-                p->exp = 0;
-                flag = 1;
-            }
-            if (flag)
-                mapif_party_optionchanged (fd, p, 0, 0);
-            break;
-        }
-    }
-
-    return 0;
-}
-
-// パーティ解散要求
-int mapif_parse_BreakParty (int fd, int party_id)
-{
-    struct party *p = (struct party *)numdb_search (party_db, party_id);
-    if (p == NULL)
-        return 0;
-
-    numdb_erase (party_db, party_id);
-    mapif_party_broken (fd, party_id);
-
-    return 0;
-}
-
-// パーティメッセージ送信
-int mapif_parse_PartyMessage (int fd, int party_id, int account_id, char *mes,
-                              int len)
-{
-    return mapif_party_message (party_id, account_id, mes, len);
-}
-
-// パーティチェック要求
-int mapif_parse_PartyCheck (int fd, int party_id, int account_id, char *nick)
-{
-    return party_check_conflict (party_id, account_id, nick);
-}
-
-// map server からの通信
-// ・1パケットのみ解析すること
-// ・パケット長データはinter.cにセットしておくこと
-// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
-// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
-int inter_party_parse_frommap (int fd)
-{
-    switch (RFIFOW (fd, 0))
-    {
-        case 0x3020:
-            mapif_parse_CreateParty (fd, RFIFOL (fd, 2), RFIFOP (fd, 6),
-                                     RFIFOP (fd, 30), RFIFOP (fd, 54),
-                                     RFIFOW (fd, 70));
-            break;
-        case 0x3021:
-            mapif_parse_PartyInfo (fd, RFIFOL (fd, 2));
-            break;
-        case 0x3022:
-            mapif_parse_PartyAddMember (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                        RFIFOP (fd, 10), RFIFOP (fd, 34),
-                                        RFIFOW (fd, 50));
-            break;
-        case 0x3023:
-            mapif_parse_PartyChangeOption (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                           RFIFOW (fd, 10), RFIFOW (fd, 12));
-            break;
-        case 0x3024:
-            mapif_parse_PartyLeave (fd, RFIFOL (fd, 2), RFIFOL (fd, 6));
-            break;
-        case 0x3025:
-            mapif_parse_PartyChangeMap (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                        RFIFOP (fd, 10), RFIFOB (fd, 26),
-                                        RFIFOW (fd, 27));
-            break;
-        case 0x3026:
-            mapif_parse_BreakParty (fd, RFIFOL (fd, 2));
-            break;
-        case 0x3027:
-            mapif_parse_PartyMessage (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
-                                      RFIFOP (fd, 12), RFIFOW (fd, 2) - 12);
-            break;
-        case 0x3028:
-            mapif_parse_PartyCheck (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                    RFIFOP (fd, 10));
-            break;
-        default:
-            return 0;
-    }
-
-    return 1;
-}
-
-// サーバーから脱退要求(キャラ削除用)
-int inter_party_leave (int party_id, int account_id)
-{
-    return mapif_parse_PartyLeave (-1, party_id, account_id);
-}
diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp
new file mode 100644
index 0000000..7d0e0ce
--- /dev/null
+++ b/src/char/int_party.cpp
@@ -0,0 +1,673 @@
+// $Id: int_party.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#include "inter.hpp"
+#include "int_party.hpp"
+#include "../common/mmo.hpp"
+#include "char.hpp"
+#include "../common/socket.hpp"
+#include "../common/db.hpp"
+#include "../common/lock.hpp"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char party_txt[1024] = "save/party.txt";
+
+static struct dbt *party_db;
+static int party_newid = 100;
+
+int  mapif_party_broken (int party_id, int flag);
+int  party_check_empty (struct party *p);
+int  mapif_parse_PartyLeave (int fd, int party_id, int account_id);
+
+// パーティデータの文字列への変換
+int inter_party_tostr (char *str, struct party *p)
+{
+    int  i, len;
+
+    len =
+        sprintf (str, "%d\t%s\t%d,%d\t", p->party_id, p->name, p->exp,
+                 p->item);
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct party_member *m = &p->member[i];
+        len +=
+            sprintf (str + len, "%d,%d\t%s\t", m->account_id, m->leader,
+                     ((m->account_id > 0) ? m->name : "NoMember"));
+    }
+
+    return 0;
+}
+
+// パーティデータの文字列からの変換
+int inter_party_fromstr (char *str, struct party *p)
+{
+    int  i, j;
+    int  tmp_int[16];
+    char tmp_str[256];
+
+    memset (p, 0, sizeof (struct party));
+
+//  printf("sscanf party main info\n");
+    if (sscanf
+        (str, "%d\t%[^\t]\t%d,%d\t", &tmp_int[0], tmp_str, &tmp_int[1],
+         &tmp_int[2]) != 4)
+        return 1;
+
+    p->party_id = tmp_int[0];
+    strcpy (p->name, tmp_str);
+    p->exp = tmp_int[1];
+    p->item = tmp_int[2];
+//  printf("%d [%s] %d %d\n", tmp_int[0], tmp_str[0], tmp_int[1], tmp_int[2]);
+
+    for (j = 0; j < 3 && str != NULL; j++)
+        str = strchr (str + 1, '\t');
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct party_member *m = &p->member[i];
+        if (str == NULL)
+            return 1;
+//      printf("sscanf party member info %d\n", i);
+
+        if (sscanf
+            (str + 1, "%d,%d\t%[^\t]\t", &tmp_int[0], &tmp_int[1],
+             tmp_str) != 3)
+            return 1;
+
+        m->account_id = tmp_int[0];
+        m->leader = tmp_int[1];
+        strncpy (m->name, tmp_str, sizeof (m->name));
+//      printf(" %d %d [%s]\n", tmp_int[0], tmp_int[1], tmp_str);
+
+        for (j = 0; j < 2 && str != NULL; j++)
+            str = strchr (str + 1, '\t');
+    }
+
+    return 0;
+}
+
+// パーティデータのロード
+int inter_party_init (void)
+{
+    char line[8192];
+    struct party *p;
+    FILE *fp;
+    int  c = 0;
+    int  i, j;
+
+    party_db = numdb_init ();
+
+    if ((fp = fopen_ (party_txt, "r")) == NULL)
+        return 1;
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        j = 0;
+        if (sscanf (line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0
+            && party_newid <= i)
+        {
+            party_newid = i;
+            continue;
+        }
+
+        CREATE (p, struct party, 1);
+        if (inter_party_fromstr (line, p) == 0 && p->party_id > 0)
+        {
+            if (p->party_id >= party_newid)
+                party_newid = p->party_id + 1;
+            numdb_insert (party_db, p->party_id, p);
+            party_check_empty (p);
+        }
+        else
+        {
+            printf ("int_party: broken data [%s] line %d\n", party_txt,
+                    c + 1);
+            free (p);
+        }
+        c++;
+    }
+    fclose_ (fp);
+//  printf("int_party: %s read done (%d parties)\n", party_txt, c);
+
+    return 0;
+}
+
+// パーティーデータのセーブ用
+void inter_party_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[8192];
+    FILE *fp;
+
+    inter_party_tostr (line, (struct party *) data);
+    fp = va_arg (ap, FILE *);
+    fprintf (fp, "%s\n", line);
+}
+
+// パーティーデータのセーブ
+int inter_party_save (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if ((fp = lock_fopen (party_txt, &lock)) == NULL)
+    {
+        printf ("int_party: cant write [%s] !!! data is lost !!!\n",
+                party_txt);
+        return 1;
+    }
+    numdb_foreach (party_db, inter_party_save_sub, fp);
+//  fprintf(fp, "%d\t%%newid%%\n", party_newid);
+    lock_fclose (fp, party_txt, &lock);
+//  printf("int_party: %s saved.\n", party_txt);
+
+    return 0;
+}
+
+// パーティ名検索用
+void search_partyname_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct party *p = (struct party *) data, **dst;
+    char *str;
+
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct party **);
+    if (strcasecmp (p->name, str) == 0)
+        *dst = p;
+}
+
+// パーティ名検索
+struct party *search_partyname (char *str)
+{
+    struct party *p = NULL;
+    numdb_foreach (party_db, search_partyname_sub, str, &p);
+
+    return p;
+}
+
+// EXP公平分配できるかチェック
+int party_check_exp_share (struct party *p)
+{
+    int  i;
+    int  maxlv = 0, minlv = 0x7fffffff;
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        int  lv = p->member[i].lv;
+        if (p->member[i].online)
+        {
+            if (lv < minlv)
+                minlv = lv;
+            if (maxlv < lv)
+                maxlv = lv;
+        }
+    }
+
+    return (maxlv == 0 || maxlv - minlv <= party_share_level);
+}
+
+// パーティが空かどうかチェック
+int party_check_empty (struct party *p)
+{
+    int  i;
+
+//  printf("party check empty %08X\n", (int)p);
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+//      printf("%d acc=%d\n", i, p->member[i].account_id);
+        if (p->member[i].account_id > 0)
+        {
+            return 0;
+        }
+    }
+    // 誰もいないので解散
+    mapif_party_broken (p->party_id, 0);
+    numdb_erase (party_db, p->party_id);
+    free (p);
+
+    return 1;
+}
+
+// キャラの競合がないかチェック用
+void party_check_conflict_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct party *p = (struct party *) data;
+    int  party_id, account_id, i;
+    char *nick;
+
+    party_id = va_arg (ap, int);
+    account_id = va_arg (ap, int);
+    nick = va_arg (ap, char *);
+
+    if (p->party_id == party_id)    // 本来の所属なので問題なし
+        return;
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        if (p->member[i].account_id == account_id
+            && strcmp (p->member[i].name, nick) == 0)
+        {
+            // 別のパーティに偽の所属データがあるので脱退
+            printf ("int_party: party conflict! %d %d %d\n", account_id,
+                    party_id, p->party_id);
+            mapif_parse_PartyLeave (-1, p->party_id, account_id);
+        }
+    }
+}
+
+// キャラの競合がないかチェック
+int party_check_conflict (int party_id, int account_id, char *nick)
+{
+    numdb_foreach (party_db, party_check_conflict_sub, party_id, account_id,
+                   nick);
+
+    return 0;
+}
+
+//-------------------------------------------------------------------
+// map serverへの通信
+
+// パーティ作成可否
+int mapif_party_created (int fd, int account_id, struct party *p)
+{
+    WFIFOW (fd, 0) = 0x3820;
+    WFIFOL (fd, 2) = account_id;
+    if (p != NULL)
+    {
+        WFIFOB (fd, 6) = 0;
+        WFIFOL (fd, 7) = p->party_id;
+        memcpy (WFIFOP (fd, 11), p->name, 24);
+        printf ("int_party: created! %d %s\n", p->party_id, p->name);
+    }
+    else
+    {
+        WFIFOB (fd, 6) = 1;
+        WFIFOL (fd, 7) = 0;
+        memcpy (WFIFOP (fd, 11), "error", 24);
+    }
+    WFIFOSET (fd, 35);
+
+    return 0;
+}
+
+// パーティ情報見つからず
+int mapif_party_noinfo (int fd, int party_id)
+{
+    WFIFOW (fd, 0) = 0x3821;
+    WFIFOW (fd, 2) = 8;
+    WFIFOL (fd, 4) = party_id;
+    WFIFOSET (fd, 8);
+    printf ("int_party: info not found %d\n", party_id);
+
+    return 0;
+}
+
+// パーティ情報まとめ送り
+int mapif_party_info (int fd, struct party *p)
+{
+    unsigned char buf[4 + sizeof (struct party)];
+
+    WBUFW (buf, 0) = 0x3821;
+    memcpy (buf + 4, p, sizeof (struct party));
+    WBUFW (buf, 2) = 4 + sizeof (struct party);
+    if (fd < 0)
+        mapif_sendall (buf, WBUFW (buf, 2));
+    else
+        mapif_send (fd, buf, WBUFW (buf, 2));
+//  printf("int_party: info %d %s\n", p->party_id, p->name);
+
+    return 0;
+}
+
+// パーティメンバ追加可否
+int mapif_party_memberadded (int fd, int party_id, int account_id, int flag)
+{
+    WFIFOW (fd, 0) = 0x3822;
+    WFIFOL (fd, 2) = party_id;
+    WFIFOL (fd, 6) = account_id;
+    WFIFOB (fd, 10) = flag;
+    WFIFOSET (fd, 11);
+
+    return 0;
+}
+
+// パーティ設定変更通知
+int mapif_party_optionchanged (int fd, struct party *p, int account_id,
+                               int flag)
+{
+    unsigned char buf[15];
+
+    WBUFW (buf, 0) = 0x3823;
+    WBUFL (buf, 2) = p->party_id;
+    WBUFL (buf, 6) = account_id;
+    WBUFW (buf, 10) = p->exp;
+    WBUFW (buf, 12) = p->item;
+    WBUFB (buf, 14) = flag;
+    if (flag == 0)
+        mapif_sendall (buf, 15);
+    else
+        mapif_send (fd, buf, 15);
+    printf ("int_party: option changed %d %d %d %d %d\n", p->party_id,
+            account_id, p->exp, p->item, flag);
+
+    return 0;
+}
+
+// パーティ脱退通知
+int mapif_party_leaved (int party_id, int account_id, char *name)
+{
+    unsigned char buf[34];
+
+    WBUFW (buf, 0) = 0x3824;
+    WBUFL (buf, 2) = party_id;
+    WBUFL (buf, 6) = account_id;
+    memcpy (WBUFP (buf, 10), name, 24);
+    mapif_sendall (buf, 34);
+    printf ("int_party: party leaved %d %d %s\n", party_id, account_id, name);
+
+    return 0;
+}
+
+// パーティマップ更新通知
+int mapif_party_membermoved (struct party *p, int idx)
+{
+    unsigned char buf[29];
+
+    WBUFW (buf, 0) = 0x3825;
+    WBUFL (buf, 2) = p->party_id;
+    WBUFL (buf, 6) = p->member[idx].account_id;
+    memcpy (WBUFP (buf, 10), p->member[idx].map, 16);
+    WBUFB (buf, 26) = p->member[idx].online;
+    WBUFW (buf, 27) = p->member[idx].lv;
+    mapif_sendall (buf, 29);
+
+    return 0;
+}
+
+// パーティ解散通知
+int mapif_party_broken (int party_id, int flag)
+{
+    unsigned char buf[7];
+    WBUFW (buf, 0) = 0x3826;
+    WBUFL (buf, 2) = party_id;
+    WBUFB (buf, 6) = flag;
+    mapif_sendall (buf, 7);
+    printf ("int_party: broken %d\n", party_id);
+
+    return 0;
+}
+
+// パーティ内発言
+int mapif_party_message (int party_id, int account_id, char *mes, int len)
+{
+    unsigned char buf[len + 12];
+
+    WBUFW (buf, 0) = 0x3827;
+    WBUFW (buf, 2) = len + 12;
+    WBUFL (buf, 4) = party_id;
+    WBUFL (buf, 8) = account_id;
+    memcpy (WBUFP (buf, 12), mes, len);
+    mapif_sendall (buf, len + 12);
+
+    return 0;
+}
+
+//-------------------------------------------------------------------
+// map serverからの通信
+
+// パーティ
+int mapif_parse_CreateParty (int fd, int account_id, char *name, char *nick,
+                             char *map, int lv)
+{
+    struct party *p;
+    int  i;
+
+    for (i = 0; i < 24 && name[i]; i++)
+    {
+        if (!(name[i] & 0xe0) || name[i] == 0x7f)
+        {
+            printf ("int_party: illegal party name [%s]\n", name);
+            mapif_party_created (fd, account_id, NULL);
+            return 0;
+        }
+    }
+
+    if ((p = search_partyname (name)) != NULL)
+    {
+        printf ("int_party: same name party exists [%s]\n", name);
+        mapif_party_created (fd, account_id, NULL);
+        return 0;
+    }
+    CREATE (p, struct party, 1);
+    p->party_id = party_newid++;
+    memcpy (p->name, name, 24);
+    p->exp = 0;
+    p->item = 0;
+    p->member[0].account_id = account_id;
+    memcpy (p->member[0].name, nick, 24);
+    memcpy (p->member[0].map, map, 16);
+    p->member[0].leader = 1;
+    p->member[0].online = 1;
+    p->member[0].lv = lv;
+
+    numdb_insert (party_db, p->party_id, p);
+
+    mapif_party_created (fd, account_id, p);
+    mapif_party_info (fd, p);
+
+    return 0;
+}
+
+// パーティ情報要求
+int mapif_parse_PartyInfo (int fd, int party_id)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p != NULL)
+        mapif_party_info (fd, p);
+    else
+        mapif_party_noinfo (fd, party_id);
+
+    return 0;
+}
+
+// パーティ追加要求
+int mapif_parse_PartyAddMember (int fd, int party_id, int account_id,
+                                char *nick, char *map, int lv)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p == NULL)
+    {
+        mapif_party_memberadded (fd, party_id, account_id, 1);
+        return 0;
+    }
+
+    for (int i = 0; i < MAX_PARTY; i++)
+    {
+        if (p->member[i].account_id == 0)
+        {
+            int  flag = 0;
+
+            p->member[i].account_id = account_id;
+            memcpy (p->member[i].name, nick, 24);
+            memcpy (p->member[i].map, map, 16);
+            p->member[i].leader = 0;
+            p->member[i].online = 1;
+            p->member[i].lv = lv;
+            mapif_party_memberadded (fd, party_id, account_id, 0);
+            mapif_party_info (-1, p);
+
+            if (p->exp > 0 && !party_check_exp_share (p))
+            {
+                p->exp = 0;
+                flag = 0x01;
+            }
+            if (flag)
+                mapif_party_optionchanged (fd, p, 0, 0);
+            return 0;
+        }
+    }
+    mapif_party_memberadded (fd, party_id, account_id, 1);
+
+    return 0;
+}
+
+// パーティー設定変更要求
+int mapif_parse_PartyChangeOption (int fd, int party_id, int account_id,
+                                   int exp, int item)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p == NULL)
+        return 0;
+
+    p->exp = exp;
+    int  flag = 0;
+    if (exp > 0 && !party_check_exp_share (p))
+    {
+        flag |= 0x01;
+        p->exp = 0;
+    }
+
+    p->item = item;
+
+    mapif_party_optionchanged (fd, p, account_id, flag);
+    return 0;
+}
+
+// パーティ脱退要求
+int mapif_parse_PartyLeave (int fd, int party_id, int account_id)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p != NULL)
+    {
+        for (int i = 0; i < MAX_PARTY; i++)
+        {
+            if (p->member[i].account_id == account_id)
+            {
+                mapif_party_leaved (party_id, account_id, p->member[i].name);
+
+                memset (&p->member[i], 0, sizeof (struct party_member));
+                if (party_check_empty (p) == 0)
+                    mapif_party_info (-1, p);   // まだ人がいるのでデータ送信
+                return 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+// パーティマップ更新要求
+int mapif_parse_PartyChangeMap (int fd, int party_id, int account_id,
+                                char *map, int online, int lv)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p == NULL)
+        return 0;
+
+    for (int i = 0; i < MAX_PARTY; i++)
+    {
+        if (p->member[i].account_id == account_id)
+        {
+            int  flag = 0;
+
+            memcpy (p->member[i].map, map, 16);
+            p->member[i].online = online;
+            p->member[i].lv = lv;
+            mapif_party_membermoved (p, i);
+
+            if (p->exp > 0 && !party_check_exp_share (p))
+            {
+                p->exp = 0;
+                flag = 1;
+            }
+            if (flag)
+                mapif_party_optionchanged (fd, p, 0, 0);
+            break;
+        }
+    }
+
+    return 0;
+}
+
+// パーティ解散要求
+int mapif_parse_BreakParty (int fd, int party_id)
+{
+    struct party *p = (struct party *)numdb_search (party_db, party_id);
+    if (p == NULL)
+        return 0;
+
+    numdb_erase (party_db, party_id);
+    mapif_party_broken (fd, party_id);
+
+    return 0;
+}
+
+// パーティメッセージ送信
+int mapif_parse_PartyMessage (int fd, int party_id, int account_id, char *mes,
+                              int len)
+{
+    return mapif_party_message (party_id, account_id, mes, len);
+}
+
+// パーティチェック要求
+int mapif_parse_PartyCheck (int fd, int party_id, int account_id, char *nick)
+{
+    return party_check_conflict (party_id, account_id, nick);
+}
+
+// map server からの通信
+// ・1パケットのみ解析すること
+// ・パケット長データはinter.cにセットしておくこと
+// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
+// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
+int inter_party_parse_frommap (int fd)
+{
+    switch (RFIFOW (fd, 0))
+    {
+        case 0x3020:
+            mapif_parse_CreateParty (fd, RFIFOL (fd, 2), RFIFOP (fd, 6),
+                                     RFIFOP (fd, 30), RFIFOP (fd, 54),
+                                     RFIFOW (fd, 70));
+            break;
+        case 0x3021:
+            mapif_parse_PartyInfo (fd, RFIFOL (fd, 2));
+            break;
+        case 0x3022:
+            mapif_parse_PartyAddMember (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                        RFIFOP (fd, 10), RFIFOP (fd, 34),
+                                        RFIFOW (fd, 50));
+            break;
+        case 0x3023:
+            mapif_parse_PartyChangeOption (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                           RFIFOW (fd, 10), RFIFOW (fd, 12));
+            break;
+        case 0x3024:
+            mapif_parse_PartyLeave (fd, RFIFOL (fd, 2), RFIFOL (fd, 6));
+            break;
+        case 0x3025:
+            mapif_parse_PartyChangeMap (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                        RFIFOP (fd, 10), RFIFOB (fd, 26),
+                                        RFIFOW (fd, 27));
+            break;
+        case 0x3026:
+            mapif_parse_BreakParty (fd, RFIFOL (fd, 2));
+            break;
+        case 0x3027:
+            mapif_parse_PartyMessage (fd, RFIFOL (fd, 4), RFIFOL (fd, 8),
+                                      RFIFOP (fd, 12), RFIFOW (fd, 2) - 12);
+            break;
+        case 0x3028:
+            mapif_parse_PartyCheck (fd, RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                    RFIFOP (fd, 10));
+            break;
+        default:
+            return 0;
+    }
+
+    return 1;
+}
+
+// サーバーから脱退要求(キャラ削除用)
+int inter_party_leave (int party_id, int account_id)
+{
+    return mapif_parse_PartyLeave (-1, party_id, account_id);
+}
diff --git a/src/char/int_party.h b/src/char/int_party.h
deleted file mode 100644
index 2007ed5..0000000
--- a/src/char/int_party.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// $Id: int_party.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#ifndef _INT_PARTY_H_
-#define _INT_PARTY_H_
-
-int  inter_party_init (void);
-int  inter_party_save (void);
-
-int  inter_party_parse_frommap (int fd);
-
-int  inter_party_leave (int party_id, int account_id);
-
-extern char party_txt[1024];
-
-#endif
diff --git a/src/char/int_party.hpp b/src/char/int_party.hpp
new file mode 100644
index 0000000..93e8887
--- /dev/null
+++ b/src/char/int_party.hpp
@@ -0,0 +1,14 @@
+// $Id: int_party.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#ifndef INT_PARTY_HPP
+#define INT_PARTY_HPP
+
+int  inter_party_init (void);
+int  inter_party_save (void);
+
+int  inter_party_parse_frommap (int fd);
+
+int  inter_party_leave (int party_id, int account_id);
+
+extern char party_txt[1024];
+
+#endif
diff --git a/src/char/int_storage.c b/src/char/int_storage.c
deleted file mode 100644
index e565572..0000000
--- a/src/char/int_storage.c
+++ /dev/null
@@ -1,576 +0,0 @@
-// $Id: int_storage.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "../common/mmo.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/lock.h"
-#include "char.h"
-#include "inter.h"
-#include "int_storage.h"
-#include "int_guild.h"
-
-// ファイル名のデフォルト
-// inter_config_read()で再設定される
-char storage_txt[1024] = "save/storage.txt";
-char guild_storage_txt[1024] = "save/g_storage.txt";
-
-static struct dbt *storage_db;
-static struct dbt *guild_storage_db;
-
-// 倉庫データを文字列に変換
-int storage_tostr (char *str, struct storage *p)
-{
-    int  i, f = 0;
-    char *str_p = str;
-    str_p += sprintf (str_p, "%d,%d\t", p->account_id, p->storage_amount);
-
-    for (i = 0; i < MAX_STORAGE; i++)
-        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
-        {
-            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                              p->storage_[i].id, p->storage_[i].nameid,
-                              p->storage_[i].amount, p->storage_[i].equip,
-                              p->storage_[i].identify, p->storage_[i].refine,
-                              p->storage_[i].attribute,
-                              p->storage_[i].card[0], p->storage_[i].card[1],
-                              p->storage_[i].card[2], p->storage_[i].card[3]);
-            f++;
-        }
-
-    *(str_p++) = '\t';
-
-    *str_p = '\0';
-    if (!f)
-        str[0] = 0;
-    return 0;
-}
-
-// 文字列を倉庫データに変換
-int storage_fromstr (char *str, struct storage *p)
-{
-    int  tmp_int[256];
-    int  set, next, len, i;
-
-    set = sscanf (str, "%d,%d%n", &tmp_int[0], &tmp_int[1], &next);
-    p->storage_amount = tmp_int[1];
-
-    if (set != 2)
-        return 1;
-    if (str[next] == '\n' || str[next] == '\r')
-        return 0;
-    next++;
-    for (i = 0; str[next] && str[next] != '\t' && i < MAX_STORAGE; i++)
-    {
-        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                    &tmp_int[10], &len) == 12)
-        {
-            p->storage_[i].id = tmp_int[0];
-            p->storage_[i].nameid = tmp_int[1];
-            p->storage_[i].amount = tmp_int[2];
-            p->storage_[i].equip = tmp_int[3];
-            p->storage_[i].identify = tmp_int[4];
-            p->storage_[i].refine = tmp_int[5];
-            p->storage_[i].attribute = tmp_int[6];
-            p->storage_[i].card[0] = tmp_int[7];
-            p->storage_[i].card[1] = tmp_int[8];
-            p->storage_[i].card[2] = tmp_int[9];
-            p->storage_[i].card[3] = tmp_int[10];
-            next += len;
-            if (str[next] == ' ')
-                next++;
-        }
-
-        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                         &len) == 11)
-        {
-            p->storage_[i].id = tmp_int[0];
-            p->storage_[i].nameid = tmp_int[1];
-            p->storage_[i].amount = tmp_int[2];
-            p->storage_[i].equip = tmp_int[3];
-            p->storage_[i].identify = tmp_int[4];
-            p->storage_[i].refine = tmp_int[5];
-            p->storage_[i].attribute = tmp_int[6];
-            p->storage_[i].card[0] = tmp_int[7];
-            p->storage_[i].card[1] = tmp_int[8];
-            p->storage_[i].card[2] = tmp_int[9];
-            p->storage_[i].card[3] = tmp_int[10];
-            next += len;
-            if (str[next] == ' ')
-                next++;
-        }
-
-        else
-            return 1;
-    }
-    if (i >= MAX_STORAGE && str[next] && str[next] != '\t')
-        printf
-            ("storage_fromstr: Found a storage line with more items than MAX_STORAGE (%d), remaining items have been discarded!\n",
-             MAX_STORAGE);
-    return 0;
-}
-
-int guild_storage_tostr (char *str, struct guild_storage *p)
-{
-    int  i, f = 0;
-    char *str_p = str;
-    str_p += sprintf (str, "%d,%d\t", p->guild_id, p->storage_amount);
-
-    for (i = 0; i < MAX_GUILD_STORAGE; i++)
-        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
-        {
-            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                              p->storage_[i].id, p->storage_[i].nameid,
-                              p->storage_[i].amount, p->storage_[i].equip,
-                              p->storage_[i].identify, p->storage_[i].refine,
-                              p->storage_[i].attribute,
-                              p->storage_[i].card[0], p->storage_[i].card[1],
-                              p->storage_[i].card[2], p->storage_[i].card[3]);
-            f++;
-        }
-
-    *(str_p++) = '\t';
-
-    *str_p = '\0';
-    if (!f)
-        str[0] = 0;
-    return 0;
-}
-
-int guild_storage_fromstr (char *str, struct guild_storage *p)
-{
-    int  tmp_int[256];
-    int  set, next, len, i;
-
-    set = sscanf (str, "%d,%d%n", &tmp_int[0], &tmp_int[1], &next);
-    p->storage_amount = tmp_int[1];
-
-    if (set != 2)
-        return 1;
-    if (str[next] == '\n' || str[next] == '\r')
-        return 0;
-    next++;
-    for (i = 0; str[next] && str[next] != '\t' && i < MAX_GUILD_STORAGE; i++)
-    {
-        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                    &tmp_int[10], &len) == 12)
-        {
-            p->storage_[i].id = tmp_int[0];
-            p->storage_[i].nameid = tmp_int[1];
-            p->storage_[i].amount = tmp_int[2];
-            p->storage_[i].equip = tmp_int[3];
-            p->storage_[i].identify = tmp_int[4];
-            p->storage_[i].refine = tmp_int[5];
-            p->storage_[i].attribute = tmp_int[6];
-            p->storage_[i].card[0] = tmp_int[7];
-            p->storage_[i].card[1] = tmp_int[8];
-            p->storage_[i].card[2] = tmp_int[9];
-            p->storage_[i].card[3] = tmp_int[10];
-            next += len;
-            if (str[next] == ' ')
-                next++;
-        }
-
-        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                         &len) == 11)
-        {
-            p->storage_[i].id = tmp_int[0];
-            p->storage_[i].nameid = tmp_int[1];
-            p->storage_[i].amount = tmp_int[2];
-            p->storage_[i].equip = tmp_int[3];
-            p->storage_[i].identify = tmp_int[4];
-            p->storage_[i].refine = tmp_int[5];
-            p->storage_[i].attribute = tmp_int[6];
-            p->storage_[i].card[0] = tmp_int[7];
-            p->storage_[i].card[1] = tmp_int[8];
-            p->storage_[i].card[2] = tmp_int[9];
-            p->storage_[i].card[3] = tmp_int[10];
-            next += len;
-            if (str[next] == ' ')
-                next++;
-        }
-
-        else
-            return 1;
-    }
-    if (i >= MAX_GUILD_STORAGE && str[next] && str[next] != '\t')
-        printf
-            ("guild_storage_fromstr: Found a storage line with more items than MAX_GUILD_STORAGE (%d), remaining items have been discarded!\n",
-             MAX_GUILD_STORAGE);
-    return 0;
-}
-
-// アカウントから倉庫データインデックスを得る(新規倉庫追加可能)
-struct storage *account2storage (int account_id)
-{
-    struct storage *s;
-    s = (struct storage *) numdb_search (storage_db, account_id);
-    if (s == NULL)
-    {
-        CREATE (s, struct storage, 1);
-        memset (s, 0, sizeof (struct storage));
-        s->account_id = account_id;
-        numdb_insert (storage_db, s->account_id, s);
-    }
-    return s;
-}
-
-struct guild_storage *guild2storage (int guild_id)
-{
-    struct guild_storage *gs = NULL;
-    if (inter_guild_search (guild_id) != NULL)
-    {
-        gs = (struct guild_storage *) numdb_search (guild_storage_db,
-                                                    guild_id);
-        if (gs == NULL)
-        {
-            CREATE (gs, struct guild_storage, 1);
-            gs->guild_id = guild_id;
-            numdb_insert (guild_storage_db, gs->guild_id, gs);
-        }
-    }
-    return gs;
-}
-
-//---------------------------------------------------------
-// 倉庫データを読み込む
-int inter_storage_init (void)
-{
-    char line[65536];
-    int  c = 0, tmp_int;
-    struct storage *s;
-    struct guild_storage *gs;
-    FILE *fp;
-
-    storage_db = numdb_init ();
-
-    fp = fopen_ (storage_txt, "r");
-    if (fp == NULL)
-    {
-        printf ("cant't read : %s\n", storage_txt);
-        return 1;
-    }
-    while (fgets (line, 65535, fp))
-    {
-        sscanf (line, "%d", &tmp_int);
-        CREATE (s, struct storage, 1);
-        s->account_id = tmp_int;
-        if (s->account_id > 0 && storage_fromstr (line, s) == 0)
-        {
-            numdb_insert (storage_db, s->account_id, s);
-        }
-        else
-        {
-            printf ("int_storage: broken data [%s] line %d\n", storage_txt,
-                    c);
-            free (s);
-        }
-        c++;
-    }
-    fclose_ (fp);
-
-    c = 0;
-    guild_storage_db = numdb_init ();
-
-    fp = fopen_ (guild_storage_txt, "r");
-    if (fp == NULL)
-    {
-        printf ("cant't read : %s\n", guild_storage_txt);
-        return 1;
-    }
-    while (fgets (line, 65535, fp))
-    {
-        sscanf (line, "%d", &tmp_int);
-        CREATE (gs, struct guild_storage, 1);
-        gs->guild_id = tmp_int;
-        if (gs->guild_id > 0 && guild_storage_fromstr (line, gs) == 0)
-        {
-            numdb_insert (guild_storage_db, gs->guild_id, gs);
-        }
-        else
-        {
-            printf ("int_storage: broken data [%s] line %d\n",
-                    guild_storage_txt, c);
-            free (gs);
-        }
-        c++;
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-void storage_db_final (db_key_t k, db_val_t data, va_list ap)
-{
-    struct storage *p = (struct storage *) data;
-    if (p)
-        free (p);
-}
-
-void guild_storage_db_final (db_key_t k, db_val_t data, va_list ap)
-{
-    struct guild_storage *p = (struct guild_storage *) data;
-    if (p)
-        free (p);
-}
-
-void inter_storage_final (void)
-{
-    numdb_final (storage_db, storage_db_final);
-    numdb_final (guild_storage_db, guild_storage_db_final);
-    return;
-}
-
-void inter_storage_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[65536];
-    FILE *fp;
-    storage_tostr (line, (struct storage *) data);
-    fp = va_arg (ap, FILE *);
-    if (*line)
-        fprintf (fp, "%s\n", line);
-}
-
-//---------------------------------------------------------
-// 倉庫データを書き込む
-int inter_storage_save (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if (!storage_db)
-        return 1;
-
-    if ((fp = lock_fopen (storage_txt, &lock)) == NULL)
-    {
-        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
-                storage_txt);
-        return 1;
-    }
-    numdb_foreach (storage_db, inter_storage_save_sub, fp);
-    lock_fclose (fp, storage_txt, &lock);
-//  printf("int_storage: %s saved.\n",storage_txt);
-    return 0;
-}
-
-void inter_guild_storage_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[65536];
-    FILE *fp;
-
-    if (inter_guild_search (((struct guild_storage *) data)->guild_id) !=
-        NULL)
-    {
-        guild_storage_tostr (line, (struct guild_storage *) data);
-        fp = va_arg (ap, FILE *);
-        if (*line)
-            fprintf (fp, "%s\n", line);
-    }
-}
-
-//---------------------------------------------------------
-// 倉庫データを書き込む
-int inter_guild_storage_save (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if (!guild_storage_db)
-        return 1;
-
-    if ((fp = lock_fopen (guild_storage_txt, &lock)) == NULL)
-    {
-        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
-                guild_storage_txt);
-        return 1;
-    }
-    numdb_foreach (guild_storage_db, inter_guild_storage_save_sub, fp);
-    lock_fclose (fp, guild_storage_txt, &lock);
-//  printf("int_storage: %s saved.\n",guild_storage_txt);
-    return 0;
-}
-
-// 倉庫データ削除
-int inter_storage_delete (int account_id)
-{
-    struct storage *s =
-        (struct storage *) numdb_search (storage_db, account_id);
-    if (s)
-    {
-        numdb_erase (storage_db, account_id);
-        free (s);
-    }
-    return 0;
-}
-
-// ギルド倉庫データ削除
-int inter_guild_storage_delete (int guild_id)
-{
-    struct guild_storage *gs =
-        (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
-    if (gs)
-    {
-        numdb_erase (guild_storage_db, guild_id);
-        free (gs);
-    }
-    return 0;
-}
-
-//---------------------------------------------------------
-// map serverへの通信
-
-// 倉庫データの送信
-int mapif_load_storage (int fd, int account_id)
-{
-    struct storage *s = account2storage (account_id);
-    WFIFOW (fd, 0) = 0x3810;
-    WFIFOW (fd, 2) = sizeof (struct storage) + 8;
-    WFIFOL (fd, 4) = account_id;
-    memcpy (WFIFOP (fd, 8), s, sizeof (struct storage));
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-// 倉庫データ保存完了送信
-int mapif_save_storage_ack (int fd, int account_id)
-{
-    WFIFOW (fd, 0) = 0x3811;
-    WFIFOL (fd, 2) = account_id;
-    WFIFOB (fd, 6) = 0;
-    WFIFOSET (fd, 7);
-    return 0;
-}
-
-int mapif_load_guild_storage (int fd, int account_id, int guild_id)
-{
-    struct guild_storage *gs = guild2storage (guild_id);
-    WFIFOW (fd, 0) = 0x3818;
-    if (gs)
-    {
-        WFIFOW (fd, 2) = sizeof (struct guild_storage) + 12;
-        WFIFOL (fd, 4) = account_id;
-        WFIFOL (fd, 8) = guild_id;
-        memcpy (WFIFOP (fd, 12), gs, sizeof (struct guild_storage));
-    }
-    else
-    {
-        WFIFOW (fd, 2) = 12;
-        WFIFOL (fd, 4) = account_id;
-        WFIFOL (fd, 8) = 0;
-    }
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-int mapif_save_guild_storage_ack (int fd, int account_id, int guild_id,
-                                  int fail)
-{
-    WFIFOW (fd, 0) = 0x3819;
-    WFIFOL (fd, 2) = account_id;
-    WFIFOL (fd, 6) = guild_id;
-    WFIFOB (fd, 10) = fail;
-    WFIFOSET (fd, 11);
-    return 0;
-}
-
-//---------------------------------------------------------
-// map serverからの通信
-
-// 倉庫データ要求受信
-int mapif_parse_LoadStorage (int fd)
-{
-    mapif_load_storage (fd, RFIFOL (fd, 2));
-    return 0;
-}
-
-// 倉庫データ受信&保存
-int mapif_parse_SaveStorage (int fd)
-{
-    struct storage *s;
-    int  account_id = RFIFOL (fd, 4);
-    int  len = RFIFOW (fd, 2);
-    if (sizeof (struct storage) != len - 8)
-    {
-        printf ("inter storage: data size error %d %d\n",
-                sizeof (struct storage), len - 8);
-    }
-    else
-    {
-        s = account2storage (account_id);
-        memcpy (s, RFIFOP (fd, 8), sizeof (struct storage));
-        mapif_save_storage_ack (fd, account_id);
-    }
-    return 0;
-}
-
-int mapif_parse_LoadGuildStorage (int fd)
-{
-    mapif_load_guild_storage (fd, RFIFOL (fd, 2), RFIFOL (fd, 6));
-    return 0;
-}
-
-int mapif_parse_SaveGuildStorage (int fd)
-{
-    struct guild_storage *gs;
-    int  guild_id = RFIFOL (fd, 8);
-    int  len = RFIFOW (fd, 2);
-    if (sizeof (struct guild_storage) != len - 12)
-    {
-        printf ("inter storage: data size error %d %d\n",
-                sizeof (struct guild_storage), len - 12);
-    }
-    else
-    {
-        gs = guild2storage (guild_id);
-        if (gs)
-        {
-            memcpy (gs, RFIFOP (fd, 12), sizeof (struct guild_storage));
-            mapif_save_guild_storage_ack (fd, RFIFOL (fd, 4), guild_id, 0);
-        }
-        else
-            mapif_save_guild_storage_ack (fd, RFIFOL (fd, 4), guild_id, 1);
-    }
-    return 0;
-}
-
-// map server からの通信
-// ・1パケットのみ解析すること
-// ・パケット長データはinter.cにセットしておくこと
-// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
-// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
-int inter_storage_parse_frommap (int fd)
-{
-    switch (RFIFOW (fd, 0))
-    {
-        case 0x3010:
-            mapif_parse_LoadStorage (fd);
-            break;
-        case 0x3011:
-            mapif_parse_SaveStorage (fd);
-            break;
-        case 0x3018:
-            mapif_parse_LoadGuildStorage (fd);
-            break;
-        case 0x3019:
-            mapif_parse_SaveGuildStorage (fd);
-            break;
-        default:
-            return 0;
-    }
-    return 1;
-}
diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp
new file mode 100644
index 0000000..b197213
--- /dev/null
+++ b/src/char/int_storage.cpp
@@ -0,0 +1,576 @@
+// $Id: int_storage.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "../common/mmo.hpp"
+#include "../common/socket.hpp"
+#include "../common/db.hpp"
+#include "../common/lock.hpp"
+#include "char.hpp"
+#include "inter.hpp"
+#include "int_storage.hpp"
+#include "int_guild.hpp"
+
+// ファイル名のデフォルト
+// inter_config_read()で再設定される
+char storage_txt[1024] = "save/storage.txt";
+char guild_storage_txt[1024] = "save/g_storage.txt";
+
+static struct dbt *storage_db;
+static struct dbt *guild_storage_db;
+
+// 倉庫データを文字列に変換
+int storage_tostr (char *str, struct storage *p)
+{
+    int  i, f = 0;
+    char *str_p = str;
+    str_p += sprintf (str_p, "%d,%d\t", p->account_id, p->storage_amount);
+
+    for (i = 0; i < MAX_STORAGE; i++)
+        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
+        {
+            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                              p->storage_[i].id, p->storage_[i].nameid,
+                              p->storage_[i].amount, p->storage_[i].equip,
+                              p->storage_[i].identify, p->storage_[i].refine,
+                              p->storage_[i].attribute,
+                              p->storage_[i].card[0], p->storage_[i].card[1],
+                              p->storage_[i].card[2], p->storage_[i].card[3]);
+            f++;
+        }
+
+    *(str_p++) = '\t';
+
+    *str_p = '\0';
+    if (!f)
+        str[0] = 0;
+    return 0;
+}
+
+// 文字列を倉庫データに変換
+int storage_fromstr (char *str, struct storage *p)
+{
+    int  tmp_int[256];
+    int  set, next, len, i;
+
+    set = sscanf (str, "%d,%d%n", &tmp_int[0], &tmp_int[1], &next);
+    p->storage_amount = tmp_int[1];
+
+    if (set != 2)
+        return 1;
+    if (str[next] == '\n' || str[next] == '\r')
+        return 0;
+    next++;
+    for (i = 0; str[next] && str[next] != '\t' && i < MAX_STORAGE; i++)
+    {
+        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                    &tmp_int[10], &len) == 12)
+        {
+            p->storage_[i].id = tmp_int[0];
+            p->storage_[i].nameid = tmp_int[1];
+            p->storage_[i].amount = tmp_int[2];
+            p->storage_[i].equip = tmp_int[3];
+            p->storage_[i].identify = tmp_int[4];
+            p->storage_[i].refine = tmp_int[5];
+            p->storage_[i].attribute = tmp_int[6];
+            p->storage_[i].card[0] = tmp_int[7];
+            p->storage_[i].card[1] = tmp_int[8];
+            p->storage_[i].card[2] = tmp_int[9];
+            p->storage_[i].card[3] = tmp_int[10];
+            next += len;
+            if (str[next] == ' ')
+                next++;
+        }
+
+        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                         &len) == 11)
+        {
+            p->storage_[i].id = tmp_int[0];
+            p->storage_[i].nameid = tmp_int[1];
+            p->storage_[i].amount = tmp_int[2];
+            p->storage_[i].equip = tmp_int[3];
+            p->storage_[i].identify = tmp_int[4];
+            p->storage_[i].refine = tmp_int[5];
+            p->storage_[i].attribute = tmp_int[6];
+            p->storage_[i].card[0] = tmp_int[7];
+            p->storage_[i].card[1] = tmp_int[8];
+            p->storage_[i].card[2] = tmp_int[9];
+            p->storage_[i].card[3] = tmp_int[10];
+            next += len;
+            if (str[next] == ' ')
+                next++;
+        }
+
+        else
+            return 1;
+    }
+    if (i >= MAX_STORAGE && str[next] && str[next] != '\t')
+        printf
+            ("storage_fromstr: Found a storage line with more items than MAX_STORAGE (%d), remaining items have been discarded!\n",
+             MAX_STORAGE);
+    return 0;
+}
+
+int guild_storage_tostr (char *str, struct guild_storage *p)
+{
+    int  i, f = 0;
+    char *str_p = str;
+    str_p += sprintf (str, "%d,%d\t", p->guild_id, p->storage_amount);
+
+    for (i = 0; i < MAX_GUILD_STORAGE; i++)
+        if ((p->storage_[i].nameid) && (p->storage_[i].amount))
+        {
+            str_p += sprintf (str_p, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                              p->storage_[i].id, p->storage_[i].nameid,
+                              p->storage_[i].amount, p->storage_[i].equip,
+                              p->storage_[i].identify, p->storage_[i].refine,
+                              p->storage_[i].attribute,
+                              p->storage_[i].card[0], p->storage_[i].card[1],
+                              p->storage_[i].card[2], p->storage_[i].card[3]);
+            f++;
+        }
+
+    *(str_p++) = '\t';
+
+    *str_p = '\0';
+    if (!f)
+        str[0] = 0;
+    return 0;
+}
+
+int guild_storage_fromstr (char *str, struct guild_storage *p)
+{
+    int  tmp_int[256];
+    int  set, next, len, i;
+
+    set = sscanf (str, "%d,%d%n", &tmp_int[0], &tmp_int[1], &next);
+    p->storage_amount = tmp_int[1];
+
+    if (set != 2)
+        return 1;
+    if (str[next] == '\n' || str[next] == '\r')
+        return 0;
+    next++;
+    for (i = 0; str[next] && str[next] != '\t' && i < MAX_GUILD_STORAGE; i++)
+    {
+        if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                    &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                    &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                    &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                    &tmp_int[10], &len) == 12)
+        {
+            p->storage_[i].id = tmp_int[0];
+            p->storage_[i].nameid = tmp_int[1];
+            p->storage_[i].amount = tmp_int[2];
+            p->storage_[i].equip = tmp_int[3];
+            p->storage_[i].identify = tmp_int[4];
+            p->storage_[i].refine = tmp_int[5];
+            p->storage_[i].attribute = tmp_int[6];
+            p->storage_[i].card[0] = tmp_int[7];
+            p->storage_[i].card[1] = tmp_int[8];
+            p->storage_[i].card[2] = tmp_int[9];
+            p->storage_[i].card[3] = tmp_int[10];
+            next += len;
+            if (str[next] == ' ')
+                next++;
+        }
+
+        else if (sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                         &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                         &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                         &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                         &len) == 11)
+        {
+            p->storage_[i].id = tmp_int[0];
+            p->storage_[i].nameid = tmp_int[1];
+            p->storage_[i].amount = tmp_int[2];
+            p->storage_[i].equip = tmp_int[3];
+            p->storage_[i].identify = tmp_int[4];
+            p->storage_[i].refine = tmp_int[5];
+            p->storage_[i].attribute = tmp_int[6];
+            p->storage_[i].card[0] = tmp_int[7];
+            p->storage_[i].card[1] = tmp_int[8];
+            p->storage_[i].card[2] = tmp_int[9];
+            p->storage_[i].card[3] = tmp_int[10];
+            next += len;
+            if (str[next] == ' ')
+                next++;
+        }
+
+        else
+            return 1;
+    }
+    if (i >= MAX_GUILD_STORAGE && str[next] && str[next] != '\t')
+        printf
+            ("guild_storage_fromstr: Found a storage line with more items than MAX_GUILD_STORAGE (%d), remaining items have been discarded!\n",
+             MAX_GUILD_STORAGE);
+    return 0;
+}
+
+// アカウントから倉庫データインデックスを得る(新規倉庫追加可能)
+struct storage *account2storage (int account_id)
+{
+    struct storage *s;
+    s = (struct storage *) numdb_search (storage_db, account_id);
+    if (s == NULL)
+    {
+        CREATE (s, struct storage, 1);
+        memset (s, 0, sizeof (struct storage));
+        s->account_id = account_id;
+        numdb_insert (storage_db, s->account_id, s);
+    }
+    return s;
+}
+
+struct guild_storage *guild2storage (int guild_id)
+{
+    struct guild_storage *gs = NULL;
+    if (inter_guild_search (guild_id) != NULL)
+    {
+        gs = (struct guild_storage *) numdb_search (guild_storage_db,
+                                                    guild_id);
+        if (gs == NULL)
+        {
+            CREATE (gs, struct guild_storage, 1);
+            gs->guild_id = guild_id;
+            numdb_insert (guild_storage_db, gs->guild_id, gs);
+        }
+    }
+    return gs;
+}
+
+//---------------------------------------------------------
+// 倉庫データを読み込む
+int inter_storage_init (void)
+{
+    char line[65536];
+    int  c = 0, tmp_int;
+    struct storage *s;
+    struct guild_storage *gs;
+    FILE *fp;
+
+    storage_db = numdb_init ();
+
+    fp = fopen_ (storage_txt, "r");
+    if (fp == NULL)
+    {
+        printf ("cant't read : %s\n", storage_txt);
+        return 1;
+    }
+    while (fgets (line, 65535, fp))
+    {
+        sscanf (line, "%d", &tmp_int);
+        CREATE (s, struct storage, 1);
+        s->account_id = tmp_int;
+        if (s->account_id > 0 && storage_fromstr (line, s) == 0)
+        {
+            numdb_insert (storage_db, s->account_id, s);
+        }
+        else
+        {
+            printf ("int_storage: broken data [%s] line %d\n", storage_txt,
+                    c);
+            free (s);
+        }
+        c++;
+    }
+    fclose_ (fp);
+
+    c = 0;
+    guild_storage_db = numdb_init ();
+
+    fp = fopen_ (guild_storage_txt, "r");
+    if (fp == NULL)
+    {
+        printf ("cant't read : %s\n", guild_storage_txt);
+        return 1;
+    }
+    while (fgets (line, 65535, fp))
+    {
+        sscanf (line, "%d", &tmp_int);
+        CREATE (gs, struct guild_storage, 1);
+        gs->guild_id = tmp_int;
+        if (gs->guild_id > 0 && guild_storage_fromstr (line, gs) == 0)
+        {
+            numdb_insert (guild_storage_db, gs->guild_id, gs);
+        }
+        else
+        {
+            printf ("int_storage: broken data [%s] line %d\n",
+                    guild_storage_txt, c);
+            free (gs);
+        }
+        c++;
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+void storage_db_final (db_key_t k, db_val_t data, va_list ap)
+{
+    struct storage *p = (struct storage *) data;
+    if (p)
+        free (p);
+}
+
+void guild_storage_db_final (db_key_t k, db_val_t data, va_list ap)
+{
+    struct guild_storage *p = (struct guild_storage *) data;
+    if (p)
+        free (p);
+}
+
+void inter_storage_final (void)
+{
+    numdb_final (storage_db, storage_db_final);
+    numdb_final (guild_storage_db, guild_storage_db_final);
+    return;
+}
+
+void inter_storage_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[65536];
+    FILE *fp;
+    storage_tostr (line, (struct storage *) data);
+    fp = va_arg (ap, FILE *);
+    if (*line)
+        fprintf (fp, "%s\n", line);
+}
+
+//---------------------------------------------------------
+// 倉庫データを書き込む
+int inter_storage_save (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if (!storage_db)
+        return 1;
+
+    if ((fp = lock_fopen (storage_txt, &lock)) == NULL)
+    {
+        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
+                storage_txt);
+        return 1;
+    }
+    numdb_foreach (storage_db, inter_storage_save_sub, fp);
+    lock_fclose (fp, storage_txt, &lock);
+//  printf("int_storage: %s saved.\n",storage_txt);
+    return 0;
+}
+
+void inter_guild_storage_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[65536];
+    FILE *fp;
+
+    if (inter_guild_search (((struct guild_storage *) data)->guild_id) !=
+        NULL)
+    {
+        guild_storage_tostr (line, (struct guild_storage *) data);
+        fp = va_arg (ap, FILE *);
+        if (*line)
+            fprintf (fp, "%s\n", line);
+    }
+}
+
+//---------------------------------------------------------
+// 倉庫データを書き込む
+int inter_guild_storage_save (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if (!guild_storage_db)
+        return 1;
+
+    if ((fp = lock_fopen (guild_storage_txt, &lock)) == NULL)
+    {
+        printf ("int_storage: cant write [%s] !!! data is lost !!!\n",
+                guild_storage_txt);
+        return 1;
+    }
+    numdb_foreach (guild_storage_db, inter_guild_storage_save_sub, fp);
+    lock_fclose (fp, guild_storage_txt, &lock);
+//  printf("int_storage: %s saved.\n",guild_storage_txt);
+    return 0;
+}
+
+// 倉庫データ削除
+int inter_storage_delete (int account_id)
+{
+    struct storage *s =
+        (struct storage *) numdb_search (storage_db, account_id);
+    if (s)
+    {
+        numdb_erase (storage_db, account_id);
+        free (s);
+    }
+    return 0;
+}
+
+// ギルド倉庫データ削除
+int inter_guild_storage_delete (int guild_id)
+{
+    struct guild_storage *gs =
+        (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
+    if (gs)
+    {
+        numdb_erase (guild_storage_db, guild_id);
+        free (gs);
+    }
+    return 0;
+}
+
+//---------------------------------------------------------
+// map serverへの通信
+
+// 倉庫データの送信
+int mapif_load_storage (int fd, int account_id)
+{
+    struct storage *s = account2storage (account_id);
+    WFIFOW (fd, 0) = 0x3810;
+    WFIFOW (fd, 2) = sizeof (struct storage) + 8;
+    WFIFOL (fd, 4) = account_id;
+    memcpy (WFIFOP (fd, 8), s, sizeof (struct storage));
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+// 倉庫データ保存完了送信
+int mapif_save_storage_ack (int fd, int account_id)
+{
+    WFIFOW (fd, 0) = 0x3811;
+    WFIFOL (fd, 2) = account_id;
+    WFIFOB (fd, 6) = 0;
+    WFIFOSET (fd, 7);
+    return 0;
+}
+
+int mapif_load_guild_storage (int fd, int account_id, int guild_id)
+{
+    struct guild_storage *gs = guild2storage (guild_id);
+    WFIFOW (fd, 0) = 0x3818;
+    if (gs)
+    {
+        WFIFOW (fd, 2) = sizeof (struct guild_storage) + 12;
+        WFIFOL (fd, 4) = account_id;
+        WFIFOL (fd, 8) = guild_id;
+        memcpy (WFIFOP (fd, 12), gs, sizeof (struct guild_storage));
+    }
+    else
+    {
+        WFIFOW (fd, 2) = 12;
+        WFIFOL (fd, 4) = account_id;
+        WFIFOL (fd, 8) = 0;
+    }
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+int mapif_save_guild_storage_ack (int fd, int account_id, int guild_id,
+                                  int fail)
+{
+    WFIFOW (fd, 0) = 0x3819;
+    WFIFOL (fd, 2) = account_id;
+    WFIFOL (fd, 6) = guild_id;
+    WFIFOB (fd, 10) = fail;
+    WFIFOSET (fd, 11);
+    return 0;
+}
+
+//---------------------------------------------------------
+// map serverからの通信
+
+// 倉庫データ要求受信
+int mapif_parse_LoadStorage (int fd)
+{
+    mapif_load_storage (fd, RFIFOL (fd, 2));
+    return 0;
+}
+
+// 倉庫データ受信&保存
+int mapif_parse_SaveStorage (int fd)
+{
+    struct storage *s;
+    int  account_id = RFIFOL (fd, 4);
+    int  len = RFIFOW (fd, 2);
+    if (sizeof (struct storage) != len - 8)
+    {
+        printf ("inter storage: data size error %d %d\n",
+                sizeof (struct storage), len - 8);
+    }
+    else
+    {
+        s = account2storage (account_id);
+        memcpy (s, RFIFOP (fd, 8), sizeof (struct storage));
+        mapif_save_storage_ack (fd, account_id);
+    }
+    return 0;
+}
+
+int mapif_parse_LoadGuildStorage (int fd)
+{
+    mapif_load_guild_storage (fd, RFIFOL (fd, 2), RFIFOL (fd, 6));
+    return 0;
+}
+
+int mapif_parse_SaveGuildStorage (int fd)
+{
+    struct guild_storage *gs;
+    int  guild_id = RFIFOL (fd, 8);
+    int  len = RFIFOW (fd, 2);
+    if (sizeof (struct guild_storage) != len - 12)
+    {
+        printf ("inter storage: data size error %d %d\n",
+                sizeof (struct guild_storage), len - 12);
+    }
+    else
+    {
+        gs = guild2storage (guild_id);
+        if (gs)
+        {
+            memcpy (gs, RFIFOP (fd, 12), sizeof (struct guild_storage));
+            mapif_save_guild_storage_ack (fd, RFIFOL (fd, 4), guild_id, 0);
+        }
+        else
+            mapif_save_guild_storage_ack (fd, RFIFOL (fd, 4), guild_id, 1);
+    }
+    return 0;
+}
+
+// map server からの通信
+// ・1パケットのみ解析すること
+// ・パケット長データはinter.cにセットしておくこと
+// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
+// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
+int inter_storage_parse_frommap (int fd)
+{
+    switch (RFIFOW (fd, 0))
+    {
+        case 0x3010:
+            mapif_parse_LoadStorage (fd);
+            break;
+        case 0x3011:
+            mapif_parse_SaveStorage (fd);
+            break;
+        case 0x3018:
+            mapif_parse_LoadGuildStorage (fd);
+            break;
+        case 0x3019:
+            mapif_parse_SaveGuildStorage (fd);
+            break;
+        default:
+            return 0;
+    }
+    return 1;
+}
diff --git a/src/char/int_storage.h b/src/char/int_storage.h
deleted file mode 100644
index f1859c6..0000000
--- a/src/char/int_storage.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// $Id: int_storage.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#ifndef _INT_STORAGE_H_
-#define _INT_STORAGE_H_
-
-int  inter_storage_init (void);
-void inter_storage_final (void);
-int  inter_storage_save (void);
-int  inter_guild_storage_save (void);
-int  inter_storage_delete (int account_id);
-int  inter_guild_storage_delete (int guild_id);
-struct storage *account2storage (int account_id);
-
-int  inter_storage_parse_frommap (int fd);
-
-extern char storage_txt[1024];
-extern char guild_storage_txt[1024];
-
-#endif
diff --git a/src/char/int_storage.hpp b/src/char/int_storage.hpp
new file mode 100644
index 0000000..9986f2d
--- /dev/null
+++ b/src/char/int_storage.hpp
@@ -0,0 +1,18 @@
+// $Id: int_storage.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#ifndef INT_STORAGE_HPP
+#define INT_STORAGE_HPP
+
+int  inter_storage_init (void);
+void inter_storage_final (void);
+int  inter_storage_save (void);
+int  inter_guild_storage_save (void);
+int  inter_storage_delete (int account_id);
+int  inter_guild_storage_delete (int guild_id);
+struct storage *account2storage (int account_id);
+
+int  inter_storage_parse_frommap (int fd);
+
+extern char storage_txt[1024];
+extern char guild_storage_txt[1024];
+
+#endif
diff --git a/src/char/inter.c b/src/char/inter.c
deleted file mode 100644
index e886bf6..0000000
--- a/src/char/inter.c
+++ /dev/null
@@ -1,635 +0,0 @@
-// $Id: inter.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#include "../common/mmo.h"
-#include "char.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/db.h"
-#include <string.h>
-#include <stdlib.h>
-
-#include "inter.h"
-#include "int_party.h"
-#include "int_guild.h"
-#include "int_storage.h"
-#include "../common/lock.h"
-
-#define WISDATA_TTL (60*1000)   // Existence time of Wisp/page data (60 seconds)
-                                // that is the waiting time of answers of all map-servers
-#define WISDELLIST_MAX 256      // Number of elements of Wisp/page data deletion list
-
-char inter_log_filename[1024] = "log/inter.log";
-
-char accreg_txt[1024] = "save/accreg.txt";
-static struct dbt *accreg_db = NULL;
-
-struct accreg
-{
-    int  account_id, reg_num;
-    struct global_reg reg[ACCOUNT_REG_NUM];
-};
-
-int  party_share_level = 10;
-
-// 送信パケット長リスト
-int  inter_send_packet_length[] = {
-    -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0,
-    35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
-    10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1,
-    9, 9, -1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-// 受信パケット長リスト
-int  inter_recv_packet_length[] = {
-    -1, -1, 7, -1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    6, -1, 0, 0, 0, 0, 0, 0, 10, -1, 0, 0, 0, 0, 0, 0,
-    72, 6, 52, 14, 10, 29, 6, -1, 34, 0, 0, 0, 0, 0, 0, 0,
-    -1, 6, -1, 0, 55, 19, 6, -1, 14, -1, -1, -1, 14, 19, 186, -1,
-    5, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    48, 14, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-struct WisData
-{
-    int  id, fd, count, len;
-    unsigned long tick;
-    unsigned char src[24], dst[24], msg[1024];
-};
-static struct dbt *wis_db = NULL;
-static int wis_dellist[WISDELLIST_MAX], wis_delnum;
-
-//--------------------------------------------------------
-
-// アカウント変数を文字列へ変換
-int inter_accreg_tostr (char *str, struct accreg *reg)
-{
-    int  j;
-    char *p = str;
-
-    p += sprintf (p, "%d\t", reg->account_id);
-    for (j = 0; j < reg->reg_num; j++)
-    {
-        p += sprintf (p, "%s,%d ", reg->reg[j].str, reg->reg[j].value);
-    }
-
-    return 0;
-}
-
-// アカウント変数を文字列から変換
-int inter_accreg_fromstr (const char *str, struct accreg *reg)
-{
-    int  j, v, n;
-    char buf[128];
-    const char *p = str;
-
-    if (sscanf (p, "%d\t%n", &reg->account_id, &n) != 1
-        || reg->account_id <= 0)
-        return 1;
-
-    for (j = 0, p += n; j < ACCOUNT_REG_NUM; j++, p += n)
-    {
-        if (sscanf (p, "%[^,],%d %n", buf, &v, &n) != 2)
-            break;
-        memcpy (reg->reg[j].str, buf, 32);
-        reg->reg[j].value = v;
-    }
-    reg->reg_num = j;
-
-    return 0;
-}
-
-// アカウント変数の読み込み
-int inter_accreg_init (void)
-{
-    char line[8192];
-    FILE *fp;
-    int  c = 0;
-    struct accreg *reg;
-
-    accreg_db = numdb_init ();
-
-    if ((fp = fopen_ (accreg_txt, "r")) == NULL)
-        return 1;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        line[sizeof (line) - 1] = '\0';
-        CREATE (reg, struct accreg, 1);
-        if (inter_accreg_fromstr (line, reg) == 0 && reg->account_id > 0)
-        {
-            numdb_insert (accreg_db, reg->account_id, reg);
-        }
-        else
-        {
-            printf ("inter: accreg: broken data [%s] line %d\n", accreg_txt,
-                    c);
-            free (reg);
-        }
-        c++;
-    }
-    fclose_ (fp);
-//  printf("inter: %s read done (%d)\n", accreg_txt, c);
-
-    return 0;
-}
-
-// アカウント変数のセーブ用
-void inter_accreg_save_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    char line[8192];
-    FILE *fp;
-    struct accreg *reg = (struct accreg *) data;
-
-    if (reg->reg_num > 0)
-    {
-        inter_accreg_tostr (line, reg);
-        fp = va_arg (ap, FILE *);
-        fprintf (fp, "%s\n", line);
-    }
-}
-
-// アカウント変数のセーブ
-int inter_accreg_save (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if ((fp = lock_fopen (accreg_txt, &lock)) == NULL)
-    {
-        printf ("int_accreg: cant write [%s] !!! data is lost !!!\n",
-                accreg_txt);
-        return 1;
-    }
-    numdb_foreach (accreg_db, inter_accreg_save_sub, fp);
-    lock_fclose (fp, accreg_txt, &lock);
-//  printf("inter: %s saved.\n", accreg_txt);
-
-    return 0;
-}
-
-//--------------------------------------------------------
-
-/*==========================================
- * 設定ファイルを読み込む
- *------------------------------------------
- */
-int inter_config_read (const char *cfgName)
-{
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        printf ("file not found: %s\n", cfgName);
-        return 1;
-    }
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        line[sizeof (line) - 1] = '\0';
-
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
-            continue;
-
-        if (strcasecmp (w1, "storage_txt") == 0)
-        {
-            strncpy (storage_txt, w2, sizeof (storage_txt));
-        }
-        else if (strcasecmp (w1, "party_txt") == 0)
-        {
-            strncpy (party_txt, w2, sizeof (party_txt));
-        }
-        else if (strcasecmp (w1, "guild_txt") == 0)
-        {
-            strncpy (guild_txt, w2, sizeof (guild_txt));
-        }
-        else if (strcasecmp (w1, "castle_txt") == 0)
-        {
-            strncpy (castle_txt, w2, sizeof (castle_txt));
-        }
-        else if (strcasecmp (w1, "accreg_txt") == 0)
-        {
-            strncpy (accreg_txt, w2, sizeof (accreg_txt));
-        }
-        else if (strcasecmp (w1, "guild_storage_txt") == 0)
-        {
-            strncpy (guild_storage_txt, w2, sizeof (guild_storage_txt));
-        }
-        else if (strcasecmp (w1, "party_share_level") == 0)
-        {
-            party_share_level = atoi (w2);
-            if (party_share_level < 0)
-                party_share_level = 0;
-        }
-        else if (strcasecmp (w1, "inter_log_filename") == 0)
-        {
-            strncpy (inter_log_filename, w2, sizeof (inter_log_filename));
-        }
-        else if (strcasecmp (w1, "import") == 0)
-        {
-            inter_config_read (w2);
-        }
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-// ログ書き出し
-int inter_log (char *fmt, ...)
-{
-    FILE *logfp;
-    va_list ap;
-
-    va_start (ap, fmt);
-    logfp = fopen_ (inter_log_filename, "a");
-    if (logfp)
-    {
-        vfprintf (logfp, fmt, ap);
-        fclose_ (logfp);
-    }
-    va_end (ap);
-
-    return 0;
-}
-
-// セーブ
-int inter_save (void)
-{
-    inter_party_save ();
-    inter_guild_save ();
-    inter_storage_save ();
-    inter_guild_storage_save ();
-    inter_accreg_save ();
-
-    return 0;
-}
-
-// 初期化
-int inter_init (const char *file)
-{
-    inter_config_read (file);
-
-    wis_db = numdb_init ();
-
-    inter_party_init ();
-    inter_guild_init ();
-    inter_storage_init ();
-    inter_accreg_init ();
-
-    return 0;
-}
-
-// マップサーバー接続
-int inter_mapif_init (int fd)
-{
-    inter_guild_mapif_init (fd);
-
-    return 0;
-}
-
-//--------------------------------------------------------
-// sended packets to map-server
-
-// GMメッセージ送信
-int mapif_GMmessage (unsigned char *mes, int len)
-{
-    unsigned char buf[len];
-
-    WBUFW (buf, 0) = 0x3800;
-    WBUFW (buf, 2) = len;
-    memcpy (WBUFP (buf, 4), mes, len - 4);
-    mapif_sendall (buf, len);
-//  printf("inter server: GM:%d %s\n", len, mes);
-
-    return 0;
-}
-
-// Wisp/page transmission to all map-server
-int mapif_wis_message (struct WisData *wd)
-{
-    unsigned char buf[56 + wd->len];
-
-    WBUFW (buf, 0) = 0x3801;
-    WBUFW (buf, 2) = 56 + wd->len;
-    WBUFL (buf, 4) = wd->id;
-    memcpy (WBUFP (buf, 8), wd->src, 24);
-    memcpy (WBUFP (buf, 32), wd->dst, 24);
-    memcpy (WBUFP (buf, 56), wd->msg, wd->len);
-    wd->count = mapif_sendall (buf, WBUFW (buf, 2));
-
-    return 0;
-}
-
-// Wisp/page transmission result to map-server
-int mapif_wis_end (struct WisData *wd, int flag)
-{
-    unsigned char buf[27];
-
-    WBUFW (buf, 0) = 0x3802;
-    memcpy (WBUFP (buf, 2), wd->src, 24);
-    WBUFB (buf, 26) = flag;     // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-    mapif_send (wd->fd, buf, 27);
-//  printf("inter server wis_end: flag: %d\n", flag);
-
-    return 0;
-}
-
-// アカウント変数送信
-int mapif_account_reg (int fd, unsigned char *src)
-{
-    unsigned char buf[WBUFW (src, 2)];
-
-    memcpy (WBUFP (buf, 0), src, WBUFW (src, 2));
-    WBUFW (buf, 0) = 0x3804;
-    mapif_sendallwos (fd, buf, WBUFW (buf, 2));
-
-    return 0;
-}
-
-// アカウント変数要求返信
-int mapif_account_reg_reply (int fd, int account_id)
-{
-    struct accreg *reg = (struct accreg *)numdb_search (accreg_db, account_id);
-
-    WFIFOW (fd, 0) = 0x3804;
-    WFIFOL (fd, 4) = account_id;
-    if (reg == NULL)
-    {
-        WFIFOW (fd, 2) = 8;
-    }
-    else
-    {
-        int  j, p;
-        for (j = 0, p = 8; j < reg->reg_num; j++, p += 36)
-        {
-            memcpy (WFIFOP (fd, p), reg->reg[j].str, 32);
-            WFIFOL (fd, p + 32) = reg->reg[j].value;
-        }
-        WFIFOW (fd, 2) = p;
-    }
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-//--------------------------------------------------------
-
-// Existence check of WISP data
-void check_ttl_wisdata_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    unsigned long tick;
-    struct WisData *wd = (struct WisData *) data;
-    tick = va_arg (ap, unsigned long);
-
-    if (DIFF_TICK (tick, wd->tick) > WISDATA_TTL
-        && wis_delnum < WISDELLIST_MAX)
-        wis_dellist[wis_delnum++] = wd->id;
-}
-
-int check_ttl_wisdata (void)
-{
-    unsigned long tick = gettick ();
-    int  i;
-
-    do
-    {
-        wis_delnum = 0;
-        numdb_foreach (wis_db, check_ttl_wisdata_sub, tick);
-        for (i = 0; i < wis_delnum; i++)
-        {
-            struct WisData *wd = (struct WisData *)numdb_search (wis_db, wis_dellist[i]);
-            printf ("inter: wis data id=%d time out : from %s to %s\n",
-                    wd->id, wd->src, wd->dst);
-            // removed. not send information after a timeout. Just no answer for the player
-            //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-            numdb_erase (wis_db, wd->id);
-            free (wd);
-        }
-    }
-    while (wis_delnum >= WISDELLIST_MAX);
-
-    return 0;
-}
-
-//--------------------------------------------------------
-// received packets from map-server
-
-// GMメッセージ送信
-int mapif_parse_GMmessage (int fd)
-{
-    mapif_GMmessage (RFIFOP (fd, 4), RFIFOW (fd, 2));
-
-    return 0;
-}
-
-// Wisp/page request to send
-int mapif_parse_WisRequest (int fd)
-{
-    struct WisData *wd;
-    static int wisid = 0;
-    int  index;
-
-    if (RFIFOW (fd, 2) - 52 >= sizeof (wd->msg))
-    {
-        printf ("inter: Wis message size too long.\n");
-        return 0;
-    }
-    else if (RFIFOW (fd, 2) - 52 <= 0)
-    {                           // normaly, impossible, but who knows...
-        printf ("inter: Wis message doesn't exist.\n");
-        return 0;
-    }
-
-    // search if character exists before to ask all map-servers
-    if ((index = search_character_index (RFIFOP (fd, 28))) == -1)
-    {
-        unsigned char buf[27];
-        WBUFW (buf, 0) = 0x3802;
-        memcpy (WBUFP (buf, 2), RFIFOP (fd, 4), 24);
-        WBUFB (buf, 26) = 1;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-        mapif_send (fd, buf, 27);
-        // Character exists. So, ask all map-servers
-    }
-    else
-    {
-        // to be sure of the correct name, rewrite it
-        memset (RFIFOP (fd, 28), 0, 24);
-        strncpy (RFIFOP (fd, 28), search_character_name (index), 24);
-        // if source is destination, don't ask other servers.
-        if (strcmp (RFIFOP (fd, 4), RFIFOP (fd, 28)) == 0)
-        {
-            unsigned char buf[27];
-            WBUFW (buf, 0) = 0x3802;
-            memcpy (WBUFP (buf, 2), RFIFOP (fd, 4), 24);
-            WBUFB (buf, 26) = 1;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-            mapif_send (fd, buf, 27);
-        }
-        else
-        {
-            CREATE (wd, struct WisData, 1);
-
-            // Whether the failure of previous wisp/page transmission (timeout)
-            check_ttl_wisdata ();
-
-            wd->id = ++wisid;
-            wd->fd = fd;
-            wd->len = RFIFOW (fd, 2) - 52;
-            memcpy (wd->src, RFIFOP (fd, 4), 24);
-            memcpy (wd->dst, RFIFOP (fd, 28), 24);
-            memcpy (wd->msg, RFIFOP (fd, 52), wd->len);
-            wd->tick = gettick ();
-            numdb_insert (wis_db, wd->id, wd);
-            mapif_wis_message (wd);
-        }
-    }
-
-    return 0;
-}
-
-// Wisp/page transmission result
-int mapif_parse_WisReply (int fd)
-{
-    int  id = RFIFOL (fd, 2), flag = RFIFOB (fd, 6);
-    struct WisData *wd = (struct WisData *)numdb_search (wis_db, id);
-
-    if (wd == NULL)
-        return 0;               // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
-
-    if ((--wd->count) <= 0 || flag != 1)
-    {
-        mapif_wis_end (wd, flag);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-        numdb_erase (wis_db, id);
-        free (wd);
-    }
-
-    return 0;
-}
-
-// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
-int mapif_parse_WisToGM (int fd)
-{
-    unsigned char buf[RFIFOW (fd, 2)];  // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
-
-    memcpy (WBUFP (buf, 0), RFIFOP (fd, 0), RFIFOW (fd, 2));
-    WBUFW (buf, 0) = 0x3803;
-    mapif_sendall (buf, RFIFOW (fd, 2));
-
-    return 0;
-}
-
-// アカウント変数保存要求
-int mapif_parse_AccReg (int fd)
-{
-    int  j, p;
-    struct accreg *reg = (struct accreg*)numdb_search (accreg_db, (numdb_key_t)RFIFOL (fd, 4));
-
-    if (reg == NULL)
-    {
-        CREATE (reg, struct accreg, 1);
-        reg->account_id = RFIFOL (fd, 4);
-        numdb_insert (accreg_db, (numdb_key_t)RFIFOL (fd, 4), reg);
-    }
-
-    for (j = 0, p = 8; j < ACCOUNT_REG_NUM && p < RFIFOW (fd, 2);
-         j++, p += 36)
-    {
-        memcpy (reg->reg[j].str, RFIFOP (fd, p), 32);
-        reg->reg[j].value = RFIFOL (fd, p + 32);
-    }
-    reg->reg_num = j;
-
-    mapif_account_reg (fd, RFIFOP (fd, 0)); // 他のMAPサーバーに送信
-
-    return 0;
-}
-
-// アカウント変数送信要求
-int mapif_parse_AccRegRequest (int fd)
-{
-//  printf("mapif: accreg request\n");
-    return mapif_account_reg_reply (fd, RFIFOL (fd, 2));
-}
-
-//--------------------------------------------------------
-
-// map server からの通信(1パケットのみ解析すること)
-// エラーなら0(false)、処理できたなら1、
-// パケット長が足りなければ2をかえさなければならない
-int inter_parse_frommap (int fd)
-{
-    int  cmd = RFIFOW (fd, 0);
-    int  len = 0;
-
-    // inter鯖管轄かを調べる
-    if (cmd < 0x3000
-        || cmd >=
-        0x3000 +
-        (sizeof (inter_recv_packet_length) /
-         sizeof (inter_recv_packet_length[0])))
-        return 0;
-
-    // パケット長を調べる
-    if ((len =
-         inter_check_length (fd,
-                             inter_recv_packet_length[cmd - 0x3000])) == 0)
-        return 2;
-
-    switch (cmd)
-    {
-        case 0x3000:
-            mapif_parse_GMmessage (fd);
-            break;
-        case 0x3001:
-            mapif_parse_WisRequest (fd);
-            break;
-        case 0x3002:
-            mapif_parse_WisReply (fd);
-            break;
-        case 0x3003:
-            mapif_parse_WisToGM (fd);
-            break;
-        case 0x3004:
-            mapif_parse_AccReg (fd);
-            break;
-        case 0x3005:
-            mapif_parse_AccRegRequest (fd);
-            break;
-        default:
-            if (inter_party_parse_frommap (fd))
-                break;
-            if (inter_guild_parse_frommap (fd))
-                break;
-            if (inter_storage_parse_frommap (fd))
-                break;
-            return 0;
-    }
-    RFIFOSKIP (fd, len);
-
-    return 1;
-}
-
-// RFIFOのパケット長確認
-// 必要パケット長があればパケット長、まだ足りなければ0
-int inter_check_length (int fd, int length)
-{
-    if (length == -1)
-    {                           // 可変パケット長
-        if (RFIFOREST (fd) < 4) // パケット長が未着
-            return 0;
-        length = RFIFOW (fd, 2);
-    }
-
-    if (RFIFOREST (fd) < length)    // パケットが未着
-        return 0;
-
-    return length;
-}
diff --git a/src/char/inter.cpp b/src/char/inter.cpp
new file mode 100644
index 0000000..af95a2d
--- /dev/null
+++ b/src/char/inter.cpp
@@ -0,0 +1,635 @@
+// $Id: inter.c,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#include "../common/mmo.hpp"
+#include "char.hpp"
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/db.hpp"
+#include <string.h>
+#include <stdlib.h>
+
+#include "inter.hpp"
+#include "int_party.hpp"
+#include "int_guild.hpp"
+#include "int_storage.hpp"
+#include "../common/lock.hpp"
+
+#define WISDATA_TTL (60*1000)   // Existence time of Wisp/page data (60 seconds)
+                                // that is the waiting time of answers of all map-servers
+#define WISDELLIST_MAX 256      // Number of elements of Wisp/page data deletion list
+
+char inter_log_filename[1024] = "log/inter.log";
+
+char accreg_txt[1024] = "save/accreg.txt";
+static struct dbt *accreg_db = NULL;
+
+struct accreg
+{
+    int  account_id, reg_num;
+    struct global_reg reg[ACCOUNT_REG_NUM];
+};
+
+int  party_share_level = 10;
+
+// 送信パケット長リスト
+int  inter_send_packet_length[] = {
+    -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0,
+    35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+    10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1,
+    9, 9, -1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+// 受信パケット長リスト
+int  inter_recv_packet_length[] = {
+    -1, -1, 7, -1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    6, -1, 0, 0, 0, 0, 0, 0, 10, -1, 0, 0, 0, 0, 0, 0,
+    72, 6, 52, 14, 10, 29, 6, -1, 34, 0, 0, 0, 0, 0, 0, 0,
+    -1, 6, -1, 0, 55, 19, 6, -1, 14, -1, -1, -1, 14, 19, 186, -1,
+    5, 9, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    48, 14, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+struct WisData
+{
+    int  id, fd, count, len;
+    unsigned long tick;
+    unsigned char src[24], dst[24], msg[1024];
+};
+static struct dbt *wis_db = NULL;
+static int wis_dellist[WISDELLIST_MAX], wis_delnum;
+
+//--------------------------------------------------------
+
+// アカウント変数を文字列へ変換
+int inter_accreg_tostr (char *str, struct accreg *reg)
+{
+    int  j;
+    char *p = str;
+
+    p += sprintf (p, "%d\t", reg->account_id);
+    for (j = 0; j < reg->reg_num; j++)
+    {
+        p += sprintf (p, "%s,%d ", reg->reg[j].str, reg->reg[j].value);
+    }
+
+    return 0;
+}
+
+// アカウント変数を文字列から変換
+int inter_accreg_fromstr (const char *str, struct accreg *reg)
+{
+    int  j, v, n;
+    char buf[128];
+    const char *p = str;
+
+    if (sscanf (p, "%d\t%n", &reg->account_id, &n) != 1
+        || reg->account_id <= 0)
+        return 1;
+
+    for (j = 0, p += n; j < ACCOUNT_REG_NUM; j++, p += n)
+    {
+        if (sscanf (p, "%[^,],%d %n", buf, &v, &n) != 2)
+            break;
+        memcpy (reg->reg[j].str, buf, 32);
+        reg->reg[j].value = v;
+    }
+    reg->reg_num = j;
+
+    return 0;
+}
+
+// アカウント変数の読み込み
+int inter_accreg_init (void)
+{
+    char line[8192];
+    FILE *fp;
+    int  c = 0;
+    struct accreg *reg;
+
+    accreg_db = numdb_init ();
+
+    if ((fp = fopen_ (accreg_txt, "r")) == NULL)
+        return 1;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        line[sizeof (line) - 1] = '\0';
+        CREATE (reg, struct accreg, 1);
+        if (inter_accreg_fromstr (line, reg) == 0 && reg->account_id > 0)
+        {
+            numdb_insert (accreg_db, reg->account_id, reg);
+        }
+        else
+        {
+            printf ("inter: accreg: broken data [%s] line %d\n", accreg_txt,
+                    c);
+            free (reg);
+        }
+        c++;
+    }
+    fclose_ (fp);
+//  printf("inter: %s read done (%d)\n", accreg_txt, c);
+
+    return 0;
+}
+
+// アカウント変数のセーブ用
+void inter_accreg_save_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    char line[8192];
+    FILE *fp;
+    struct accreg *reg = (struct accreg *) data;
+
+    if (reg->reg_num > 0)
+    {
+        inter_accreg_tostr (line, reg);
+        fp = va_arg (ap, FILE *);
+        fprintf (fp, "%s\n", line);
+    }
+}
+
+// アカウント変数のセーブ
+int inter_accreg_save (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if ((fp = lock_fopen (accreg_txt, &lock)) == NULL)
+    {
+        printf ("int_accreg: cant write [%s] !!! data is lost !!!\n",
+                accreg_txt);
+        return 1;
+    }
+    numdb_foreach (accreg_db, inter_accreg_save_sub, fp);
+    lock_fclose (fp, accreg_txt, &lock);
+//  printf("inter: %s saved.\n", accreg_txt);
+
+    return 0;
+}
+
+//--------------------------------------------------------
+
+/*==========================================
+ * 設定ファイルを読み込む
+ *------------------------------------------
+ */
+int inter_config_read (const char *cfgName)
+{
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        printf ("file not found: %s\n", cfgName);
+        return 1;
+    }
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        line[sizeof (line) - 1] = '\0';
+
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+            continue;
+
+        if (strcasecmp (w1, "storage_txt") == 0)
+        {
+            strncpy (storage_txt, w2, sizeof (storage_txt));
+        }
+        else if (strcasecmp (w1, "party_txt") == 0)
+        {
+            strncpy (party_txt, w2, sizeof (party_txt));
+        }
+        else if (strcasecmp (w1, "guild_txt") == 0)
+        {
+            strncpy (guild_txt, w2, sizeof (guild_txt));
+        }
+        else if (strcasecmp (w1, "castle_txt") == 0)
+        {
+            strncpy (castle_txt, w2, sizeof (castle_txt));
+        }
+        else if (strcasecmp (w1, "accreg_txt") == 0)
+        {
+            strncpy (accreg_txt, w2, sizeof (accreg_txt));
+        }
+        else if (strcasecmp (w1, "guild_storage_txt") == 0)
+        {
+            strncpy (guild_storage_txt, w2, sizeof (guild_storage_txt));
+        }
+        else if (strcasecmp (w1, "party_share_level") == 0)
+        {
+            party_share_level = atoi (w2);
+            if (party_share_level < 0)
+                party_share_level = 0;
+        }
+        else if (strcasecmp (w1, "inter_log_filename") == 0)
+        {
+            strncpy (inter_log_filename, w2, sizeof (inter_log_filename));
+        }
+        else if (strcasecmp (w1, "import") == 0)
+        {
+            inter_config_read (w2);
+        }
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+// ログ書き出し
+int inter_log (char *fmt, ...)
+{
+    FILE *logfp;
+    va_list ap;
+
+    va_start (ap, fmt);
+    logfp = fopen_ (inter_log_filename, "a");
+    if (logfp)
+    {
+        vfprintf (logfp, fmt, ap);
+        fclose_ (logfp);
+    }
+    va_end (ap);
+
+    return 0;
+}
+
+// セーブ
+int inter_save (void)
+{
+    inter_party_save ();
+    inter_guild_save ();
+    inter_storage_save ();
+    inter_guild_storage_save ();
+    inter_accreg_save ();
+
+    return 0;
+}
+
+// 初期化
+int inter_init (const char *file)
+{
+    inter_config_read (file);
+
+    wis_db = numdb_init ();
+
+    inter_party_init ();
+    inter_guild_init ();
+    inter_storage_init ();
+    inter_accreg_init ();
+
+    return 0;
+}
+
+// マップサーバー接続
+int inter_mapif_init (int fd)
+{
+    inter_guild_mapif_init (fd);
+
+    return 0;
+}
+
+//--------------------------------------------------------
+// sended packets to map-server
+
+// GMメッセージ送信
+int mapif_GMmessage (unsigned char *mes, int len)
+{
+    unsigned char buf[len];
+
+    WBUFW (buf, 0) = 0x3800;
+    WBUFW (buf, 2) = len;
+    memcpy (WBUFP (buf, 4), mes, len - 4);
+    mapif_sendall (buf, len);
+//  printf("inter server: GM:%d %s\n", len, mes);
+
+    return 0;
+}
+
+// Wisp/page transmission to all map-server
+int mapif_wis_message (struct WisData *wd)
+{
+    unsigned char buf[56 + wd->len];
+
+    WBUFW (buf, 0) = 0x3801;
+    WBUFW (buf, 2) = 56 + wd->len;
+    WBUFL (buf, 4) = wd->id;
+    memcpy (WBUFP (buf, 8), wd->src, 24);
+    memcpy (WBUFP (buf, 32), wd->dst, 24);
+    memcpy (WBUFP (buf, 56), wd->msg, wd->len);
+    wd->count = mapif_sendall (buf, WBUFW (buf, 2));
+
+    return 0;
+}
+
+// Wisp/page transmission result to map-server
+int mapif_wis_end (struct WisData *wd, int flag)
+{
+    unsigned char buf[27];
+
+    WBUFW (buf, 0) = 0x3802;
+    memcpy (WBUFP (buf, 2), wd->src, 24);
+    WBUFB (buf, 26) = flag;     // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+    mapif_send (wd->fd, buf, 27);
+//  printf("inter server wis_end: flag: %d\n", flag);
+
+    return 0;
+}
+
+// アカウント変数送信
+int mapif_account_reg (int fd, unsigned char *src)
+{
+    unsigned char buf[WBUFW (src, 2)];
+
+    memcpy (WBUFP (buf, 0), src, WBUFW (src, 2));
+    WBUFW (buf, 0) = 0x3804;
+    mapif_sendallwos (fd, buf, WBUFW (buf, 2));
+
+    return 0;
+}
+
+// アカウント変数要求返信
+int mapif_account_reg_reply (int fd, int account_id)
+{
+    struct accreg *reg = (struct accreg *)numdb_search (accreg_db, account_id);
+
+    WFIFOW (fd, 0) = 0x3804;
+    WFIFOL (fd, 4) = account_id;
+    if (reg == NULL)
+    {
+        WFIFOW (fd, 2) = 8;
+    }
+    else
+    {
+        int  j, p;
+        for (j = 0, p = 8; j < reg->reg_num; j++, p += 36)
+        {
+            memcpy (WFIFOP (fd, p), reg->reg[j].str, 32);
+            WFIFOL (fd, p + 32) = reg->reg[j].value;
+        }
+        WFIFOW (fd, 2) = p;
+    }
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+//--------------------------------------------------------
+
+// Existence check of WISP data
+void check_ttl_wisdata_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    unsigned long tick;
+    struct WisData *wd = (struct WisData *) data;
+    tick = va_arg (ap, unsigned long);
+
+    if (DIFF_TICK (tick, wd->tick) > WISDATA_TTL
+        && wis_delnum < WISDELLIST_MAX)
+        wis_dellist[wis_delnum++] = wd->id;
+}
+
+int check_ttl_wisdata (void)
+{
+    unsigned long tick = gettick ();
+    int  i;
+
+    do
+    {
+        wis_delnum = 0;
+        numdb_foreach (wis_db, check_ttl_wisdata_sub, tick);
+        for (i = 0; i < wis_delnum; i++)
+        {
+            struct WisData *wd = (struct WisData *)numdb_search (wis_db, wis_dellist[i]);
+            printf ("inter: wis data id=%d time out : from %s to %s\n",
+                    wd->id, wd->src, wd->dst);
+            // removed. not send information after a timeout. Just no answer for the player
+            //mapif_wis_end(wd, 1); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+            numdb_erase (wis_db, wd->id);
+            free (wd);
+        }
+    }
+    while (wis_delnum >= WISDELLIST_MAX);
+
+    return 0;
+}
+
+//--------------------------------------------------------
+// received packets from map-server
+
+// GMメッセージ送信
+int mapif_parse_GMmessage (int fd)
+{
+    mapif_GMmessage (RFIFOP (fd, 4), RFIFOW (fd, 2));
+
+    return 0;
+}
+
+// Wisp/page request to send
+int mapif_parse_WisRequest (int fd)
+{
+    struct WisData *wd;
+    static int wisid = 0;
+    int  index;
+
+    if (RFIFOW (fd, 2) - 52 >= sizeof (wd->msg))
+    {
+        printf ("inter: Wis message size too long.\n");
+        return 0;
+    }
+    else if (RFIFOW (fd, 2) - 52 <= 0)
+    {                           // normaly, impossible, but who knows...
+        printf ("inter: Wis message doesn't exist.\n");
+        return 0;
+    }
+
+    // search if character exists before to ask all map-servers
+    if ((index = search_character_index (RFIFOP (fd, 28))) == -1)
+    {
+        unsigned char buf[27];
+        WBUFW (buf, 0) = 0x3802;
+        memcpy (WBUFP (buf, 2), RFIFOP (fd, 4), 24);
+        WBUFB (buf, 26) = 1;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+        mapif_send (fd, buf, 27);
+        // Character exists. So, ask all map-servers
+    }
+    else
+    {
+        // to be sure of the correct name, rewrite it
+        memset (RFIFOP (fd, 28), 0, 24);
+        strncpy (RFIFOP (fd, 28), search_character_name (index), 24);
+        // if source is destination, don't ask other servers.
+        if (strcmp (RFIFOP (fd, 4), RFIFOP (fd, 28)) == 0)
+        {
+            unsigned char buf[27];
+            WBUFW (buf, 0) = 0x3802;
+            memcpy (WBUFP (buf, 2), RFIFOP (fd, 4), 24);
+            WBUFB (buf, 26) = 1;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+            mapif_send (fd, buf, 27);
+        }
+        else
+        {
+            CREATE (wd, struct WisData, 1);
+
+            // Whether the failure of previous wisp/page transmission (timeout)
+            check_ttl_wisdata ();
+
+            wd->id = ++wisid;
+            wd->fd = fd;
+            wd->len = RFIFOW (fd, 2) - 52;
+            memcpy (wd->src, RFIFOP (fd, 4), 24);
+            memcpy (wd->dst, RFIFOP (fd, 28), 24);
+            memcpy (wd->msg, RFIFOP (fd, 52), wd->len);
+            wd->tick = gettick ();
+            numdb_insert (wis_db, wd->id, wd);
+            mapif_wis_message (wd);
+        }
+    }
+
+    return 0;
+}
+
+// Wisp/page transmission result
+int mapif_parse_WisReply (int fd)
+{
+    int  id = RFIFOL (fd, 2), flag = RFIFOB (fd, 6);
+    struct WisData *wd = (struct WisData *)numdb_search (wis_db, id);
+
+    if (wd == NULL)
+        return 0;               // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
+
+    if ((--wd->count) <= 0 || flag != 1)
+    {
+        mapif_wis_end (wd, flag);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+        numdb_erase (wis_db, id);
+        free (wd);
+    }
+
+    return 0;
+}
+
+// Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
+int mapif_parse_WisToGM (int fd)
+{
+    unsigned char buf[RFIFOW (fd, 2)];  // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
+
+    memcpy (WBUFP (buf, 0), RFIFOP (fd, 0), RFIFOW (fd, 2));
+    WBUFW (buf, 0) = 0x3803;
+    mapif_sendall (buf, RFIFOW (fd, 2));
+
+    return 0;
+}
+
+// アカウント変数保存要求
+int mapif_parse_AccReg (int fd)
+{
+    int  j, p;
+    struct accreg *reg = (struct accreg*)numdb_search (accreg_db, (numdb_key_t)RFIFOL (fd, 4));
+
+    if (reg == NULL)
+    {
+        CREATE (reg, struct accreg, 1);
+        reg->account_id = RFIFOL (fd, 4);
+        numdb_insert (accreg_db, (numdb_key_t)RFIFOL (fd, 4), reg);
+    }
+
+    for (j = 0, p = 8; j < ACCOUNT_REG_NUM && p < RFIFOW (fd, 2);
+         j++, p += 36)
+    {
+        memcpy (reg->reg[j].str, RFIFOP (fd, p), 32);
+        reg->reg[j].value = RFIFOL (fd, p + 32);
+    }
+    reg->reg_num = j;
+
+    mapif_account_reg (fd, RFIFOP (fd, 0)); // 他のMAPサーバーに送信
+
+    return 0;
+}
+
+// アカウント変数送信要求
+int mapif_parse_AccRegRequest (int fd)
+{
+//  printf("mapif: accreg request\n");
+    return mapif_account_reg_reply (fd, RFIFOL (fd, 2));
+}
+
+//--------------------------------------------------------
+
+// map server からの通信(1パケットのみ解析すること)
+// エラーなら0(false)、処理できたなら1、
+// パケット長が足りなければ2をかえさなければならない
+int inter_parse_frommap (int fd)
+{
+    int  cmd = RFIFOW (fd, 0);
+    int  len = 0;
+
+    // inter鯖管轄かを調べる
+    if (cmd < 0x3000
+        || cmd >=
+        0x3000 +
+        (sizeof (inter_recv_packet_length) /
+         sizeof (inter_recv_packet_length[0])))
+        return 0;
+
+    // パケット長を調べる
+    if ((len =
+         inter_check_length (fd,
+                             inter_recv_packet_length[cmd - 0x3000])) == 0)
+        return 2;
+
+    switch (cmd)
+    {
+        case 0x3000:
+            mapif_parse_GMmessage (fd);
+            break;
+        case 0x3001:
+            mapif_parse_WisRequest (fd);
+            break;
+        case 0x3002:
+            mapif_parse_WisReply (fd);
+            break;
+        case 0x3003:
+            mapif_parse_WisToGM (fd);
+            break;
+        case 0x3004:
+            mapif_parse_AccReg (fd);
+            break;
+        case 0x3005:
+            mapif_parse_AccRegRequest (fd);
+            break;
+        default:
+            if (inter_party_parse_frommap (fd))
+                break;
+            if (inter_guild_parse_frommap (fd))
+                break;
+            if (inter_storage_parse_frommap (fd))
+                break;
+            return 0;
+    }
+    RFIFOSKIP (fd, len);
+
+    return 1;
+}
+
+// RFIFOのパケット長確認
+// 必要パケット長があればパケット長、まだ足りなければ0
+int inter_check_length (int fd, int length)
+{
+    if (length == -1)
+    {                           // 可変パケット長
+        if (RFIFOREST (fd) < 4) // パケット長が未着
+            return 0;
+        length = RFIFOW (fd, 2);
+    }
+
+    if (RFIFOREST (fd) < length)    // パケットが未着
+        return 0;
+
+    return length;
+}
diff --git a/src/char/inter.h b/src/char/inter.h
deleted file mode 100644
index 219f195..0000000
--- a/src/char/inter.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// $Id: inter.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
-#ifndef _INTER_H_
-#define _INTER_H_
-
-int  inter_init (const char *file);
-int  inter_save (void);
-int  inter_parse_frommap (int fd);
-int  inter_mapif_init (int fd);
-
-int  inter_check_length (int fd, int length);
-
-int  inter_log (char *fmt, ...);
-
-#define inter_cfgName "conf/inter_athena.conf"
-
-extern int party_share_level;
-extern char inter_log_filename[1024];
-
-#endif
diff --git a/src/char/inter.hpp b/src/char/inter.hpp
new file mode 100644
index 0000000..769324c
--- /dev/null
+++ b/src/char/inter.hpp
@@ -0,0 +1,19 @@
+// $Id: inter.h,v 1.1.1.1 2004/09/10 17:26:51 MagicalTux Exp $
+#ifndef INTER_HPP
+#define INTER_HPP
+
+int  inter_init (const char *file);
+int  inter_save (void);
+int  inter_parse_frommap (int fd);
+int  inter_mapif_init (int fd);
+
+int  inter_check_length (int fd, int length);
+
+int  inter_log (char *fmt, ...);
+
+#define inter_cfgName "conf/inter_athena.conf"
+
+extern int party_share_level;
+extern char inter_log_filename[1024];
+
+#endif
diff --git a/src/common/core.c b/src/common/core.c
deleted file mode 100644
index b08276c..0000000
--- a/src/common/core.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include "core.h"
-#include "socket.h"
-#include "timer.h"
-#include "version.h"
-#include "mt_rand.h"
-#include "nullpo.h"
-
-/// Defined by each server
-extern int  do_init (int, char **);
-extern void term_func (void);
-
-// Added by Gabuzomeu
-//
-// This is an implementation of signal() using sigaction() for portability.
-// (sigaction() is POSIX; signal() is not.)  Taken from Stevens' _Advanced
-// Programming in the UNIX Environment_.
-//
-typedef void (*sigfunc)(int);
-sigfunc compat_signal (int signo, sigfunc func)
-{
-    struct sigaction sact, oact;
-
-    sact.sa_handler = func;
-    sigfillset (&sact.sa_mask);
-    sigdelset(&sact.sa_mask, SIGSEGV);
-    sigdelset(&sact.sa_mask, SIGBUS);
-    sigdelset(&sact.sa_mask, SIGTRAP);
-    sigdelset(&sact.sa_mask, SIGILL);
-    sigdelset(&sact.sa_mask, SIGFPE);
-    sact.sa_flags = 0;
-
-    if (sigaction (signo, &sact, &oact) < 0)
-        return SIG_ERR;
-
-    return oact.sa_handler;
-}
-
-static void chld_proc (int UNUSED)
-{
-    wait(NULL);
-}
-static void sig_proc (int UNUSED)
-{
-    for (int i = 1; i < 31; ++i)
-        compat_signal(i, SIG_IGN);
-    term_func ();
-    _exit (0);
-}
-
-bool runflag = true;
-
-/*
-    Note about fatal signals:
-
-    Under certain circumstances,
-    the following signals MUST not be ignored:
-    SIGFPE, SIGSEGV, SIGILL
-    Unless you use SA_SIGINFO and *carefully* check the origin,
-    that means they must be SIG_DFL.
- */
-int main (int argc, char **argv)
-{
-    /// Note that getpid() and getppid() may be very close
-    mt_seed (time (NULL) ^ (getpid () << 16) ^ (getppid () << 8));
-
-    do_socket ();
-
-    do_init (argc, argv);
-    // set up exit handlers *after* the initialization has happened.
-    // This is because term_func is likely to depend on successful init.
-
-    compat_signal (SIGPIPE, SIG_IGN);
-    compat_signal (SIGTERM, sig_proc);
-    compat_signal (SIGINT, sig_proc);
-    compat_signal (SIGCHLD, chld_proc);
-
-    // Signal to create coredumps by system when necessary (crash)
-    compat_signal (SIGSEGV, SIG_DFL);
-    compat_signal (SIGBUS, SIG_DFL);
-    compat_signal (SIGTRAP, SIG_DFL);
-    compat_signal (SIGILL, SIG_DFL);
-    compat_signal (SIGFPE, SIG_DFL);
-
-    atexit (term_func);
-
-    while (runflag)
-    {
-        do_sendrecv (do_timer (gettick_nocache ()));
-        do_parsepacket ();
-    }
-}
diff --git a/src/common/core.cpp b/src/common/core.cpp
new file mode 100644
index 0000000..38b2260
--- /dev/null
+++ b/src/common/core.cpp
@@ -0,0 +1,97 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include "core.hpp"
+#include "socket.hpp"
+#include "timer.hpp"
+#include "version.hpp"
+#include "mt_rand.hpp"
+#include "nullpo.hpp"
+
+/// Defined by each server
+extern int  do_init (int, char **);
+extern void term_func (void);
+
+// Added by Gabuzomeu
+//
+// This is an implementation of signal() using sigaction() for portability.
+// (sigaction() is POSIX; signal() is not.)  Taken from Stevens' _Advanced
+// Programming in the UNIX Environment_.
+//
+typedef void (*sigfunc)(int);
+sigfunc compat_signal (int signo, sigfunc func)
+{
+    struct sigaction sact, oact;
+
+    sact.sa_handler = func;
+    sigfillset (&sact.sa_mask);
+    sigdelset(&sact.sa_mask, SIGSEGV);
+    sigdelset(&sact.sa_mask, SIGBUS);
+    sigdelset(&sact.sa_mask, SIGTRAP);
+    sigdelset(&sact.sa_mask, SIGILL);
+    sigdelset(&sact.sa_mask, SIGFPE);
+    sact.sa_flags = 0;
+
+    if (sigaction (signo, &sact, &oact) < 0)
+        return SIG_ERR;
+
+    return oact.sa_handler;
+}
+
+static void chld_proc (int UNUSED)
+{
+    wait(NULL);
+}
+static void sig_proc (int UNUSED)
+{
+    for (int i = 1; i < 31; ++i)
+        compat_signal(i, SIG_IGN);
+    term_func ();
+    _exit (0);
+}
+
+bool runflag = true;
+
+/*
+    Note about fatal signals:
+
+    Under certain circumstances,
+    the following signals MUST not be ignored:
+    SIGFPE, SIGSEGV, SIGILL
+    Unless you use SA_SIGINFO and *carefully* check the origin,
+    that means they must be SIG_DFL.
+ */
+int main (int argc, char **argv)
+{
+    /// Note that getpid() and getppid() may be very close
+    mt_seed (time (NULL) ^ (getpid () << 16) ^ (getppid () << 8));
+
+    do_socket ();
+
+    do_init (argc, argv);
+    // set up exit handlers *after* the initialization has happened.
+    // This is because term_func is likely to depend on successful init.
+
+    compat_signal (SIGPIPE, SIG_IGN);
+    compat_signal (SIGTERM, sig_proc);
+    compat_signal (SIGINT, sig_proc);
+    compat_signal (SIGCHLD, chld_proc);
+
+    // Signal to create coredumps by system when necessary (crash)
+    compat_signal (SIGSEGV, SIG_DFL);
+    compat_signal (SIGBUS, SIG_DFL);
+    compat_signal (SIGTRAP, SIG_DFL);
+    compat_signal (SIGILL, SIG_DFL);
+    compat_signal (SIGFPE, SIG_DFL);
+
+    atexit (term_func);
+
+    while (runflag)
+    {
+        do_sendrecv (do_timer (gettick_nocache ()));
+        do_parsepacket ();
+    }
+}
diff --git a/src/common/core.h b/src/common/core.h
deleted file mode 100644
index 44473e9..0000000
--- a/src/common/core.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef CORE_H
-#define CORE_H
-#include <stdbool.h>
-/// core.c contains a server-independent main() function
-/// and then runs a do_sendrecv loop
-
-/// When this is cleared, the server exits gracefully
-/// only used by map server's GM command: @mapexit
-extern bool runflag;
-
-/// This is an external function defined by each server
-/// This function must register stuff for the parse loop
-extern int  do_init (int, char **);
-
-/// Cleanup function called whenever a signal kills us
-/// or when if we manage to exit() gracefully.
-extern void term_func (void);
-
-#endif // CORE_H
diff --git a/src/common/core.hpp b/src/common/core.hpp
new file mode 100644
index 0000000..8a52c55
--- /dev/null
+++ b/src/common/core.hpp
@@ -0,0 +1,19 @@
+#ifndef CORE_HPP
+#define CORE_HPP
+#include <stdbool.h>
+/// core.c contains a server-independent main() function
+/// and then runs a do_sendrecv loop
+
+/// When this is cleared, the server exits gracefully
+/// only used by map server's GM command: @mapexit
+extern bool runflag;
+
+/// This is an external function defined by each server
+/// This function must register stuff for the parse loop
+extern int  do_init (int, char **);
+
+/// Cleanup function called whenever a signal kills us
+/// or when if we manage to exit() gracefully.
+extern void term_func (void);
+
+#endif // CORE_HPP
diff --git a/src/common/db.c b/src/common/db.c
deleted file mode 100644
index f56a511..0000000
--- a/src/common/db.c
+++ /dev/null
@@ -1,546 +0,0 @@
-#include "db.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "utils.h"
-
-#define ROOT_SIZE 4096
-
-static int strdb_cmp (struct dbt *table, const char *a, const char* b)
-{
-    if (table->maxlen)
-        return strncmp (a, b, table->maxlen);
-    return strcmp (a, b);
-}
-
-static hash_t strdb_hash (struct dbt *table, const char *a)
-{
-    size_t i = table->maxlen;
-    if (i == 0)
-        i = (size_t)-1;
-    hash_t h = 0;
-    const unsigned char *p = (const unsigned char*)a;
-    while (*p && i--)
-    {
-        h = (h * 33 + *p++) ^ (h >> 24);
-    }
-    return h;
-}
-
-struct dbt *strdb_init (size_t maxlen)
-{
-    struct dbt *table;
-    CREATE (table, struct dbt, 1);
-    table->type = DB_STRING;
-    table->maxlen = maxlen;
-    return table;
-}
-
-static int numdb_cmp (numdb_key_t a, numdb_key_t b)
-{
-    if (a == b)
-        return 0;
-    if (a < b)
-        return -1;
-    return 1;
-}
-
-static hash_t numdb_hash (numdb_key_t a)
-{
-    return (hash_t) a;
-}
-
-struct dbt *numdb_init (void)
-{
-    struct dbt *table;
-    CREATE (table, struct dbt, 1);
-    table->type = DB_NUMBER;
-    return table;
-}
-
-static int table_cmp (struct dbt *table, db_key_t a, db_key_t b)
-{
-    switch(table->type)
-    {
-    case DB_NUMBER: return numdb_cmp (a.i, b.i);
-    case DB_STRING: return strdb_cmp (table, a.s, b.s);
-    }
-    abort();
-}
-
-static hash_t table_hash (struct dbt *table, db_key_t key)
-{
-    switch(table->type)
-    {
-    case DB_NUMBER: return numdb_hash (key.i);
-    case DB_STRING: return strdb_hash (table, key.s);
-    }
-    abort();
-}
-
-/// Search for a node with the given key
-db_val_t db_search (struct dbt *table, db_key_t key)
-{
-    struct dbn *p = table->ht[table_hash (table, key) % HASH_SIZE];
-
-    while (p)
-    {
-        int  c = table_cmp (table, key, p->key);
-        if (c == 0)
-            return p->data;
-        if (c < 0)
-            p = p->left;
-        else
-            p = p->right;
-    }
-    return NULL;
-}
-
-// Tree maintainance methods
-static void db_rotate_left (struct dbn *p, struct dbn **root)
-{
-    struct dbn *y = p->right;
-    p->right = y->left;
-    if (y->left)
-        y->left->parent = p;
-    y->parent = p->parent;
-
-    if (p == *root)
-        *root = y;
-    else if (p == p->parent->left)
-        p->parent->left = y;
-    else
-        p->parent->right = y;
-    y->left = p;
-    p->parent = y;
-}
-
-static void db_rotate_right (struct dbn *p, struct dbn **root)
-{
-    struct dbn *y = p->left;
-    p->left = y->right;
-    if (y->right)
-        y->right->parent = p;
-    y->parent = p->parent;
-
-    if (p == *root)
-        *root = y;
-    else if (p == p->parent->right)
-        p->parent->right = y;
-    else
-        p->parent->left = y;
-    y->right = p;
-    p->parent = y;
-}
-
-static void db_rebalance (struct dbn *p, struct dbn **root)
-{
-    p->color = RED;
-    while (p != *root && p->parent->color == RED)
-    {
-        if (p->parent == p->parent->parent->left)
-        {
-            struct dbn *y = p->parent->parent->right;
-            if (y && y->color == RED)
-            {
-                p->parent->color = BLACK;
-                y->color = BLACK;
-                p->parent->parent->color = RED;
-                p = p->parent->parent;
-            }
-            else
-            {
-                if (p == p->parent->right)
-                {
-                    p = p->parent;
-                    db_rotate_left (p, root);
-                }
-                p->parent->color = BLACK;
-                p->parent->parent->color = RED;
-                db_rotate_right (p->parent->parent, root);
-            }
-        }
-        else
-        {
-            struct dbn *y = p->parent->parent->left;
-            if (y && y->color == RED)
-            {
-                p->parent->color = BLACK;
-                y->color = BLACK;
-                p->parent->parent->color = RED;
-                p = p->parent->parent;
-            }
-            else
-            {
-                if (p == p->parent->left)
-                {
-                    p = p->parent;
-                    db_rotate_right (p, root);
-                }
-                p->parent->color = BLACK;
-                p->parent->parent->color = RED;
-                db_rotate_left (p->parent->parent, root);
-            }
-        }
-    }
-    (*root)->color = BLACK;
-}
-
-// param z = node to remove
-static void db_rebalance_erase (struct dbn *z, struct dbn **root)
-{
-    struct dbn *y = z;
-    struct dbn *x = NULL;
-
-    if (!y->left)
-        x = y->right;
-    else if (!y->right)
-        x = y->left;
-    else
-    {
-        y = y->right;
-        while (y->left)
-            y = y->left;
-        x = y->right;
-    }
-    struct dbn *x_parent = NULL;
-    if (y != z)
-    {
-        z->left->parent = y;
-        y->left = z->left;
-        if (y != z->right)
-        {
-            x_parent = y->parent;
-            if (x)
-                x->parent = y->parent;
-            y->parent->left = x;
-            y->right = z->right;
-            z->right->parent = y;
-        }
-        else
-            x_parent = y;
-        if (*root == z)
-            *root = y;
-        else if (z->parent->left == z)
-            z->parent->left = y;
-        else
-            z->parent->right = y;
-        y->parent = z->parent;
-        {
-            dbn_color tmp = y->color;
-            y->color = z->color;
-            z->color = tmp;
-        }
-        y = z;
-    }
-    else
-    {
-        x_parent = y->parent;
-        if (x)
-            x->parent = y->parent;
-        if (*root == z)
-            *root = x;
-        else if (z->parent->left == z)
-            z->parent->left = x;
-        else
-            z->parent->right = x;
-    }
-    if (y->color != RED)
-    {
-        while (x != *root && (!x || x->color == BLACK))
-            if (x == x_parent->left)
-            {
-                struct dbn *w = x_parent->right;
-                if (w->color == RED)
-                {
-                    w->color = BLACK;
-                    x_parent->color = RED;
-                    db_rotate_left (x_parent, root);
-                    w = x_parent->right;
-                }
-                if ((!w->left || w->left->color == BLACK) &&
-                    (!w->right || w->right->color == BLACK))
-                {
-                    w->color = RED;
-                    x = x_parent;
-                    x_parent = x->parent;
-                }
-                else
-                {
-                    if (!w->right|| w->right->color == BLACK)
-                    {
-                        if (w->left)
-                            w->left->color = BLACK;
-                        w->color = RED;
-                        db_rotate_right (w, root);
-                        w = x_parent->right;
-                    }
-                    w->color = x_parent->color;
-                    x_parent->color = BLACK;
-                    if (w->right)
-                        w->right->color = BLACK;
-                    db_rotate_left (x_parent, root);
-                    break;
-                }
-            }
-            else
-            {
-                // same as above, with right <-> left.
-                struct dbn *w = x_parent->left;
-                if (w->color == RED)
-                {
-                    w->color = BLACK;
-                    x_parent->color = RED;
-                    db_rotate_right (x_parent, root);
-                    w = x_parent->left;
-                }
-                if ((!w->right || w->right->color == BLACK) &&
-                    (!w->left || w->left->color == BLACK))
-                {
-                    w->color = RED;
-                    x = x_parent;
-                    x_parent = x_parent->parent;
-                }
-                else
-                {
-                    if (!w->left || w->left->color == BLACK)
-                    {
-                        if (w->right)
-                            w->right->color = BLACK;
-                        w->color = RED;
-                        db_rotate_left (w, root);
-                        w = x_parent->left;
-                    }
-                    w->color = x_parent->color;
-                    x_parent->color = BLACK;
-                    if (w->left)
-                        w->left->color = BLACK;
-                    db_rotate_right (x_parent, root);
-                    break;
-                }
-            }
-        if (x)
-            x->color = BLACK;
-    }
-}
-
-struct dbn *db_insert (struct dbt *table, db_key_t key, db_val_t data)
-{
-    hash_t hash = table_hash (table, key) % HASH_SIZE;
-    int c = 0;
-    struct dbn *prev = NULL;
-    struct dbn *p = table->ht[hash];
-    while (p)
-    {
-        c = table_cmp (table, key, p->key);
-        if (c == 0)
-        {
-            // key found in table, replace
-            // Tell the user of the table to free the key and value
-            if (table->release)
-                table->release (p->key, p->data);
-            p->data = data;
-            p->key = key;
-            return p;
-        }
-        // prev is always p->parent?
-        prev = p;
-        if (c < 0)
-            p = p->left;
-        else
-            p = p->right;
-    }
-    CREATE (p, struct dbn, 1);
-    p->key = key;
-    p->data = data;
-    p->color = RED;
-    if (c == 0)
-    {                           // hash entry is empty
-        table->ht[hash] = p;
-        p->color = BLACK;
-        return p;
-    }
-    p->parent = prev;
-    if (c < 0)
-        prev->left = p;
-    else
-        prev->right = p;
-    if (prev->color == RED)
-    {
-        // must rebalance
-        db_rebalance (p, &table->ht[hash]);
-    }
-    return p;
-}
-
-db_val_t db_erase (struct dbt *table, db_key_t key)
-{
-    hash_t hash = table_hash (table, key) % HASH_SIZE;
-    struct dbn *p = table->ht[hash];
-    while (p)
-    {
-        int c = table_cmp (table, key, p->key);
-        if (c == 0)
-            break;
-        if (c < 0)
-            p = p->left;
-        else
-            p = p->right;
-    }
-    if (!p)
-        return NULL;
-    db_val_t data = p->data;
-    db_rebalance_erase (p, &table->ht[hash]);
-    free (p);
-    return data;
-}
-#ifdef SMART_WALK_TREE
-static inline void db_walk_tree (bool dealloc, struct dbn* p, db_func_t func, va_list ap)
-{
-    if (!p)
-        return;
-    if (!dealloc && !func)
-    {
-        fprintf(stderr, "DEBUG: Must walk tree to either free or invoke a function.\n");
-        abort();
-    }
-    if (p->parent)
-    {
-        fprintf(stderr, "DEBUG: Root nodes must not have parents\n");
-        abort();
-    }
-    while (true)
-    {
-        // apply_func loop
-        if (func)
-            func (p->key, p->data, ap);
-        if (p->left)
-        {
-            // continue descending
-            p = p->left;
-            continue; //goto apply_func;
-        }
-        if (p->right)
-        {
-            // descending the other side
-            p = p->right;
-            continue; //goto apply_func;
-        }
-        while (true)
-        {
-            // backtrack loop
-            if (!p->parent)
-            {
-                if (dealloc)
-                    free (p);
-                // if we have already done both children, there is no more to do
-                return;
-            }
-            if (p->parent->left == p && p->parent->right)
-            {
-                // finished the left tree, now walk the right tree
-                p = p->parent->right;
-                if (dealloc)
-                    free (p->parent->left);
-                break; //goto apply_func;
-            }
-            // p->parent->right == p
-            // or p->parent->left == p but p->parent->right == NULL
-            // keep backtracking
-            p = p->parent;
-            if (dealloc)
-                free (p->right?:p->left);
-        } //backtrack loop
-    } // apply_func loop
-}
-#endif // SMART_WALK_TREE
-
-void db_foreach (struct dbt *table, db_func_t func, ...)
-{
-    va_list ap;
-    va_start (ap, func);
-
-    for (int i = 0; i < HASH_SIZE; i++)
-    {
-#ifdef SMART_WALK_TREE
-        db_walk_tree (false, table->ht[i], func, ap);
-#else
-        struct dbn *p = table->ht[i];
-        if (!p)
-            continue;
-        struct dbn *stack[64];
-        int sp = 0;
-        while (1)
-        {
-            func (p->key, p->data, ap);
-            struct dbn *pn = p->left;
-            if (pn)
-            {
-                if (p->right)
-                    stack[sp++] = p->right;
-                p = pn;
-            }
-            else // pn == NULL, time to do the right branch
-            {
-                if (p->right)
-                    p = p->right;
-                else
-                {
-                    if (sp == 0)
-                        break;
-                    p = stack[--sp];
-                }
-            } // if pn else if !pn
-        } // while true
-#endif // else ! SMART_WALK_TREE
-    } // for i
-    va_end (ap);
-}
-
-// This function is suspiciously similar to the previous
-void db_final (struct dbt *table, db_func_t func, ...)
-{
-    va_list ap;
-    va_start (ap, func);
-
-    for (int i = 0; i < HASH_SIZE; i++)
-    {
-#ifdef SMART_WALK_TREE
-        db_walk_tree (true, table->ht[i], func, ap);
-#else
-        struct dbn *p = table->ht[i];
-        if (!p)
-            continue;
-        struct dbn *stack[64];
-        int sp = 0;
-        while (1)
-        {
-            if (func)
-                func (p->key, p->data, ap);
-            struct dbn *pn = p->left;
-            if (pn)
-            {
-                if (p->right)
-                    stack[sp++] = p->right;
-            }
-            else // pn == NULL, check the right
-            {
-                if (p->right)
-                    pn = p->right;
-                else
-                {
-                    if (sp == 0)
-                        break;
-                    pn = stack[--sp];
-                }
-            } // if pn else if !pn
-            free (p);
-            p = pn;
-        } // while true
-#endif // else ! SMART_WALK_TREE
-    } // for i
-    free (table);
-    va_end (ap);
-}
diff --git a/src/common/db.cpp b/src/common/db.cpp
new file mode 100644
index 0000000..21a3597
--- /dev/null
+++ b/src/common/db.cpp
@@ -0,0 +1,546 @@
+#include "db.hpp"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.hpp"
+
+#define ROOT_SIZE 4096
+
+static int strdb_cmp (struct dbt *table, const char *a, const char* b)
+{
+    if (table->maxlen)
+        return strncmp (a, b, table->maxlen);
+    return strcmp (a, b);
+}
+
+static hash_t strdb_hash (struct dbt *table, const char *a)
+{
+    size_t i = table->maxlen;
+    if (i == 0)
+        i = (size_t)-1;
+    hash_t h = 0;
+    const unsigned char *p = (const unsigned char*)a;
+    while (*p && i--)
+    {
+        h = (h * 33 + *p++) ^ (h >> 24);
+    }
+    return h;
+}
+
+struct dbt *strdb_init (size_t maxlen)
+{
+    struct dbt *table;
+    CREATE (table, struct dbt, 1);
+    table->type = DB_STRING;
+    table->maxlen = maxlen;
+    return table;
+}
+
+static int numdb_cmp (numdb_key_t a, numdb_key_t b)
+{
+    if (a == b)
+        return 0;
+    if (a < b)
+        return -1;
+    return 1;
+}
+
+static hash_t numdb_hash (numdb_key_t a)
+{
+    return (hash_t) a;
+}
+
+struct dbt *numdb_init (void)
+{
+    struct dbt *table;
+    CREATE (table, struct dbt, 1);
+    table->type = DB_NUMBER;
+    return table;
+}
+
+static int table_cmp (struct dbt *table, db_key_t a, db_key_t b)
+{
+    switch(table->type)
+    {
+    case DB_NUMBER: return numdb_cmp (a.i, b.i);
+    case DB_STRING: return strdb_cmp (table, a.s, b.s);
+    }
+    abort();
+}
+
+static hash_t table_hash (struct dbt *table, db_key_t key)
+{
+    switch(table->type)
+    {
+    case DB_NUMBER: return numdb_hash (key.i);
+    case DB_STRING: return strdb_hash (table, key.s);
+    }
+    abort();
+}
+
+/// Search for a node with the given key
+db_val_t db_search (struct dbt *table, db_key_t key)
+{
+    struct dbn *p = table->ht[table_hash (table, key) % HASH_SIZE];
+
+    while (p)
+    {
+        int  c = table_cmp (table, key, p->key);
+        if (c == 0)
+            return p->data;
+        if (c < 0)
+            p = p->left;
+        else
+            p = p->right;
+    }
+    return NULL;
+}
+
+// Tree maintainance methods
+static void db_rotate_left (struct dbn *p, struct dbn **root)
+{
+    struct dbn *y = p->right;
+    p->right = y->left;
+    if (y->left)
+        y->left->parent = p;
+    y->parent = p->parent;
+
+    if (p == *root)
+        *root = y;
+    else if (p == p->parent->left)
+        p->parent->left = y;
+    else
+        p->parent->right = y;
+    y->left = p;
+    p->parent = y;
+}
+
+static void db_rotate_right (struct dbn *p, struct dbn **root)
+{
+    struct dbn *y = p->left;
+    p->left = y->right;
+    if (y->right)
+        y->right->parent = p;
+    y->parent = p->parent;
+
+    if (p == *root)
+        *root = y;
+    else if (p == p->parent->right)
+        p->parent->right = y;
+    else
+        p->parent->left = y;
+    y->right = p;
+    p->parent = y;
+}
+
+static void db_rebalance (struct dbn *p, struct dbn **root)
+{
+    p->color = RED;
+    while (p != *root && p->parent->color == RED)
+    {
+        if (p->parent == p->parent->parent->left)
+        {
+            struct dbn *y = p->parent->parent->right;
+            if (y && y->color == RED)
+            {
+                p->parent->color = BLACK;
+                y->color = BLACK;
+                p->parent->parent->color = RED;
+                p = p->parent->parent;
+            }
+            else
+            {
+                if (p == p->parent->right)
+                {
+                    p = p->parent;
+                    db_rotate_left (p, root);
+                }
+                p->parent->color = BLACK;
+                p->parent->parent->color = RED;
+                db_rotate_right (p->parent->parent, root);
+            }
+        }
+        else
+        {
+            struct dbn *y = p->parent->parent->left;
+            if (y && y->color == RED)
+            {
+                p->parent->color = BLACK;
+                y->color = BLACK;
+                p->parent->parent->color = RED;
+                p = p->parent->parent;
+            }
+            else
+            {
+                if (p == p->parent->left)
+                {
+                    p = p->parent;
+                    db_rotate_right (p, root);
+                }
+                p->parent->color = BLACK;
+                p->parent->parent->color = RED;
+                db_rotate_left (p->parent->parent, root);
+            }
+        }
+    }
+    (*root)->color = BLACK;
+}
+
+// param z = node to remove
+static void db_rebalance_erase (struct dbn *z, struct dbn **root)
+{
+    struct dbn *y = z;
+    struct dbn *x = NULL;
+
+    if (!y->left)
+        x = y->right;
+    else if (!y->right)
+        x = y->left;
+    else
+    {
+        y = y->right;
+        while (y->left)
+            y = y->left;
+        x = y->right;
+    }
+    struct dbn *x_parent = NULL;
+    if (y != z)
+    {
+        z->left->parent = y;
+        y->left = z->left;
+        if (y != z->right)
+        {
+            x_parent = y->parent;
+            if (x)
+                x->parent = y->parent;
+            y->parent->left = x;
+            y->right = z->right;
+            z->right->parent = y;
+        }
+        else
+            x_parent = y;
+        if (*root == z)
+            *root = y;
+        else if (z->parent->left == z)
+            z->parent->left = y;
+        else
+            z->parent->right = y;
+        y->parent = z->parent;
+        {
+            dbn_color tmp = y->color;
+            y->color = z->color;
+            z->color = tmp;
+        }
+        y = z;
+    }
+    else
+    {
+        x_parent = y->parent;
+        if (x)
+            x->parent = y->parent;
+        if (*root == z)
+            *root = x;
+        else if (z->parent->left == z)
+            z->parent->left = x;
+        else
+            z->parent->right = x;
+    }
+    if (y->color != RED)
+    {
+        while (x != *root && (!x || x->color == BLACK))
+            if (x == x_parent->left)
+            {
+                struct dbn *w = x_parent->right;
+                if (w->color == RED)
+                {
+                    w->color = BLACK;
+                    x_parent->color = RED;
+                    db_rotate_left (x_parent, root);
+                    w = x_parent->right;
+                }
+                if ((!w->left || w->left->color == BLACK) &&
+                    (!w->right || w->right->color == BLACK))
+                {
+                    w->color = RED;
+                    x = x_parent;
+                    x_parent = x->parent;
+                }
+                else
+                {
+                    if (!w->right|| w->right->color == BLACK)
+                    {
+                        if (w->left)
+                            w->left->color = BLACK;
+                        w->color = RED;
+                        db_rotate_right (w, root);
+                        w = x_parent->right;
+                    }
+                    w->color = x_parent->color;
+                    x_parent->color = BLACK;
+                    if (w->right)
+                        w->right->color = BLACK;
+                    db_rotate_left (x_parent, root);
+                    break;
+                }
+            }
+            else
+            {
+                // same as above, with right <-> left.
+                struct dbn *w = x_parent->left;
+                if (w->color == RED)
+                {
+                    w->color = BLACK;
+                    x_parent->color = RED;
+                    db_rotate_right (x_parent, root);
+                    w = x_parent->left;
+                }
+                if ((!w->right || w->right->color == BLACK) &&
+                    (!w->left || w->left->color == BLACK))
+                {
+                    w->color = RED;
+                    x = x_parent;
+                    x_parent = x_parent->parent;
+                }
+                else
+                {
+                    if (!w->left || w->left->color == BLACK)
+                    {
+                        if (w->right)
+                            w->right->color = BLACK;
+                        w->color = RED;
+                        db_rotate_left (w, root);
+                        w = x_parent->left;
+                    }
+                    w->color = x_parent->color;
+                    x_parent->color = BLACK;
+                    if (w->left)
+                        w->left->color = BLACK;
+                    db_rotate_right (x_parent, root);
+                    break;
+                }
+            }
+        if (x)
+            x->color = BLACK;
+    }
+}
+
+struct dbn *db_insert (struct dbt *table, db_key_t key, db_val_t data)
+{
+    hash_t hash = table_hash (table, key) % HASH_SIZE;
+    int c = 0;
+    struct dbn *prev = NULL;
+    struct dbn *p = table->ht[hash];
+    while (p)
+    {
+        c = table_cmp (table, key, p->key);
+        if (c == 0)
+        {
+            // key found in table, replace
+            // Tell the user of the table to free the key and value
+            if (table->release)
+                table->release (p->key, p->data);
+            p->data = data;
+            p->key = key;
+            return p;
+        }
+        // prev is always p->parent?
+        prev = p;
+        if (c < 0)
+            p = p->left;
+        else
+            p = p->right;
+    }
+    CREATE (p, struct dbn, 1);
+    p->key = key;
+    p->data = data;
+    p->color = RED;
+    if (c == 0)
+    {                           // hash entry is empty
+        table->ht[hash] = p;
+        p->color = BLACK;
+        return p;
+    }
+    p->parent = prev;
+    if (c < 0)
+        prev->left = p;
+    else
+        prev->right = p;
+    if (prev->color == RED)
+    {
+        // must rebalance
+        db_rebalance (p, &table->ht[hash]);
+    }
+    return p;
+}
+
+db_val_t db_erase (struct dbt *table, db_key_t key)
+{
+    hash_t hash = table_hash (table, key) % HASH_SIZE;
+    struct dbn *p = table->ht[hash];
+    while (p)
+    {
+        int c = table_cmp (table, key, p->key);
+        if (c == 0)
+            break;
+        if (c < 0)
+            p = p->left;
+        else
+            p = p->right;
+    }
+    if (!p)
+        return NULL;
+    db_val_t data = p->data;
+    db_rebalance_erase (p, &table->ht[hash]);
+    free (p);
+    return data;
+}
+#ifdef SMART_WALK_TREE
+static inline void db_walk_tree (bool dealloc, struct dbn* p, db_func_t func, va_list ap)
+{
+    if (!p)
+        return;
+    if (!dealloc && !func)
+    {
+        fprintf(stderr, "DEBUG: Must walk tree to either free or invoke a function.\n");
+        abort();
+    }
+    if (p->parent)
+    {
+        fprintf(stderr, "DEBUG: Root nodes must not have parents\n");
+        abort();
+    }
+    while (true)
+    {
+        // apply_func loop
+        if (func)
+            func (p->key, p->data, ap);
+        if (p->left)
+        {
+            // continue descending
+            p = p->left;
+            continue; //goto apply_func;
+        }
+        if (p->right)
+        {
+            // descending the other side
+            p = p->right;
+            continue; //goto apply_func;
+        }
+        while (true)
+        {
+            // backtrack loop
+            if (!p->parent)
+            {
+                if (dealloc)
+                    free (p);
+                // if we have already done both children, there is no more to do
+                return;
+            }
+            if (p->parent->left == p && p->parent->right)
+            {
+                // finished the left tree, now walk the right tree
+                p = p->parent->right;
+                if (dealloc)
+                    free (p->parent->left);
+                break; //goto apply_func;
+            }
+            // p->parent->right == p
+            // or p->parent->left == p but p->parent->right == NULL
+            // keep backtracking
+            p = p->parent;
+            if (dealloc)
+                free (p->right?:p->left);
+        } //backtrack loop
+    } // apply_func loop
+}
+#endif // SMART_WALK_TREE
+
+void db_foreach (struct dbt *table, db_func_t func, ...)
+{
+    va_list ap;
+    va_start (ap, func);
+
+    for (int i = 0; i < HASH_SIZE; i++)
+    {
+#ifdef SMART_WALK_TREE
+        db_walk_tree (false, table->ht[i], func, ap);
+#else
+        struct dbn *p = table->ht[i];
+        if (!p)
+            continue;
+        struct dbn *stack[64];
+        int sp = 0;
+        while (1)
+        {
+            func (p->key, p->data, ap);
+            struct dbn *pn = p->left;
+            if (pn)
+            {
+                if (p->right)
+                    stack[sp++] = p->right;
+                p = pn;
+            }
+            else // pn == NULL, time to do the right branch
+            {
+                if (p->right)
+                    p = p->right;
+                else
+                {
+                    if (sp == 0)
+                        break;
+                    p = stack[--sp];
+                }
+            } // if pn else if !pn
+        } // while true
+#endif // else ! SMART_WALK_TREE
+    } // for i
+    va_end (ap);
+}
+
+// This function is suspiciously similar to the previous
+void db_final (struct dbt *table, db_func_t func, ...)
+{
+    va_list ap;
+    va_start (ap, func);
+
+    for (int i = 0; i < HASH_SIZE; i++)
+    {
+#ifdef SMART_WALK_TREE
+        db_walk_tree (true, table->ht[i], func, ap);
+#else
+        struct dbn *p = table->ht[i];
+        if (!p)
+            continue;
+        struct dbn *stack[64];
+        int sp = 0;
+        while (1)
+        {
+            if (func)
+                func (p->key, p->data, ap);
+            struct dbn *pn = p->left;
+            if (pn)
+            {
+                if (p->right)
+                    stack[sp++] = p->right;
+            }
+            else // pn == NULL, check the right
+            {
+                if (p->right)
+                    pn = p->right;
+                else
+                {
+                    if (sp == 0)
+                        break;
+                    pn = stack[--sp];
+                }
+            } // if pn else if !pn
+            free (p);
+            p = pn;
+        } // while true
+#endif // else ! SMART_WALK_TREE
+    } // for i
+    free (table);
+    va_end (ap);
+}
diff --git a/src/common/db.h b/src/common/db.h
deleted file mode 100644
index 7152854..0000000
--- a/src/common/db.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// WARNING: there is a system header by this name
-#ifndef DB_H
-#define DB_H
-# include "sanity.h"
-
-# include <stdarg.h>
-
-/// Number of tree roots
-// Somewhat arbitrary - larger wastes more space but is faster for large trees
-// num % HASH_SIZE minimize collisions even for similar num
-# define HASH_SIZE (256+27)
-
-typedef enum dbn_color
-{
-    RED,
-    BLACK
-} dbn_color;
-
-typedef intptr_t numdb_key_t;
-typedef union db_key_t
-{
-    char *ms __attribute__((deprecated));
-    const char* s;
-    numdb_key_t i;
-} db_key_t;
-typedef void* db_val_t;
-typedef uint32_t hash_t;
-typedef void (*db_func_t)(db_key_t, db_val_t, va_list);
-
-/// DataBase Node
-struct dbn
-{
-    struct dbn *parent, *left, *right;
-    dbn_color color;
-    db_key_t key;
-    db_val_t data;
-};
-
-typedef enum dbt_type
-{
-    DB_NUMBER,
-    DB_STRING,
-} dbt_type;
-
-/// DataBase Table
-struct dbt
-{
-    dbt_type type;
-    /// Note, before replacement, key/values to be replaced
-    // TODO refactor to decrease/eliminate the uses of this?
-    void (*release) (db_key_t, db_val_t) __attribute__((deprecated));
-    /// Maximum length of a string key - TODO refactor to ensure all strings are NUL-terminated
-    size_t maxlen __attribute__((deprecated));
-    /// The root trees
-    struct dbn *ht[HASH_SIZE];
-};
-
-# define strdb_search(t,k)   db_search((t),(db_key_t)(k))
-# define strdb_insert(t,k,d) db_insert((t),(db_key_t)(k),(db_val_t)(d))
-# define strdb_erase(t,k)    db_erase ((t),(db_key_t)(k))
-# define strdb_foreach       db_foreach
-# define strdb_final         db_final
-# define numdb_search(t,k)   db_search((t),(db_key_t)(k))
-# define numdb_insert(t,k,d) db_insert((t),(db_key_t)(k),(db_val_t)(d))
-# define numdb_erase(t,k)    db_erase ((t),(db_key_t)(k))
-# define numdb_foreach       db_foreach
-# define numdb_final         db_final
-
-/// Create a map from char* to void*, with strings possibly not null-terminated
-struct dbt *strdb_init (size_t maxlen);
-/// Create a map from int to void*
-struct dbt *numdb_init (void);
-/// Return the value corresponding to the key, or NULL if not found
-db_val_t db_search (struct dbt *table, db_key_t key);
-/// Add or replace table[key] = data
-// if it was already there, call release
-struct dbn *db_insert (struct dbt *table, db_key_t key, db_val_t data);
-/// Remove a key from the table, returning the data
-db_val_t db_erase (struct dbt *table, db_key_t key);
-
-/// Execute a function for every element, in unspecified order
-void db_foreach (struct dbt *, db_func_t, ...);
-// opposite of init? Calls release for every element and frees memory
-// This probably isn't really needed: we don't have to free memory while exiting
-void db_final (struct dbt *, db_func_t, ...) __attribute__((deprecated));
-
-#endif
diff --git a/src/common/db.hpp b/src/common/db.hpp
new file mode 100644
index 0000000..145ba13
--- /dev/null
+++ b/src/common/db.hpp
@@ -0,0 +1,87 @@
+// WARNING: there is a system header by this name
+#ifndef DB_HPP
+#define DB_HPP
+# include "sanity.hpp"
+
+# include <stdarg.h>
+
+/// Number of tree roots
+// Somewhat arbitrary - larger wastes more space but is faster for large trees
+// num % HASH_SIZE minimize collisions even for similar num
+# define HASH_SIZE (256+27)
+
+typedef enum dbn_color
+{
+    RED,
+    BLACK
+} dbn_color;
+
+typedef intptr_t numdb_key_t;
+typedef union db_key_t
+{
+    char *ms __attribute__((deprecated));
+    const char* s;
+    numdb_key_t i;
+} db_key_t;
+typedef void* db_val_t;
+typedef uint32_t hash_t;
+typedef void (*db_func_t)(db_key_t, db_val_t, va_list);
+
+/// DataBase Node
+struct dbn
+{
+    struct dbn *parent, *left, *right;
+    dbn_color color;
+    db_key_t key;
+    db_val_t data;
+};
+
+typedef enum dbt_type
+{
+    DB_NUMBER,
+    DB_STRING,
+} dbt_type;
+
+/// DataBase Table
+struct dbt
+{
+    dbt_type type;
+    /// Note, before replacement, key/values to be replaced
+    // TODO refactor to decrease/eliminate the uses of this?
+    void (*release) (db_key_t, db_val_t) __attribute__((deprecated));
+    /// Maximum length of a string key - TODO refactor to ensure all strings are NUL-terminated
+    size_t maxlen __attribute__((deprecated));
+    /// The root trees
+    struct dbn *ht[HASH_SIZE];
+};
+
+# define strdb_search(t,k)   db_search((t),(db_key_t)(k))
+# define strdb_insert(t,k,d) db_insert((t),(db_key_t)(k),(db_val_t)(d))
+# define strdb_erase(t,k)    db_erase ((t),(db_key_t)(k))
+# define strdb_foreach       db_foreach
+# define strdb_final         db_final
+# define numdb_search(t,k)   db_search((t),(db_key_t)(k))
+# define numdb_insert(t,k,d) db_insert((t),(db_key_t)(k),(db_val_t)(d))
+# define numdb_erase(t,k)    db_erase ((t),(db_key_t)(k))
+# define numdb_foreach       db_foreach
+# define numdb_final         db_final
+
+/// Create a map from char* to void*, with strings possibly not null-terminated
+struct dbt *strdb_init (size_t maxlen);
+/// Create a map from int to void*
+struct dbt *numdb_init (void);
+/// Return the value corresponding to the key, or NULL if not found
+db_val_t db_search (struct dbt *table, db_key_t key);
+/// Add or replace table[key] = data
+// if it was already there, call release
+struct dbn *db_insert (struct dbt *table, db_key_t key, db_val_t data);
+/// Remove a key from the table, returning the data
+db_val_t db_erase (struct dbt *table, db_key_t key);
+
+/// Execute a function for every element, in unspecified order
+void db_foreach (struct dbt *, db_func_t, ...);
+// opposite of init? Calls release for every element and frees memory
+// This probably isn't really needed: we don't have to free memory while exiting
+void db_final (struct dbt *, db_func_t, ...) __attribute__((deprecated));
+
+#endif
diff --git a/src/common/grfio.c b/src/common/grfio.c
deleted file mode 100644
index d640263..0000000
--- a/src/common/grfio.c
+++ /dev/null
@@ -1,212 +0,0 @@
-// Reads .gat files by name-mapping .wlk files
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "utils.h"
-#include "grfio.h"
-#include "mmo.h"
-#include "socket.h"
-
-//----------------------------
-//  file entry table struct
-//----------------------------
-typedef struct
-{
-    size_t declen;
-    int16_t next; // next index into the filelist[] array, or -1
-    char fn[128 - 4 - 2];       // file name
-} FILELIST;
-
-#define FILELIST_LIMIT  32768   // limit to number of filelists - if you increase this, change all shorts to int
-#define FILELIST_ADDS   1024    // amount to increment when reallocing
-
-static FILELIST *filelist = NULL;
-/// Number of entries used
-static uint16_t filelist_entrys = 0;
-/// Number of FILELIST entries actually allocated
-static uint16_t filelist_maxentry = 0;
-
-/// First index of the given hash, into the filelist[] array
-static int16_t filelist_hash[256] = {[0 ... 255] = -1};
-
-/// Hash a filename
-static uint8_t filehash (const char *fname)
-{
-    // Larger than the return type - upper bits are used in the process
-    uint32_t hash = 0;
-    while (*fname)
-    {
-        hash = (hash << 1) + (hash >> 7) * 9 + (unsigned char)*fname;
-        fname++;
-    }
-    return hash;
-}
-
-/// Find the filelist entry for the given filename, or NULL if it is not
-FILELIST *filelist_find (const char *fname)
-{
-    int16_t index = filelist_hash[filehash (fname)];
-    while (index >= 0)
-    {
-        if (strcmp (filelist[index].fn, fname) == 0)
-            return &filelist[index];
-        index = filelist[index].next;
-    }
-    return NULL;
-}
-
-/// Copy a temporary entry into the hash map
-static FILELIST *filelist_add (FILELIST * entry)
-{
-    if (filelist_entrys >= FILELIST_LIMIT)
-    {
-        fprintf (stderr, "filelist limit : filelist_add\n");
-        exit (1);
-    }
-
-    if (filelist_entrys >= filelist_maxentry)
-    {
-        RECREATE(filelist, FILELIST, filelist_maxentry + FILELIST_ADDS);
-        memset (filelist + filelist_maxentry, '\0',
-                FILELIST_ADDS * sizeof (FILELIST));
-        filelist_maxentry += FILELIST_ADDS;
-    }
-
-    uint16_t new_index = filelist_entrys++;
-    uint8_t hash = filehash (entry->fn);
-    entry->next = filelist_hash[hash];
-    filelist_hash[hash] = new_index;
-
-    filelist[new_index] = *entry;
-
-    return &filelist[new_index];
-}
-
-static FILELIST *filelist_modify (FILELIST * entry)
-{
-    FILELIST *fentry = filelist_find (entry->fn);
-    if (fentry)
-    {
-        entry->next = fentry->next;
-        *fentry = *entry;
-        return fentry;
-    }
-    return filelist_add (entry);
-}
-
-/// Change fname data/*.gat to lfname data/*.wlk
-// TODO even if the file exists, don't keep reopening it every time one loads
-void grfio_resnametable (const char *fname, char *lfname)
-{
-    char restable[] = "data/resnametable.txt";
-
-    FILE *fp = fopen_ (restable, "rb");
-    if (fp == NULL)
-    {
-        fprintf(stderr, "No resnametable, can't look for %s\n", fname);
-        strcpy(lfname, fname);
-        char* ext = lfname + strlen(lfname) - 4;
-        if (!strcmp(ext, ".gat"))
-            strcpy(ext, ".wlk");
-        return;
-    }
-
-    char line[512];
-    while (fgets (line, sizeof (line), fp))
-    {
-        char w1[256], w2[256];
-        if (
-            // line is of the form foo.gat#foo.wlk#
-            (sscanf (line, "%[^#]#%[^#]#", w1, w2) == 2)
-            // strip data/ from foo.gat before comparing
-            && (!strcmp (w1, fname + 5)))
-        {
-            strcpy (lfname, "data/");
-            strcpy (lfname + 5, w2);
-            fclose_ (fp);
-            return;
-        }
-    }
-    fprintf(stderr, "Unable to find resource: %s\n", fname);
-    fclose_ (fp);
-
-    strcpy(lfname, fname);
-    char* ext = lfname + strlen(lfname) - 4;
-    if (!strcmp(ext, ".gat"))
-        strcpy(ext, ".wlk");
-    return;
-}
-
-/// Size of resource
-size_t grfio_size (const char *fname)
-{
-    FILELIST *entry = filelist_find (fname);
-    if (entry)
-        return entry->declen;
-
-    char lfname[256];
-    FILELIST lentry;
-    struct stat st;
-
-    grfio_resnametable (fname, lfname);
-
-    for (char *p = lfname; *p; p++)
-        if (*p == '\\')
-            *p = '/';
-
-    if (stat (lfname, &st) == 0)
-    {
-        strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1);
-        lentry.declen = st.st_size;
-        entry = filelist_modify (&lentry);
-    }
-    else
-    {
-        printf ("%s not found\n", fname);
-        return 0;
-    }
-    return entry->declen;
-}
-
-void *grfio_reads (const char *fname, size_t *size)
-{
-    char lfname[256];
-    grfio_resnametable (fname, lfname);
-
-    for (char *p = &lfname[0]; *p != 0; p++)
-        if (*p == '\\')
-            *p = '/';       // * At the time of Unix
-
-    FILE *in = fopen_ (lfname, "rb");
-    if (!in)
-    {
-        fprintf (stderr, "%s not found\n", fname);
-        return NULL;
-    }
-    FILELIST lentry;
-    FILELIST *entry = filelist_find (fname);
-    if (entry)
-    {
-        lentry.declen = entry->declen;
-    }
-    else
-    {
-        fseek (in, 0, SEEK_END);
-        lentry.declen = ftell (in);
-        fseek (in, 0, SEEK_SET);
-        strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1);
-        entry = filelist_modify (&lentry);
-    }
-    uint8_t *buf2;
-    CREATE (buf2, uint8_t, lentry.declen + 1024);
-    if (fread (buf2, 1, lentry.declen, in) != lentry.declen)
-        exit(1);
-    fclose_ (in);
-    in = NULL;
-
-    if (size)
-        *size = entry->declen;
-    return buf2;
-}
diff --git a/src/common/grfio.cpp b/src/common/grfio.cpp
new file mode 100644
index 0000000..1b89b18
--- /dev/null
+++ b/src/common/grfio.cpp
@@ -0,0 +1,212 @@
+// Reads .gat files by name-mapping .wlk files
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "utils.hpp"
+#include "grfio.hpp"
+#include "mmo.hpp"
+#include "socket.hpp"
+
+//----------------------------
+//  file entry table struct
+//----------------------------
+typedef struct
+{
+    size_t declen;
+    int16_t next; // next index into the filelist[] array, or -1
+    char fn[128 - 4 - 2];       // file name
+} FILELIST;
+
+#define FILELIST_LIMIT  32768   // limit to number of filelists - if you increase this, change all shorts to int
+#define FILELIST_ADDS   1024    // amount to increment when reallocing
+
+static FILELIST *filelist = NULL;
+/// Number of entries used
+static uint16_t filelist_entrys = 0;
+/// Number of FILELIST entries actually allocated
+static uint16_t filelist_maxentry = 0;
+
+/// First index of the given hash, into the filelist[] array
+static int16_t filelist_hash[256] = {[0 ... 255] = -1};
+
+/// Hash a filename
+static uint8_t filehash (const char *fname)
+{
+    // Larger than the return type - upper bits are used in the process
+    uint32_t hash = 0;
+    while (*fname)
+    {
+        hash = (hash << 1) + (hash >> 7) * 9 + (unsigned char)*fname;
+        fname++;
+    }
+    return hash;
+}
+
+/// Find the filelist entry for the given filename, or NULL if it is not
+FILELIST *filelist_find (const char *fname)
+{
+    int16_t index = filelist_hash[filehash (fname)];
+    while (index >= 0)
+    {
+        if (strcmp (filelist[index].fn, fname) == 0)
+            return &filelist[index];
+        index = filelist[index].next;
+    }
+    return NULL;
+}
+
+/// Copy a temporary entry into the hash map
+static FILELIST *filelist_add (FILELIST * entry)
+{
+    if (filelist_entrys >= FILELIST_LIMIT)
+    {
+        fprintf (stderr, "filelist limit : filelist_add\n");
+        exit (1);
+    }
+
+    if (filelist_entrys >= filelist_maxentry)
+    {
+        RECREATE(filelist, FILELIST, filelist_maxentry + FILELIST_ADDS);
+        memset (filelist + filelist_maxentry, '\0',
+                FILELIST_ADDS * sizeof (FILELIST));
+        filelist_maxentry += FILELIST_ADDS;
+    }
+
+    uint16_t new_index = filelist_entrys++;
+    uint8_t hash = filehash (entry->fn);
+    entry->next = filelist_hash[hash];
+    filelist_hash[hash] = new_index;
+
+    filelist[new_index] = *entry;
+
+    return &filelist[new_index];
+}
+
+static FILELIST *filelist_modify (FILELIST * entry)
+{
+    FILELIST *fentry = filelist_find (entry->fn);
+    if (fentry)
+    {
+        entry->next = fentry->next;
+        *fentry = *entry;
+        return fentry;
+    }
+    return filelist_add (entry);
+}
+
+/// Change fname data/*.gat to lfname data/*.wlk
+// TODO even if the file exists, don't keep reopening it every time one loads
+void grfio_resnametable (const char *fname, char *lfname)
+{
+    char restable[] = "data/resnametable.txt";
+
+    FILE *fp = fopen_ (restable, "rb");
+    if (fp == NULL)
+    {
+        fprintf(stderr, "No resnametable, can't look for %s\n", fname);
+        strcpy(lfname, fname);
+        char* ext = lfname + strlen(lfname) - 4;
+        if (!strcmp(ext, ".gat"))
+            strcpy(ext, ".wlk");
+        return;
+    }
+
+    char line[512];
+    while (fgets (line, sizeof (line), fp))
+    {
+        char w1[256], w2[256];
+        if (
+            // line is of the form foo.gat#foo.wlk#
+            (sscanf (line, "%[^#]#%[^#]#", w1, w2) == 2)
+            // strip data/ from foo.gat before comparing
+            && (!strcmp (w1, fname + 5)))
+        {
+            strcpy (lfname, "data/");
+            strcpy (lfname + 5, w2);
+            fclose_ (fp);
+            return;
+        }
+    }
+    fprintf(stderr, "Unable to find resource: %s\n", fname);
+    fclose_ (fp);
+
+    strcpy(lfname, fname);
+    char* ext = lfname + strlen(lfname) - 4;
+    if (!strcmp(ext, ".gat"))
+        strcpy(ext, ".wlk");
+    return;
+}
+
+/// Size of resource
+size_t grfio_size (const char *fname)
+{
+    FILELIST *entry = filelist_find (fname);
+    if (entry)
+        return entry->declen;
+
+    char lfname[256];
+    FILELIST lentry;
+    struct stat st;
+
+    grfio_resnametable (fname, lfname);
+
+    for (char *p = lfname; *p; p++)
+        if (*p == '\\')
+            *p = '/';
+
+    if (stat (lfname, &st) == 0)
+    {
+        strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1);
+        lentry.declen = st.st_size;
+        entry = filelist_modify (&lentry);
+    }
+    else
+    {
+        printf ("%s not found\n", fname);
+        return 0;
+    }
+    return entry->declen;
+}
+
+void *grfio_reads (const char *fname, size_t *size)
+{
+    char lfname[256];
+    grfio_resnametable (fname, lfname);
+
+    for (char *p = &lfname[0]; *p != 0; p++)
+        if (*p == '\\')
+            *p = '/';       // * At the time of Unix
+
+    FILE *in = fopen_ (lfname, "rb");
+    if (!in)
+    {
+        fprintf (stderr, "%s not found\n", fname);
+        return NULL;
+    }
+    FILELIST lentry;
+    FILELIST *entry = filelist_find (fname);
+    if (entry)
+    {
+        lentry.declen = entry->declen;
+    }
+    else
+    {
+        fseek (in, 0, SEEK_END);
+        lentry.declen = ftell (in);
+        fseek (in, 0, SEEK_SET);
+        strncpy (lentry.fn, fname, sizeof (lentry.fn) - 1);
+        entry = filelist_modify (&lentry);
+    }
+    uint8_t *buf2;
+    CREATE (buf2, uint8_t, lentry.declen + 1024);
+    if (fread (buf2, 1, lentry.declen, in) != lentry.declen)
+        exit(1);
+    fclose_ (in);
+    in = NULL;
+
+    if (size)
+        *size = entry->declen;
+    return buf2;
+}
diff --git a/src/common/grfio.h b/src/common/grfio.h
deleted file mode 100644
index 4919a7b..0000000
--- a/src/common/grfio.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/// Accessor to the .gat map virtual files
-// Note .gat files are mapped to .wlk files by data/resnametable.txt
-// Note that there currently is a 1-1 correlation between them,
-// but it is possible for a single .wlk to have multiple .gats reference it
-#ifndef GRFIO_H
-#define GRFIO_H
-
-/// Load file into memory
-# define grfio_read(resourcename) grfio_reads (resourcename, NULL)
-/// Load file into memory and possibly record length
-// For some reason, this allocates an extra 1024 bytes at the end
-void *grfio_reads (const char *resourcename, size_t *size);
-/// Get size of file
-// This is only called once, and that is to check the existence of a file.
-size_t grfio_size (const char *resourcename) __attribute__((deprecated));
-
-#endif // GRFIO_H
diff --git a/src/common/grfio.hpp b/src/common/grfio.hpp
new file mode 100644
index 0000000..3485904
--- /dev/null
+++ b/src/common/grfio.hpp
@@ -0,0 +1,17 @@
+/// Accessor to the .gat map virtual files
+// Note .gat files are mapped to .wlk files by data/resnametable.txt
+// Note that there currently is a 1-1 correlation between them,
+// but it is possible for a single .wlk to have multiple .gats reference it
+#ifndef GRFIO_HPP
+#define GRFIO_HPP
+
+/// Load file into memory
+# define grfio_read(resourcename) grfio_reads (resourcename, NULL)
+/// Load file into memory and possibly record length
+// For some reason, this allocates an extra 1024 bytes at the end
+void *grfio_reads (const char *resourcename, size_t *size);
+/// Get size of file
+// This is only called once, and that is to check the existence of a file.
+size_t grfio_size (const char *resourcename) __attribute__((deprecated));
+
+#endif // GRFIO_HPP
diff --git a/src/common/lock.c b/src/common/lock.c
deleted file mode 100644
index dd42ef2..0000000
--- a/src/common/lock.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include "lock.h"
-#include "socket.h"
-
-/// Protected file writing
-/// (Until the file is closed, it keeps the old file)
-
-// Start writing a tmpfile
-FILE *lock_fopen (const char *filename, int *info)
-{
-    char newfile[512];
-    FILE *fp;
-    int  no = getpid ();
-
-    // Get a filename that doesn't already exist
-    do
-    {
-        sprintf (newfile, "%s_%d.tmp", filename, no++);
-    }
-    while ((fp = fopen_ (newfile, "r")) && (fclose_ (fp), 1));
-    *info = --no;
-    return fopen_ (newfile, "w");
-}
-
-// Delete the old file and rename the new file
-void lock_fclose (FILE * fp, const char *filename, int *info)
-{
-    char newfile[512];
-    if (fp)
-    {
-        fclose_ (fp);
-        sprintf (newfile, "%s_%d.tmp", filename, *info);
-        rename (newfile, filename);
-    }
-}
diff --git a/src/common/lock.cpp b/src/common/lock.cpp
new file mode 100644
index 0000000..2ba9a0a
--- /dev/null
+++ b/src/common/lock.cpp
@@ -0,0 +1,36 @@
+#include <unistd.h>
+#include <stdio.h>
+#include "lock.hpp"
+#include "socket.hpp"
+
+/// Protected file writing
+/// (Until the file is closed, it keeps the old file)
+
+// Start writing a tmpfile
+FILE *lock_fopen (const char *filename, int *info)
+{
+    char newfile[512];
+    FILE *fp;
+    int  no = getpid ();
+
+    // Get a filename that doesn't already exist
+    do
+    {
+        sprintf (newfile, "%s_%d.tmp", filename, no++);
+    }
+    while ((fp = fopen_ (newfile, "r")) && (fclose_ (fp), 1));
+    *info = --no;
+    return fopen_ (newfile, "w");
+}
+
+// Delete the old file and rename the new file
+void lock_fclose (FILE * fp, const char *filename, int *info)
+{
+    char newfile[512];
+    if (fp)
+    {
+        fclose_ (fp);
+        sprintf (newfile, "%s_%d.tmp", filename, *info);
+        rename (newfile, filename);
+    }
+}
diff --git a/src/common/lock.h b/src/common/lock.h
deleted file mode 100644
index 2f087fd..0000000
--- a/src/common/lock.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LOCK_H
-#define LOCK_H
-/// Locked FILE I/O
-// Changes are made in a separate file until lock_fclose
-FILE *lock_fopen (const char *filename, int *info);
-void lock_fclose (FILE * fp, const char *filename, int *info);
-
-#endif // LOCK_H
diff --git a/src/common/lock.hpp b/src/common/lock.hpp
new file mode 100644
index 0000000..19c1302
--- /dev/null
+++ b/src/common/lock.hpp
@@ -0,0 +1,8 @@
+#ifndef LOCK_HPP
+#define LOCK_HPP
+/// Locked FILE I/O
+// Changes are made in a separate file until lock_fclose
+FILE *lock_fopen (const char *filename, int *info);
+void lock_fclose (FILE * fp, const char *filename, int *info);
+
+#endif // LOCK_HPP
diff --git a/src/common/md5calc.c b/src/common/md5calc.c
deleted file mode 100644
index ba8f6af..0000000
--- a/src/common/md5calc.c
+++ /dev/null
@@ -1,339 +0,0 @@
-#include "md5calc.h"
-#include <string.h>
-#include "mt_rand.h"
-
-// auxilary data
-/*
-sin() constant table
-# Reformatted output of:
-echo 'scale=40; obase=16; for (i=1;i<=64;i++) print 2^32 * sin(i), "\n"' |
-bc | sed 's/^-//;s/^/0x/;s/\..*$/,/'
-*/
-static const uint32_t T[64] =
-{
-    // used by round 1
-    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, //0
-    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, //4
-    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //8
-    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, //12
-    // used by round 2
-    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, //16
-    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, //20
-    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, //24
-    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, //28
-    // used by round 3
-    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, //32
-    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, //36
-    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, //40
-    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, //44
-    // used by round 4
-    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, //48
-    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, //52
-    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, //56
-    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, //60
-};
-
-// auxilary functions
-// note - the RFC defines these by non-CS conventions: or=v, and=(empty)
-static inline uint32_t rotate_left(uint32_t val, unsigned shift)
-{
-    return val << shift | val >> (32-shift);
-}
-
-static inline uint32_t F(uint32_t X, uint32_t Y, uint32_t Z)
-{
-    return (X & Y) | (~X & Z);
-}
-static inline uint32_t G(uint32_t X, uint32_t Y, uint32_t Z)
-{
-    return (X & Z) | (Y & ~Z);
-}
-static inline uint32_t H(uint32_t X, uint32_t Y, uint32_t Z)
-{
-    return X ^ Y ^ Z;
-}
-static inline uint32_t I(uint32_t X, uint32_t Y, uint32_t Z)
-{
-    return Y ^ (X | ~Z);
-}
-
-static const struct
-{
-    uint8_t k : 4;
-    uint8_t : 0;
-    uint8_t s : 5;
-//    uint8_t i : 6; just increments constantly, from 1 .. 64 over all rounds
-}
-MD5_round1[16] =
-{
-    { 0,  7}, { 1, 12}, { 2, 17}, { 3, 22},
-    { 4,  7}, { 5, 12}, { 6, 17}, { 7, 22},
-    { 8,  7}, { 9, 12}, {10, 17}, {11, 22},
-    {12,  7}, {13, 12}, {14, 17}, {15, 22},
-},
-MD5_round2[16] =
-{
-    { 1,  5}, { 6,  9}, {11, 14}, { 0, 20},
-    { 5,  5}, {10,  9}, {15, 14}, { 4, 20},
-    { 9,  5}, {14,  9}, { 3, 14}, { 8, 20},
-    {13,  5}, { 2,  9}, { 7, 14}, {12, 20},
-},
-MD5_round3[16] =
-{
-    { 5,  4}, { 8, 11}, {11, 16}, {14, 23},
-    { 1,  4}, { 4, 11}, { 7, 16}, {10, 23},
-    {13,  4}, { 0, 11}, { 3, 16}, { 6, 23},
-    { 9,  4}, {12, 11}, {15, 16}, { 2, 23},
-},
-MD5_round4[16] =
-{
-    { 0,  6}, { 7, 10}, {14, 15}, { 5, 21},
-    {12,  6}, { 3, 10}, {10, 15}, { 1, 21},
-    { 8,  6}, {15, 10}, { 6, 15}, {13, 21},
-    { 4,  6}, {11, 10}, { 2, 15}, { 9, 21},
-};
-
-
-void MD5_init(MD5_state* state)
-{
-    // in the RFC, these are specified as bytes, interpreted as little-endian
-    state->val[0] = 0x67452301;
-    state->val[1] = 0xEFCDAB89;
-    state->val[2] = 0x98BADCFE;
-    state->val[3] = 0x10325476;
-}
-
-void MD5_do_block(MD5_state* state, MD5_block block)
-{
-#define X block.data
-#define a state->val[(16-i)%4]
-#define b state->val[(17-i)%4]
-#define c state->val[(18-i)%4]
-#define d state->val[(19-i)%4]
-    // save the values
-    const MD5_state saved = *state;
-    // round 1
-    for (int i=0; i<16; i++)
-    {
-#define k MD5_round1[i].k
-#define s MD5_round1[i].s
-        a = b + rotate_left(a + F(b,c,d) + X[k] + T[i+0x0], s);
-#undef k
-#undef s
-    }
-    // round 2
-    for (int i=0; i<16; i++)
-    {
-#define k MD5_round2[i].k
-#define s MD5_round2[i].s
-        a = b + rotate_left(a + G(b,c,d) + X[k] + T[i+0x10], s);
-#undef k
-#undef s
-    }
-    // round 3
-    for (int i=0; i<16; i++)
-    {
-#define k MD5_round3[i].k
-#define s MD5_round3[i].s
-        a = b + rotate_left(a + H(b,c,d) + X[k] + T[i+0x20], s);
-#undef k
-#undef s
-    }
-    // round 4
-    for (int i=0; i<16; i++)
-    {
-#define k MD5_round4[i].k
-#define s MD5_round4[i].s
-        a = b + rotate_left(a + I(b,c,d) + X[k] + T[i+0x30], s);
-#undef k
-#undef s
-    }
-    // adjust state based on original
-    state->val[0] += saved.val[0];
-    state->val[1] += saved.val[1];
-    state->val[2] += saved.val[2];
-    state->val[3] += saved.val[3];
-#undef a
-#undef b
-#undef c
-#undef d
-}
-
-void MD5_to_bin(MD5_state state, uint8_t out[0x10])
-{
-    for (int i=0; i<0x10; i++)
-        out[i] = state.val[i/4] >> 8*(i%4);
-}
-
-static const char hex[] = "0123456789abcdef";
-
-void MD5_to_str(MD5_state state, char out[0x21])
-{
-    uint8_t bin[16];
-    MD5_to_bin(state, bin);
-    for (int i=0; i<0x10; i++)
-        out[2*i] = hex[bin[i] >> 4],
-        out[2*i+1] = hex[bin[i] & 0xf];
-    out[0x20] = '\0';
-}
-
-MD5_state MD5_from_string(const char* msg, const size_t msglen)
-{
-    MD5_state state;
-    MD5_init(&state);
-    MD5_block block;
-    size_t rem = msglen;
-    while (rem >= 64)
-    {
-        for (int i=0; i<0x10; i++)
-            X[i] = msg[4*i+0] | msg[4*i+1]<<8 | msg[4*i+2]<<16 | msg[4*i+3]<<24;
-        MD5_do_block(&state, block);
-        msg += 64;
-        rem -= 64;
-    }
-    // now pad 1-512 bits + the 64-bit length - may be two blocks
-    uint8_t buf[0x40] = {};
-    memcpy (buf, msg, rem);
-    buf[rem] = 0x80; // a single one bit
-    if (64 - rem > 8)
-    {
-        for (int i=0; i<8; i++)
-            buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8);
-    }
-    for (int i=0; i<0x10; i++)
-        X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
-    MD5_do_block(&state, block);
-    if (64 - rem <= 8)
-    {
-        memset(buf,'\0', 0x38);
-        for (int i=0; i<8; i++)
-            buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8);
-        for (int i=0; i<0x10; i++)
-            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
-        MD5_do_block(&state, block);
-    }
-    return state;
-}
-
-// This could be reimplemented without the strlen()
-MD5_state MD5_from_cstring(const char* msg)
-{
-    return MD5_from_string(msg, strlen(msg));
-}
-
-MD5_state MD5_from_FILE(FILE* in) {
-    uint64_t total_len = 0;
-
-    uint8_t buf[0x40];
-    uint8_t block_len = 0;
-
-    MD5_state state;
-    MD5_init(&state);
-
-    MD5_block block;
-
-    while (true)
-    {
-        size_t rv = fread(buf + block_len, 1, 0x40 - block_len, in);
-        if (!rv)
-            break;
-        total_len += 8*rv; // in bits
-        block_len += rv;
-        if (block_len != 0x40)
-            continue;
-        for (int i=0; i<0x10; i++)
-            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
-        MD5_do_block(&state, block);
-        block_len = 0;
-    }
-    // no more input, just pad and append the length
-    buf[block_len] = 0x80;
-    memset(buf + block_len + 1, '\0', 0x40 - block_len - 1);
-    if (block_len < 0x38)
-    {
-        for (int i=0; i<8; i++)
-            buf[0x38+i] = total_len >> i*8;
-    }
-    for (int i=0; i<0x10; i++)
-        X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
-    MD5_do_block(&state, block);
-    if (0x38 <= block_len)
-    {
-        memset(buf, '\0', 0x38);
-        for (int i=0; i<8; i++)
-            buf[0x38+i] = total_len >> i*8;
-        for (int i=0; i<0x10; i++)
-            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
-        MD5_do_block(&state, block);
-    }
-    return state;
-}
-
-
-// Hash a password with a salt.
-// Whoever wrote this FAILS programming
-const char *MD5_saltcrypt(const char *key, const char *salt)
-{
-    char buf[65];
-
-    // hash the key then the salt
-    // buf ends up as a 64-char NUL-terminated string
-    MD5_to_str(MD5_from_cstring(key), buf);
-    MD5_to_str(MD5_from_cstring(salt), buf+32);
-
-    // Hash the buffer back into sbuf - this is stupid
-    // (luckily, putting the result into itself is safe)
-    MD5_to_str(MD5_from_cstring(buf), buf+32);
-
-    static char obuf[33];
-    // This truncates the string, but we have to keep it like that for compatibility
-    snprintf(obuf, 32, "!%s$%s", salt, buf+32);
-    return obuf;
-}
-
-const char *make_salt(void) {
-    static char salt[6];
-    for (int i=0; i<5; i++)
-        salt[i] = MPRAND(48, 78);
-    return salt;
-}
-
-bool pass_ok(const char *password, const char *crypted) {
-    char buf[40];
-    strncpy(buf, crypted, 40);
-    char *salt = buf + 1;
-    *strchr(salt, '$') = '\0';
-
-    return !strcmp(crypted, MD5_saltcrypt(password, salt));
-}
-
-// [M|h]ashes up an IP address and a secret key
-// to return a hopefully unique masked IP.
-in_addr_t MD5_ip(char *secret, in_addr_t ip)
-{
-    char ipbuf[32];
-    uint8_t obuf[16];
-    union {
-        struct bytes {
-            uint8_t b1;
-            uint8_t b2;
-            uint8_t b3;
-            uint8_t b4;
-        } bytes;
-        in_addr_t ip;
-    } conv;
-
-    // MD5sum a secret + the IP address
-    memset(&ipbuf, 0, sizeof(ipbuf));
-    snprintf(ipbuf, sizeof(ipbuf), "%lu%s", (unsigned long)ip, secret);
-    /// TODO stop it from being a cstring
-    MD5_to_bin(MD5_from_cstring(ipbuf), obuf);
-
-    // Fold the md5sum to 32 bits, pack the bytes to an in_addr_t
-    conv.bytes.b1 = obuf[0] ^ obuf[1] ^ obuf[8] ^ obuf[9];
-    conv.bytes.b2 = obuf[2] ^ obuf[3] ^ obuf[10] ^ obuf[11];
-    conv.bytes.b3 = obuf[4] ^ obuf[5] ^ obuf[12] ^ obuf[13];
-    conv.bytes.b4 = obuf[6] ^ obuf[7] ^ obuf[14] ^ obuf[15];
-
-    return conv.ip;
-}
diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp
new file mode 100644
index 0000000..f00861d
--- /dev/null
+++ b/src/common/md5calc.cpp
@@ -0,0 +1,339 @@
+#include "md5calc.hpp"
+#include <string.h>
+#include "mt_rand.hpp"
+
+// auxilary data
+/*
+sin() constant table
+# Reformatted output of:
+echo 'scale=40; obase=16; for (i=1;i<=64;i++) print 2^32 * sin(i), "\n"' |
+bc | sed 's/^-//;s/^/0x/;s/\..*$/,/'
+*/
+static const uint32_t T[64] =
+{
+    // used by round 1
+    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, //0
+    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, //4
+    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //8
+    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, //12
+    // used by round 2
+    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, //16
+    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, //20
+    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, //24
+    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, //28
+    // used by round 3
+    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, //32
+    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, //36
+    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, //40
+    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, //44
+    // used by round 4
+    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, //48
+    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, //52
+    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, //56
+    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, //60
+};
+
+// auxilary functions
+// note - the RFC defines these by non-CS conventions: or=v, and=(empty)
+static inline uint32_t rotate_left(uint32_t val, unsigned shift)
+{
+    return val << shift | val >> (32-shift);
+}
+
+static inline uint32_t F(uint32_t X, uint32_t Y, uint32_t Z)
+{
+    return (X & Y) | (~X & Z);
+}
+static inline uint32_t G(uint32_t X, uint32_t Y, uint32_t Z)
+{
+    return (X & Z) | (Y & ~Z);
+}
+static inline uint32_t H(uint32_t X, uint32_t Y, uint32_t Z)
+{
+    return X ^ Y ^ Z;
+}
+static inline uint32_t I(uint32_t X, uint32_t Y, uint32_t Z)
+{
+    return Y ^ (X | ~Z);
+}
+
+static const struct
+{
+    uint8_t k : 4;
+    uint8_t : 0;
+    uint8_t s : 5;
+//    uint8_t i : 6; just increments constantly, from 1 .. 64 over all rounds
+}
+MD5_round1[16] =
+{
+    { 0,  7}, { 1, 12}, { 2, 17}, { 3, 22},
+    { 4,  7}, { 5, 12}, { 6, 17}, { 7, 22},
+    { 8,  7}, { 9, 12}, {10, 17}, {11, 22},
+    {12,  7}, {13, 12}, {14, 17}, {15, 22},
+},
+MD5_round2[16] =
+{
+    { 1,  5}, { 6,  9}, {11, 14}, { 0, 20},
+    { 5,  5}, {10,  9}, {15, 14}, { 4, 20},
+    { 9,  5}, {14,  9}, { 3, 14}, { 8, 20},
+    {13,  5}, { 2,  9}, { 7, 14}, {12, 20},
+},
+MD5_round3[16] =
+{
+    { 5,  4}, { 8, 11}, {11, 16}, {14, 23},
+    { 1,  4}, { 4, 11}, { 7, 16}, {10, 23},
+    {13,  4}, { 0, 11}, { 3, 16}, { 6, 23},
+    { 9,  4}, {12, 11}, {15, 16}, { 2, 23},
+},
+MD5_round4[16] =
+{
+    { 0,  6}, { 7, 10}, {14, 15}, { 5, 21},
+    {12,  6}, { 3, 10}, {10, 15}, { 1, 21},
+    { 8,  6}, {15, 10}, { 6, 15}, {13, 21},
+    { 4,  6}, {11, 10}, { 2, 15}, { 9, 21},
+};
+
+
+void MD5_init(MD5_state* state)
+{
+    // in the RFC, these are specified as bytes, interpreted as little-endian
+    state->val[0] = 0x67452301;
+    state->val[1] = 0xEFCDAB89;
+    state->val[2] = 0x98BADCFE;
+    state->val[3] = 0x10325476;
+}
+
+void MD5_do_block(MD5_state* state, MD5_block block)
+{
+#define X block.data
+#define a state->val[(16-i)%4]
+#define b state->val[(17-i)%4]
+#define c state->val[(18-i)%4]
+#define d state->val[(19-i)%4]
+    // save the values
+    const MD5_state saved = *state;
+    // round 1
+    for (int i=0; i<16; i++)
+    {
+#define k MD5_round1[i].k
+#define s MD5_round1[i].s
+        a = b + rotate_left(a + F(b,c,d) + X[k] + T[i+0x0], s);
+#undef k
+#undef s
+    }
+    // round 2
+    for (int i=0; i<16; i++)
+    {
+#define k MD5_round2[i].k
+#define s MD5_round2[i].s
+        a = b + rotate_left(a + G(b,c,d) + X[k] + T[i+0x10], s);
+#undef k
+#undef s
+    }
+    // round 3
+    for (int i=0; i<16; i++)
+    {
+#define k MD5_round3[i].k
+#define s MD5_round3[i].s
+        a = b + rotate_left(a + H(b,c,d) + X[k] + T[i+0x20], s);
+#undef k
+#undef s
+    }
+    // round 4
+    for (int i=0; i<16; i++)
+    {
+#define k MD5_round4[i].k
+#define s MD5_round4[i].s
+        a = b + rotate_left(a + I(b,c,d) + X[k] + T[i+0x30], s);
+#undef k
+#undef s
+    }
+    // adjust state based on original
+    state->val[0] += saved.val[0];
+    state->val[1] += saved.val[1];
+    state->val[2] += saved.val[2];
+    state->val[3] += saved.val[3];
+#undef a
+#undef b
+#undef c
+#undef d
+}
+
+void MD5_to_bin(MD5_state state, uint8_t out[0x10])
+{
+    for (int i=0; i<0x10; i++)
+        out[i] = state.val[i/4] >> 8*(i%4);
+}
+
+static const char hex[] = "0123456789abcdef";
+
+void MD5_to_str(MD5_state state, char out[0x21])
+{
+    uint8_t bin[16];
+    MD5_to_bin(state, bin);
+    for (int i=0; i<0x10; i++)
+        out[2*i] = hex[bin[i] >> 4],
+        out[2*i+1] = hex[bin[i] & 0xf];
+    out[0x20] = '\0';
+}
+
+MD5_state MD5_from_string(const char* msg, const size_t msglen)
+{
+    MD5_state state;
+    MD5_init(&state);
+    MD5_block block;
+    size_t rem = msglen;
+    while (rem >= 64)
+    {
+        for (int i=0; i<0x10; i++)
+            X[i] = msg[4*i+0] | msg[4*i+1]<<8 | msg[4*i+2]<<16 | msg[4*i+3]<<24;
+        MD5_do_block(&state, block);
+        msg += 64;
+        rem -= 64;
+    }
+    // now pad 1-512 bits + the 64-bit length - may be two blocks
+    uint8_t buf[0x40] = {};
+    memcpy (buf, msg, rem);
+    buf[rem] = 0x80; // a single one bit
+    if (64 - rem > 8)
+    {
+        for (int i=0; i<8; i++)
+            buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8);
+    }
+    for (int i=0; i<0x10; i++)
+        X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+    MD5_do_block(&state, block);
+    if (64 - rem <= 8)
+    {
+        memset(buf,'\0', 0x38);
+        for (int i=0; i<8; i++)
+            buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8);
+        for (int i=0; i<0x10; i++)
+            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+        MD5_do_block(&state, block);
+    }
+    return state;
+}
+
+// This could be reimplemented without the strlen()
+MD5_state MD5_from_cstring(const char* msg)
+{
+    return MD5_from_string(msg, strlen(msg));
+}
+
+MD5_state MD5_from_FILE(FILE* in) {
+    uint64_t total_len = 0;
+
+    uint8_t buf[0x40];
+    uint8_t block_len = 0;
+
+    MD5_state state;
+    MD5_init(&state);
+
+    MD5_block block;
+
+    while (true)
+    {
+        size_t rv = fread(buf + block_len, 1, 0x40 - block_len, in);
+        if (!rv)
+            break;
+        total_len += 8*rv; // in bits
+        block_len += rv;
+        if (block_len != 0x40)
+            continue;
+        for (int i=0; i<0x10; i++)
+            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+        MD5_do_block(&state, block);
+        block_len = 0;
+    }
+    // no more input, just pad and append the length
+    buf[block_len] = 0x80;
+    memset(buf + block_len + 1, '\0', 0x40 - block_len - 1);
+    if (block_len < 0x38)
+    {
+        for (int i=0; i<8; i++)
+            buf[0x38+i] = total_len >> i*8;
+    }
+    for (int i=0; i<0x10; i++)
+        X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+    MD5_do_block(&state, block);
+    if (0x38 <= block_len)
+    {
+        memset(buf, '\0', 0x38);
+        for (int i=0; i<8; i++)
+            buf[0x38+i] = total_len >> i*8;
+        for (int i=0; i<0x10; i++)
+            X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+        MD5_do_block(&state, block);
+    }
+    return state;
+}
+
+
+// Hash a password with a salt.
+// Whoever wrote this FAILS programming
+const char *MD5_saltcrypt(const char *key, const char *salt)
+{
+    char buf[65];
+
+    // hash the key then the salt
+    // buf ends up as a 64-char NUL-terminated string
+    MD5_to_str(MD5_from_cstring(key), buf);
+    MD5_to_str(MD5_from_cstring(salt), buf+32);
+
+    // Hash the buffer back into sbuf - this is stupid
+    // (luckily, putting the result into itself is safe)
+    MD5_to_str(MD5_from_cstring(buf), buf+32);
+
+    static char obuf[33];
+    // This truncates the string, but we have to keep it like that for compatibility
+    snprintf(obuf, 32, "!%s$%s", salt, buf+32);
+    return obuf;
+}
+
+const char *make_salt(void) {
+    static char salt[6];
+    for (int i=0; i<5; i++)
+        salt[i] = MPRAND(48, 78);
+    return salt;
+}
+
+bool pass_ok(const char *password, const char *crypted) {
+    char buf[40];
+    strncpy(buf, crypted, 40);
+    char *salt = buf + 1;
+    *strchr(salt, '$') = '\0';
+
+    return !strcmp(crypted, MD5_saltcrypt(password, salt));
+}
+
+// [M|h]ashes up an IP address and a secret key
+// to return a hopefully unique masked IP.
+in_addr_t MD5_ip(char *secret, in_addr_t ip)
+{
+    char ipbuf[32];
+    uint8_t obuf[16];
+    union {
+        struct bytes {
+            uint8_t b1;
+            uint8_t b2;
+            uint8_t b3;
+            uint8_t b4;
+        } bytes;
+        in_addr_t ip;
+    } conv;
+
+    // MD5sum a secret + the IP address
+    memset(&ipbuf, 0, sizeof(ipbuf));
+    snprintf(ipbuf, sizeof(ipbuf), "%lu%s", (unsigned long)ip, secret);
+    /// TODO stop it from being a cstring
+    MD5_to_bin(MD5_from_cstring(ipbuf), obuf);
+
+    // Fold the md5sum to 32 bits, pack the bytes to an in_addr_t
+    conv.bytes.b1 = obuf[0] ^ obuf[1] ^ obuf[8] ^ obuf[9];
+    conv.bytes.b2 = obuf[2] ^ obuf[3] ^ obuf[10] ^ obuf[11];
+    conv.bytes.b3 = obuf[4] ^ obuf[5] ^ obuf[12] ^ obuf[13];
+    conv.bytes.b4 = obuf[6] ^ obuf[7] ^ obuf[14] ^ obuf[15];
+
+    return conv.ip;
+}
diff --git a/src/common/md5calc.h b/src/common/md5calc.h
deleted file mode 100644
index b864791..0000000
--- a/src/common/md5calc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef MD5CALC_H
-#define MD5CALC_H
-
-#include "sanity.h"
-
-#include <netinet/in.h>
-
-#include <stdint.h> // uint32_t, uint8_t
-#include <stddef.h> // size_t
-#include <stdio.h> // FILE*
-
-/// The digest state - becomes the output
-typedef struct
-{
-    // classically named {A,B,C,D}
-    // but use an so we can index
-    uint32_t val[4];
-} MD5_state;
-typedef struct
-{
-    uint32_t data[16];
-} MD5_block;
-
-// Implementation
-void MD5_init(MD5_state* state);
-void MD5_do_block(MD5_state* state, MD5_block block);
-
-// Output formatting
-void MD5_to_bin(MD5_state state, uint8_t out[0x10]);
-void MD5_to_str(MD5_state state, char out[0x21]);
-
-// Convenience
-MD5_state MD5_from_string(const char* msg, const size_t msglen);
-MD5_state MD5_from_cstring(const char* msg);
-MD5_state MD5_from_FILE(FILE* in);
-
-
-/// Output in ASCII - with lowercase hex digits, null-terminated
-// these may overlap safely
-static void MD5_String (const char *string, char output[33]) __attribute__((deprecated));
-static inline void MD5_String (const char *string, char output[33]) {
-    MD5_to_str(MD5_from_cstring(string), output);
-}
-/// Output in binary
-static void MD5_String2binary (const char *string, uint8_t output[16]) __attribute__((deprecated));
-static inline void MD5_String2binary (const char *string, uint8_t output[16]) {
-    MD5_to_bin(MD5_from_cstring(string), output);
-}
-
-// statically-allocated output
-// whoever wrote this fails basic understanding of
-const char *MD5_saltcrypt(const char *key, const char *salt);
-
-/// return some random characters (statically allocated)
-// Currently, returns a 5-char string
-const char *make_salt(void);
-
-/// check plaintext password against saved saltcrypt
-bool pass_ok(const char *password, const char *crypted);
-
-/// This returns an in_addr_t because it is configurable whether it gets called at all
-in_addr_t MD5_ip(char *secret, in_addr_t ip);
-
-#endif
diff --git a/src/common/md5calc.hpp b/src/common/md5calc.hpp
new file mode 100644
index 0000000..1dde2ed
--- /dev/null
+++ b/src/common/md5calc.hpp
@@ -0,0 +1,64 @@
+#ifndef MD5CALC_HPP
+#define MD5CALC_HPP
+
+#include "sanity.hpp"
+
+#include <netinet/in.h>
+
+#include <stdint.h> // uint32_t, uint8_t
+#include <stddef.h> // size_t
+#include <stdio.h> // FILE*
+
+/// The digest state - becomes the output
+typedef struct
+{
+    // classically named {A,B,C,D}
+    // but use an so we can index
+    uint32_t val[4];
+} MD5_state;
+typedef struct
+{
+    uint32_t data[16];
+} MD5_block;
+
+// Implementation
+void MD5_init(MD5_state* state);
+void MD5_do_block(MD5_state* state, MD5_block block);
+
+// Output formatting
+void MD5_to_bin(MD5_state state, uint8_t out[0x10]);
+void MD5_to_str(MD5_state state, char out[0x21]);
+
+// Convenience
+MD5_state MD5_from_string(const char* msg, const size_t msglen);
+MD5_state MD5_from_cstring(const char* msg);
+MD5_state MD5_from_FILE(FILE* in);
+
+
+/// Output in ASCII - with lowercase hex digits, null-terminated
+// these may overlap safely
+static void MD5_String (const char *string, char output[33]) __attribute__((deprecated));
+static inline void MD5_String (const char *string, char output[33]) {
+    MD5_to_str(MD5_from_cstring(string), output);
+}
+/// Output in binary
+static void MD5_String2binary (const char *string, uint8_t output[16]) __attribute__((deprecated));
+static inline void MD5_String2binary (const char *string, uint8_t output[16]) {
+    MD5_to_bin(MD5_from_cstring(string), output);
+}
+
+// statically-allocated output
+// whoever wrote this fails basic understanding of
+const char *MD5_saltcrypt(const char *key, const char *salt);
+
+/// return some random characters (statically allocated)
+// Currently, returns a 5-char string
+const char *make_salt(void);
+
+/// check plaintext password against saved saltcrypt
+bool pass_ok(const char *password, const char *crypted);
+
+/// This returns an in_addr_t because it is configurable whether it gets called at all
+in_addr_t MD5_ip(char *secret, in_addr_t ip);
+
+#endif
diff --git a/src/common/mmo.h b/src/common/mmo.h
deleted file mode 100644
index 64e0523..0000000
--- a/src/common/mmo.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/// Global structures and defines
-#ifndef MMO_H
-#define MMO_H
-
-# include <time.h>
-# include "utils.h"              // LCCWIN32
-
-# define FIFOSIZE_SERVERLINK    256*1024
-
-// set to 0 to not check IP of player between each server.
-// set to another value if you want to check (1)
-# define CMP_AUTHFIFO_IP 1
-
-# define CMP_AUTHFIFO_LOGIN2 1
-
-# define MAX_MAP_PER_SERVER 512
-# define MAX_INVENTORY 100
-# define MAX_AMOUNT 30000
-# define MAX_ZENY 1000000000     // 1G zeny
-# define MAX_CART 100
-# define MAX_SKILL 450
-# define GLOBAL_REG_NUM 96
-# define ACCOUNT_REG_NUM 16
-# define ACCOUNT_REG2_NUM 16
-# define DEFAULT_WALK_SPEED 150
-# define MIN_WALK_SPEED 0
-# define MAX_WALK_SPEED 1000
-# define MAX_STORAGE 300
-# define MAX_GUILD_STORAGE 1000
-# define MAX_PARTY 12
-# define MAX_GUILD 120            // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW]
-# define MAX_GUILDPOSITION 20    // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
-# define MAX_GUILDEXPLUSION 32
-# define MAX_GUILDALLIANCE 16
-# define MAX_GUILDSKILL	8
-# define MAX_GUILDCASTLE 24      // increased to include novice castles [Valaris]
-# define MAX_GUILDLEVEL 50
-
-# define MIN_HAIR_STYLE battle_config.min_hair_style
-# define MAX_HAIR_STYLE battle_config.max_hair_style
-# define MIN_HAIR_COLOR battle_config.min_hair_color
-# define MAX_HAIR_COLOR battle_config.max_hair_color
-# define MIN_CLOTH_COLOR battle_config.min_cloth_color
-# define MAX_CLOTH_COLOR battle_config.max_cloth_color
-
-// for produce
-# define MIN_ATTRIBUTE 0
-# define MAX_ATTRIBUTE 4
-# define ATTRIBUTE_NORMAL 0
-# define MIN_STAR 0
-# define MAX_STAR 3
-
-# define MIN_PORTAL_MEMO 0
-# define MAX_PORTAL_MEMO 2
-
-# define MAX_STATUS_TYPE 5
-
-# define CHAR_CONF_NAME  "conf/char_athena.conf"
-
-struct item
-{
-    int  id;
-    short nameid;
-    short amount;
-    unsigned short equip;
-    char identify;
-    char refine;
-    char attribute;
-    short card[4];
-    short broken;
-};
-
-struct point
-{
-    char map[24];
-    short x, y;
-};
-
-struct skill
-{
-    unsigned short id, lv, flags;
-};
-
-struct global_reg
-{
-    char str[32];
-    int  value;
-};
-
-struct mmo_charstatus
-{
-    int  char_id;
-    int  account_id;
-    int  partner_id;
-
-    int  base_exp, job_exp, zeny;
-
-    short pc_class;
-    short status_point, skill_point;
-    int  hp, max_hp, sp, max_sp;
-    short option, karma, manner;
-    short hair, hair_color, clothes_color;
-    int  party_id, guild_id;
-
-    short weapon, shield;
-    short head_top, head_mid, head_bottom;
-
-    char name[24];
-    unsigned char base_level, job_level;
-    short str, agi, vit, int_, dex, luk;
-    unsigned char char_num, sex;
-
-    unsigned long mapip;
-    unsigned int mapport;
-
-    struct point last_point, save_point, memo_point[10];
-    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
-    struct skill skill[MAX_SKILL];
-    int  global_reg_num;
-    struct global_reg global_reg[GLOBAL_REG_NUM];
-    int  account_reg_num;
-    struct global_reg account_reg[ACCOUNT_REG_NUM];
-    int  account_reg2_num;
-    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
-};
-
-struct storage
-{
-    int  dirty;
-    int  account_id;
-    short storage_status;
-    short storage_amount;
-    struct item storage_[MAX_STORAGE];
-};
-
-struct guild_storage
-{
-    int  dirty;
-    int  guild_id;
-    short storage_status;
-    short storage_amount;
-    struct item storage_[MAX_GUILD_STORAGE];
-};
-
-struct map_session_data;
-
-struct gm_account
-{
-    int  account_id;
-    int  level;
-};
-
-struct party_member
-{
-    int  account_id;
-    char name[24], map[24];
-    int  leader, online, lv;
-    struct map_session_data *sd;
-};
-
-struct party
-{
-    int  party_id;
-    char name[24];
-    int  exp;
-    int  item;
-    struct party_member member[MAX_PARTY];
-};
-
-struct guild_member
-{
-    int  account_id, char_id;
-    short hair, hair_color, gender, pc_class, lv;
-    int  exp, exp_payper;
-    short online, position;
-    int  rsv1, rsv2;
-    char name[24];
-    struct map_session_data *sd;
-};
-
-struct guild_position
-{
-    char name[24];
-    int  mode;
-    int  exp_mode;
-};
-
-struct guild_alliance
-{
-    int  opposition;
-    int  guild_id;
-    char name[24];
-};
-
-struct guild_explusion
-{
-    char name[24];
-    char mes[40];
-    char acc[40];
-    int  account_id;
-    int  rsv1, rsv2, rsv3;
-};
-
-struct guild_skill
-{
-    int  id, lv;
-};
-
-struct guild
-{
-    int  guild_id;
-    short guild_lv, connect_member, max_member, average_lv;
-    int  exp, next_exp, skill_point, castle_id;
-    char name[24], master[24];
-    struct guild_member member[MAX_GUILD];
-    struct guild_position position[MAX_GUILDPOSITION];
-    char mes1[60], mes2[120];
-    int  emblem_len, emblem_id;
-    char emblem_data[2048];
-    struct guild_alliance alliance[MAX_GUILDALLIANCE];
-    struct guild_explusion explusion[MAX_GUILDEXPLUSION];
-    struct guild_skill skill[MAX_GUILDSKILL];
-};
-
-struct guild_castle
-{
-    int  castle_id;
-    char map_name[24];
-    char castle_name[24];
-    char castle_event[24];
-    int  guild_id;
-    int  economy;
-    int  defense;
-    int  triggerE;
-    int  triggerD;
-    int  nextTime;
-    int  payTime;
-    int  createTime;
-    int  visibleC;
-    int  visibleG0;
-    int  visibleG1;
-    int  visibleG2;
-    int  visibleG3;
-    int  visibleG4;
-    int  visibleG5;
-    int  visibleG6;
-    int  visibleG7;
-    int  Ghp0;                  // added Guardian HP [Valaris]
-    int  Ghp1;
-    int  Ghp2;
-    int  Ghp3;
-    int  Ghp4;
-    int  Ghp5;
-    int  Ghp6;
-    int  Ghp7;
-    int  GID0;
-    int  GID1;
-    int  GID2;
-    int  GID3;
-    int  GID4;
-    int  GID5;
-    int  GID6;
-    int  GID7;                  // end addition [Valaris]
-};
-struct square
-{
-    int  val1[5];
-    int  val2[5];
-};
-
-enum
-{
-    GBI_EXP = 1,                // ギルドのEXP
-    GBI_GUILDLV = 2,            // ギルドのLv
-    GBI_SKILLPOINT = 3,         // ギルドのスキルポイント
-    GBI_SKILLLV = 4,            // ギルドスキルLv
-
-    GMI_POSITION = 0,           // メンバーの役職変更
-    GMI_EXP = 1,                // メンバーのEXP
-
-};
-
-#endif // MMO_H
diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp
new file mode 100644
index 0000000..2ca93b0
--- /dev/null
+++ b/src/common/mmo.hpp
@@ -0,0 +1,283 @@
+/// Global structures and defines
+#ifndef MMO_HPP
+#define MMO_HPP
+
+# include <time.h>
+# include "utils.hpp"              // LCCWIN32
+
+# define FIFOSIZE_SERVERLINK    256*1024
+
+// set to 0 to not check IP of player between each server.
+// set to another value if you want to check (1)
+# define CMP_AUTHFIFO_IP 1
+
+# define CMP_AUTHFIFO_LOGIN2 1
+
+# define MAX_MAP_PER_SERVER 512
+# define MAX_INVENTORY 100
+# define MAX_AMOUNT 30000
+# define MAX_ZENY 1000000000     // 1G zeny
+# define MAX_CART 100
+# define MAX_SKILL 450
+# define GLOBAL_REG_NUM 96
+# define ACCOUNT_REG_NUM 16
+# define ACCOUNT_REG2_NUM 16
+# define DEFAULT_WALK_SPEED 150
+# define MIN_WALK_SPEED 0
+# define MAX_WALK_SPEED 1000
+# define MAX_STORAGE 300
+# define MAX_GUILD_STORAGE 1000
+# define MAX_PARTY 12
+# define MAX_GUILD 120            // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW]
+# define MAX_GUILDPOSITION 20    // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
+# define MAX_GUILDEXPLUSION 32
+# define MAX_GUILDALLIANCE 16
+# define MAX_GUILDSKILL	8
+# define MAX_GUILDCASTLE 24      // increased to include novice castles [Valaris]
+# define MAX_GUILDLEVEL 50
+
+# define MIN_HAIR_STYLE battle_config.min_hair_style
+# define MAX_HAIR_STYLE battle_config.max_hair_style
+# define MIN_HAIR_COLOR battle_config.min_hair_color
+# define MAX_HAIR_COLOR battle_config.max_hair_color
+# define MIN_CLOTH_COLOR battle_config.min_cloth_color
+# define MAX_CLOTH_COLOR battle_config.max_cloth_color
+
+// for produce
+# define MIN_ATTRIBUTE 0
+# define MAX_ATTRIBUTE 4
+# define ATTRIBUTE_NORMAL 0
+# define MIN_STAR 0
+# define MAX_STAR 3
+
+# define MIN_PORTAL_MEMO 0
+# define MAX_PORTAL_MEMO 2
+
+# define MAX_STATUS_TYPE 5
+
+# define CHAR_CONF_NAME  "conf/char_athena.conf"
+
+struct item
+{
+    int  id;
+    short nameid;
+    short amount;
+    unsigned short equip;
+    char identify;
+    char refine;
+    char attribute;
+    short card[4];
+    short broken;
+};
+
+struct point
+{
+    char map[24];
+    short x, y;
+};
+
+struct skill
+{
+    unsigned short id, lv, flags;
+};
+
+struct global_reg
+{
+    char str[32];
+    int  value;
+};
+
+struct mmo_charstatus
+{
+    int  char_id;
+    int  account_id;
+    int  partner_id;
+
+    int  base_exp, job_exp, zeny;
+
+    short pc_class;
+    short status_point, skill_point;
+    int  hp, max_hp, sp, max_sp;
+    short option, karma, manner;
+    short hair, hair_color, clothes_color;
+    int  party_id, guild_id;
+
+    short weapon, shield;
+    short head_top, head_mid, head_bottom;
+
+    char name[24];
+    unsigned char base_level, job_level;
+    short str, agi, vit, int_, dex, luk;
+    unsigned char char_num, sex;
+
+    unsigned long mapip;
+    unsigned int mapport;
+
+    struct point last_point, save_point, memo_point[10];
+    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
+    struct skill skill[MAX_SKILL];
+    int  global_reg_num;
+    struct global_reg global_reg[GLOBAL_REG_NUM];
+    int  account_reg_num;
+    struct global_reg account_reg[ACCOUNT_REG_NUM];
+    int  account_reg2_num;
+    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+};
+
+struct storage
+{
+    int  dirty;
+    int  account_id;
+    short storage_status;
+    short storage_amount;
+    struct item storage_[MAX_STORAGE];
+};
+
+struct guild_storage
+{
+    int  dirty;
+    int  guild_id;
+    short storage_status;
+    short storage_amount;
+    struct item storage_[MAX_GUILD_STORAGE];
+};
+
+struct map_session_data;
+
+struct gm_account
+{
+    int  account_id;
+    int  level;
+};
+
+struct party_member
+{
+    int  account_id;
+    char name[24], map[24];
+    int  leader, online, lv;
+    struct map_session_data *sd;
+};
+
+struct party
+{
+    int  party_id;
+    char name[24];
+    int  exp;
+    int  item;
+    struct party_member member[MAX_PARTY];
+};
+
+struct guild_member
+{
+    int  account_id, char_id;
+    short hair, hair_color, gender, pc_class, lv;
+    int  exp, exp_payper;
+    short online, position;
+    int  rsv1, rsv2;
+    char name[24];
+    struct map_session_data *sd;
+};
+
+struct guild_position
+{
+    char name[24];
+    int  mode;
+    int  exp_mode;
+};
+
+struct guild_alliance
+{
+    int  opposition;
+    int  guild_id;
+    char name[24];
+};
+
+struct guild_explusion
+{
+    char name[24];
+    char mes[40];
+    char acc[40];
+    int  account_id;
+    int  rsv1, rsv2, rsv3;
+};
+
+struct guild_skill
+{
+    int  id, lv;
+};
+
+struct guild
+{
+    int  guild_id;
+    short guild_lv, connect_member, max_member, average_lv;
+    int  exp, next_exp, skill_point, castle_id;
+    char name[24], master[24];
+    struct guild_member member[MAX_GUILD];
+    struct guild_position position[MAX_GUILDPOSITION];
+    char mes1[60], mes2[120];
+    int  emblem_len, emblem_id;
+    char emblem_data[2048];
+    struct guild_alliance alliance[MAX_GUILDALLIANCE];
+    struct guild_explusion explusion[MAX_GUILDEXPLUSION];
+    struct guild_skill skill[MAX_GUILDSKILL];
+};
+
+struct guild_castle
+{
+    int  castle_id;
+    char map_name[24];
+    char castle_name[24];
+    char castle_event[24];
+    int  guild_id;
+    int  economy;
+    int  defense;
+    int  triggerE;
+    int  triggerD;
+    int  nextTime;
+    int  payTime;
+    int  createTime;
+    int  visibleC;
+    int  visibleG0;
+    int  visibleG1;
+    int  visibleG2;
+    int  visibleG3;
+    int  visibleG4;
+    int  visibleG5;
+    int  visibleG6;
+    int  visibleG7;
+    int  Ghp0;                  // added Guardian HP [Valaris]
+    int  Ghp1;
+    int  Ghp2;
+    int  Ghp3;
+    int  Ghp4;
+    int  Ghp5;
+    int  Ghp6;
+    int  Ghp7;
+    int  GID0;
+    int  GID1;
+    int  GID2;
+    int  GID3;
+    int  GID4;
+    int  GID5;
+    int  GID6;
+    int  GID7;                  // end addition [Valaris]
+};
+struct square
+{
+    int  val1[5];
+    int  val2[5];
+};
+
+enum
+{
+    GBI_EXP = 1,                // ギルドのEXP
+    GBI_GUILDLV = 2,            // ギルドのLv
+    GBI_SKILLPOINT = 3,         // ギルドのスキルポイント
+    GBI_SKILLLV = 4,            // ギルドスキルLv
+
+    GMI_POSITION = 0,           // メンバーの役職変更
+    GMI_EXP = 1,                // メンバーのEXP
+
+};
+
+#endif // MMO_HPP
diff --git a/src/common/mt_rand.c b/src/common/mt_rand.c
deleted file mode 100644
index e4e8d12..0000000
--- a/src/common/mt_rand.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-// This is the ``Mersenne Twister'' random number generator MT19937, which
-// generates pseudorandom integers uniformly distributed in 0..(2^32 - 1)
-// starting from any odd seed in 0..(2^32 - 1).  This version is a recode
-// by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by
-// Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in
-// July-August 1997).
-//
-// Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha
-// running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to
-// generate 300 million random numbers; after recoding: 24.0 sec. for the same
-// (i.e., 46.5% of original time), so speed is now about 12.5 million random
-// number generations per second on this machine.
-//
-// According to the URL <http://www.math.keio.ac.jp/~matumoto/emt.html>
-// (and paraphrasing a bit in places), the Mersenne Twister is ``designed
-// with consideration of the flaws of various existing generators,'' has
-// a period of 2^19937 - 1, gives a sequence that is 623-dimensionally
-// equidistributed, and ``has passed many stringent tests, including the
-// die-hard test of G. Marsaglia and the load test of P. Hellekalek and
-// S. Wegenkittl.''  It is efficient in memory usage (typically using 2506
-// to 5012 bytes of static data, depending on data type sizes, and the code
-// is quite short as well).  It generates random numbers in batches of 624
-// at a time, so the caching and pipelining of modern systems is exploited.
-// It is also divide- and mod-free.
-//
-// This library is free software; you can redistribute it and/or modify it
-// under the terms of the GNU Library General Public License as published by
-// the Free Software Foundation (either version 2 of the License or, at your
-// option, any later version).  This library is distributed in the hope that
-// it will be useful, but WITHOUT ANY WARRANTY, without even the implied
-// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
-// the GNU Library General Public License for more details.  You should have
-// received a copy of the GNU Library General Public License along with this
-// library; if not, write to the Free Software Foundation, Inc., 59 Temple
-// Place, Suite 330, Boston, MA 02111-1307, USA.
-//
-// The code as Shawn received it included the following notice:
-//
-//   Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.  When
-//   you use this, send an e-mail to <matumoto@math.keio.ac.jp> with
-//   an appropriate reference to your work.
-//
-// It would be nice to CC: <Cokus@math.washington.edu> when you write.
-//
-*/
-
-#include <time.h>
-#include "mt_rand.h"
-
-#define N              624                  // length of state vector
-#define M              397                  // a period parameter
-#define K              0x9908B0DFU          // a magic constant
-
-#define hiBit(u)       ((u) & 0x80000000U)  // mask all but highest bit of u
-#define loBit(u)       ((u) & 0x00000001U)  // mask all but lowest bit of u
-#define loBits(u)      ((u) & 0x7FFFFFFFU)  // mask the highest bit of u
-#define mixBits(u, v)  (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
-
-static uint32_t state[N+1]; // state vector the +1 is needed due to the coding
-static uint32_t *next;      // next random value is computed from here
-static int left = -1;       // can *next++ this many times before reloading
-
-void mt_seed (uint32_t seed)
-{
-    uint32_t x = seed | 1U;
-    uint32_t *s = state;
-    left = 0;
-
-    for (int j = N; *s++ = x, --j; x *= 69069U);
-}
-
-void mt_reload (void)
-{
-    // if mt_seed has never been called
-    if (left < -1)
-        mt_seed (time (NULL));
-
-    // conceptually, these are indices into the state that wrap
-    uint32_t *p0 = state;
-    uint32_t *p2 = state + 2;
-    uint32_t *pM = state + M;
-
-    uint32_t s0 = state[0];
-    uint32_t s1 = state[1];
-
-    // regenerate the lower N-M elements of the state
-    for (int j = N-M+1; --j != 0; s0 = s1, s1 = *p2++)
-        *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
-
-    pM = state;
-    // regenerate the next M-1 elements of the state
-    // note that s1 is set to state[N] at the end, but discarded
-    for (int j = M; --j != 0; s0 = s1, s1 = *p2++)
-        *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
-
-    // regenerate the last 1 element of the state
-    s1 = state[0];
-    *p0 = *pM ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
-
-    // ready for the normal mt_random algorithm
-    left = N;
-    next = state;
-}
-
-uint32_t mt_random (void)
-{
-    if (--left < 0)
-        mt_reload ();
-
-    uint32_t y = *next++;
-    y ^= (y >> 11);
-    y ^= (y << 7) & 0x9D2C5680U;
-    y ^= (y << 15) & 0xEFC60000U;
-    return y ^ (y >> 18);
-}
diff --git a/src/common/mt_rand.cpp b/src/common/mt_rand.cpp
new file mode 100644
index 0000000..89872ad
--- /dev/null
+++ b/src/common/mt_rand.cpp
@@ -0,0 +1,116 @@
+/*
+// This is the ``Mersenne Twister'' random number generator MT19937, which
+// generates pseudorandom integers uniformly distributed in 0..(2^32 - 1)
+// starting from any odd seed in 0..(2^32 - 1).  This version is a recode
+// by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by
+// Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in
+// July-August 1997).
+//
+// Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha
+// running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to
+// generate 300 million random numbers; after recoding: 24.0 sec. for the same
+// (i.e., 46.5% of original time), so speed is now about 12.5 million random
+// number generations per second on this machine.
+//
+// According to the URL <http://www.math.keio.ac.jp/~matumoto/emt.html>
+// (and paraphrasing a bit in places), the Mersenne Twister is ``designed
+// with consideration of the flaws of various existing generators,'' has
+// a period of 2^19937 - 1, gives a sequence that is 623-dimensionally
+// equidistributed, and ``has passed many stringent tests, including the
+// die-hard test of G. Marsaglia and the load test of P. Hellekalek and
+// S. Wegenkittl.''  It is efficient in memory usage (typically using 2506
+// to 5012 bytes of static data, depending on data type sizes, and the code
+// is quite short as well).  It generates random numbers in batches of 624
+// at a time, so the caching and pipelining of modern systems is exploited.
+// It is also divide- and mod-free.
+//
+// This library is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Library General Public License as published by
+// the Free Software Foundation (either version 2 of the License or, at your
+// option, any later version).  This library is distributed in the hope that
+// it will be useful, but WITHOUT ANY WARRANTY, without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+// the GNU Library General Public License for more details.  You should have
+// received a copy of the GNU Library General Public License along with this
+// library; if not, write to the Free Software Foundation, Inc., 59 Temple
+// Place, Suite 330, Boston, MA 02111-1307, USA.
+//
+// The code as Shawn received it included the following notice:
+//
+//   Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.  When
+//   you use this, send an e-mail to <matumoto@math.keio.ac.jp> with
+//   an appropriate reference to your work.
+//
+// It would be nice to CC: <Cokus@math.washington.edu> when you write.
+//
+*/
+
+#include <time.h>
+#include "mt_rand.hpp"
+
+#define N              624                  // length of state vector
+#define M              397                  // a period parameter
+#define K              0x9908B0DFU          // a magic constant
+
+#define hiBit(u)       ((u) & 0x80000000U)  // mask all but highest bit of u
+#define loBit(u)       ((u) & 0x00000001U)  // mask all but lowest bit of u
+#define loBits(u)      ((u) & 0x7FFFFFFFU)  // mask the highest bit of u
+#define mixBits(u, v)  (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
+
+static uint32_t state[N+1]; // state vector the +1 is needed due to the coding
+static uint32_t *next;      // next random value is computed from here
+static int left = -1;       // can *next++ this many times before reloading
+
+void mt_seed (uint32_t seed)
+{
+    uint32_t x = seed | 1U;
+    uint32_t *s = state;
+    left = 0;
+
+    for (int j = N; *s++ = x, --j; x *= 69069U);
+}
+
+void mt_reload (void)
+{
+    // if mt_seed has never been called
+    if (left < -1)
+        mt_seed (time (NULL));
+
+    // conceptually, these are indices into the state that wrap
+    uint32_t *p0 = state;
+    uint32_t *p2 = state + 2;
+    uint32_t *pM = state + M;
+
+    uint32_t s0 = state[0];
+    uint32_t s1 = state[1];
+
+    // regenerate the lower N-M elements of the state
+    for (int j = N-M+1; --j != 0; s0 = s1, s1 = *p2++)
+        *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
+
+    pM = state;
+    // regenerate the next M-1 elements of the state
+    // note that s1 is set to state[N] at the end, but discarded
+    for (int j = M; --j != 0; s0 = s1, s1 = *p2++)
+        *p0++ = *pM++ ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
+
+    // regenerate the last 1 element of the state
+    s1 = state[0];
+    *p0 = *pM ^ (mixBits (s0, s1) >> 1) ^ (loBit (s1) ? K : 0U);
+
+    // ready for the normal mt_random algorithm
+    left = N;
+    next = state;
+}
+
+uint32_t mt_random (void)
+{
+    if (--left < 0)
+        mt_reload ();
+
+    uint32_t y = *next++;
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9D2C5680U;
+    y ^= (y << 15) & 0xEFC60000U;
+    return y ^ (y >> 18);
+}
diff --git a/src/common/mt_rand.h b/src/common/mt_rand.h
deleted file mode 100644
index 84d32e5..0000000
--- a/src/common/mt_rand.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef MT_RAND_H
-#define MT_RAND_H
-
-# include "sanity.h"
-
-/// Initialize the generator (called automatically with time() if you don't)
-void mt_seed (uint32_t seed);
-/// Get a random number
-uint32_t mt_random (void);
-
-/**
- * ModuloRand and ModuloPlusRand
- * These macros are used to replace the vast number of calls to rand()%mod
- * TODO eliminate the rest of the calls to rand()
- * MRAND(10)    returns 0..9
- * MPRAND(5,10) returns 5..14
- */
-// The cast is essential because the result is sometimes
-// compared with a possibly negative number.
-// Because it's using modulus, high numbers shouldn't happen anyway.
-# define MRAND(mod) ((int)(mt_random() % (mod)))
-# define MPRAND(add, mod) ((add) + MRAND(mod))
-
-#endif // MT_RAND_H
diff --git a/src/common/mt_rand.hpp b/src/common/mt_rand.hpp
new file mode 100644
index 0000000..c7bae4e
--- /dev/null
+++ b/src/common/mt_rand.hpp
@@ -0,0 +1,24 @@
+#ifndef MT_RAND_HPP
+#define MT_RAND_HPP
+
+# include "sanity.hpp"
+
+/// Initialize the generator (called automatically with time() if you don't)
+void mt_seed (uint32_t seed);
+/// Get a random number
+uint32_t mt_random (void);
+
+/**
+ * ModuloRand and ModuloPlusRand
+ * These macros are used to replace the vast number of calls to rand()%mod
+ * TODO eliminate the rest of the calls to rand()
+ * MRAND(10)    returns 0..9
+ * MPRAND(5,10) returns 5..14
+ */
+// The cast is essential because the result is sometimes
+// compared with a possibly negative number.
+// Because it's using modulus, high numbers shouldn't happen anyway.
+# define MRAND(mod) ((int)(mt_random() % (mod)))
+# define MPRAND(add, mod) ((add) + MRAND(mod))
+
+#endif // MT_RAND_HPP
diff --git a/src/common/nullpo.c b/src/common/nullpo.c
deleted file mode 100644
index 8c7c405..0000000
--- a/src/common/nullpo.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include "nullpo.h"
-
-static void nullpo_info_core (const char *file, int line, const char *func,
-                              const char *fmt, va_list ap);
-
-/// Null check and print format
-bool nullpo_chk_f (const char *file, int line, const char *func,
-                   const void *target, const char *fmt, ...)
-{
-    va_list ap;
-
-    if (target)
-        return 0;
-
-    va_start (ap, fmt);
-    nullpo_info_core (file, line, func, fmt, ap);
-    va_end (ap);
-    return 1;
-}
-bool nullpo_chk (const char *file, int line, const char *func,
-                 const void *target)
-{
-    if (target)
-        return 0;
-
-    nullpo_info_core (file, line, func, NULL, NULL);
-    return 1;
-}
-
-/// External functions
-void nullpo_info_f (const char *file, int line, const char *func,
-                    const char *fmt, ...)
-{
-    va_list ap;
-
-    va_start (ap, fmt);
-    nullpo_info_core (file, line, func, fmt, ap);
-    va_end (ap);
-}
-void nullpo_info (const char *file, int line, const char *func)
-{
-    nullpo_info_core (file, line, func, NULL, NULL);
-}
-
-/// Actual output function
-static void nullpo_info_core (const char *file, int line, const char *func,
-                              const char *fmt, va_list ap) __attribute__((format(printf, 4, 0)));
-static void nullpo_info_core (const char *file, int line, const char *func,
-                              const char *fmt, va_list ap)
-{
-    if (!file)
-        file = "??";
-    if (!func || !*func)
-        func = "unknown";
-
-    fprintf (stderr, "%s:%d: in func `%s': NULL pointer\n", file, line, func);
-    if (fmt && *fmt)
-    {
-        vfprintf (stderr, fmt, ap);
-        if (fmt[strlen (fmt) - 1] != '\n')
-            fputc('\n', stderr);
-    }
-}
diff --git a/src/common/nullpo.cpp b/src/common/nullpo.cpp
new file mode 100644
index 0000000..6dd2736
--- /dev/null
+++ b/src/common/nullpo.cpp
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "nullpo.hpp"
+
+static void nullpo_info_core (const char *file, int line, const char *func,
+                              const char *fmt, va_list ap);
+
+/// Null check and print format
+bool nullpo_chk_f (const char *file, int line, const char *func,
+                   const void *target, const char *fmt, ...)
+{
+    va_list ap;
+
+    if (target)
+        return 0;
+
+    va_start (ap, fmt);
+    nullpo_info_core (file, line, func, fmt, ap);
+    va_end (ap);
+    return 1;
+}
+bool nullpo_chk (const char *file, int line, const char *func,
+                 const void *target)
+{
+    if (target)
+        return 0;
+
+    nullpo_info_core (file, line, func, NULL, NULL);
+    return 1;
+}
+
+/// External functions
+void nullpo_info_f (const char *file, int line, const char *func,
+                    const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start (ap, fmt);
+    nullpo_info_core (file, line, func, fmt, ap);
+    va_end (ap);
+}
+void nullpo_info (const char *file, int line, const char *func)
+{
+    nullpo_info_core (file, line, func, NULL, NULL);
+}
+
+/// Actual output function
+static void nullpo_info_core (const char *file, int line, const char *func,
+                              const char *fmt, va_list ap) __attribute__((format(printf, 4, 0)));
+static void nullpo_info_core (const char *file, int line, const char *func,
+                              const char *fmt, va_list ap)
+{
+    if (!file)
+        file = "??";
+    if (!func || !*func)
+        func = "unknown";
+
+    fprintf (stderr, "%s:%d: in func `%s': NULL pointer\n", file, line, func);
+    if (fmt && *fmt)
+    {
+        vfprintf (stderr, fmt, ap);
+        if (fmt[strlen (fmt) - 1] != '\n')
+            fputc('\n', stderr);
+    }
+}
diff --git a/src/common/nullpo.h b/src/common/nullpo.h
deleted file mode 100644
index 9b33b4b..0000000
--- a/src/common/nullpo.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/// return wrappers for unexpected NULL pointers
-#ifndef NULLPO_H
-#define NULLPO_H
-/// Comment this out to live dangerously
-# define NULLPO_CHECK
-
-/// All functions print to standard error (was: standard output)
-/// nullpo_ret(cond) - return 0 if given pointer is NULL
-/// nullpo_retv(cond) - just return (function returns void)
-/// nullpo_retr(rv, cond) - return given value instead
-/// the _f variants take a printf-format string and arguments
-
-# ifdef NULLPO_CHECK
-# define NLP_MARK __FILE__, __LINE__, __func__
-#  define nullpo_ret(t) \
-    if (nullpo_chk(NLP_MARK, t)) \
-        return 0;
-#  define nullpo_retv(t) \
-    if (nullpo_chk(NLP_MARK, t)) \
-        return;
-#  define nullpo_retr(ret, t) \
-    if (nullpo_chk(NLP_MARK, t)) \
-        return ret;
-#  define nullpo_ret_f(t, fmt, ...) \
-    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
-        return 0;
-#  define nullpo_retv_f(t, fmt, ...) \
-    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
-        return;
-#  define nullpo_retr_f(ret, t, fmt, ...) \
-    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
-        return ret;
-# else // NULLPO_CHECK
-#  define nullpo_ret(t) t;
-#  define nullpo_retv(t) t;
-#  define nullpo_retr(ret, t) t;
-#  define nullpo_ret_f(t, fmt, ...) t;
-#  define nullpo_retv_f(t, fmt, ...) t;
-#  define nullpo_retr_f(ret, t, fmt, ...) t;
-# endif // NULLPO_CHECK
-
-# include "sanity.h"
-
-/// Used by macros in this header
-bool nullpo_chk (const char *file, int line, const char *func,
-                 const void *target);
-
-/// Used by macros in this header
-bool nullpo_chk_f (const char *file, int line, const char *func,
-                   const void *target, const char *fmt, ...)
-    __attribute__ ((format (printf, 5, 6)));
-
-/// Used only by map/battle.c
-void nullpo_info (const char *file, int line, const char *func);
-
-/// Not used
-void nullpo_info_f (const char *file, int line, const char *func,
-                    const char *fmt, ...)
-    __attribute__ ((format (printf, 4, 5)));
-
-#endif // NULLPO_H
diff --git a/src/common/nullpo.hpp b/src/common/nullpo.hpp
new file mode 100644
index 0000000..7aff691
--- /dev/null
+++ b/src/common/nullpo.hpp
@@ -0,0 +1,61 @@
+/// return wrappers for unexpected NULL pointers
+#ifndef NULLPO_HPP
+#define NULLPO_HPP
+/// Comment this out to live dangerously
+# define NULLPO_CHECK
+
+/// All functions print to standard error (was: standard output)
+/// nullpo_ret(cond) - return 0 if given pointer is NULL
+/// nullpo_retv(cond) - just return (function returns void)
+/// nullpo_retr(rv, cond) - return given value instead
+/// the _f variants take a printf-format string and arguments
+
+# ifdef NULLPO_CHECK
+# define NLP_MARK __FILE__, __LINE__, __func__
+#  define nullpo_ret(t) \
+    if (nullpo_chk(NLP_MARK, t)) \
+        return 0;
+#  define nullpo_retv(t) \
+    if (nullpo_chk(NLP_MARK, t)) \
+        return;
+#  define nullpo_retr(ret, t) \
+    if (nullpo_chk(NLP_MARK, t)) \
+        return ret;
+#  define nullpo_ret_f(t, fmt, ...) \
+    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
+        return 0;
+#  define nullpo_retv_f(t, fmt, ...) \
+    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
+        return;
+#  define nullpo_retr_f(ret, t, fmt, ...) \
+    if (nullpo_chk_f(NLP_MARK, t, fmt, ##__VA_ARGS__)) \
+        return ret;
+# else // NULLPO_CHECK
+#  define nullpo_ret(t) t;
+#  define nullpo_retv(t) t;
+#  define nullpo_retr(ret, t) t;
+#  define nullpo_ret_f(t, fmt, ...) t;
+#  define nullpo_retv_f(t, fmt, ...) t;
+#  define nullpo_retr_f(ret, t, fmt, ...) t;
+# endif // NULLPO_CHECK
+
+# include "sanity.hpp"
+
+/// Used by macros in this header
+bool nullpo_chk (const char *file, int line, const char *func,
+                 const void *target);
+
+/// Used by macros in this header
+bool nullpo_chk_f (const char *file, int line, const char *func,
+                   const void *target, const char *fmt, ...)
+    __attribute__ ((format (printf, 5, 6)));
+
+/// Used only by map/battle.c
+void nullpo_info (const char *file, int line, const char *func);
+
+/// Not used
+void nullpo_info_f (const char *file, int line, const char *func,
+                    const char *fmt, ...)
+    __attribute__ ((format (printf, 4, 5)));
+
+#endif // NULLPO_HPP
diff --git a/src/common/sanity.h b/src/common/sanity.h
deleted file mode 100644
index 168671f..0000000
--- a/src/common/sanity.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/// return wrappers for unexpected NULL pointers
-#ifndef SANITY_H
-#define SANITY_H
-# if __STDC_VERSION__ < 199901L
-#  error "Please compile in C99 mode"
-# endif
-# if __GNUC__ < 3
-// I don't specifically know what version this requires,
-// but GCC 3 was the beginning of modern GCC
-#  error "Please upgrade your compiler to at least GCC 3"
-# endif
-# ifndef __i386__
-// Known platform dependencies:
-// endianness for the [RW]FIFO.* macros
-// possibly, some signal-handling
-#  error "Unsupported platform"
-# endif
-# ifdef __x86_64__
-// I'm working on it - I know there are some pointer-size assumptions.
-#  error "Sorry, this code is believed not to be 64-bit safe"
-#  error "please compile with -m32"
-# endif
-
-/// A name for unused function arguments - can be repeated
-# define UNUSED UNUSED_IMPL(__COUNTER__)
-// Don't you just love the hoops the preprocessor makes you go through?
-#  define UNUSED_IMPL(arg) UNUSED_IMPL2(arg)
-#  define UNUSED_IMPL2(suffix) unused_ ## suffix __attribute__((unused))
-/// Convert conditions to use the bool type
-# include <stdbool.h>
-/// Convert type assumptions to use the standard types here
-# include <stdint.h>
-/// size_t, NULL
-# include <stddef.h>
-
-#endif // SANITY_H
diff --git a/src/common/sanity.hpp b/src/common/sanity.hpp
new file mode 100644
index 0000000..7ffd077
--- /dev/null
+++ b/src/common/sanity.hpp
@@ -0,0 +1,31 @@
+/// return wrappers for unexpected NULL pointers
+#ifndef SANITY_HPP
+#define SANITY_HPP
+# ifndef __cplusplus
+#  error "Please compile in C++ mode"
+# endif
+# if __GNUC__ < 3
+// I don't specifically know what version this requires,
+// but GCC 3 was the beginning of modern GCC
+#  error "Please upgrade your compiler to at least GCC 3"
+# endif
+# ifndef __i386__
+// Known platform dependencies:
+// endianness for the [RW]FIFO.* macros
+// possibly, some signal-handling
+#  error "Unsupported platform"
+# endif
+# ifdef __x86_64__
+// I'm working on it - I know there are some pointer-size assumptions.
+#  error "Sorry, this code is believed not to be 64-bit safe"
+#  error "please compile with -m32"
+# endif
+
+/// A name for unused function arguments - can be repeated
+# define UNUSED /* empty works for C++ */
+/// Convert type assumptions to use the standard types here
+# include <cstdint>
+/// size_t, NULL
+# include <cstddef>
+
+#endif // SANITY_HPP
diff --git a/src/common/socket.c b/src/common/socket.c
deleted file mode 100644
index 67a5102..0000000
--- a/src/common/socket.c
+++ /dev/null
@@ -1,405 +0,0 @@
-// $Id: socket.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
-// original : core.c 2003/02/26 18:03:12 Rev 1.7
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include <fcntl.h>
-#include <string.h>
-
-#include "mmo.h"                // [Valaris] thanks to fov
-#include "socket.h"
-#include "utils.h"
-
-fd_set readfds;
-int  fd_max;
-int  currentuse;
-
-const uint32_t RFIFO_SIZE = 65536;
-const uint32_t WFIFO_SIZE = 65536;
-
-struct socket_data *session[FD_SETSIZE];
-
-/// Discard all input
-static void null_parse (int fd);
-/// Default parser for new connections
-static void (*default_func_parse) (int) = null_parse;
-
-void set_defaultparse (void (*defaultparse) (int))
-{
-    default_func_parse = defaultparse;
-}
-
-/// Read from socket to the queue
-static void recv_to_fifo (int fd)
-{
-    if (session[fd]->eof)
-        return;
-
-    ssize_t len = read (fd, session[fd]->rdata + session[fd]->rdata_size,
-                        RFIFOSPACE (fd));
-
-    if (len > 0)
-    {
-        session[fd]->rdata_size += len;
-        session[fd]->connected = 1;
-    }
-    else
-    {
-        session[fd]->eof = 1;
-    }
-}
-
-static void send_from_fifo (int fd)
-{
-    if (session[fd]->eof)
-        return;
-
-    ssize_t len = write (fd, session[fd]->wdata, session[fd]->wdata_size);
-
-    if (len > 0)
-    {
-        session[fd]->wdata_size -= len;
-        if (len < (ssize_t)session[fd]->wdata_size)
-        {
-            memmove (session[fd]->wdata, session[fd]->wdata + len,
-                     session[fd]->wdata_size);
-        }
-        session[fd]->connected = 1;
-    }
-    else
-    {
-        session[fd]->eof = 1;
-    }
-}
-
-static void null_parse (int fd)
-{
-    printf ("null_parse : %d\n", fd);
-    RFIFOSKIP (fd, RFIFOREST (fd));
-}
-
-
-static void connect_client (int listen_fd)
-{
-    struct sockaddr_in client_address;
-    socklen_t len = sizeof (client_address);
-
-    int fd = accept (listen_fd, (struct sockaddr *) &client_address, &len);
-    if (fd == -1)
-    {
-        perror ("accept");
-        return;
-    }
-    if (fd_max <= fd)
-    {
-        fd_max = fd + 1;
-    }
-    if (!free_fds ())
-    {
-        fprintf (stderr, "softlimit reached, disconnecting : %d\n", fd);
-        delete_session (fd);
-        return;
-    }
-
-    const int yes = 1;
-    /// Allow to bind() again after the server restarts.
-    // Since the socket is still in the TIME_WAIT, there's a possibility
-    // that formerly lost packets might be delivered and confuse the server.
-    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
-    /// Send packets as soon as possible
-    /// even if the kernel thinks there is too little for it to be worth it!
-    // I'm not convinced this is a good idea; although in minimizes the
-    // latency for an individual write, it increases traffic in general.
-    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
-
-    FD_SET (fd, &readfds);
-
-    fcntl (fd, F_SETFL, O_NONBLOCK);
-
-    CREATE (session[fd], struct socket_data, 1);
-    CREATE (session[fd]->rdata, uint8_t, RFIFO_SIZE);
-    CREATE (session[fd]->wdata, uint8_t, WFIFO_SIZE);
-
-    session[fd]->max_rdata = RFIFO_SIZE;
-    session[fd]->max_wdata = WFIFO_SIZE;
-    session[fd]->func_recv = recv_to_fifo;
-    session[fd]->func_send = send_from_fifo;
-    session[fd]->func_parse = default_func_parse;
-    session[fd]->client_addr = client_address;
-    session[fd]->created = time (NULL);
-    session[fd]->connected = 0;
-
-    currentuse++;
-}
-
-int make_listen_port (uint16_t port)
-{
-    struct sockaddr_in server_address;
-    int  fd = socket (AF_INET, SOCK_STREAM, 0);
-    if (fd == -1)
-    {
-        perror ("socket");
-        return -1;
-    }
-    if (fd_max <= fd)
-        fd_max = fd + 1;
-
-    fcntl (fd, F_SETFL, O_NONBLOCK);
-
-    const int yes = 1;
-    /// Allow to bind() again after the server restarts.
-    // Since the socket is still in the TIME_WAIT, there's a possibility
-    // that formerly lost packets might be delivered and confuse the server.
-    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
-    /// Send packets as soon as possible
-    /// even if the kernel thinks there is too little for it to be worth it!
-    // I'm not convinced this is a good idea; although in minimizes the
-    // latency for an individual write, it increases traffic in general.
-    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
-
-    server_address.sin_family = AF_INET;
-    server_address.sin_addr.s_addr = htonl (INADDR_ANY);
-    server_address.sin_port = htons (port);
-
-    if (bind (fd, (struct sockaddr *) &server_address,
-              sizeof (server_address)) == -1)
-    {
-        perror ("bind");
-        exit (1);
-    }
-    if (listen (fd, 5) == -1)
-    {                           /* error */
-        perror ("listen");
-        exit (1);
-    }
-
-    FD_SET (fd, &readfds);
-
-    CREATE (session[fd], struct socket_data, 1);
-
-    session[fd]->func_recv = connect_client;
-    session[fd]->created = time (NULL);
-    session[fd]->connected = 1;
-
-    currentuse++;
-    return fd;
-}
-
-int make_connection (uint32_t ip, uint16_t port)
-{
-    struct sockaddr_in server_address;
-    int  fd = socket (AF_INET, SOCK_STREAM, 0);
-    if (fd == -1)
-    {
-        perror ("socket");
-        return -1;
-    }
-    if (fd_max <= fd)
-        fd_max = fd + 1;
-
-    const int yes = 1;
-    /// Allow to bind() again after the server restarts.
-    // Since the socket is still in the TIME_WAIT, there's a possibility
-    // that formerly lost packets might be delivered and confuse the server.
-    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
-    /// Send packets as soon as possible
-    /// even if the kernel thinks there is too little for it to be worth it!
-    // I'm not convinced this is a good idea; although in minimizes the
-    // latency for an individual write, it increases traffic in general.
-    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
-
-    server_address.sin_family = AF_INET;
-    server_address.sin_addr.s_addr = ip;
-    server_address.sin_port = htons (port);
-
-    fcntl (fd, F_SETFL, O_NONBLOCK);
-
-    /// Errors not caught - we must not block
-    /// Let the main select() loop detect when we know the state
-    connect (fd, (struct sockaddr *) &server_address,
-             sizeof (struct sockaddr_in));
-
-    FD_SET (fd, &readfds);
-
-    CREATE (session[fd], struct socket_data, 1);
-    CREATE (session[fd]->rdata, uint8_t, RFIFO_SIZE);
-    CREATE (session[fd]->wdata, uint8_t, WFIFO_SIZE);
-
-    session[fd]->max_rdata = RFIFO_SIZE;
-    session[fd]->max_wdata = WFIFO_SIZE;
-    session[fd]->func_recv = recv_to_fifo;
-    session[fd]->func_send = send_from_fifo;
-    session[fd]->func_parse = default_func_parse;
-    session[fd]->created = time (NULL);
-    session[fd]->connected = 1;
-
-    currentuse++;
-    return fd;
-}
-
-void delete_session (int fd)
-{
-    if (fd < 0 || fd >= FD_SETSIZE)
-        return;
-    // If this was the highest fd, decrease it
-    // We could add a loop to decrement fd_max further for every null session,
-    // but this is cheap and good enough for the typical case
-    if (fd == fd_max - 1)
-        fd_max--;
-    FD_CLR (fd, &readfds);
-    if (session[fd])
-    {
-        free (session[fd]->rdata);
-        free (session[fd]->wdata);
-        free (session[fd]->session_data);
-        free (session[fd]);
-    }
-    session[fd] = NULL;
-
-    // just close() would try to keep sending buffers
-    shutdown (fd, SHUT_RDWR);
-    close (fd);
-    currentuse--;
-    if (currentuse < 0)
-    {
-        fprintf (stderr, "delete_session: current sessions negative!\n");
-        currentuse = 0;
-    }
-    return;
-}
-
-void realloc_fifo (int fd, size_t rfifo_size, size_t wfifo_size)
-{
-    struct socket_data *s = session[fd];
-    if (s->max_rdata != rfifo_size && s->rdata_size < rfifo_size)
-    {
-        RECREATE (s->rdata, uint8_t, rfifo_size);
-        s->max_rdata = rfifo_size;
-    }
-    if (s->max_wdata != wfifo_size && s->wdata_size < wfifo_size)
-    {
-        RECREATE (s->wdata, uint8_t, wfifo_size);
-        s->max_wdata = wfifo_size;
-    }
-}
-
-void WFIFOSET (int fd, size_t len)
-{
-    struct socket_data *s = session[fd];
-    if (s->wdata_size + len + 16384 > s->max_wdata)
-    {
-        realloc_fifo (fd, s->max_rdata, s->max_wdata << 1);
-        printf ("socket: %d wdata expanded to %d bytes.\n", fd, s->max_wdata);
-    }
-    if (s->wdata_size + len + 2048 < s->max_wdata)
-        s->wdata_size += len;
-    else
-        fprintf (stderr, "socket: %d wdata lost !!\n", fd), abort ();
-}
-
-void do_sendrecv (uint32_t next)
-{
-    fd_set rfd = readfds, wfd;
-    FD_ZERO (&wfd);
-    for (int i = 0; i < fd_max; i++)
-    {
-        if (session[i] && session[i]->wdata_size)
-            FD_SET (i, &wfd);
-    }
-    struct timeval timeout;
-    timeout.tv_sec = next / 1000;
-    timeout.tv_usec = next % 1000 * 1000;
-    if (select (fd_max, &rfd, &wfd, NULL, &timeout) <= 0)
-        return;
-    for (int i = 0; i < fd_max; i++)
-    {
-        if (!session[i])
-            continue;
-        if (FD_ISSET (i, &wfd))
-        {
-            if (session[i]->func_send)
-                //send_from_fifo(i);
-                session[i]->func_send (i);
-        }
-        if (FD_ISSET (i, &rfd))
-        {
-            if (session[i]->func_recv)
-                //recv_to_fifo(i);
-                //or connect_client(i);
-                session[i]->func_recv (i);
-        }
-    }
-}
-
-void do_parsepacket (void)
-{
-    for (int i = 0; i < fd_max; i++)
-    {
-        if (!session[i])
-            continue;
-        if (!session[i]->connected
-            && time (NULL) - session[i]->created > CONNECT_TIMEOUT)
-        {
-            printf ("Session #%d timed out\n", i);
-            session[i]->eof = 1;
-        }
-        if (!session[i]->rdata_size && !session[i]->eof)
-            continue;
-        if (session[i]->func_parse)
-        {
-            session[i]->func_parse (i);
-            /// some func_parse may call delete_session
-            if (!session[i])
-                continue;
-        }
-        /// Reclaim buffer space for what was read
-        RFIFOFLUSH (i);
-    }
-}
-
-void do_socket (void)
-{
-    FD_ZERO (&readfds);
-    currentuse = 3;
-}
-
-void RFIFOSKIP (int fd, size_t len)
-{
-    struct socket_data *s = session[fd];
-    s->rdata_pos += len;
-
-    if (s->rdata_size < s->rdata_pos)
-    {
-        fprintf (stderr, "too many skip\n");
-        abort ();
-    }
-}
-
-void fclose_ (FILE * fp)
-{
-    if (fclose (fp))
-        perror ("fclose"), abort ();
-    currentuse--;
-}
-
-FILE *fopen_ (const char *path, const char *mode)
-{
-    FILE *f = fopen (path, mode);
-    if (f)
-        currentuse++;
-    return f;
-}
-
-bool free_fds (void)
-{
-    return currentuse < SOFT_LIMIT;
-}
diff --git a/src/common/socket.cpp b/src/common/socket.cpp
new file mode 100644
index 0000000..cc6e4b3
--- /dev/null
+++ b/src/common/socket.cpp
@@ -0,0 +1,405 @@
+// $Id: socket.c,v 1.1.1.1 2004/09/10 17:44:49 MagicalTux Exp $
+// original : core.c 2003/02/26 18:03:12 Rev 1.7
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+#include "mmo.hpp"                // [Valaris] thanks to fov
+#include "socket.hpp"
+#include "utils.hpp"
+
+fd_set readfds;
+int  fd_max;
+int  currentuse;
+
+const uint32_t RFIFO_SIZE = 65536;
+const uint32_t WFIFO_SIZE = 65536;
+
+struct socket_data *session[FD_SETSIZE];
+
+/// Discard all input
+static void null_parse (int fd);
+/// Default parser for new connections
+static void (*default_func_parse) (int) = null_parse;
+
+void set_defaultparse (void (*defaultparse) (int))
+{
+    default_func_parse = defaultparse;
+}
+
+/// Read from socket to the queue
+static void recv_to_fifo (int fd)
+{
+    if (session[fd]->eof)
+        return;
+
+    ssize_t len = read (fd, session[fd]->rdata + session[fd]->rdata_size,
+                        RFIFOSPACE (fd));
+
+    if (len > 0)
+    {
+        session[fd]->rdata_size += len;
+        session[fd]->connected = 1;
+    }
+    else
+    {
+        session[fd]->eof = 1;
+    }
+}
+
+static void send_from_fifo (int fd)
+{
+    if (session[fd]->eof)
+        return;
+
+    ssize_t len = write (fd, session[fd]->wdata, session[fd]->wdata_size);
+
+    if (len > 0)
+    {
+        session[fd]->wdata_size -= len;
+        if (len < (ssize_t)session[fd]->wdata_size)
+        {
+            memmove (session[fd]->wdata, session[fd]->wdata + len,
+                     session[fd]->wdata_size);
+        }
+        session[fd]->connected = 1;
+    }
+    else
+    {
+        session[fd]->eof = 1;
+    }
+}
+
+static void null_parse (int fd)
+{
+    printf ("null_parse : %d\n", fd);
+    RFIFOSKIP (fd, RFIFOREST (fd));
+}
+
+
+static void connect_client (int listen_fd)
+{
+    struct sockaddr_in client_address;
+    socklen_t len = sizeof (client_address);
+
+    int fd = accept (listen_fd, (struct sockaddr *) &client_address, &len);
+    if (fd == -1)
+    {
+        perror ("accept");
+        return;
+    }
+    if (fd_max <= fd)
+    {
+        fd_max = fd + 1;
+    }
+    if (!free_fds ())
+    {
+        fprintf (stderr, "softlimit reached, disconnecting : %d\n", fd);
+        delete_session (fd);
+        return;
+    }
+
+    const int yes = 1;
+    /// Allow to bind() again after the server restarts.
+    // Since the socket is still in the TIME_WAIT, there's a possibility
+    // that formerly lost packets might be delivered and confuse the server.
+    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+    /// Send packets as soon as possible
+    /// even if the kernel thinks there is too little for it to be worth it!
+    // I'm not convinced this is a good idea; although in minimizes the
+    // latency for an individual write, it increases traffic in general.
+    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+
+    FD_SET (fd, &readfds);
+
+    fcntl (fd, F_SETFL, O_NONBLOCK);
+
+    CREATE (session[fd], struct socket_data, 1);
+    CREATE (session[fd]->rdata, uint8_t, RFIFO_SIZE);
+    CREATE (session[fd]->wdata, uint8_t, WFIFO_SIZE);
+
+    session[fd]->max_rdata = RFIFO_SIZE;
+    session[fd]->max_wdata = WFIFO_SIZE;
+    session[fd]->func_recv = recv_to_fifo;
+    session[fd]->func_send = send_from_fifo;
+    session[fd]->func_parse = default_func_parse;
+    session[fd]->client_addr = client_address;
+    session[fd]->created = time (NULL);
+    session[fd]->connected = 0;
+
+    currentuse++;
+}
+
+int make_listen_port (uint16_t port)
+{
+    struct sockaddr_in server_address;
+    int  fd = socket (AF_INET, SOCK_STREAM, 0);
+    if (fd == -1)
+    {
+        perror ("socket");
+        return -1;
+    }
+    if (fd_max <= fd)
+        fd_max = fd + 1;
+
+    fcntl (fd, F_SETFL, O_NONBLOCK);
+
+    const int yes = 1;
+    /// Allow to bind() again after the server restarts.
+    // Since the socket is still in the TIME_WAIT, there's a possibility
+    // that formerly lost packets might be delivered and confuse the server.
+    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+    /// Send packets as soon as possible
+    /// even if the kernel thinks there is too little for it to be worth it!
+    // I'm not convinced this is a good idea; although in minimizes the
+    // latency for an individual write, it increases traffic in general.
+    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+
+    server_address.sin_family = AF_INET;
+    server_address.sin_addr.s_addr = htonl (INADDR_ANY);
+    server_address.sin_port = htons (port);
+
+    if (bind (fd, (struct sockaddr *) &server_address,
+              sizeof (server_address)) == -1)
+    {
+        perror ("bind");
+        exit (1);
+    }
+    if (listen (fd, 5) == -1)
+    {                           /* error */
+        perror ("listen");
+        exit (1);
+    }
+
+    FD_SET (fd, &readfds);
+
+    CREATE (session[fd], struct socket_data, 1);
+
+    session[fd]->func_recv = connect_client;
+    session[fd]->created = time (NULL);
+    session[fd]->connected = 1;
+
+    currentuse++;
+    return fd;
+}
+
+int make_connection (uint32_t ip, uint16_t port)
+{
+    struct sockaddr_in server_address;
+    int  fd = socket (AF_INET, SOCK_STREAM, 0);
+    if (fd == -1)
+    {
+        perror ("socket");
+        return -1;
+    }
+    if (fd_max <= fd)
+        fd_max = fd + 1;
+
+    const int yes = 1;
+    /// Allow to bind() again after the server restarts.
+    // Since the socket is still in the TIME_WAIT, there's a possibility
+    // that formerly lost packets might be delivered and confuse the server.
+    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+    /// Send packets as soon as possible
+    /// even if the kernel thinks there is too little for it to be worth it!
+    // I'm not convinced this is a good idea; although in minimizes the
+    // latency for an individual write, it increases traffic in general.
+    setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+
+    server_address.sin_family = AF_INET;
+    server_address.sin_addr.s_addr = ip;
+    server_address.sin_port = htons (port);
+
+    fcntl (fd, F_SETFL, O_NONBLOCK);
+
+    /// Errors not caught - we must not block
+    /// Let the main select() loop detect when we know the state
+    connect (fd, (struct sockaddr *) &server_address,
+             sizeof (struct sockaddr_in));
+
+    FD_SET (fd, &readfds);
+
+    CREATE (session[fd], struct socket_data, 1);
+    CREATE (session[fd]->rdata, uint8_t, RFIFO_SIZE);
+    CREATE (session[fd]->wdata, uint8_t, WFIFO_SIZE);
+
+    session[fd]->max_rdata = RFIFO_SIZE;
+    session[fd]->max_wdata = WFIFO_SIZE;
+    session[fd]->func_recv = recv_to_fifo;
+    session[fd]->func_send = send_from_fifo;
+    session[fd]->func_parse = default_func_parse;
+    session[fd]->created = time (NULL);
+    session[fd]->connected = 1;
+
+    currentuse++;
+    return fd;
+}
+
+void delete_session (int fd)
+{
+    if (fd < 0 || fd >= FD_SETSIZE)
+        return;
+    // If this was the highest fd, decrease it
+    // We could add a loop to decrement fd_max further for every null session,
+    // but this is cheap and good enough for the typical case
+    if (fd == fd_max - 1)
+        fd_max--;
+    FD_CLR (fd, &readfds);
+    if (session[fd])
+    {
+        free (session[fd]->rdata);
+        free (session[fd]->wdata);
+        free (session[fd]->session_data);
+        free (session[fd]);
+    }
+    session[fd] = NULL;
+
+    // just close() would try to keep sending buffers
+    shutdown (fd, SHUT_RDWR);
+    close (fd);
+    currentuse--;
+    if (currentuse < 0)
+    {
+        fprintf (stderr, "delete_session: current sessions negative!\n");
+        currentuse = 0;
+    }
+    return;
+}
+
+void realloc_fifo (int fd, size_t rfifo_size, size_t wfifo_size)
+{
+    struct socket_data *s = session[fd];
+    if (s->max_rdata != rfifo_size && s->rdata_size < rfifo_size)
+    {
+        RECREATE (s->rdata, uint8_t, rfifo_size);
+        s->max_rdata = rfifo_size;
+    }
+    if (s->max_wdata != wfifo_size && s->wdata_size < wfifo_size)
+    {
+        RECREATE (s->wdata, uint8_t, wfifo_size);
+        s->max_wdata = wfifo_size;
+    }
+}
+
+void WFIFOSET (int fd, size_t len)
+{
+    struct socket_data *s = session[fd];
+    if (s->wdata_size + len + 16384 > s->max_wdata)
+    {
+        realloc_fifo (fd, s->max_rdata, s->max_wdata << 1);
+        printf ("socket: %d wdata expanded to %d bytes.\n", fd, s->max_wdata);
+    }
+    if (s->wdata_size + len + 2048 < s->max_wdata)
+        s->wdata_size += len;
+    else
+        fprintf (stderr, "socket: %d wdata lost !!\n", fd), abort ();
+}
+
+void do_sendrecv (uint32_t next)
+{
+    fd_set rfd = readfds, wfd;
+    FD_ZERO (&wfd);
+    for (int i = 0; i < fd_max; i++)
+    {
+        if (session[i] && session[i]->wdata_size)
+            FD_SET (i, &wfd);
+    }
+    struct timeval timeout;
+    timeout.tv_sec = next / 1000;
+    timeout.tv_usec = next % 1000 * 1000;
+    if (select (fd_max, &rfd, &wfd, NULL, &timeout) <= 0)
+        return;
+    for (int i = 0; i < fd_max; i++)
+    {
+        if (!session[i])
+            continue;
+        if (FD_ISSET (i, &wfd))
+        {
+            if (session[i]->func_send)
+                //send_from_fifo(i);
+                session[i]->func_send (i);
+        }
+        if (FD_ISSET (i, &rfd))
+        {
+            if (session[i]->func_recv)
+                //recv_to_fifo(i);
+                //or connect_client(i);
+                session[i]->func_recv (i);
+        }
+    }
+}
+
+void do_parsepacket (void)
+{
+    for (int i = 0; i < fd_max; i++)
+    {
+        if (!session[i])
+            continue;
+        if (!session[i]->connected
+            && time (NULL) - session[i]->created > CONNECT_TIMEOUT)
+        {
+            printf ("Session #%d timed out\n", i);
+            session[i]->eof = 1;
+        }
+        if (!session[i]->rdata_size && !session[i]->eof)
+            continue;
+        if (session[i]->func_parse)
+        {
+            session[i]->func_parse (i);
+            /// some func_parse may call delete_session
+            if (!session[i])
+                continue;
+        }
+        /// Reclaim buffer space for what was read
+        RFIFOFLUSH (i);
+    }
+}
+
+void do_socket (void)
+{
+    FD_ZERO (&readfds);
+    currentuse = 3;
+}
+
+void RFIFOSKIP (int fd, size_t len)
+{
+    struct socket_data *s = session[fd];
+    s->rdata_pos += len;
+
+    if (s->rdata_size < s->rdata_pos)
+    {
+        fprintf (stderr, "too many skip\n");
+        abort ();
+    }
+}
+
+void fclose_ (FILE * fp)
+{
+    if (fclose (fp))
+        perror ("fclose"), abort ();
+    currentuse--;
+}
+
+FILE *fopen_ (const char *path, const char *mode)
+{
+    FILE *f = fopen (path, mode);
+    if (f)
+        currentuse++;
+    return f;
+}
+
+bool free_fds (void)
+{
+    return currentuse < SOFT_LIMIT;
+}
diff --git a/src/common/socket.h b/src/common/socket.h
deleted file mode 100644
index b886df0..0000000
--- a/src/common/socket.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef SOCKET_H
-#define SOCKET_H
-
-# include "sanity.h"
-
-# include <stdio.h>
-
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-
-# include <time.h>
-
-/// Check how much can be read
-# define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos)
-/// Read from the queue
-# define RFIFOP(fd,pos) (session[fd]->rdata+session[fd]->rdata_pos+(pos))
-# define RFIFOB(fd,pos) (*(uint8_t*)(RFIFOP(fd, pos)))
-# define RFIFOW(fd,pos) (*(uint16_t*)(RFIFOP(fd, pos)))
-# define RFIFOL(fd,pos) (*(uint32_t*)(RFIFOP(fd, pos)))
-/// Done reading
-void RFIFOSKIP (int fd, size_t len);
-/// Internal - clean up by discarding handled bytes
-// Atm this is also called in char/char.c, but that is unnecessary
-# define RFIFOFLUSH(fd) (memmove(session[fd]->rdata,RFIFOP(fd,0),RFIFOREST(fd)),\
-session[fd]->rdata_size=RFIFOREST(fd),\
-session[fd]->rdata_pos=0)
-
-/// Used internally - how much room there is to read more data
-# define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size)
-
-/// Read from an arbitrary buffer
-# define RBUFP(p,pos) (((uint8_t*)(p))+(pos))
-# define RBUFB(p,pos) (*(uint8_t*)RBUFP((p),(pos)))
-# define RBUFW(p,pos) (*(uint16_t*)RBUFP((p),(pos)))
-# define RBUFL(p,pos) (*(uint32_t*)RBUFP((p),(pos)))
-
-
-
-/// Unused - check how much data can be written
-# define WFIFOSPACE(fd) (session[fd]->max_wdata-session[fd]->wdata_size)
-/// Write to the queue
-# define WFIFOP(fd,pos) (session[fd]->wdata+session[fd]->wdata_size+(pos))
-# define WFIFOB(fd,pos) (*(uint8_t*)(WFIFOP(fd,pos)))
-# define WFIFOW(fd,pos) (*(uint16_t*)(WFIFOP(fd,pos)))
-# define WFIFOL(fd,pos) (*(uint32_t*)(WFIFOP(fd,pos)))
-/// Finish writing
-void WFIFOSET (int fd, size_t len);
-
-/// Write to an arbitrary buffer
-#define WBUFP(p,pos) (((uint8_t*)(p))+(pos))
-#define WBUFB(p,pos) (*(uint8_t*)WBUFP((p),(pos)))
-#define WBUFW(p,pos) (*(uint16_t*)WBUFP((p),(pos)))
-#define WBUFL(p,pos) (*(uint32_t*)WBUFP((p),(pos)))
-
-// Struct declaration
-
-struct socket_data
-{
-    /// Checks whether a newly-connected socket actually does anything
-    time_t created;
-    bool connected;
-
-    /// Flag needed since structure must be freed in a server-dependent manner
-    bool eof;
-
-    /// Since this is a single-threaded application, it can't block
-    /// These are the read/write queues
-    uint8_t *rdata, *wdata;
-    size_t max_rdata, max_wdata;
-    /// How much is actually in the queue
-    size_t rdata_size, wdata_size;
-    /// How much has already been read from the queue
-    /// Note that there is no need for a wdata_pos
-    size_t rdata_pos;
-
-    struct sockaddr_in client_addr;
-
-    /// Send or recieve
-    /// Only called when select() indicates the socket is ready
-    /// If, after that, nothing is read, it sets eof
-    // These could probably be hard-coded with a little work
-    void (*func_recv) (int);
-    void (*func_send) (int);
-    /// This is the important one
-    /// Set to different functions depending on whether the connection
-    /// is a player or a server/ladmin
-    /// Can be set explicitly or via set_defaultparse
-    void (*func_parse) (int);
-    /// Server-specific data type
-    void *session_data;
-};
-
-// save file descriptors for important stuff
-# define SOFT_LIMIT (FD_SETSIZE - 50)
-
-// socket timeout to establish a full connection in seconds
-# define CONNECT_TIMEOUT 15
-
-/// Everyone who has connected
-// note: call delete_session(i) to null out an element
-extern struct socket_data *session[FD_SETSIZE];
-
-/// Maximum used FD, +1
-extern int fd_max;
-
-/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails,
-/// but exit if bind() or listen() fails
-int  make_listen_port (uint16_t port);
-/// Connect to an address, return a connected socket or -1
-// FIXME - this is IPv4 only!
-int  make_connection (uint32_t ip, uint16_t port);
-/// free() the structure and close() the fd
-void delete_session (int);
-/// Make a the internal queues bigger
-void realloc_fifo (int fd, size_t rfifo_size, size_t wfifo_size);
-/// Update all sockets that can be read/written from the queues
-void do_sendrecv (uint32_t next);
-/// Call the parser function for every socket that has read data
-void do_parsepacket (void);
-
-/// An init function
-void do_socket (void);
-
-/// Change the default parser for newly connected clients
-// typically called once per server, but individual clients may identify
-// themselves as servers
-void set_defaultparse (void (*defaultparse) (int));
-
-/// Wrappers to track number of free FDs
-void fclose_ (FILE * fp);
-FILE *fopen_ (const char *path, const char *mode);
-bool free_fds (void);
-
-#endif // SOCKET_H
diff --git a/src/common/socket.hpp b/src/common/socket.hpp
new file mode 100644
index 0000000..00f2df0
--- /dev/null
+++ b/src/common/socket.hpp
@@ -0,0 +1,135 @@
+#ifndef SOCKET_HPP
+#define SOCKET_HPP
+
+# include "sanity.hpp"
+
+# include <stdio.h>
+
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+
+# include <time.h>
+
+/// Check how much can be read
+# define RFIFOREST(fd) (session[fd]->rdata_size-session[fd]->rdata_pos)
+/// Read from the queue
+# define RFIFOP(fd,pos) (session[fd]->rdata+session[fd]->rdata_pos+(pos))
+# define RFIFOB(fd,pos) (*(uint8_t*)(RFIFOP(fd, pos)))
+# define RFIFOW(fd,pos) (*(uint16_t*)(RFIFOP(fd, pos)))
+# define RFIFOL(fd,pos) (*(uint32_t*)(RFIFOP(fd, pos)))
+/// Done reading
+void RFIFOSKIP (int fd, size_t len);
+/// Internal - clean up by discarding handled bytes
+// Atm this is also called in char/char.c, but that is unnecessary
+# define RFIFOFLUSH(fd) (memmove(session[fd]->rdata,RFIFOP(fd,0),RFIFOREST(fd)),\
+session[fd]->rdata_size=RFIFOREST(fd),\
+session[fd]->rdata_pos=0)
+
+/// Used internally - how much room there is to read more data
+# define RFIFOSPACE(fd) (session[fd]->max_rdata-session[fd]->rdata_size)
+
+/// Read from an arbitrary buffer
+# define RBUFP(p,pos) (((uint8_t*)(p))+(pos))
+# define RBUFB(p,pos) (*(uint8_t*)RBUFP((p),(pos)))
+# define RBUFW(p,pos) (*(uint16_t*)RBUFP((p),(pos)))
+# define RBUFL(p,pos) (*(uint32_t*)RBUFP((p),(pos)))
+
+
+
+/// Unused - check how much data can be written
+# define WFIFOSPACE(fd) (session[fd]->max_wdata-session[fd]->wdata_size)
+/// Write to the queue
+# define WFIFOP(fd,pos) (session[fd]->wdata+session[fd]->wdata_size+(pos))
+# define WFIFOB(fd,pos) (*(uint8_t*)(WFIFOP(fd,pos)))
+# define WFIFOW(fd,pos) (*(uint16_t*)(WFIFOP(fd,pos)))
+# define WFIFOL(fd,pos) (*(uint32_t*)(WFIFOP(fd,pos)))
+/// Finish writing
+void WFIFOSET (int fd, size_t len);
+
+/// Write to an arbitrary buffer
+#define WBUFP(p,pos) (((uint8_t*)(p))+(pos))
+#define WBUFB(p,pos) (*(uint8_t*)WBUFP((p),(pos)))
+#define WBUFW(p,pos) (*(uint16_t*)WBUFP((p),(pos)))
+#define WBUFL(p,pos) (*(uint32_t*)WBUFP((p),(pos)))
+
+// Struct declaration
+
+struct socket_data
+{
+    /// Checks whether a newly-connected socket actually does anything
+    time_t created;
+    bool connected;
+
+    /// Flag needed since structure must be freed in a server-dependent manner
+    bool eof;
+
+    /// Since this is a single-threaded application, it can't block
+    /// These are the read/write queues
+    uint8_t *rdata, *wdata;
+    size_t max_rdata, max_wdata;
+    /// How much is actually in the queue
+    size_t rdata_size, wdata_size;
+    /// How much has already been read from the queue
+    /// Note that there is no need for a wdata_pos
+    size_t rdata_pos;
+
+    struct sockaddr_in client_addr;
+
+    /// Send or recieve
+    /// Only called when select() indicates the socket is ready
+    /// If, after that, nothing is read, it sets eof
+    // These could probably be hard-coded with a little work
+    void (*func_recv) (int);
+    void (*func_send) (int);
+    /// This is the important one
+    /// Set to different functions depending on whether the connection
+    /// is a player or a server/ladmin
+    /// Can be set explicitly or via set_defaultparse
+    void (*func_parse) (int);
+    /// Server-specific data type
+    void *session_data;
+};
+
+// save file descriptors for important stuff
+# define SOFT_LIMIT (FD_SETSIZE - 50)
+
+// socket timeout to establish a full connection in seconds
+# define CONNECT_TIMEOUT 15
+
+/// Everyone who has connected
+// note: call delete_session(i) to null out an element
+extern struct socket_data *session[FD_SETSIZE];
+
+/// Maximum used FD, +1
+extern int fd_max;
+
+/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails,
+/// but exit if bind() or listen() fails
+int  make_listen_port (uint16_t port);
+/// Connect to an address, return a connected socket or -1
+// FIXME - this is IPv4 only!
+int  make_connection (uint32_t ip, uint16_t port);
+/// free() the structure and close() the fd
+void delete_session (int);
+/// Make a the internal queues bigger
+void realloc_fifo (int fd, size_t rfifo_size, size_t wfifo_size);
+/// Update all sockets that can be read/written from the queues
+void do_sendrecv (uint32_t next);
+/// Call the parser function for every socket that has read data
+void do_parsepacket (void);
+
+/// An init function
+void do_socket (void);
+
+/// Change the default parser for newly connected clients
+// typically called once per server, but individual clients may identify
+// themselves as servers
+void set_defaultparse (void (*defaultparse) (int));
+
+/// Wrappers to track number of free FDs
+void fclose_ (FILE * fp);
+FILE *fopen_ (const char *path, const char *mode);
+bool free_fds (void);
+
+#endif // SOCKET_HPP
diff --git a/src/common/timer.c b/src/common/timer.c
deleted file mode 100644
index 6795824..0000000
--- a/src/common/timer.c
+++ /dev/null
@@ -1,257 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include "timer.h"
-#include "utils.h"
-
-static struct TimerData *timer_data;
-static uint32_t timer_data_max, timer_data_num;
-static timer_id *free_timer_list;
-static uint32_t free_timer_list_max, free_timer_list_pos;
-
-/// Okay, I think I understand this structure now:
-/// the timer heap is a magic queue that allows inserting timers and then popping them in order
-/// designed to copy only log2(N) entries instead of N
-// timer_heap[0] is the size (greatest index into the heap)
-// timer_heap[1] is the first actual element
-// timer_heap_max increases 256 at a time and never decreases
-static uint32_t timer_heap_max = 0;
-/// FIXME: refactor the code to put the size in a separate variable
-//nontrivial because indices get multiplied
-static timer_id *timer_heap = NULL;
-
-
-static uint32_t gettick_cache;
-static uint8_t gettick_count = 0;
-
-uint32_t gettick_nocache (void)
-{
-    struct timeval tval;
-    // BUG: This will cause strange behavior if the system clock is changed!
-    // it should be reimplemented in terms of clock_gettime(CLOCK_MONOTONIC, )
-    gettimeofday (&tval, NULL);
-    gettick_count = 255;
-    return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000;
-}
-
-uint32_t gettick (void)
-{
-    if (gettick_count--)
-        return gettick_cache;
-    return gettick_nocache ();
-}
-
-static void push_timer_heap (timer_id index)
-{
-    if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max)
-    {
-        timer_heap_max += 256;
-        RECREATE (timer_heap, timer_id, timer_heap_max);
-        memset (timer_heap + (timer_heap_max - 256), 0, sizeof (timer_id) * 256);
-    }
-// timer_heap[0] is the greatest index into the heap, which increases
-    timer_heap[0]++;
-
-    timer_id h = timer_heap[0]-1, i = (h - 1) / 2;
-    while (h)
-    {
-        // avoid wraparound problems, it really means this:
-        //   timer_data[index].tick >= timer_data[timer_heap[i+1]].tick
-        if ( DIFF_TICK(timer_data[index].tick, timer_data[timer_heap[i+1]].tick) >= 0)
-            break;
-        timer_heap[h + 1] = timer_heap[i + 1];
-        h = i;
-        i = (h - 1) / 2;
-    }
-    timer_heap[h + 1] = index;
-}
-
-static timer_id top_timer_heap (void)
-{
-    if (!timer_heap || !timer_heap[0])
-        return -1;
-    return timer_heap[1];
-}
-
-static timer_id pop_timer_heap (void)
-{
-    if (!timer_heap || !timer_heap[0])
-        return -1;
-    timer_id ret = timer_heap[1];
-    timer_id last = timer_heap[timer_heap[0]];
-    timer_heap[0]--;
-
-    uint32_t h, k;
-    for (h = 0, k = 2; k < timer_heap[0]; k = k * 2 + 2)
-    {
-        if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick, timer_data[timer_heap[k]].tick) > 0)
-            k--;
-        timer_heap[h + 1] = timer_heap[k + 1], h = k;
-    }
-    if (k == timer_heap[0])
-        timer_heap[h + 1] = timer_heap[k], h = k - 1;
-
-    uint32_t i = (h - 1) / 2;
-    while (h)
-    {
-        if (DIFF_TICK (timer_data[timer_heap[i + 1]].tick, timer_data[last].tick) <= 0)
-            break;
-        timer_heap[h + 1] = timer_heap[i + 1];
-        h = i;
-        i = (h - 1) / 2;
-    }
-    timer_heap[h + 1] = last;
-
-    return ret;
-}
-
-timer_id add_timer (tick_t tick, timer_func func, custom_id_t id, custom_data_t data)
-{
-    timer_id i;
-
-    if (free_timer_list_pos)
-    {
-        // Retrieve a freed timer id instead of a new one
-        // I think it should be possible to avoid the loop somehow
-        do
-        {
-            i = free_timer_list[--free_timer_list_pos];
-        }
-        while (i >= timer_data_num && free_timer_list_pos > 0);
-    }
-    else
-        i = timer_data_num;
-
-    // I have no idea what this is doing
-    if (i >= timer_data_num)
-        for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++)
-            ;
-    if (i >= timer_data_num && i >= timer_data_max)
-    {
-        if (timer_data_max == 0)
-        {
-            timer_data_max = 256;
-            CREATE (timer_data, struct TimerData, timer_data_max);
-        }
-        else
-        {
-            timer_data_max += 256;
-            RECREATE (timer_data, struct TimerData, timer_data_max);
-            memset (timer_data + (timer_data_max - 256), 0,
-                    sizeof (struct TimerData) * 256);
-        }
-    }
-    timer_data[i].tick = tick;
-    timer_data[i].func = func;
-    timer_data[i].id = id;
-    timer_data[i].data = data;
-    timer_data[i].type = TIMER_ONCE_AUTODEL;
-    timer_data[i].interval = 1000;
-    push_timer_heap (i);
-    if (i >= timer_data_num)
-        timer_data_num = i + 1;
-    return i;
-}
-
-timer_id add_timer_interval (tick_t tick, timer_func func, custom_id_t id,
-                             custom_data_t data, interval_t interval)
-{
-    timer_id tid = add_timer (tick, func, id, data);
-    timer_data[tid].type = TIMER_INTERVAL;
-    timer_data[tid].interval = interval;
-    return tid;
-}
-
-void delete_timer (timer_id id, timer_func func)
-{
-    if (id == 0 || id >= timer_data_num)
-    {
-        fprintf (stderr, "delete_timer error : no such timer %d\n", id);
-        abort ();
-    }
-    if (timer_data[id].func != func)
-    {
-        fprintf (stderr, "Timer mismatch\n");
-        abort ();
-    }
-    // "to let them disappear" - is this just in case?
-    timer_data[id].func = NULL;
-    timer_data[id].type = TIMER_ONCE_AUTODEL;
-    timer_data[id].tick -= 60 * 60 * 1000;
-}
-
-tick_t addtick_timer (timer_id tid, interval_t tick)
-{
-    return timer_data[tid].tick += tick;
-}
-
-struct TimerData *get_timer (timer_id tid)
-{
-    return &timer_data[tid];
-}
-
-interval_t do_timer (tick_t tick)
-{
-    timer_id i;
-    /// Number of milliseconds until it calls this again
-    // this says to wait 1 sec if all timers get popped
-    interval_t nextmin = 1000;
-
-    while ((i = top_timer_heap ()) != (timer_id)-1)
-    {
-        // while the heap is not empty and
-        if (DIFF_TICK (timer_data[i].tick, tick) > 0)
-        {
-            /// Return the time until the next timer needs to goes off
-            nextmin = DIFF_TICK (timer_data[i].tick, tick);
-            break;
-        }
-        pop_timer_heap ();
-        if (timer_data[i].func)
-        {
-            if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
-            {
-                // If we are too far past the requested tick, call with the current tick instead to fix reregistering problems
-                timer_data[i].func (i, tick, timer_data[i].id, timer_data[i].data);
-            }
-            else
-            {
-                timer_data[i].func (i, timer_data[i].tick, timer_data[i].id, timer_data[i].data);
-            }
-        }
-        switch (timer_data[i].type)
-        {
-            case TIMER_ONCE_AUTODEL:
-                timer_data[i].type = TIMER_NONE;
-                if (free_timer_list_pos >= free_timer_list_max)
-                {
-                    free_timer_list_max += 256;
-                    RECREATE (free_timer_list, uint32_t, free_timer_list_max);
-                    memset (free_timer_list + (free_timer_list_max - 256),
-                            0, 256 * sizeof (uint32_t));
-                }
-                free_timer_list[free_timer_list_pos++] = i;
-                break;
-            case TIMER_INTERVAL:
-                if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
-                {
-                    timer_data[i].tick = tick + timer_data[i].interval;
-                }
-                else
-                {
-                    timer_data[i].tick += timer_data[i].interval;
-                }
-                push_timer_heap (i);
-                break;
-        }
-    }
-
-    if (nextmin < 10)
-        nextmin = 10;
-    return nextmin;
-}
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
new file mode 100644
index 0000000..66aaa9b
--- /dev/null
+++ b/src/common/timer.cpp
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include "timer.hpp"
+#include "utils.hpp"
+
+static struct TimerData *timer_data;
+static uint32_t timer_data_max, timer_data_num;
+static timer_id *free_timer_list;
+static uint32_t free_timer_list_max, free_timer_list_pos;
+
+/// Okay, I think I understand this structure now:
+/// the timer heap is a magic queue that allows inserting timers and then popping them in order
+/// designed to copy only log2(N) entries instead of N
+// timer_heap[0] is the size (greatest index into the heap)
+// timer_heap[1] is the first actual element
+// timer_heap_max increases 256 at a time and never decreases
+static uint32_t timer_heap_max = 0;
+/// FIXME: refactor the code to put the size in a separate variable
+//nontrivial because indices get multiplied
+static timer_id *timer_heap = NULL;
+
+
+static uint32_t gettick_cache;
+static uint8_t gettick_count = 0;
+
+uint32_t gettick_nocache (void)
+{
+    struct timeval tval;
+    // BUG: This will cause strange behavior if the system clock is changed!
+    // it should be reimplemented in terms of clock_gettime(CLOCK_MONOTONIC, )
+    gettimeofday (&tval, NULL);
+    gettick_count = 255;
+    return gettick_cache = tval.tv_sec * 1000 + tval.tv_usec / 1000;
+}
+
+uint32_t gettick (void)
+{
+    if (gettick_count--)
+        return gettick_cache;
+    return gettick_nocache ();
+}
+
+static void push_timer_heap (timer_id index)
+{
+    if (timer_heap == NULL || timer_heap[0] + 1 >= timer_heap_max)
+    {
+        timer_heap_max += 256;
+        RECREATE (timer_heap, timer_id, timer_heap_max);
+        memset (timer_heap + (timer_heap_max - 256), 0, sizeof (timer_id) * 256);
+    }
+// timer_heap[0] is the greatest index into the heap, which increases
+    timer_heap[0]++;
+
+    timer_id h = timer_heap[0]-1, i = (h - 1) / 2;
+    while (h)
+    {
+        // avoid wraparound problems, it really means this:
+        //   timer_data[index].tick >= timer_data[timer_heap[i+1]].tick
+        if ( DIFF_TICK(timer_data[index].tick, timer_data[timer_heap[i+1]].tick) >= 0)
+            break;
+        timer_heap[h + 1] = timer_heap[i + 1];
+        h = i;
+        i = (h - 1) / 2;
+    }
+    timer_heap[h + 1] = index;
+}
+
+static timer_id top_timer_heap (void)
+{
+    if (!timer_heap || !timer_heap[0])
+        return -1;
+    return timer_heap[1];
+}
+
+static timer_id pop_timer_heap (void)
+{
+    if (!timer_heap || !timer_heap[0])
+        return -1;
+    timer_id ret = timer_heap[1];
+    timer_id last = timer_heap[timer_heap[0]];
+    timer_heap[0]--;
+
+    uint32_t h, k;
+    for (h = 0, k = 2; k < timer_heap[0]; k = k * 2 + 2)
+    {
+        if (DIFF_TICK(timer_data[timer_heap[k + 1]].tick, timer_data[timer_heap[k]].tick) > 0)
+            k--;
+        timer_heap[h + 1] = timer_heap[k + 1], h = k;
+    }
+    if (k == timer_heap[0])
+        timer_heap[h + 1] = timer_heap[k], h = k - 1;
+
+    uint32_t i = (h - 1) / 2;
+    while (h)
+    {
+        if (DIFF_TICK (timer_data[timer_heap[i + 1]].tick, timer_data[last].tick) <= 0)
+            break;
+        timer_heap[h + 1] = timer_heap[i + 1];
+        h = i;
+        i = (h - 1) / 2;
+    }
+    timer_heap[h + 1] = last;
+
+    return ret;
+}
+
+timer_id add_timer (tick_t tick, timer_func func, custom_id_t id, custom_data_t data)
+{
+    timer_id i;
+
+    if (free_timer_list_pos)
+    {
+        // Retrieve a freed timer id instead of a new one
+        // I think it should be possible to avoid the loop somehow
+        do
+        {
+            i = free_timer_list[--free_timer_list_pos];
+        }
+        while (i >= timer_data_num && free_timer_list_pos > 0);
+    }
+    else
+        i = timer_data_num;
+
+    // I have no idea what this is doing
+    if (i >= timer_data_num)
+        for (i = timer_data_num; i < timer_data_max && timer_data[i].type; i++)
+            ;
+    if (i >= timer_data_num && i >= timer_data_max)
+    {
+        if (timer_data_max == 0)
+        {
+            timer_data_max = 256;
+            CREATE (timer_data, struct TimerData, timer_data_max);
+        }
+        else
+        {
+            timer_data_max += 256;
+            RECREATE (timer_data, struct TimerData, timer_data_max);
+            memset (timer_data + (timer_data_max - 256), 0,
+                    sizeof (struct TimerData) * 256);
+        }
+    }
+    timer_data[i].tick = tick;
+    timer_data[i].func = func;
+    timer_data[i].id = id;
+    timer_data[i].data = data;
+    timer_data[i].type = TIMER_ONCE_AUTODEL;
+    timer_data[i].interval = 1000;
+    push_timer_heap (i);
+    if (i >= timer_data_num)
+        timer_data_num = i + 1;
+    return i;
+}
+
+timer_id add_timer_interval (tick_t tick, timer_func func, custom_id_t id,
+                             custom_data_t data, interval_t interval)
+{
+    timer_id tid = add_timer (tick, func, id, data);
+    timer_data[tid].type = TIMER_INTERVAL;
+    timer_data[tid].interval = interval;
+    return tid;
+}
+
+void delete_timer (timer_id id, timer_func func)
+{
+    if (id == 0 || id >= timer_data_num)
+    {
+        fprintf (stderr, "delete_timer error : no such timer %d\n", id);
+        abort ();
+    }
+    if (timer_data[id].func != func)
+    {
+        fprintf (stderr, "Timer mismatch\n");
+        abort ();
+    }
+    // "to let them disappear" - is this just in case?
+    timer_data[id].func = NULL;
+    timer_data[id].type = TIMER_ONCE_AUTODEL;
+    timer_data[id].tick -= 60 * 60 * 1000;
+}
+
+tick_t addtick_timer (timer_id tid, interval_t tick)
+{
+    return timer_data[tid].tick += tick;
+}
+
+struct TimerData *get_timer (timer_id tid)
+{
+    return &timer_data[tid];
+}
+
+interval_t do_timer (tick_t tick)
+{
+    timer_id i;
+    /// Number of milliseconds until it calls this again
+    // this says to wait 1 sec if all timers get popped
+    interval_t nextmin = 1000;
+
+    while ((i = top_timer_heap ()) != (timer_id)-1)
+    {
+        // while the heap is not empty and
+        if (DIFF_TICK (timer_data[i].tick, tick) > 0)
+        {
+            /// Return the time until the next timer needs to goes off
+            nextmin = DIFF_TICK (timer_data[i].tick, tick);
+            break;
+        }
+        pop_timer_heap ();
+        if (timer_data[i].func)
+        {
+            if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
+            {
+                // If we are too far past the requested tick, call with the current tick instead to fix reregistering problems
+                timer_data[i].func (i, tick, timer_data[i].id, timer_data[i].data);
+            }
+            else
+            {
+                timer_data[i].func (i, timer_data[i].tick, timer_data[i].id, timer_data[i].data);
+            }
+        }
+        switch (timer_data[i].type)
+        {
+            case TIMER_ONCE_AUTODEL:
+                timer_data[i].type = TIMER_NONE;
+                if (free_timer_list_pos >= free_timer_list_max)
+                {
+                    free_timer_list_max += 256;
+                    RECREATE (free_timer_list, uint32_t, free_timer_list_max);
+                    memset (free_timer_list + (free_timer_list_max - 256),
+                            0, 256 * sizeof (uint32_t));
+                }
+                free_timer_list[free_timer_list_pos++] = i;
+                break;
+            case TIMER_INTERVAL:
+                if (DIFF_TICK (timer_data[i].tick, tick) < -1000)
+                {
+                    timer_data[i].tick = tick + timer_data[i].interval;
+                }
+                else
+                {
+                    timer_data[i].tick += timer_data[i].interval;
+                }
+                push_timer_heap (i);
+                break;
+        }
+    }
+
+    if (nextmin < 10)
+        nextmin = 10;
+    return nextmin;
+}
diff --git a/src/common/timer.h b/src/common/timer.h
deleted file mode 100644
index e6a292c..0000000
--- a/src/common/timer.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef TIMER_H
-#define TIMER_H
-
-# include "sanity.h"
-
-enum TIMER_TYPE
-{
-    TIMER_NONE,
-    TIMER_ONCE_AUTODEL,
-    TIMER_INTERVAL,
-};
-/// This is needed to produce a signed result when 2 ticks are subtracted
-# define DIFF_TICK(a,b) ((int32_t)((a)-(b)))
-
-// TODO replace with signed 64-bit to make code more clear and protect from the future
-typedef uint32_t tick_t;
-typedef uint32_t interval_t;
-typedef uint32_t timer_id;
-// BUG: pointers are stored in here
-typedef int32_t custom_id_t;
-typedef int32_t custom_data_t;
-typedef void (*timer_func) (timer_id, tick_t, custom_id_t, custom_data_t);
-
-struct TimerData
-{
-    /// When it will be triggered
-    tick_t tick;
-    /// What will be done
-    timer_func func;
-    /// Arbitrary data. WARNING, callers are stupid and put pointers in here
-    // Should we change to void* or intptr_t ?
-    custom_id_t  id;
-    custom_data_t  data;
-    /// Type of timer - 0 initially
-    enum TIMER_TYPE type;
-    /// Repeat rate
-    interval_t interval;
-};
-
-/// Server time, in milliseconds, since the epoch,
-/// but use of 32-bit integers means it wraps every 49 days.
-// The only external caller of this function is the core.c main loop, but that makes sense
-// in fact, it might make more sense if gettick() ALWAYS returned that cached value
-tick_t gettick_nocache (void);
-/// This function is called enough that it's worth caching the result for
-/// the next 255 times
-tick_t gettick (void);
-
-timer_id add_timer (tick_t, timer_func, custom_id_t, custom_data_t);
-timer_id add_timer_interval (tick_t, timer_func, custom_id_t, custom_data_t, interval_t);
-void delete_timer (timer_id, timer_func);
-
-tick_t addtick_timer (timer_id, interval_t);
-struct TimerData *get_timer (timer_id tid);
-
-/// Do all timers scheduled before tick, and return the number of milliseconds until the next timer happens
-interval_t do_timer (tick_t tick);
-
-
-
-#endif // TIMER_H
diff --git a/src/common/timer.hpp b/src/common/timer.hpp
new file mode 100644
index 0000000..fdda344
--- /dev/null
+++ b/src/common/timer.hpp
@@ -0,0 +1,61 @@
+#ifndef TIMER_HPP
+#define TIMER_HPP
+
+# include "sanity.hpp"
+
+enum TIMER_TYPE
+{
+    TIMER_NONE,
+    TIMER_ONCE_AUTODEL,
+    TIMER_INTERVAL,
+};
+/// This is needed to produce a signed result when 2 ticks are subtracted
+# define DIFF_TICK(a,b) ((int32_t)((a)-(b)))
+
+// TODO replace with signed 64-bit to make code more clear and protect from the future
+typedef uint32_t tick_t;
+typedef uint32_t interval_t;
+typedef uint32_t timer_id;
+// BUG: pointers are stored in here
+typedef int32_t custom_id_t;
+typedef int32_t custom_data_t;
+typedef void (*timer_func) (timer_id, tick_t, custom_id_t, custom_data_t);
+
+struct TimerData
+{
+    /// When it will be triggered
+    tick_t tick;
+    /// What will be done
+    timer_func func;
+    /// Arbitrary data. WARNING, callers are stupid and put pointers in here
+    // Should we change to void* or intptr_t ?
+    custom_id_t  id;
+    custom_data_t  data;
+    /// Type of timer - 0 initially
+    enum TIMER_TYPE type;
+    /// Repeat rate
+    interval_t interval;
+};
+
+/// Server time, in milliseconds, since the epoch,
+/// but use of 32-bit integers means it wraps every 49 days.
+// The only external caller of this function is the core.c main loop, but that makes sense
+// in fact, it might make more sense if gettick() ALWAYS returned that cached value
+tick_t gettick_nocache (void);
+/// This function is called enough that it's worth caching the result for
+/// the next 255 times
+tick_t gettick (void);
+
+timer_id add_timer (tick_t, timer_func, custom_id_t, custom_data_t);
+timer_id add_timer_interval (tick_t, timer_func, custom_id_t, custom_data_t, interval_t);
+void delete_timer (timer_id, timer_func);
+
+tick_t addtick_timer (timer_id, interval_t);
+struct TimerData *get_timer (timer_id tid);
+
+/// Do all timers scheduled before tick, and return the number of milliseconds until the next timer happens
+interval_t do_timer (tick_t tick);
+
+
+
+#endif // TIMER_HPP
diff --git a/src/common/utils.h b/src/common/utils.h
deleted file mode 100644
index 961d960..0000000
--- a/src/common/utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef UTILS_H
-#define UTILS_H
-/*
-Notes about memory allocation in tmwAthena:
-There used to be 3 sources of allocation: these macros,
-a{C,M,Re}alloc in common/malloc.{h,c}, and direct calls.
-I deleted malloc.{h,c} because it was redundant;
-future calls should either use this or depend on the coming segfault.
-*/
-# define CREATE(result, type, number) \
-   if (!((result) = (type *) calloc ((number), sizeof(type))))   \
-      { perror("SYSERR: malloc failure"); abort(); } else (void)0
-
-# define RECREATE(result,type,number) \
-  if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\
-      { perror("SYSERR: realloc failure"); abort(); } else (void)0
-
-#endif //UTILS_H
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
new file mode 100644
index 0000000..7c7da16
--- /dev/null
+++ b/src/common/utils.hpp
@@ -0,0 +1,18 @@
+#ifndef UTILS_HPP
+#define UTILS_HPP
+/*
+Notes about memory allocation in tmwAthena:
+There used to be 3 sources of allocation: these macros,
+a{C,M,Re}alloc in common/malloc.{h,c}, and direct calls.
+I deleted malloc.{h,c} because it was redundant;
+future calls should either use this or depend on the coming segfault.
+*/
+# define CREATE(result, type, number) \
+   if (!((result) = (type *) calloc ((number), sizeof(type))))   \
+      { perror("SYSERR: malloc failure"); abort(); } else (void)0
+
+# define RECREATE(result,type,number) \
+  if (!((result) = (type *) realloc ((result), sizeof(type) * (number))))\
+      { perror("SYSERR: realloc failure"); abort(); } else (void)0
+
+#endif //UTILS_HPP
diff --git a/src/common/version.h b/src/common/version.h
deleted file mode 100644
index 46165aa..0000000
--- a/src/common/version.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/// Some constants to identify the version of (e)Athena
-/// The values are different if the client connects (-1,'T','M','W',flags32)
-// These numbers have never been changed while TMW
-#ifndef VERSION_H
-#define VERSION_H
-//When a server receives a 0x7530 packet from an admin connection,
-//it sends an 0x7531 packet with the following bytes
-# define ATHENA_MAJOR_VERSION    1   // Major Version
-# define ATHENA_MINOR_VERSION    0   // Minor Version
-# define ATHENA_REVISION         0   // Revision
-
-# define ATHENA_RELEASE_FLAG     1   // 1=Develop,0=Stable
-# define ATHENA_OFFICIAL_FLAG    1   // 1=Mod,0=Official
-
-// and a bitmask of these (the char server sends char and inter)
-# define ATHENA_SERVER_LOGIN     1   // login server
-# define ATHENA_SERVER_CHAR      2   // char server
-# define ATHENA_SERVER_INTER     4   // inter server
-# define ATHENA_SERVER_MAP       8   // map server
-
-// and this as two bytes
-# define ATHENA_MOD_VERSION   1052   // mod version (patch No.)
-
-#endif // VERSION_H
diff --git a/src/common/version.hpp b/src/common/version.hpp
new file mode 100644
index 0000000..d72f41e
--- /dev/null
+++ b/src/common/version.hpp
@@ -0,0 +1,24 @@
+/// Some constants to identify the version of (e)Athena
+/// The values are different if the client connects (-1,'T','M','W',flags32)
+// These numbers have never been changed while TMW
+#ifndef VERSION_HPP
+#define VERSION_HPP
+//When a server receives a 0x7530 packet from an admin connection,
+//it sends an 0x7531 packet with the following bytes
+# define ATHENA_MAJOR_VERSION    1   // Major Version
+# define ATHENA_MINOR_VERSION    0   // Minor Version
+# define ATHENA_REVISION         0   // Revision
+
+# define ATHENA_RELEASE_FLAG     1   // 1=Develop,0=Stable
+# define ATHENA_OFFICIAL_FLAG    1   // 1=Mod,0=Official
+
+// and a bitmask of these (the char server sends char and inter)
+# define ATHENA_SERVER_LOGIN     1   // login server
+# define ATHENA_SERVER_CHAR      2   // char server
+# define ATHENA_SERVER_INTER     4   // inter server
+# define ATHENA_SERVER_MAP       8   // map server
+
+// and this as two bytes
+# define ATHENA_MOD_VERSION   1052   // mod version (patch No.)
+
+#endif // VERSION_HPP
diff --git a/src/ladmin/ladmin.c b/src/ladmin/ladmin.c
deleted file mode 100644
index 3728799..0000000
--- a/src/ladmin/ladmin.c
+++ /dev/null
@@ -1,6476 +0,0 @@
-// $Id: ladmin.c,v 1.1.1.1 2004/09/10 17:26:52 MagicalTux Exp $
-///////////////////////////////////////////////////////////////////////////
-// EAthena login-server remote administration tool
-// Ladamin in C by [Yor]
-// if you modify this software, modify ladmin in tool too.
-///////////////////////////////////////////////////////////////////////////
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <sys/time.h>           // gettimeofday
-#include <time.h>
-#include <sys/ioctl.h>
-#include <unistd.h>             // close
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>             // str*
-#include <arpa/inet.h>          // inet_addr
-#include <netdb.h>              // gethostbyname
-#include <stdarg.h>             // valist
-#include <ctype.h>              // tolower
-
-#include "../common/core.h"
-#include "../common/socket.h"
-#include "ladmin.h"
-#include "../common/version.h"
-#include "../common/mmo.h"
-
-#ifdef PASSWORDENC
-#include "../common/md5calc.h"
-#endif
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-int eathena_interactive_session; // from core.c
-#define Iprintf if (eathena_interactive_session) printf
-
-//-------------------------------INSTRUCTIONS------------------------------
-// Set the variables below:
-//   IP of the login server.
-//   Port where the login-server listens incoming packets.
-//   Password of administration (same of config_athena.conf).
-//   Displayed language of the sofware (if not correct, english is used).
-// IMPORTANT:
-//   Be sure that you authorize remote administration in login-server
-//   (see login_athena.conf, 'admin_state' parameter)
-//-------------------------------------------------------------------------
-char loginserverip[16] = "127.0.0.1";   // IP of login-server
-int  loginserverport = 6900;    // Port of login-server
-char loginserveradminpassword[24] = "admin";    // Administration password
-#ifdef PASSWORDENC
-int  passenc = 2;               // Encoding type of the password
-#else
-int  passenc = 0;               // Encoding type of the password
-#endif
-char defaultlanguage = 'E';     // Default language (F: Français/E: English)
-                                             // (if it's not 'F', default is English)
-char ladmin_log_filename[1024] = "log/ladmin.log";
-char date_format[32] = "%Y-%m-%d %H:%M:%S";
-//-------------------------------------------------------------------------
-//  LIST of COMMANDs that you can type at the prompt:
-//    To use these commands you can only type only the first letters.
-//    You must type a minimum of letters (you can not type 'a',
-//      because ladmin doesn't know if it's for 'aide' or for 'add')
-//    <Example> q <= quit, li <= list, pass <= passwd, etc.
-//
-//  Note: every time you must give a account_name, you can use "" or '' (spaces can be included)
-//
-//  aide/help/?
-//    Display the description of the commands
-//  aide/help/? [command]
-//    Display the description of the specified command
-//
-//  add <account_name> <sex> <password>
-//    Create an account with the default email (a@a.com).
-//    Concerning the sex, only the first letter is used (F or M).
-//    The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.
-//    When the password is omitted, the input is done without displaying of the pressed keys.
-//    <example> add testname Male testpass
-//
-//  ban/banish yyyy/mm/dd hh:mm:ss <account name>
-//    Changes the final date of a banishment of an account.
-//    Like banset, but <account name> is at end.
-//
-//  banadd <account_name> <modifier>
-//    Adds or substracts time from the final date of a banishment of an account.
-//    Modifier is done as follows:
-//      Adjustment value (-1, 1, +1, etc...)
-//      Modified element:
-//        a or y: year
-//        m:  month
-//        j or d: day
-//        h:  hour
-//        mn: minute
-//        s:  second
-//    <example> banadd testname +1m-2mn1s-6y
-//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-//  NOTE: If you modify the final date of a non-banished account,
-//        you fix the final date to (actual time +- adjustments)
-//
-//  banset <account_name> yyyy/mm/dd [hh:mm:ss]
-//    Changes the final date of a banishment of an account.
-//    Default time [hh:mm:ss]: 23:59:59.
-//  banset <account_name> 0
-//    Set a non-banished account (0 = unbanished).
-//
-//  block <account name>
-//    Set state 5 (You have been blocked by the GM Team) to an account.
-//    Like state <account name> 5.
-//
-//  check <account_name> <password>
-//    Check the validity of a password for an account
-//    NOTE: Server will never sends back a password.
-//          It's the only method you have to know if a password is correct.
-//          The other method is to have a ('physical') access to the accounts file.
-//
-//  create <account_name> <sex> <email> <password>
-//    Like the 'add' command, but with e-mail moreover.
-//    <example> create testname Male my@mail.com testpass
-//
-//  del <account name>
-//    Remove an account.
-//    This order requires confirmation. After confirmation, the account is deleted.
-//
-//  email <account_name> <email>
-//    Modify the e-mail of an account.
-//
-//  getcount
-//    Give the number of players online on all char-servers.
-//
-//  gm <account_name> [GM_level]
-//    Modify the GM level of an account.
-//    Default value remove GM level (GM level = 0).
-//    <example> gm testname 80
-//
-//  id <account name>
-//    Give the id of an account.
-//
-//  info <account_id>
-//    Display complete information of an account.
-//
-//  kami <message>
-//    Sends a broadcast message on all map-server (in yellow).
-//  kamib <message>
-//    Sends a broadcast message on all map-server (in blue).
-//
-//  language <language>
-//    Change the language of displaying.
-//
-//  list/ls [start_id [end_id]]
-//    Display a list of accounts.
-//    'start_id', 'end_id': indicate end and start identifiers.
-//    Research by name is not possible with this command.
-//    <example> list 10 9999999
-//
-//  listBan/lsBan [start_id [end_id]]
-//    Like list/ls, but only for accounts with state or banished
-//
-//  listGM/lsGM [start_id [end_id]]
-//    Like list/ls, but only for GM accounts
-//
-//  listOK/lsOK [start_id [end_id]]
-//    Like list/ls, but only for accounts without state and not banished
-//
-//  memo <account_name> <memo>
-//    Modify the memo of an account.
-//    'memo': it can have until 253 characters (with spaces or not).
-//
-//  name <account_id>
-//    Give the name of an account.
-//
-//  passwd <account_name> <new_password>
-//    Change the password of an account.
-//    When new password is omitted, the input is done without displaying of the pressed keys.
-//
-//  quit/end/exit
-//    End of the program of administration
-//
-//  reloadGM
-//    Reload GM configuration file
-//
-//  search <expression>
-//    Seek accounts.
-//    Displays the accounts whose names correspond.
-//  search -r/-e/--expr/--regex <expression>
-//    Seek accounts by regular expression.
-//    Displays the accounts whose names correspond.
-//
-//  sex <account_name> <sex>
-//    Modify the sex of an account.
-//    <example> sex testname Male
-//
-//  state <account_name> <new_state> <error_message_#7>
-//    Change the state of an account.
-//    'new_state': state is the state of the packet 0x006a + 1. The possibilities are:
-//                 0 = Account ok            6 = Your Game's EXE file is not the latest version
-//                 1 = Unregistered ID       7 = You are Prohibited to log in until %s
-//                 2 = Incorrect Password    8 = Server is jammed due to over populated
-//                 3 = This ID is expired    9 = No MSG
-//                 4 = Rejected from Server  100 = This ID has been totally erased
-//                 5 = You have been blocked by the GM Team
-//                 all other values are 'No MSG', then use state 9 please.
-//    'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
-//
-//  timeadd <account_name> <modifier>
-//    Adds or substracts time from the validity limit of an account.
-//    Modifier is done as follows:
-//      Adjustment value (-1, 1, +1, etc...)
-//      Modified element:
-//        a or y: year
-//        m:  month
-//        j or d: day
-//        h:  hour
-//        mn: minute
-//        s:  second
-//    <example> timeadd testname +1m-2mn1s-6y
-//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-//  NOTE: You can not modify a unlimited validity limit.
-//        If you want modify it, you want probably create a limited validity limit.
-//        So, at first, you must set the validity limit to a date/time.
-//
-//  timeset <account_name> yyyy/mm/dd [hh:mm:ss]
-//    Changes the validity limit of an account.
-//    Default time [hh:mm:ss]: 23:59:59.
-//  timeset <account_name> 0
-//    Gives an unlimited validity limit (0 = unlimited).
-//
-//  unban/unbanish <account name>
-//    Unban an account.
-//    Like banset <account name> 0.
-//
-//  unblock <account name>
-//    Set state 0 (Account ok) to an account.
-//    Like state <account name> 0.
-//
-//  version
-//    Display the version of the login-server.
-//
-//  who <account name>
-//    Displays complete information of an account.
-//
-//-------------------------------------------------------------------------
-int  login_fd;
-int  login_ip;
-int  bytes_to_read = 0;         // flag to know if we waiting bytes from login-server
-char command[1024];
-char parameters[1024];
-int  list_first, list_last, list_type, list_count;  // parameter to display a list of accounts
-int  already_exit_function = 0; // sometimes, the exit function is called twice... so, don't log twice the message
-
-//------------------------------
-// Writing function of logs file
-//------------------------------
-int ladmin_log (const char *fmt, ...)
-{
-    FILE *logfp;
-    va_list ap;
-    struct timeval tv;
-    char tmpstr[2048];
-
-    va_start (ap, fmt);
-
-    logfp = fopen_ (ladmin_log_filename, "a");
-    if (logfp)
-    {
-        if (fmt[0] == '\0')     // jump a line if no message
-            fprintf (logfp, "\n");
-        else
-        {
-            gettimeofday (&tv, NULL);
-            strftime (tmpstr, 24, date_format, localtime (&(tv.tv_sec)));
-            sprintf (tmpstr + strlen (tmpstr), ".%03d: %s",
-                     (int) tv.tv_usec / 1000, fmt);
-            vfprintf (logfp, tmpstr, ap);
-        }
-        fclose_ (logfp);
-    }
-
-    va_end (ap);
-    return 0;
-}
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars (unsigned char *str)
-{
-    int  i;
-    int  change = 0;
-
-    for (i = 0; str[i]; i++)
-    {
-        if (str[i] < 32)
-        {
-            str[i] = '_';
-            change = 1;
-        }
-    }
-
-    return change;
-}
-
-//---------------------------------------------
-// Function to return ordonal text of a number.
-//---------------------------------------------
-const char *makeordinal (int number)
-{
-    if (defaultlanguage == 'F')
-    {
-        if (number == 0)
-            return "";
-        else if (number == 1)
-            return "er";
-        else
-            return "ème";
-    }
-    else
-    {
-        if ((number % 10) < 4 && (number % 10) != 0
-            && (number < 10 || number > 20))
-        {
-            if ((number % 10) == 1)
-                return "st";
-            else if ((number % 10) == 2)
-                return "nd";
-            else
-                return "rd";
-        }
-        else
-        {
-            return "th";
-        }
-    }
-    return "";
-}
-
-//-----------------------------------------------------------------------------------------
-// Function to test of the validity of an account name (return 0 if incorrect, and 1 if ok)
-//-----------------------------------------------------------------------------------------
-int verify_accountname (char *account_name)
-{
-    int  i;
-
-    for (i = 0; account_name[i]; i++)
-    {
-        if (account_name[i] < 32)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
-                     i + 1, makeordinal (i + 1));
-                ladmin_log
-                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
-                      i + 1, makeordinal (i + 1));
-            }
-            else
-            {
-                printf
-                    ("Illegal character found in the account name (%d%s character).\n",
-                     i + 1, makeordinal (i + 1));
-                ladmin_log
-                    ("Illegal character found in the account name (%d%s character).\n",
-                      i + 1, makeordinal (i + 1));
-            }
-            return 0;
-        }
-    }
-
-    if (strlen (account_name) < 4)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
-            ladmin_log
-                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
-        }
-        else
-        {
-            printf
-                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
-            ladmin_log
-                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
-        }
-        return 0;
-    }
-
-    if (strlen (account_name) > 23)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n");
-            ladmin_log
-                ("Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n");
-        }
-        else
-        {
-            printf
-                ("Account name is too long. Please input an account name of 4-23 bytes.\n");
-            ladmin_log
-                ("Account name is too long. Please input an account name of 4-23 bytes.\n");
-        }
-        return 0;
-    }
-
-    return 1;
-}
-
-//---------------------------------------------------
-// E-mail check: return 0 (not correct) or 1 (valid).
-//---------------------------------------------------
-int e_mail_check (unsigned char *email)
-{
-    char ch;
-    unsigned char *last_arobas;
-
-    // athena limits
-    if (strlen (email) < 3 || strlen (email) > 39)
-        return 0;
-
-    // part of RFC limits (official reference of e-mail description)
-    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
-        return 0;
-
-    if (email[strlen (email) - 1] == '.')
-        return 0;
-
-    last_arobas = strrchr (email, '@');
-
-    if (strstr (last_arobas, "@.") != NULL ||
-        strstr (last_arobas, "..") != NULL)
-        return 0;
-
-    for (ch = 1; ch < 32; ch++)
-    {
-        if (strchr (last_arobas, ch) != NULL)
-        {
-            return 0;
-            break;
-        }
-    }
-
-    if (strchr (last_arobas, ' ') != NULL ||
-        strchr (last_arobas, ';') != NULL)
-        return 0;
-
-    // all correct
-    return 1;
-}
-
-//----------------------------------
-// Sub-function: Input of a password
-//----------------------------------
-int typepasswd (char *password)
-{
-    char password1[1023], password2[1023];
-    int  letter;
-    int  i;
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Aucun mot de passe n'a été donné. Demande d'un mot de passe.\n");
-    }
-    else
-    {
-        ladmin_log ("No password was given. Request to obtain a password.\n");
-    }
-
-    memset (password1, '\0', sizeof (password1));
-    memset (password2, '\0', sizeof (password2));
-    if (defaultlanguage == 'F')
-        printf ("\033[1;36m Entrez le mot de passe > \033[0;32;42m");
-    else
-        printf ("\033[1;36m Type the password > \033[0;32;42m");
-    i = 0;
-    while ((letter = getchar ()) != '\n')
-        password1[i++] = letter;
-    if (defaultlanguage == 'F')
-        printf
-            ("\033[0m\033[1;36m Ré-entrez le mot de passe > \033[0;32;42m");
-    else
-        printf ("\033[0m\033[1;36m Verify the password > \033[0;32;42m");
-    i = 0;
-    while ((letter = getchar ()) != '\n')
-        password2[i++] = letter;
-
-    printf ("\033[0m");
-    fflush (stdout);
-    fflush (stdin);
-
-    if (strcmp (password1, password2) != 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n");
-            ladmin_log
-                ("Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n");
-            ladmin_log ("  Premier mot de passe: %s, second mot de passe: %s.\n",
-                         password1, password2);
-        }
-        else
-        {
-            printf
-                ("Password verification failed. Please input same password.\n");
-            ladmin_log
-                ("Password verification failed. Please input same password.\n");
-            ladmin_log ("  First password: %s, second password: %s.\n",
-                        password1, password2);
-        }
-        return 0;
-    }
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log ("Mot de passe saisi: %s.\n", password1);
-    }
-    else
-    {
-        ladmin_log ("Typed password: %s.\n", password1);
-    }
-    strcpy (password, password1);
-    return 1;
-}
-
-//------------------------------------------------------------------------------------
-// Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
-//------------------------------------------------------------------------------------
-int verify_password (char *password)
-{
-    int  i;
-
-    for (i = 0; password[i]; i++)
-    {
-        if (password[i] < 32)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Caractère interdit trouvé dans le mot de passe (%d%s caractère).\n",
-                     i + 1, makeordinal (i + 1));
-                ladmin_log
-                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
-                      i + 1, makeordinal (i + 1));
-            }
-            else
-            {
-                printf
-                    ("Illegal character found in the password (%d%s character).\n",
-                     i + 1, makeordinal (i + 1));
-                ladmin_log
-                    ("Illegal character found in the password (%d%s character).\n",
-                      i + 1, makeordinal (i + 1));
-            }
-            return 0;
-        }
-    }
-
-    if (strlen (password) < 4)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
-            ladmin_log
-                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
-        }
-        else
-        {
-            printf
-                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
-            ladmin_log
-                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
-        }
-        return 0;
-    }
-
-    if (strlen (password) > 23)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n");
-            ladmin_log
-                ("Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n");
-        }
-        else
-        {
-            printf
-                ("Password is too long. Please input a password of 4-23 bytes.\n");
-            ladmin_log
-                ("Password is too long. Please input a password of 4-23 bytes.\n");
-        }
-        return 0;
-    }
-
-    return 1;
-}
-
-//------------------------------------------------------------------
-// Sub-function: Check the name of a command (return complete name)
-//-----------------------------------------------------------------
-int check_command (char *command)
-{
-// help
-    if (strncmp (command, "aide", 2) == 0 && strncmp (command, "aide", strlen (command)) == 0)  // not 1 letter command: 'aide' or 'add'?
-        strcpy (command, "aide");
-    else if (strncmp (command, "help", 1) == 0
-             && strncmp (command, "help", strlen (command)) == 0)
-        strcpy (command, "help");
-// general commands
-    else if (strncmp (command, "add", 2) == 0 && strncmp (command, "add", strlen (command)) == 0)   // not 1 letter command: 'aide' or 'add'?
-        strcpy (command, "add");
-    else if ((strncmp (command, "ban", 3) == 0
-              && strncmp (command, "ban", strlen (command)) == 0)
-             || (strncmp (command, "banish", 4) == 0
-                 && strncmp (command, "banish", strlen (command)) == 0))
-        strcpy (command, "ban");
-    else if ((strncmp (command, "banadd", 4) == 0 && strncmp (command, "banadd", strlen (command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
-             strcmp (command, "ba") == 0)
-        strcpy (command, "banadd");
-    else if ((strncmp (command, "banset", 4) == 0 && strncmp (command, "banset", strlen (command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
-             strcmp (command, "bs") == 0)
-        strcpy (command, "banset");
-    else if (strncmp (command, "block", 2) == 0
-             && strncmp (command, "block", strlen (command)) == 0)
-        strcpy (command, "block");
-    else if (strncmp (command, "check", 2) == 0 && strncmp (command, "check", strlen (command)) == 0)   // not 1 letter command: 'check' or 'create'?
-        strcpy (command, "check");
-    else if (strncmp (command, "create", 2) == 0 && strncmp (command, "create", strlen (command)) == 0) // not 1 letter command: 'check' or 'create'?
-        strcpy (command, "create");
-    else if (strncmp (command, "delete", 1) == 0
-             && strncmp (command, "delete", strlen (command)) == 0)
-        strcpy (command, "delete");
-    else if ((strncmp (command, "email", 2) == 0 && strncmp (command, "email", strlen (command)) == 0) ||   // not 1 letter command: 'email', 'end' or 'exit'?
-             (strncmp (command, "e-mail", 2) == 0
-              && strncmp (command, "e-mail", strlen (command)) == 0))
-        strcpy (command, "email");
-    else if (strncmp (command, "getcount", 2) == 0 && strncmp (command, "getcount", strlen (command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
-        strcpy (command, "getcount");
-//  else if (strncmp(command, "gm", 2) == 0 && strncmp(command, "gm", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
-//      strcpy(command, "gm");
-//  else if (strncmp(command, "id", 2) == 0 && strncmp(command, "id", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
-//      strcpy(command, "id");
-    else if (strncmp (command, "info", 2) == 0 && strncmp (command, "info", strlen (command)) == 0) // not 1 letter command: 'id' or 'info'?
-        strcpy (command, "info");
-//  else if (strncmp(command, "kami", 4) == 0 && strncmp(command, "kami", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-//      strcpy(command, "kami");
-//  else if (strncmp(command, "kamib", 5) == 0 && strncmp(command, "kamib", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
-//      strcpy(command, "kamib");
-    else if ((strncmp (command, "language", 2) == 0 && strncmp (command, "language", strlen (command)) == 0))   // not 1 letter command: 'language' or 'list'?
-        strcpy (command, "language");
-    else if ((strncmp (command, "list", 2) == 0 && strncmp (command, "list", strlen (command)) == 0) || // 'list' is default list command // not 1 letter command: 'language' or 'list'?
-             strcmp (command, "ls") == 0)
-        strcpy (command, "list");
-    else if (strncmp (command, "itemfrob", 6) == 0)
-        strcpy (command, "itemfrob");
-    else if ((strncmp (command, "listban", 5) == 0
-              && strncmp (command, "listban", strlen (command)) == 0)
-             || (strncmp (command, "lsban", 3) == 0
-                 && strncmp (command, "lsban", strlen (command)) == 0)
-             || strcmp (command, "lb") == 0)
-        strcpy (command, "listban");
-    else if ((strncmp (command, "listgm", 5) == 0
-              && strncmp (command, "listgm", strlen (command)) == 0)
-             || (strncmp (command, "lsgm", 3) == 0
-                 && strncmp (command, "lsgm", strlen (command)) == 0)
-             || strcmp (command, "lg") == 0)
-        strcpy (command, "listgm");
-    else if ((strncmp (command, "listok", 5) == 0
-              && strncmp (command, "listok", strlen (command)) == 0)
-             || (strncmp (command, "lsok", 3) == 0
-                 && strncmp (command, "lsok", strlen (command)) == 0)
-             || strcmp (command, "lo") == 0)
-        strcpy (command, "listok");
-    else if (strncmp (command, "memo", 1) == 0
-             && strncmp (command, "memo", strlen (command)) == 0)
-        strcpy (command, "memo");
-    else if (strncmp (command, "name", 1) == 0
-             && strncmp (command, "name", strlen (command)) == 0)
-        strcpy (command, "name");
-    else if ((strncmp (command, "password", 1) == 0
-              && strncmp (command, "password", strlen (command)) == 0)
-             || strcmp (command, "passwd") == 0)
-        strcpy (command, "password");
-    else if (strncmp (command, "reloadgm", 1) == 0
-             && strncmp (command, "reloadgm", strlen (command)) == 0)
-        strcpy (command, "reloadgm");
-    else if (strncmp (command, "search", 3) == 0 && strncmp (command, "search", strlen (command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-        strcpy (command, "search"); // not 2 letters command: 'search' or 'sex'?
-//  else if (strncmp(command, "sex", 3) == 0 && strncmp(command, "sex", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
-//      strcpy(command, "sex"); // not 2 letters command: 'search' or 'sex'?
-    else if (strncmp (command, "state", 2) == 0 && strncmp (command, "state", strlen (command)) == 0)   // not 1 letter command: 'search', 'state' or 'sex'?
-        strcpy (command, "state");
-    else if ((strncmp (command, "timeadd", 5) == 0 && strncmp (command, "timeadd", strlen (command)) == 0) ||   // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
-             strcmp (command, "ta") == 0)
-        strcpy (command, "timeadd");
-    else if ((strncmp (command, "timeset", 5) == 0 && strncmp (command, "timeset", strlen (command)) == 0) ||   // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
-             strcmp (command, "ts") == 0)
-        strcpy (command, "timeset");
-    else if ((strncmp (command, "unban", 5) == 0
-              && strncmp (command, "unban", strlen (command)) == 0)
-             || (strncmp (command, "unbanish", 4) == 0
-                 && strncmp (command, "unbanish", strlen (command)) == 0))
-        strcpy (command, "unban");
-    else if (strncmp (command, "unblock", 4) == 0
-             && strncmp (command, "unblock", strlen (command)) == 0)
-        strcpy (command, "unblock");
-    else if (strncmp (command, "version", 1) == 0
-             && strncmp (command, "version", strlen (command)) == 0)
-        strcpy (command, "version");
-    else if (strncmp (command, "who", 1) == 0
-             && strncmp (command, "who", strlen (command)) == 0)
-        strcpy (command, "who");
-// quit
-    else if (strncmp (command, "quit", 1) == 0
-             && strncmp (command, "quit", strlen (command)) == 0)
-        strcpy (command, "quit");
-    else if (strncmp (command, "exit", 2) == 0 && strncmp (command, "exit", strlen (command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
-        strcpy (command, "exit");
-    else if (strncmp (command, "end", 2) == 0 && strncmp (command, "end", strlen (command)) == 0)   // not 1 letter command: 'email', 'end' or 'exit'?
-        strcpy (command, "end");
-
-    return 0;
-}
-
-//-----------------------------------------
-// Sub-function: Display commands of ladmin
-//-----------------------------------------
-void display_help (char *param, int language)
-{
-    char command[1023];
-    int  i;
-
-    memset (command, '\0', sizeof (command));
-
-    if (sscanf (param, "%s ", command) < 1 || strlen (command) == 0)
-        strcpy (command, "");   // any value that is not a command
-
-    if (command[0] == '?')
-    {
-        if (defaultlanguage == 'F')
-            strcpy (command, "aide");
-        else
-            strcpy (command, "help");
-    }
-
-    // lowercase for command
-    for (i = 0; command[i]; i++)
-        command[i] = tolower (command[i]);
-
-    // Analyse of the command
-    check_command (command);    // give complete name to the command
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log ("Affichage des commandes ou d'une commande.\n");
-    }
-    else
-    {
-        ladmin_log ("Displaying of the commands or a command.\n");
-    }
-
-    if (language == 1)
-    {
-        if (strcmp (command, "aide") == 0)
-        {
-            printf ("aide/help/?\n");
-            printf ("  Affiche la description des commandes\n");
-            printf ("aide/help/? [commande]\n");
-            printf ("  Affiche la description de la commande specifiée\n");
-        }
-        else if (strcmp (command, "help") == 0)
-        {
-            printf ("aide/help/?\n");
-            printf ("  Display the description of the commands\n");
-            printf ("aide/help/? [command]\n");
-            printf ("  Display the description of the specified command\n");
-// general commands
-        }
-        else if (strcmp (command, "add") == 0)
-        {
-            printf ("add <nomcompte> <sexe> <motdepasse>\n");
-            printf ("  Crée un compte avec l'email par défaut (a@a.com).\n");
-            printf
-                ("  Concernant le sexe, seule la première lettre compte (F ou M).\n");
-            printf
-                ("  L'e-mail est a@a.com (e-mail par défaut). C'est comme n'avoir aucun e-mail.\n");
-            printf
-                ("  Lorsque motdepasse est omis, la saisie se fait sans que la frappe se voit.\n");
-            printf ("  <exemple> add testname Male testpass\n");
-        }
-        else if (strcmp (command, "ban") == 0)
-        {
-            printf ("ban/banish aaaa/mm/jj hh:mm:ss <nom compte>\n");
-            printf ("  Change la date de fin de bannissement d'un compte.\n");
-            printf ("  Comme banset, mais <nom compte> est à la fin.\n");
-        }
-        else if (strcmp (command, "banadd") == 0)
-        {
-            printf ("banadd <nomcompte> <Modificateur>\n");
-            printf
-                ("  Ajoute ou soustrait du temps à la date de banissement d'un compte.\n");
-            printf ("  Les modificateurs sont construits comme suit:\n");
-            printf ("    Valeur d'ajustement (-1, 1, +1, etc...)\n");
-            printf ("    Elément modifié:\n");
-            printf ("      a ou y: année\n");
-            printf ("      m:      mois\n");
-            printf ("      j ou d: jour\n");
-            printf ("      h:      heure\n");
-            printf ("      mn:     minute\n");
-            printf ("      s:      seconde\n");
-            printf ("  <exemple> banadd testname +1m-2mn1s-6a\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            printf
-                ("NOTE: Si vous modifez la date de banissement d'un compte non bani,\n");
-            printf
-                ("      vous indiquez comme date (le moment actuel +- les ajustements)\n");
-        }
-        else if (strcmp (command, "banset") == 0)
-        {
-            printf ("banset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf ("  Change la date de fin de bannissement d'un compte.\n");
-            printf ("  Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            printf ("banset <nomcompte> 0\n");
-            printf ("  Débanni un compte (0 = de-banni).\n");
-        }
-        else if (strcmp (command, "block") == 0)
-        {
-            printf ("block <nom compte>\n");
-            printf
-                ("  Place le status d'un compte à 5 (You have been blocked by the GM Team).\n");
-            printf
-                ("  La commande est l'équivalent de state <nom_compte> 5.\n");
-        }
-        else if (strcmp (command, "check") == 0)
-        {
-            printf ("check <nomcompte> <motdepasse>\n");
-            printf
-                ("  Vérifie la validité d'un mot de passe pour un compte\n");
-            printf ("  NOTE: Le serveur n'enverra jamais un mot de passe.\n");
-            printf
-                ("        C'est la seule méthode que vous possédez pour savoir\n");
-            printf
-                ("        si un mot de passe est le bon. L'autre méthode est\n");
-            printf
-                ("        d'avoir un accès ('physique') au fichier des comptes.\n");
-        }
-        else if (strcmp (command, "create") == 0)
-        {
-            printf ("create <nomcompte> <sexe> <email> <motdepasse>\n");
-            printf ("  Comme la commande add, mais avec l'e-mail en plus.\n");
-            printf
-                ("  <exemple> create testname Male mon@mail.com testpass\n");
-        }
-        else if (strcmp (command, "delete") == 0)
-        {
-            printf ("del <nom compte>\n");
-            printf ("  Supprime un compte.\n");
-            printf
-                ("  La commande demande confirmation. Après confirmation, le compte est détruit.\n");
-        }
-        else if (strcmp (command, "email") == 0)
-        {
-            printf ("email <nomcompte> <email>\n");
-            printf ("  Modifie l'e-mail d'un compte.\n");
-        }
-        else if (strcmp (command, "getcount") == 0)
-        {
-            printf ("getcount\n");
-            printf
-                ("  Donne le nombre de joueurs en ligne par serveur de char.\n");
-        }
-        else if (strcmp (command, "gm") == 0)
-        {
-            printf ("gm <nomcompte> [Niveau_GM]\n");
-            printf ("  Modifie le niveau de GM d'un compte.\n");
-            printf
-                ("  Valeur par défaut: 0 (suppression du niveau de GM).\n");
-            printf ("  <exemple> gm nomtest 80\n");
-        }
-        else if (strcmp (command, "id") == 0)
-        {
-            printf ("id <nom compte>\n");
-            printf ("  Donne l'id d'un compte.\n");
-        }
-        else if (strcmp (command, "info") == 0)
-        {
-            printf ("info <idcompte>\n");
-            printf ("  Affiche les informations sur un compte.\n");
-        }
-        else if (strcmp (command, "kami") == 0)
-        {
-            printf ("kami <message>\n");
-            printf
-                ("  Envoi un message général sur tous les serveurs de map (en jaune).\n");
-        }
-        else if (strcmp (command, "kamib") == 0)
-        {
-            printf ("kamib <message>\n");
-            printf
-                ("  Envoi un message général sur tous les serveurs de map (en bleu).\n");
-        }
-        else if (strcmp (command, "language") == 0)
-        {
-            printf ("language <langue>\n");
-            printf ("  Change la langue d'affichage.\n");
-            printf ("  Langues possibles: 'Français' ou 'English'.\n");
-        }
-        else if (strcmp (command, "list") == 0)
-        {
-            printf ("list/ls [Premier_id [Dernier_id]]\n");
-            printf ("  Affiche une liste de comptes.\n");
-            printf
-                ("  'Premier_id', 'Dernier_id': indique les identifiants de départ et de fin.\n");
-            printf
-                ("  La recherche par nom n'est pas possible avec cette commande.\n");
-            printf ("  <example> list 10 9999999\n");
-        }
-        else if (strcmp (command, "itemfrob") == 0)
-        {
-            printf ("Not localised yet.\n");
-        }
-        else if (strcmp (command, "listban") == 0)
-        {
-            printf ("listBan/lsBan [Premier_id [Dernier_id]]\n");
-            printf
-                ("  Comme list/ls, mais seulement pour les comptes avec statut ou bannis.\n");
-        }
-        else if (strcmp (command, "listgm") == 0)
-        {
-            printf ("listGM/lsGM [Premier_id [Dernier_id]]\n");
-            printf ("  Comme list/ls, mais seulement pour les comptes GM.\n");
-        }
-        else if (strcmp (command, "listok") == 0)
-        {
-            printf ("listOK/lsOK [Premier_id [Dernier_id]]\n");
-            printf
-                ("  Comme list/ls, mais seulement pour les comptes sans statut et non bannis.\n");
-        }
-        else if (strcmp (command, "memo") == 0)
-        {
-            printf ("memo <nomcompte> <memo>\n");
-            printf ("  Modifie le mémo d'un compte.\n");
-            printf
-                ("  'memo': Il peut avoir jusqu'à 253 caractères (avec des espaces ou non).\n");
-        }
-        else if (strcmp (command, "name") == 0)
-        {
-            printf ("name <idcompte>\n");
-            printf ("  Donne le nom d'un compte.\n");
-        }
-        else if (strcmp (command, "password") == 0)
-        {
-            printf ("passwd <nomcompte> <nouveaumotdepasse>\n");
-            printf ("  Change le mot de passe d'un compte.\n");
-            printf ("  Lorsque nouveaumotdepasse est omis,\n");
-            printf ("  la saisie se fait sans que la frappe ne se voit.\n");
-        }
-        else if (strcmp (command, "reloadgm") == 0)
-        {
-            printf ("reloadGM\n");
-            printf ("  Reload GM configuration file\n");
-        }
-        else if (strcmp (command, "search") == 0)
-        {
-            printf ("search <expression>\n");
-            printf ("  Cherche des comptes.\n");
-            printf ("  Affiche les comptes dont les noms correspondent.\n");
-//          printf("search -r/-e/--expr/--regex <expression>\n");
-//          printf("  Cherche des comptes par expression regulière.\n");
-//          printf("  Affiche les comptes dont les noms correspondent.\n");
-        }
-        else if (strcmp (command, "sex") == 0)
-        {
-            printf ("sex <nomcompte> <sexe>\n");
-            printf ("  Modifie le sexe d'un compte.\n");
-            printf ("  <exemple> sex testname Male\n");
-        }
-        else if (strcmp (command, "state") == 0)
-        {
-            printf ("state <nomcompte> <nouveaustatut> <message_erreur_7>\n");
-            printf ("  Change le statut d'un compte.\n");
-            printf
-                ("  'nouveaustatut': Le statut est le même que celui du packet 0x006a + 1.\n");
-            printf ("               les possibilités sont:\n");
-            printf ("               0 = Compte ok\n");
-            printf ("               1 = Unregistered ID\n");
-            printf ("               2 = Incorrect Password\n");
-            printf ("               3 = This ID is expired\n");
-            printf ("               4 = Rejected from Server\n");
-            printf
-                ("               5 = You have been blocked by the GM Team\n");
-            printf
-                ("               6 = Your Game's EXE file is not the latest version\n");
-            printf
-                ("               7 = You are Prohibited to log in until...\n");
-            printf
-                ("               8 = Server is jammed due to over populated\n");
-            printf ("               9 = No MSG\n");
-            printf ("               100 = This ID has been totally erased\n");
-            printf
-                ("               all other values are 'No MSG', then use state 9 please.\n");
-            printf ("  'message_erreur_7': message du code erreur 6 =\n");
-            printf
-                ("                      = Your are Prohibited to log in until... (packet 0x006a)\n");
-        }
-        else if (strcmp (command, "timeadd") == 0)
-        {
-            printf ("timeadd <nomcompte> <modificateur>\n");
-            printf
-                ("  Ajoute/soustrait du temps à la limite de validité d'un compte.\n");
-            printf ("  Le modificateur est composé comme suit:\n");
-            printf ("    Valeur modificatrice (-1, 1, +1, etc...)\n");
-            printf ("    Elément modifié:\n");
-            printf ("      a ou y: année\n");
-            printf ("      m:      mois\n");
-            printf ("      j ou d: jour\n");
-            printf ("      h:      heure\n");
-            printf ("      mn:     minute\n");
-            printf ("      s:      seconde\n");
-            printf ("  <exemple> timeadd testname +1m-2mn1s-6a\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            printf
-                ("NOTE: Vous ne pouvez pas modifier une limite de validité illimitée. Si vous\n");
-            printf
-                ("      désirez le faire, c'est que vous voulez probablement créer un limite de\n");
-            printf
-                ("      validité limitée. Donc, en premier, fixé une limite de valitidé.\n");
-        }
-        else if (strcmp (command, "timeadd") == 0)
-        {
-            printf ("timeset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf ("  Change la limite de validité d'un compte.\n");
-            printf ("  Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            printf ("timeset <nomcompte> 0\n");
-            printf
-                ("  Donne une limite de validité illimitée (0 = illimitée).\n");
-        }
-        else if (strcmp (command, "unban") == 0)
-        {
-            printf ("unban/unbanish <nom compte>\n");
-            printf ("  Ote le banissement d'un compte.\n");
-            printf
-                ("  La commande est l'équivalent de banset <nom_compte> 0.\n");
-        }
-        else if (strcmp (command, "unblock") == 0)
-        {
-            printf ("unblock <nom compte>\n");
-            printf ("  Place le status d'un compte à 0 (Compte ok).\n");
-            printf
-                ("  La commande est l'équivalent de state <nom_compte> 0.\n");
-        }
-        else if (strcmp (command, "version") == 0)
-        {
-            printf ("version\n");
-            printf ("  Affiche la version du login-serveur.\n");
-        }
-        else if (strcmp (command, "who") == 0)
-        {
-            printf ("who <nom compte>\n");
-            printf ("  Affiche les informations sur un compte.\n");
-// quit
-        }
-        else if (strcmp (command, "quit") == 0 ||
-                 strcmp (command, "exit") == 0 ||
-                 strcmp (command, "end") == 0)
-        {
-            printf ("quit/end/exit\n");
-            printf ("  Fin du programme d'administration.\n");
-// unknown command
-        }
-        else
-        {
-            if (strlen (command) > 0)
-                printf
-                    ("Commande inconnue [%s] pour l'aide. Affichage de toutes les commandes.\n",
-                     command);
-            printf
-                (" aide/help/?                             -- Affiche cet aide\n");
-            printf
-                (" aide/help/? [commande]                  -- Affiche l'aide de la commande\n");
-            printf
-                (" add <nomcompte> <sexe> <motdepasse>     -- Crée un compte (sans email)\n");
-            printf
-                (" ban/banish aaaa/mm/jj hh:mm:ss <nom compte> -- Fixe la date finale de banismnt\n");
-            printf
-                (" banadd/ba <nomcompte> <modificateur>    -- Ajout/soustrait du temps à la\n");
-            printf
-                ("   exemple: ba moncompte +1m-2mn1s-2y       date finale de banissement\n");
-            printf
-                (" banset/bs <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la date fin de banisemnt\n");
-            printf
-                (" banset/bs <nomcompte> 0                 -- Dé-banis un compte.\n");
-            printf
-                (" block <nom compte>  -- Mets le status d'un compte à 5 (blocked by the GM Team)\n");
-            printf
-                (" check <nomcompte> <motdepasse>          -- Vérifie un mot de passe d'un compte\n");
-            printf
-                (" create <nomcompte> <sexe> <email> <motdepasse> -- Crée un compte (avec email)\n");
-            printf
-                (" del <nom compte>                        -- Supprime un compte\n");
-            printf
-                (" email <nomcompte> <email>               -- Modifie l'e-mail d'un compte\n");
-            printf
-                (" getcount                                -- Donne le nb de joueurs en ligne\n");
-            printf
-                ("  gm <nomcompte> [Niveau_GM]              -- Modifie le niveau de GM d'un compte\n");
-            printf
-                (" id <nom compte>                         -- Donne l'id d'un compte\n");
-            printf
-                (" info <idcompte>                         -- Affiche les infos sur un compte\n");
-            printf
-                (" kami <message>                          -- Envoi un message général (en jaune)\n");
-            printf
-                (" kamib <message>                         -- Envoi un message général (en bleu)\n");
-            printf
-                (" language <langue>                       -- Change la langue d'affichage.\n");
-            printf
-                (" list/ls [Premier_id [Dernier_id] ]      -- Affiche une liste de comptes\n");
-            printf
-                (" listBan/lsBan [Premier_id [Dernier_id] ] -- Affiche une liste de comptes\n");
-            printf
-                ("                                             avec un statut ou bannis\n");
-            printf
-                (" listGM/lsGM [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes GM\n");
-            printf
-                (" listOK/lsOK [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes\n");
-            printf
-                ("                                            sans status et non bannis\n");
-            printf
-                (" memo <nomcompte> <memo>                 -- Modifie le memo d'un compte\n");
-            printf
-                (" name <idcompte>                         -- Donne le nom d'un compte\n");
-            printf
-                (" passwd <nomcompte> <nouveaumotdepasse>  -- Change le mot de passe d'un compte\n");
-            printf
-                (" quit/end/exit                           -- Fin du programme d'administation\n");
-            printf
-                (" reloadGM                              -- Recharger le fichier de config des GM\n");
-            printf
-                (" search <expression>                     -- Cherche des comptes\n");
-//          printf(" search -e/-r/--expr/--regex <expression> -- Cherche des comptes par REGEX\n");
-            printf
-                (" sex <nomcompte> <sexe>                  -- Modifie le sexe d'un compte\n");
-            printf
-                (" state <nomcompte> <nouveaustatut> <messageerr7> -- Change le statut d'1 compte\n");
-            printf
-                (" timeadd/ta <nomcompte> <modificateur>   -- Ajout/soustrait du temps à la\n");
-            printf
-                ("   exemple: ta moncompte +1m-2mn1s-2y       limite de validité\n");
-            printf
-                (" timeset/ts <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la limite de validité\n");
-            printf
-                (" timeset/ts <nomcompte> 0                -- limite de validité = illimitée\n");
-            printf
-                (" unban/unbanish <nom compte>             -- Ote le banissement d'un compte\n");
-            printf
-                (" unblock <nom compte>             -- Mets le status d'un compte à 0 (Compte ok)\n");
-            printf
-                (" version                                 -- Donne la version du login-serveur\n");
-            printf
-                (" who <nom compte>                        -- Affiche les infos sur un compte\n");
-            printf
-                (" Note: Pour les noms de compte avec des espaces, tapez \"<nom compte>\" (ou ').\n");
-        }
-    }
-    else
-    {
-        if (strcmp (command, "aide") == 0)
-        {
-            printf ("aide/help/?\n");
-            printf ("  Display the description of the commands\n");
-            printf ("aide/help/? [command]\n");
-            printf ("  Display the description of the specified command\n");
-        }
-        else if (strcmp (command, "help") == 0)
-        {
-            printf ("aide/help/?\n");
-            printf ("  Display the description of the commands\n");
-            printf ("aide/help/? [command]\n");
-            printf ("  Display the description of the specified command\n");
-// general commands
-        }
-        else if (strcmp (command, "add") == 0)
-        {
-            printf ("add <account_name> <sex> <password>\n");
-            printf
-                ("  Create an account with the default email (a@a.com).\n");
-            printf
-                ("  Concerning the sex, only the first letter is used (F or M).\n");
-            printf
-                ("  The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n");
-            printf ("  When the password is omitted,\n");
-            printf
-                ("  the input is done without displaying of the pressed keys.\n");
-            printf ("  <example> add testname Male testpass\n");
-        }
-        else if (strcmp (command, "ban") == 0)
-        {
-            printf ("ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-            printf
-                ("  Changes the final date of a banishment of an account.\n");
-            printf ("  Like banset, but <account name> is at end.\n");
-        }
-        else if (strcmp (command, "banadd") == 0)
-        {
-            printf ("banadd <account_name> <modifier>\n");
-            printf
-                ("  Adds or substracts time from the final date of a banishment of an account.\n");
-            printf ("  Modifier is done as follows:\n");
-            printf ("    Adjustment value (-1, 1, +1, etc...)\n");
-            printf ("    Modified element:\n");
-            printf ("      a or y: year\n");
-            printf ("      m:  month\n");
-            printf ("      j or d: day\n");
-            printf ("      h:  hour\n");
-            printf ("      mn: minute\n");
-            printf ("      s:  second\n");
-            printf ("  <example> banadd testname +1m-2mn1s-6y\n");
-            printf
-                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("            and 6 years at the same time.\n");
-            printf
-                ("NOTE: If you modify the final date of a non-banished account,\n");
-            printf
-                ("      you fix the final date to (actual time +- adjustments)\n");
-        }
-        else if (strcmp (command, "banset") == 0)
-        {
-            printf ("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf
-                ("  Changes the final date of a banishment of an account.\n");
-            printf ("  Default time [hh:mm:ss]: 23:59:59.\n");
-            printf ("banset <account_name> 0\n");
-            printf ("  Set a non-banished account (0 = unbanished).\n");
-        }
-        else if (strcmp (command, "block") == 0)
-        {
-            printf ("block <account name>\n");
-            printf
-                ("  Set state 5 (You have been blocked by the GM Team) to an account.\n");
-            printf ("  This command works like state <account_name> 5.\n");
-        }
-        else if (strcmp (command, "check") == 0)
-        {
-            printf ("check <account_name> <password>\n");
-            printf ("  Check the validity of a password for an account.\n");
-            printf ("  NOTE: Server will never sends back a password.\n");
-            printf
-                ("        It's the only method you have to know if a password is correct.\n");
-            printf
-                ("        The other method is to have a ('physical') access to the accounts file.\n");
-        }
-        else if (strcmp (command, "create") == 0)
-        {
-            printf ("create <account_name> <sex> <email> <password>\n");
-            printf ("  Like the 'add' command, but with e-mail moreover.\n");
-            printf
-                ("  <example> create testname Male my@mail.com testpass\n");
-        }
-        else if (strcmp (command, "delete") == 0)
-        {
-            printf ("del <account name>\n");
-            printf ("  Remove an account.\n");
-            printf
-                ("  This order requires confirmation. After confirmation, the account is deleted.\n");
-        }
-        else if (strcmp (command, "email") == 0)
-        {
-            printf ("email <account_name> <email>\n");
-            printf ("  Modify the e-mail of an account.\n");
-        }
-        else if (strcmp (command, "getcount") == 0)
-        {
-            printf ("getcount\n");
-            printf
-                ("  Give the number of players online on all char-servers.\n");
-        }
-        else if (strcmp (command, "gm") == 0)
-        {
-            printf ("gm <account_name> [GM_level]\n");
-            printf ("  Modify the GM level of an account.\n");
-            printf ("  Default value remove GM level (GM level = 0).\n");
-            printf ("  <example> gm testname 80\n");
-        }
-        else if (strcmp (command, "id") == 0)
-        {
-            printf ("id <account name>\n");
-            printf ("  Give the id of an account.\n");
-        }
-        else if (strcmp (command, "info") == 0)
-        {
-            printf ("info <account_id>\n");
-            printf ("  Display complete information of an account.\n");
-        }
-        else if (strcmp (command, "kami") == 0)
-        {
-            printf ("kami <message>\n");
-            printf
-                ("  Sends a broadcast message on all map-server (in yellow).\n");
-        }
-        else if (strcmp (command, "kamib") == 0)
-        {
-            printf ("kamib <message>\n");
-            printf
-                ("  Sends a broadcast message on all map-server (in blue).\n");
-        }
-        else if (strcmp (command, "language") == 0)
-        {
-            printf ("language <language>\n");
-            printf ("  Change the language of displaying.\n");
-            printf ("  Possible languages: Français or English.\n");
-        }
-        else if (strcmp (command, "list") == 0)
-        {
-            printf ("list/ls [start_id [end_id]]\n");
-            printf ("  Display a list of accounts.\n");
-            printf
-                ("  'start_id', 'end_id': indicate end and start identifiers.\n");
-            printf
-                ("  Research by name is not possible with this command.\n");
-            printf ("  <example> list 10 9999999\n");
-        }
-        else if (strcmp (command, "itemfrob") == 0)
-        {
-            printf ("itemfrob <source-id> <dest-id>\n");
-            printf ("  Translates item IDs for all accounts.\n");
-            printf
-                ("  Any items matching the source item ID will be mapped to the dest-id.\n");
-            printf ("  <example> itemfrob 500 700\n");
-        }
-        else if (strcmp (command, "listban") == 0)
-        {
-            printf ("listBan/lsBan [start_id [end_id]]\n");
-            printf
-                ("  Like list/ls, but only for accounts with state or banished.\n");
-        }
-        else if (strcmp (command, "listgm") == 0)
-        {
-            printf ("listGM/lsGM [start_id [end_id]]\n");
-            printf ("  Like list/ls, but only for GM accounts.\n");
-        }
-        else if (strcmp (command, "listok") == 0)
-        {
-            printf ("listOK/lsOK [start_id [end_id]]\n");
-            printf
-                ("  Like list/ls, but only for accounts without state and not banished.\n");
-        }
-        else if (strcmp (command, "memo") == 0)
-        {
-            printf ("memo <account_name> <memo>\n");
-            printf ("  Modify the memo of an account.\n");
-            printf
-                ("  'memo': it can have until 253 characters (with spaces or not).\n");
-        }
-        else if (strcmp (command, "name") == 0)
-        {
-            printf ("name <account_id>\n");
-            printf ("  Give the name of an account.\n");
-        }
-        else if (strcmp (command, "password") == 0)
-        {
-            printf ("passwd <account_name> <new_password>\n");
-            printf ("  Change the password of an account.\n");
-            printf ("  When new password is omitted,\n");
-            printf
-                ("  the input is done without displaying of the pressed keys.\n");
-        }
-        else if (strcmp (command, "reloadgm") == 0)
-        {
-            printf ("reloadGM\n");
-            printf ("  Reload GM configuration file\n");
-        }
-        else if (strcmp (command, "search") == 0)
-        {
-            printf ("search <expression>\n");
-            printf ("  Seek accounts.\n");
-            printf ("  Displays the accounts whose names correspond.\n");
-//          printf("search -r/-e/--expr/--regex <expression>\n");
-//          printf("  Seek accounts by regular expression.\n");
-//          printf("  Displays the accounts whose names correspond.\n");
-        }
-        else if (strcmp (command, "sex") == 0)
-        {
-            printf ("sex <account_name> <sex>\n");
-            printf ("  Modify the sex of an account.\n");
-            printf ("  <example> sex testname Male\n");
-        }
-        else if (strcmp (command, "state") == 0)
-        {
-            printf ("state <account_name> <new_state> <error_message_#7>\n");
-            printf ("  Change the state of an account.\n");
-            printf
-                ("  'new_state': state is the state of the packet 0x006a + 1.\n");
-            printf ("               The possibilities are:\n");
-            printf ("               0 = Account ok\n");
-            printf ("               1 = Unregistered ID\n");
-            printf ("               2 = Incorrect Password\n");
-            printf ("               3 = This ID is expired\n");
-            printf ("               4 = Rejected from Server\n");
-            printf
-                ("               5 = You have been blocked by the GM Team\n");
-            printf
-                ("               6 = Your Game's EXE file is not the latest version\n");
-            printf
-                ("               7 = You are Prohibited to log in until...\n");
-            printf
-                ("               8 = Server is jammed due to over populated\n");
-            printf ("               9 = No MSG\n");
-            printf ("               100 = This ID has been totally erased\n");
-            printf
-                ("               all other values are 'No MSG', then use state 9 please.\n");
-            printf ("  'error_message_#7': message of the code error 6\n");
-            printf
-                ("                      = Your are Prohibited to log in until... (packet 0x006a)\n");
-        }
-        else if (strcmp (command, "timeadd") == 0)
-        {
-            printf ("timeadd <account_name> <modifier>\n");
-            printf
-                ("  Adds or substracts time from the validity limit of an account.\n");
-            printf ("  Modifier is done as follows:\n");
-            printf ("    Adjustment value (-1, 1, +1, etc...)\n");
-            printf ("    Modified element:\n");
-            printf ("      a or y: year\n");
-            printf ("      m:  month\n");
-            printf ("      j or d: day\n");
-            printf ("      h:  hour\n");
-            printf ("      mn: minute\n");
-            printf ("      s:  second\n");
-            printf ("  <example> timeadd testname +1m-2mn1s-6y\n");
-            printf
-                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("            and 6 years at the same time.\n");
-            printf ("NOTE: You can not modify a unlimited validity limit.\n");
-            printf
-                ("      If you want modify it, you want probably create a limited validity limit.\n");
-            printf
-                ("      So, at first, you must set the validity limit to a date/time.\n");
-        }
-        else if (strcmp (command, "timeadd") == 0)
-        {
-            printf ("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf ("  Changes the validity limit of an account.\n");
-            printf ("  Default time [hh:mm:ss]: 23:59:59.\n");
-            printf ("timeset <account_name> 0\n");
-            printf ("  Gives an unlimited validity limit (0 = unlimited).\n");
-        }
-        else if (strcmp (command, "unban") == 0)
-        {
-            printf ("unban/unbanish <account name>\n");
-            printf ("  Remove the banishment of an account.\n");
-            printf ("  This command works like banset <account_name> 0.\n");
-        }
-        else if (strcmp (command, "unblock") == 0)
-        {
-            printf ("unblock <account name>\n");
-            printf ("  Set state 0 (Account ok) to an account.\n");
-            printf ("  This command works like state <account_name> 0.\n");
-        }
-        else if (strcmp (command, "version") == 0)
-        {
-            printf ("version\n");
-            printf ("  Display the version of the login-server.\n");
-        }
-        else if (strcmp (command, "who") == 0)
-        {
-            printf ("who <account name>\n");
-            printf ("  Displays complete information of an account.\n");
-// quit
-        }
-        else if (strcmp (command, "quit") == 0 ||
-                 strcmp (command, "exit") == 0 ||
-                 strcmp (command, "end") == 0)
-        {
-            printf ("quit/end/exit\n");
-            printf ("  End of the program of administration.\n");
-// unknown command
-        }
-        else
-        {
-            if (strlen (command) > 0)
-                printf
-                    ("Unknown command [%s] for help. Displaying of all commands.\n",
-                     command);
-            printf
-                (" aide/help/?                          -- Display this help\n");
-            printf
-                (" aide/help/? [command]                -- Display the help of the command\n");
-            printf
-                (" add <account_name> <sex> <password>  -- Create an account with default email\n");
-            printf
-                (" ban/banish yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n");
-            printf
-                (" banadd/ba <account_name> <modifier>  -- Add or substract time from the final\n");
-            printf
-                ("   example: ba apple +1m-2mn1s-2y        date of a banishment of an account\n");
-            printf
-                (" banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n");
-            printf
-                (" banset/bs <account_name> 0           -- Un-banish an account\n");
-            printf
-                (" block <account name>     -- Set state 5 (blocked by the GM Team) to an account\n");
-            printf
-                (" check <account_name> <password>      -- Check the validity of a password\n");
-            printf
-                (" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n");
-            printf
-                (" del <account name>                   -- Remove an account\n");
-            printf
-                (" email <account_name> <email>         -- Modify an email of an account\n");
-            printf
-                (" getcount                             -- Give the number of players online\n");
-            printf
-                (" gm <account_name> [GM_level]         -- Modify the GM level of an account\n");
-            printf
-                (" id <account name>                    -- Give the id of an account\n");
-            printf
-                (" info <account_id>                    -- Display all information of an account\n");
-            printf
-                (" itemfrob <source-id> <dest-id>       -- Map all items from one item ID to another\n");
-            printf
-                (" kami <message>                       -- Sends a broadcast message (in yellow)\n");
-            printf
-                (" kamib <message>                      -- Sends a broadcast message (in blue)\n");
-            printf
-                (" language <language>                  -- Change the language of displaying.\n");
-            printf
-                (" list/ls [First_id [Last_id]]         -- Display a list of accounts\n");
-            printf
-                (" listBan/lsBan [First_id [Last_id] ]  -- Display a list of accounts\n");
-            printf
-                ("                                         with state or banished\n");
-            printf
-                (" listGM/lsGM [First_id [Last_id]]     -- Display a list of GM accounts\n");
-            printf
-                (" listOK/lsOK [First_id [Last_id] ]    -- Display a list of accounts\n");
-            printf
-                ("                                         without state and not banished\n");
-            printf
-                (" memo <account_name> <memo>           -- Modify the memo of an account\n");
-            printf
-                (" name <account_id>                    -- Give the name of an account\n");
-            printf
-                (" passwd <account_name> <new_password> -- Change the password of an account\n");
-            printf
-                (" quit/end/exit                        -- End of the program of administation\n");
-            printf
-                (" reloadGM                             -- Reload GM configuration file\n");
-            printf
-                (" search <expression>                  -- Seek accounts\n");
-//          printf(" search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression\n");
-            printf
-                (" sex <nomcompte> <sexe>               -- Modify the sex of an account\n");
-            printf
-                (" state <account_name> <new_state> <error_message_#7> -- Change the state\n");
-            printf
-                (" timeadd/ta <account_name> <modifier> -- Add or substract time from the\n");
-            printf
-                ("   example: ta apple +1m-2mn1s-2y        validity limit of an account\n");
-            printf
-                (" timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n");
-            printf
-                (" timeset/ts <account_name> 0          -- Give a unlimited validity limit\n");
-            printf
-                (" unban/unbanish <account name>        -- Remove the banishment of an account\n");
-            printf
-                (" unblock <account name>               -- Set state 0 (Account ok) to an account\n");
-            printf
-                (" version                              -- Gives the version of the login-server\n");
-            printf
-                (" who <account name>                   -- Display all information of an account\n");
-            printf
-                (" who <account name>                   -- Display all information of an account\n");
-            printf
-                (" Note: To use spaces in an account name, type \"<account name>\" (or ').\n");
-        }
-    }
-}
-
-//-----------------------------
-// Sub-function: add an account
-//-----------------------------
-int addaccount (char *param, int emailflag)
-{
-    char name[1023], sex[1023], email[1023], password[1023];
-//  int i;
-
-    memset (name, '\0', sizeof (name));
-    memset (sex, '\0', sizeof (sex));
-    memset (email, '\0', sizeof (email));
-    memset (password, '\0', sizeof (password));
-
-    if (emailflag == 0)
-    {                           // add command
-        if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, sex, password) < 2 &&    // password can be void
-            sscanf (param, "'%[^']' %s %[^\r\n]", name, sex, password) < 2 &&   // password can be void
-            sscanf (param, "%s %s %[^\r\n]", name, sex, password) < 2)
-        {                       // password can be void
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez un nom de compte, un sexe et un mot de passe svp.\n");
-                printf ("<exemple> add nomtest Male motdepassetest\n");
-                ladmin_log
-                    ("Nombre incorrect de paramètres pour créer un compte (commande 'add').\n");
-            }
-            else
-            {
-                printf
-                    ("Please input an account name, a sex and a password.\n");
-                printf ("<example> add testname Male testpass\n");
-                ladmin_log
-                    ("Incomplete parameters to create an account ('add' command).\n");
-            }
-            return 136;
-        }
-        strcpy (email, "a@a.com");  // default email
-    }
-    else
-    {                           // 1: create command
-        if (sscanf (param, "\"%[^\"]\" %s %s %[^\r\n]", name, sex, email, password) < 3 &&  // password can be void
-            sscanf (param, "'%[^']' %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
-            sscanf (param, "%s %s %s %[^\r\n]", name, sex, email,
-                    password) < 3)
-        {                       // password can be void
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez un nom de compte, un sexe et un mot de passe svp.\n");
-                printf
-                    ("<exemple> create nomtest Male mo@mail.com motdepassetest\n");
-                ladmin_log
-                    ("Nombre incorrect de paramètres pour créer un compte (commande 'create').\n");
-            }
-            else
-            {
-                printf
-                    ("Please input an account name, a sex and a password.\n");
-                printf
-                    ("<example> create testname Male my@mail.com testpass\n");
-                ladmin_log
-                    ("Incomplete parameters to create an account ('create' command).\n");
-            }
-            return 136;
-        }
-    }
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-/*	for(i = 0; name[i]; i++) {
-		if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_", name[i]) == NULL) {
-			if (defaultlanguage == 'F') {
-				printf("Caractère interdit (%c) trouvé dans le nom du compte (%d%s caractère).\n", name[i], i+1, makeordinal(i+1));
-				ladmin_log("Caractère interdit (%c) trouvé dans le nom du compte (%d%s caractère).\n", name[i], i+1, makeordinal(i+1));
-			} else {
-				printf("Illegal character (%c) found in the account name (%d%s character).\n", name[i], i+1, makeordinal(i+1));
-				ladmin_log("Illegal character (%c) found in the account name (%d%s character).\n", name[i], i+1, makeordinal(i+1));
-			}
-			return 101;
-		}
-	}*/
-
-    sex[0] = toupper (sex[0]);
-    if (strchr ("MF", sex[0]) == NULL)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Sexe incorrect [%s]. Entrez M ou F svp.\n", sex);
-            ladmin_log ("Sexe incorrect [%s]. Entrez M ou F svp.\n",
-                        sex);
-        }
-        else
-        {
-            printf ("Illegal gender [%s]. Please input M or F.\n", sex);
-            ladmin_log ("Illegal gender [%s]. Please input M or F.\n",
-                        sex);
-        }
-        return 103;
-    }
-
-    if (strlen (email) < 3)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
-                    email);
-            ladmin_log
-                ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
-                  email);
-        }
-        else
-        {
-            printf ("Email is too short [%s]. Please input a valid e-mail.\n",
-                    email);
-            ladmin_log
-                ("Email is too short [%s]. Please input a valid e-mail.\n",
-                  email);
-        }
-        return 109;
-    }
-    if (strlen (email) > 39)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
-                 email);
-            ladmin_log
-                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
-                  email);
-        }
-        else
-        {
-            printf
-                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
-                 email);
-            ladmin_log
-                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
-                  email);
-        }
-        return 109;
-    }
-    if (e_mail_check (email) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
-                    email);
-            ladmin_log ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
-                         email);
-        }
-        else
-        {
-            printf ("Invalid email [%s]. Please input a valid e-mail.\n",
-                    email);
-            ladmin_log ("Invalid email [%s]. Please input a valid e-mail.\n",
-                         email);
-        }
-        return 109;
-    }
-
-    if (strlen (password) == 0)
-    {
-        if (typepasswd (password) == 0)
-            return 108;
-    }
-    if (verify_password (password) == 0)
-        return 104;
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour créer un compte.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to create an account.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7930;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    memcpy (WFIFOP (login_fd, 26), password, 24);
-    WFIFOB (login_fd, 50) = sex[0];
-    memcpy (WFIFOP (login_fd, 51), email, 40);
-    WFIFOSET (login_fd, 91);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//---------------------------------------------------------------------------------
-// Sub-function: Add/substract time to the final date of a banishment of an account
-//---------------------------------------------------------------------------------
-int banaddaccount (char *param)
-{
-    char name[1023], modif[1023];
-    int  year, month, day, hour, minute, second;
-    char *p_modif;
-    int  value, i;
-
-    memset (name, '\0', sizeof (name));
-    memset (modif, '\0', sizeof (modif));
-    year = month = day = hour = minute = second = 0;
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
-        sscanf (param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
-        sscanf (param, "%s %[^\r\n]", name, modif) < 2)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un modificateur svp.\n");
-            printf ("  <exemple> banadd nomtest +1m-2mn1s-6y\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour modifier la fin de ban d'un compte (commande 'banadd').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a modifier.\n");
-            printf ("  <example>: banadd testname +1m-2mn1s-6y\n");
-            printf
-                ("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("             and 6 years at the same time.\n");
-            ladmin_log
-                ("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n");
-        }
-        return 136;
-    }
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    // lowercase for modif
-    for (i = 0; modif[i]; i++)
-        modif[i] = tolower (modif[i]);
-    p_modif = modif;
-    while (strlen (p_modif) > 0)
-    {
-        value = atoi (p_modif);
-        if (value == 0)
-        {
-            p_modif++;
-        }
-        else
-        {
-            if (p_modif[0] == '-' || p_modif[0] == '+')
-                p_modif++;
-            while (strlen (p_modif) > 0 && p_modif[0] >= '0'
-                   && p_modif[0] <= '9')
-            {
-                p_modif++;
-            }
-            if (p_modif[0] == 's')
-            {
-                second = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'm' && p_modif[1] == 'n')
-            {
-                minute = value;
-                p_modif += 2;
-            }
-            else if (p_modif[0] == 'h')
-            {
-                hour = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'd' || p_modif[0] == 'j')
-            {
-                day = value;
-                p_modif += 2;
-            }
-            else if (p_modif[0] == 'm')
-            {
-                month = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'y' || p_modif[0] == 'a')
-            {
-                year = value;
-                p_modif++;
-            }
-            else
-            {
-                p_modif++;
-            }
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        printf (" année:   %d\n", year);
-        printf (" mois:    %d\n", month);
-        printf (" jour:    %d\n", day);
-        printf (" heure:   %d\n", hour);
-        printf (" minute:  %d\n", minute);
-        printf (" seconde: %d\n", second);
-    }
-    else
-    {
-        printf (" year:   %d\n", year);
-        printf (" month:  %d\n", month);
-        printf (" day:    %d\n", day);
-        printf (" hour:   %d\n", hour);
-        printf (" minute: %d\n", minute);
-        printf (" second: %d\n", second);
-    }
-
-    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
-        && second == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Vous devez entrer un ajustement avec cette commande, svp:\n");
-            printf ("  Valeur d'ajustement (-1, 1, +1, etc...)\n");
-            printf ("  Element modifié:\n");
-            printf ("    a ou y: année\n");
-            printf ("    m:      mois\n");
-            printf ("    j ou d: jour\n");
-            printf ("    h:      heure\n");
-            printf ("    mn:     minute\n");
-            printf ("    s:      seconde\n");
-            printf ("  <exemple> banadd nomtest +1m-2mn1s-6y\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            ladmin_log
-                ("Aucun ajustement n'est pas un ajustement (commande 'banadd').\n");
-        }
-        else
-        {
-            printf ("Please give an adjustment with this command:\n");
-            printf ("  Adjustment value (-1, 1, +1, etc...)\n");
-            printf ("  Modified element:\n");
-            printf ("    a or y: year\n");
-            printf ("    m: month\n");
-            printf ("    j or d: day\n");
-            printf ("    h: hour\n");
-            printf ("    mn: minute\n");
-            printf ("    s: second\n");
-            printf ("  <example> banadd testname +1m-2mn1s-6y\n");
-            printf
-                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("            and 6 years at the same time.\n");
-            ladmin_log
-                ("No adjustment isn't an adjustment ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (year > 127 || year < -127)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement d'années correct (de -127 à 127), svp.\n");
-            ladmin_log
-                ("Ajustement de l'année hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the years (from -127 to 127).\n");
-            ladmin_log
-                ("Abnormal adjustement for the year ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (month > 255 || month < -255)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de mois correct (de -255 à 255), svp.\n");
-            ladmin_log ("Ajustement du mois hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the months (from -255 to 255).\n");
-            ladmin_log
-                ("Abnormal adjustement for the month ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (day > 32767 || day < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n");
-            ladmin_log ("Ajustement des jours hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the days (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the days ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (hour > 32767 || hour < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des heures hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the hours ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (minute > 32767 || minute < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des minutes hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the minutes ('banadd' command).\n");
-        }
-        return 137;
-    }
-    if (second > 32767 || second < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des secondes hors norme (commande 'banadd').\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the seconds ('banadd' command).\n");
-        }
-        return 137;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour modifier la date d'un bannissement.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to modify a ban date/time.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x794c;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOW (login_fd, 26) = (short) year;
-    WFIFOW (login_fd, 28) = (short) month;
-    WFIFOW (login_fd, 30) = (short) day;
-    WFIFOW (login_fd, 32) = (short) hour;
-    WFIFOW (login_fd, 34) = (short) minute;
-    WFIFOW (login_fd, 36) = (short) second;
-    WFIFOSET (login_fd, 38);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-----------------------------------------------------------------------
-// Sub-function of sub-function banaccount, unbanaccount or bansetaccount
-// Set the final date of a banishment of an account
-//-----------------------------------------------------------------------
-int bansetaccountsub (char *name, char *date, char *time)
-{
-    int  year, month, day, hour, minute, second;
-    time_t ban_until_time;      // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-    struct tm *tmtime;
-
-    year = month = day = hour = minute = second = 0;
-    ban_until_time = 0;
-    tmtime = localtime (&ban_until_time);   // initialize
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (atoi (date) != 0 &&
-        ((sscanf (date, "%d/%d/%d", &year, &month, &day) < 3 &&
-          sscanf (date, "%d-%d-%d", &year, &month, &day) < 3 &&
-          sscanf (date, "%d.%d.%d", &year, &month, &day) < 3) ||
-         sscanf (time, "%d:%d:%d", &hour, &minute, &second) < 3))
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez une date et une heure svp (format: aaaa/mm/jj hh:mm:ss).\n");
-            printf
-                ("Vous pouvez aussi mettre 0 à la place si vous utilisez la commande 'banset'.\n");
-            ladmin_log
-                ("Format incorrect pour la date/heure (commande'banset' ou 'ban').\n");
-        }
-        else
-        {
-            printf
-                ("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
-            printf
-                ("You can imput 0 instead of if you use 'banset' command.\n");
-            ladmin_log
-                ("Invalid format for the date/time ('banset' or 'ban' command).\n");
-        }
-        return 102;
-    }
-
-    if (atoi (date) == 0)
-    {
-        ban_until_time = 0;
-    }
-    else
-    {
-        if (year < 70)
-        {
-            year = year + 100;
-        }
-        if (year >= 1900)
-        {
-            year = year - 1900;
-        }
-        if (month < 1 || month > 12)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez un mois correct svp (entre 1 et 12).\n");
-                ladmin_log
-                    ("Mois incorrect pour la date (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the month (from 1 to 12).\n");
-                ladmin_log
-                    ("Invalid month for the date ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        month = month - 1;
-        if (day < 1 || day > 31)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez un jour correct svp (entre 1 et 31).\n");
-                ladmin_log
-                    ("Jour incorrect pour la date (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the day (from 1 to 31).\n");
-                ladmin_log
-                    ("Invalid day for the date ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        if (((month == 3 || month == 5 || month == 8 || month == 10)
-             && day > 30) || (month == 1 && day > 29))
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez un jour correct en fonction du mois (%d) svp.\n",
-                     month);
-                ladmin_log
-                    ("Jour incorrect pour ce mois correspondant (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for a day of this month (%d).\n",
-                     month);
-                ladmin_log
-                    ("Invalid day for this month ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        if (hour < 0 || hour > 23)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez une heure correcte svp (entre 0 et 23).\n");
-                ladmin_log
-                    ("Heure incorrecte pour l'heure (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the hour (from 0 to 23).\n");
-                ladmin_log
-                    ("Invalid hour for the time ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        if (minute < 0 || minute > 59)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez des minutes correctes svp (entre 0 et 59).\n");
-                ladmin_log
-                    ("Minute incorrecte pour l'heure (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the minutes (from 0 to 59).\n");
-                ladmin_log
-                    ("Invalid minute for the time ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        if (second < 0 || second > 59)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez des secondes correctes svp (entre 0 et 59).\n");
-                ladmin_log
-                    ("Seconde incorrecte pour l'heure (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the seconds (from 0 to 59).\n");
-                ladmin_log
-                    ("Invalid second for the time ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-        tmtime->tm_year = year;
-        tmtime->tm_mon = month;
-        tmtime->tm_mday = day;
-        tmtime->tm_hour = hour;
-        tmtime->tm_min = minute;
-        tmtime->tm_sec = second;
-        tmtime->tm_isdst = -1;  // -1: no winter/summer time modification
-        ban_until_time = timegm (tmtime);
-        if (ban_until_time == -1)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Date incorrecte.\n");
-                printf
-                    ("Entrez une date et une heure svp (format: aaaa/mm/jj hh:mm:ss).\n");
-                printf
-                    ("Vous pouvez aussi mettre 0 à la place si vous utilisez la commande 'banset'.\n");
-                ladmin_log ("Date incorrecte. (command 'banset' ou 'ban').\n");
-            }
-            else
-            {
-                printf ("Invalid date.\n");
-                printf
-                    ("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
-                printf
-                    ("You can imput 0 instead of if you use 'banset' command.\n");
-                ladmin_log ("Invalid date. ('banset' or 'ban' command).\n");
-            }
-            return 102;
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour fixer un ban.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to set a ban.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x794a;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOL (login_fd, 26) = (int) ban_until_time;
-    WFIFOSET (login_fd, 30);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//---------------------------------------------------------------------
-// Sub-function: Set the final date of a banishment of an account (ban)
-//---------------------------------------------------------------------
-int banaccount (char *param)
-{
-    char name[1023], date[1023], time[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (date, '\0', sizeof (date));
-    memset (time, '\0', sizeof (time));
-
-    if (sscanf (param, "%s %s \"%[^\"]\"", date, time, name) < 3 &&
-        sscanf (param, "%s %s '%[^']'", date, time, name) < 3 &&
-        sscanf (param, "%s %s %[^\r\n]", date, time, name) < 3)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte, une date et une heure svp.\n");
-            printf
-                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
-            printf
-                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
-            printf ("           unban/unbanish <nom du compte>\n");
-            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour fixer un ban (commande 'banset' ou 'ban').\n");
-        }
-        else
-        {
-            printf ("Please input an account name, a date and a hour.\n");
-            printf
-                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf
-                ("           banset <account_name> 0   (0 = un-banished)\n");
-            printf
-                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-            printf ("           unban/unbanish <account name>\n");
-            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
-        }
-        return 136;
-    }
-
-    return bansetaccountsub (name, date, time);
-}
-
-//------------------------------------------------------------------------
-// Sub-function: Set the final date of a banishment of an account (banset)
-//------------------------------------------------------------------------
-int bansetaccount (char *param)
-{
-    char name[1023], date[1023], time[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (date, '\0', sizeof (date));
-    memset (time, '\0', sizeof (time));
-
-    if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 &&   // if date = 0, time can be void
-        sscanf (param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 &&  // if date = 0, time can be void
-        sscanf (param, "%s %s %[^\r\n]", name, date, time) < 2)
-    {                           // if date = 0, time can be void
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte, une date et une heure svp.\n");
-            printf
-                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
-            printf
-                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
-            printf ("           unban/unbanish <nom du compte>\n");
-            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour fixer un ban (commande 'banset' ou 'ban').\n");
-        }
-        else
-        {
-            printf ("Please input an account name, a date and a hour.\n");
-            printf
-                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf
-                ("           banset <account_name> 0   (0 = un-banished)\n");
-            printf
-                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-            printf ("           unban/unbanish <account name>\n");
-            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
-        }
-        return 136;
-    }
-
-    if (time[0] == '\0')
-        strcpy (time, "23:59:59");
-
-    return bansetaccountsub (name, date, time);
-}
-
-//-------------------------------------------------
-// Sub-function: unbanishment of an account (unban)
-//-------------------------------------------------
-int unbanaccount (char *param)
-{
-    char name[1023];
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf
-                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
-            printf
-                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
-            printf ("           unban/unbanish <nom du compte>\n");
-            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour fixer un ban (commande 'unban').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf
-                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf
-                ("           banset <account_name> 0   (0 = un-banished)\n");
-            printf
-                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
-            printf ("           unban/unbanish <account name>\n");
-            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Incomplete parameters to set a ban ('unban' command).\n");
-        }
-        return 136;
-    }
-
-    return bansetaccountsub (name, "0", "");
-}
-
-//---------------------------------------------------------
-// Sub-function: Asking to check the validity of a password
-// (Note: never send back a password with login-server!! security of passwords)
-//---------------------------------------------------------
-int checkaccount (char *param)
-{
-    char name[1023], password[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (password, '\0', sizeof (password));
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&    // password can be void
-        sscanf (param, "'%[^']' %[^\r\n]", name, password) < 1 &&   // password can be void
-        sscanf (param, "%s %[^\r\n]", name, password) < 1)
-    {                           // password can be void
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemple> check testname motdepasse\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour tester le mot d'un passe d'un compte (commande 'check').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<example> check testname password\n");
-            ladmin_log
-                ("Incomplete parameters to check the password of an account ('check' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (strlen (password) == 0)
-    {
-        if (typepasswd (password) == 0)
-            return 134;
-    }
-    if (verify_password (password) == 0)
-        return 131;
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour test un mot de passe.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to check a password.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x793a;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    memcpy (WFIFOP (login_fd, 26), password, 24);
-    WFIFOSET (login_fd, 50);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//------------------------------------------------
-// Sub-function: Asking for deletion of an account
-//------------------------------------------------
-int delaccount (char *param)
-{
-    char name[1023];
-    char letter;
-    char confirm[1023];
-    int  i;
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemple> del nomtestasupprimer\n");
-            ladmin_log
-                ("Aucun nom donné pour supprimer un compte (commande 'delete').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<example> del testnametodelete\n");
-            ladmin_log
-                ("No name given to delete an account ('delete' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    memset (confirm, '\0', sizeof (confirm));
-    while ((confirm[0] != 'o' || defaultlanguage != 'F') && confirm[0] != 'n'
-           && (confirm[0] != 'y' || defaultlanguage == 'F'))
-    {
-        if (defaultlanguage == 'F')
-            printf
-                ("\033[1;36m ** Etes-vous vraiment sûr de vouloir SUPPRIMER le compte [$userid]? (o/n) > \033[0m");
-        else
-            printf
-                ("\033[1;36m ** Are you really sure to DELETE account [$userid]? (y/n) > \033[0m");
-        fflush (stdout);
-        memset (confirm, '\0', sizeof (confirm));
-        i = 0;
-        while ((letter = getchar ()) != '\n')
-            confirm[i++] = letter;
-    }
-
-    if (confirm[0] == 'n')
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Suppression annulée.\n");
-            ladmin_log
-                ("Suppression annulée par l'utilisateur (commande 'delete').\n");
-        }
-        else
-        {
-            printf ("Deletion canceled.\n");
-            ladmin_log ("Deletion canceled by user ('delete' command).\n");
-        }
-        return 121;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour détruire un compte.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to delete an acount.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7932;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOSET (login_fd, 26);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//----------------------------------------------------------
-// Sub-function: Asking to modification of an account e-mail
-//----------------------------------------------------------
-int changeemail (char *param)
-{
-    char name[1023], email[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (email, '\0', sizeof (email));
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, email) < 2 &&
-        sscanf (param, "'%[^']' %[^\r\n]", name, email) < 2 &&
-        sscanf (param, "%s %[^\r\n]", name, email) < 2)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et une email svp.\n");
-            printf ("<exemple> email testname nouveauemail\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer l'email d'un compte (commande 'email').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and an email.\n");
-            printf ("<example> email testname newemail\n");
-            ladmin_log
-                ("Incomplete parameters to change the email of an account ('email' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (strlen (email) < 3)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
-                    email);
-            ladmin_log
-                ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
-                  email);
-        }
-        else
-        {
-            printf ("Email is too short [%s]. Please input a valid e-mail.\n",
-                    email);
-            ladmin_log
-                ("Email is too short [%s]. Please input a valid e-mail.\n",
-                  email);
-        }
-        return 109;
-    }
-    if (strlen (email) > 39)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
-                 email);
-            ladmin_log
-                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
-                  email);
-        }
-        else
-        {
-            printf
-                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
-                 email);
-            ladmin_log
-                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
-                  email);
-        }
-        return 109;
-    }
-    if (e_mail_check (email) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
-                    email);
-            ladmin_log ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
-                         email);
-        }
-        else
-        {
-            printf ("Invalid email [%s]. Please input a valid e-mail.\n",
-                    email);
-            ladmin_log ("Invalid email [%s]. Please input a valid e-mail.\n",
-                         email);
-        }
-        return 109;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer une email.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change an email.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7940;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    memcpy (WFIFOP (login_fd, 26), email, 40);
-    WFIFOSET (login_fd, 66);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-----------------------------------------------------
-// Sub-function: Asking of the number of online players
-//-----------------------------------------------------
-int getlogincount (void)
-{
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour obtenir le nombre de joueurs en jeu.\n");
-    }
-    else
-    {
-        ladmin_log
-            ("Request to login-server to obtain the # of online players.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7938;
-    WFIFOSET (login_fd, 2);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//----------------------------------------------------------
-// Sub-function: Asking to modify the GM level of an account
-//----------------------------------------------------------
-int changegmlevel (char *param)
-{
-    char name[1023];
-    int  GM_level;
-
-    memset (name, '\0', sizeof (name));
-    GM_level = 0;
-
-    if (sscanf (param, "\"%[^\"]\" %d", name, &GM_level) < 1 &&
-        sscanf (param, "'%[^']' %d", name, &GM_level) < 1 &&
-        sscanf (param, "%s %d", name, &GM_level) < 1)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un niveau de GM svp.\n");
-            printf ("<exemple> gm nomtest 80\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le Niveau de GM d'un compte (commande 'gm').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a GM level.\n");
-            printf ("<example> gm testname 80\n");
-            ladmin_log
-                ("Incomplete parameters to change the GM level of an account ('gm' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (GM_level < 0 || GM_level > 99)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Niveau de GM incorrect [%d]. Entrez une valeur de 0 à 99 svp.\n",
-                 GM_level);
-            ladmin_log
-                ("Niveau de GM incorrect [%d]. La valeur peut être de 0 à 99.\n",
-                  GM_level);
-        }
-        else
-        {
-            printf
-                ("Illegal GM level [%d]. Please input a value from 0 to 99.\n",
-                 GM_level);
-            ladmin_log
-                ("Illegal GM level [%d]. The value can be from 0 to 99.\n",
-                  GM_level);
-        }
-        return 103;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer un niveau de GM.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change a GM level.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x793e;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOB (login_fd, 26) = GM_level;
-    WFIFOSET (login_fd, 27);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//---------------------------------------------
-// Sub-function: Asking to obtain an account id
-//---------------------------------------------
-int idaccount (char *param)
-{
-    char name[1023];
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemple> id nomtest\n");
-            ladmin_log
-                ("Aucun nom donné pour rechecher l'id d'un compte (commande 'id').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<example> id testname\n");
-            ladmin_log
-                ("No name given to search an account id ('id' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour connaître l'id d'un compte.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to know an account id.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7944;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOSET (login_fd, 26);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//----------------------------------------------------------------------------
-// Sub-function: Asking to displaying information about an account (by its id)
-//----------------------------------------------------------------------------
-int infoaccount (int account_id)
-{
-    if (account_id < 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un id ayant une valeur positive svp.\n");
-            ladmin_log
-                ("Une valeur négative a été donné pour trouver le compte.\n");
-        }
-        else
-        {
-            printf ("Please input a positive value for the id.\n");
-            ladmin_log ("Negative value was given to found the account.\n");
-        }
-        return 136;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour obtenir le information d'un compte (par l'id).\n");
-    }
-    else
-    {
-        ladmin_log
-            ("Request to login-server to obtain information about an account (by its id).\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7954;
-    WFIFOL (login_fd, 2) = account_id;
-    WFIFOSET (login_fd, 6);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//---------------------------------------
-// Sub-function: Send a broadcast message
-//---------------------------------------
-int sendbroadcast (short type, char *message)
-{
-    if (strlen (message) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un message svp.\n");
-            if (type == 0)
-            {
-                printf ("<exemple> kami un message\n");
-            }
-            else
-            {
-                printf ("<exemple> kamib un message\n");
-            }
-            ladmin_log ("Le message est vide (commande 'kami(b)').\n");
-        }
-        else
-        {
-            printf ("Please input a message.\n");
-            if (type == 0)
-            {
-                printf ("<example> kami a message\n");
-            }
-            else
-            {
-                printf ("<example> kamib a message\n");
-            }
-            ladmin_log ("The message is void ('kami(b)' command).\n");
-        }
-        return 136;
-    }
-
-    WFIFOW (login_fd, 0) = 0x794e;
-    WFIFOW (login_fd, 2) = type;
-    WFIFOL (login_fd, 4) = strlen (message) + 1;
-    memcpy (WFIFOP (login_fd, 8), message, strlen (message) + 1);
-    WFIFOSET (login_fd, 8 + strlen (message) + 1);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//--------------------------------------------
-// Sub-function: Change language of displaying
-//--------------------------------------------
-int changelanguage (char *language)
-{
-    if (strlen (language) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez une langue svp.\n");
-            printf ("<exemple> language english\n");
-            printf ("          language français\n");
-            ladmin_log ("La langue est vide (commande 'language').\n");
-        }
-        else
-        {
-            printf ("Please input a language.\n");
-            printf ("<example> language english\n");
-            printf ("          language français\n");
-            ladmin_log ("The language is void ('language' command).\n");
-        }
-        return 136;
-    }
-
-    language[0] = toupper (language[0]);
-    if (language[0] == 'F' || language[0] == 'E')
-    {
-        defaultlanguage = language[0];
-        if (defaultlanguage == 'F')
-        {
-            printf ("Changement de la langue d'affichage en Français.\n");
-            ladmin_log ("Changement de la langue d'affichage en Français.\n");
-        }
-        else
-        {
-            printf ("Displaying language changed to English.\n");
-            ladmin_log ("Displaying language changed to English.\n");
-        }
-    }
-    else
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Langue non paramétrée (langues possibles: 'Français' ou 'English').\n");
-            ladmin_log
-                ("Langue non paramétrée (Français ou English nécessaire).\n");
-        }
-        else
-        {
-            printf
-                ("Undefined language (possible languages: Français or English).\n");
-            ladmin_log ("Undefined language (must be Français or English).\n");
-        }
-    }
-
-    return 0;
-}
-
-//--------------------------------------------------------
-// Sub-function: Asking to Displaying of the accounts list
-//--------------------------------------------------------
-int listaccount (char *param, int type)
-{
-//int list_first, list_last, list_type; // parameter to display a list of accounts
-    int  i;
-
-    list_type = type;
-
-    // set default values
-    list_first = 0;
-    list_last = 0;
-
-    if (list_type == 1)
-    {                           // if listgm
-        // get all accounts = use default
-    }
-    else if (list_type == 2)
-    {                           // if search
-        for (i = 0; param[i]; i++)
-            param[i] = tolower (param[i]);
-        // get all accounts = use default
-    }
-    else if (list_type == 3)
-    {                           // if listban
-        // get all accounts = use default
-    }
-    else if (list_type == 4)
-    {                           // if listok
-        // get all accounts = use default
-    }
-    else
-    {                           // if list (list_type == 0)
-        switch (sscanf (param, "%d %d", &list_first, &list_last))
-        {
-            case 0:
-                // get all accounts = use default
-                break;
-            case 1:
-                list_last = 0;
-                // use tests of the following value
-            default:
-                if (list_first < 0)
-                    list_first = 0;
-                if (list_last < list_first || list_last < 0)
-                    list_last = 0;
-                break;
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour obtenir la liste des comptes de %d à %d.\n",
-              list_first, list_last);
-    }
-    else
-    {
-        ladmin_log
-            ("Request to login-server to obtain the list of accounts from %d to %d.\n",
-              list_first, list_last);
-    }
-
-    WFIFOW (login_fd, 0) = 0x7920;
-    WFIFOL (login_fd, 2) = list_first;
-    WFIFOL (login_fd, 6) = list_last;
-    WFIFOSET (login_fd, 10);
-    bytes_to_read = 1;
-
-    //          0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
-    if (defaultlanguage == 'F')
-    {
-        Iprintf
-            (" id_compte GM nom_utilisateur         sexe   count statut\n");
-    }
-    else
-    {
-        Iprintf
-            ("account_id GM user_name               sex    count state\n");
-    }
-    Iprintf
-        ("-------------------------------------------------------------------------------\n");
-    list_count = 0;
-
-    return 0;
-}
-
-//--------------------------------------------------------
-// Sub-function: Frobnicate items
-//--------------------------------------------------------
-int itemfrob (char *param)
-{
-    int  source_id, dest_id;
-
-    if (sscanf (param, "%d %d", &source_id, &dest_id) < 2)
-    {
-        printf ("You must provide the source and destination item IDs.\n");
-        return 1;
-    }
-
-    WFIFOW (login_fd, 0) = 0x7924;
-    WFIFOL (login_fd, 2) = source_id;
-    WFIFOL (login_fd, 6) = dest_id;
-    WFIFOSET (login_fd, 10);
-    bytes_to_read = 1;          // all logging is done to the three main servers
-
-    return 0;
-}
-
-//--------------------------------------------
-// Sub-function: Asking to modify a memo field
-//--------------------------------------------
-int changememo (char *param)
-{
-    char name[1023], memo[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (memo, '\0', sizeof (memo));
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, memo) < 1 &&    // memo can be void
-        sscanf (param, "'%[^']' %[^\r\n]", name, memo) < 1 &&   // memo can be void
-        sscanf (param, "%s %[^\r\n]", name, memo) < 1)
-    {                           // memo can be void
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un mémo svp.\n");
-            printf ("<exemple> memo nomtest nouveau memo\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le mémo d'un compte (commande 'email').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a memo.\n");
-            printf ("<example> memo testname new memo\n");
-            ladmin_log
-                ("Incomplete parameters to change the memo of an account ('email' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (strlen (memo) > 254)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Mémo trop long (%d caractères).\n", strlen (memo));
-            printf ("Entrez un mémo de 254 caractères maximum svp.\n");
-            ladmin_log
-                ("Mémo trop long (%d caractères). Entrez un mémo de 254 caractères maximum svp.\n",
-                  strlen (memo));
-        }
-        else
-        {
-            printf ("Memo is too long (%d characters).\n", strlen (memo));
-            printf ("Please input a memo of 254 bytes at the maximum.\n");
-            ladmin_log
-                ("Email is too long (%d characters). Please input a memo of 254 bytes at the maximum.\n",
-                  strlen (memo));
-        }
-        return 102;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer un mémo.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change a memo.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7942;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOW (login_fd, 26) = strlen (memo);
-    if (strlen (memo) > 0)
-        memcpy (WFIFOP (login_fd, 28), memo, strlen (memo));
-    WFIFOSET (login_fd, 28 + strlen (memo));
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-----------------------------------------------
-// Sub-function: Asking to obtain an account name
-//-----------------------------------------------
-int nameaccount (int id)
-{
-    if (id < 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un id ayant une valeur positive svp.\n");
-            ladmin_log
-                ("Id négatif donné pour rechecher le nom d'un compte (commande 'name').\n");
-        }
-        else
-        {
-            printf ("Please input a positive value for the id.\n");
-            ladmin_log
-                ("Negativ id given to search an account name ('name' command).\n");
-        }
-        return 136;
-    }
-
-    if (defaultlanguage == 'F')
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour connaître le nom d'un compte.\n");
-    else
-        ladmin_log ("Request to login-server to know an account name.\n");
-
-    WFIFOW (login_fd, 0) = 0x7946;
-    WFIFOL (login_fd, 2) = id;
-    WFIFOSET (login_fd, 6);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//------------------------------------------
-// Sub-function: Asking to modify a password
-// (Note: never send back a password with login-server!! security of passwords)
-//------------------------------------------
-int changepasswd (char *param)
-{
-    char name[1023], password[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (password, '\0', sizeof (password));
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&
-        sscanf (param, "'%[^']' %[^\r\n]", name, password) < 1 &&
-        sscanf (param, "%s %[^\r\n]", name, password) < 1)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemple> passwd nomtest nouveaumotdepasse\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le mot d'un passe d'un compte (commande 'password').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<example> passwd testname newpassword\n");
-            ladmin_log
-                ("Incomplete parameters to change the password of an account ('password' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (strlen (password) == 0)
-    {
-        if (typepasswd (password) == 0)
-            return 134;
-    }
-    if (verify_password (password) == 0)
-        return 131;
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer un mot de passe.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change a password.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7934;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    memcpy (WFIFOP (login_fd, 26), password, 24);
-    WFIFOSET (login_fd, 50);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//----------------------------------------------------------------------
-// Sub-function: Request to login-server to reload GM configuration file
-// this function have no answer
-//----------------------------------------------------------------------
-int reloadGM (void)
-{
-    WFIFOW (login_fd, 0) = 0x7955;
-    WFIFOSET (login_fd, 2);
-    bytes_to_read = 0;
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Demande de recharger le fichier de configuration des GM envoyée.\n");
-        printf
-            ("Demande de recharger le fichier de configuration des GM envoyée.\n");
-        printf ("Vérifiez les comptes GM actuels (après rechargement):\n");
-    }
-    else
-    {
-        ladmin_log ("Request to reload the GM configuration file sended.\n");
-        printf ("Request to reload the GM configuration file sended.\n");
-        printf ("Check the actual GM accounts (after reloading):\n");
-    }
-    listaccount (parameters, 1);    // 1: to list only GM
-
-    return 180;
-}
-
-//-----------------------------------------------------
-// Sub-function: Asking to modify the sex of an account
-//-----------------------------------------------------
-int changesex (char *param)
-{
-    char name[1023], sex[1023];
-
-    memset (name, '\0', sizeof (name));
-    memset (sex, '\0', sizeof (sex));
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, sex) < 2 &&
-        sscanf (param, "'%[^']' %[^\r\n]", name, sex) < 2 &&
-        sscanf (param, "%s %[^\r\n]", name, sex) < 2)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un sexe svp.\n");
-            printf ("<exemple> sex nomtest Male\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le sexe d'un compte (commande 'sex').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a sex.\n");
-            printf ("<example> sex testname Male\n");
-            ladmin_log
-                ("Incomplete parameters to change the sex of an account ('sex' command).\n");
-        }
-        return 136;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    sex[0] = toupper (sex[0]);
-    if (strchr ("MF", sex[0]) == NULL)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Sexe incorrect [%s]. Entrez M ou F svp.\n", sex);
-            ladmin_log ("Sexe incorrect [%s]. Entrez M ou F svp.\n",
-                        sex);
-        }
-        else
-        {
-            printf ("Illegal gender [%s]. Please input M or F.\n", sex);
-            ladmin_log ("Illegal gender [%s]. Please input M or F.\n",
-                        sex);
-        }
-        return 103;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer un sexe.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change a sex.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x793c;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOB (login_fd, 26) = sex[0];
-    WFIFOSET (login_fd, 27);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-------------------------------------------------------------------------
-// Sub-function of sub-function changestate, blockaccount or unblockaccount
-// Asking to modify the state of an account
-//-------------------------------------------------------------------------
-int changestatesub (char *name, int state, char *error_message7)
-{
-    char error_message[1023];   // need to use, because we can modify error_message7
-
-    memset (error_message, '\0', sizeof (error_message));
-    strncpy (error_message, error_message7, sizeof (error_message) - 1);
-
-    if ((state < 0 || state > 9) && state != 100)
-    {                           // Valid values: 0: ok, or value of the 0x006a packet + 1
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez une des statuts suivantes svp:\n");
-            printf
-                ("  0 = Compte ok             6 = Your Game's EXE file is not the latest version\n");
-        }
-        else
-        {
-            printf ("Please input one of these states:\n");
-            printf
-                ("  0 = Account ok            6 = Your Game's EXE file is not the latest version\n");
-        }
-        printf
-            ("  1 = Unregistered ID       7 = You are Prohibited to log in until + message\n");
-        printf
-            ("  2 = Incorrect Password    8 = Server is jammed due to over populated\n");
-        printf ("  3 = This ID is expired    9 = No MSG\n");
-        printf
-            ("  4 = Rejected from Server  100 = This ID has been totally erased\n");
-        printf ("  5 = You have been blocked by the GM Team\n");
-        if (defaultlanguage == 'F')
-        {
-            printf ("<exemples> state nomtest 5\n");
-            printf ("           state nomtest 7 fin de votre ban\n");
-            printf ("           block <nom compte>\n");
-            printf ("           unblock <nom compte>\n");
-            ladmin_log
-                ("Valeur incorrecte pour le statut d'un compte (commande 'state', 'block' ou 'unblock').\n");
-        }
-        else
-        {
-            printf ("<examples> state testname 5\n");
-            printf ("           state testname 7 end of your ban\n");
-            printf ("           block <account name>\n");
-            printf ("           unblock <account name>\n");
-            ladmin_log
-                ("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n");
-        }
-        return 151;
-    }
-
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (state != 7)
-    {
-        strcpy (error_message, "-");
-    }
-    else
-    {
-        if (strlen (error_message) < 1)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Message d'erreur trop court. Entrez un message de 1-19 caractères.\n");
-                ladmin_log
-                    ("Message d'erreur trop court. Entrez un message de 1-19 caractères.\n");
-            }
-            else
-            {
-                printf
-                    ("Error message is too short. Please input a message of 1-19 bytes.\n");
-                ladmin_log
-                    ("Error message is too short. Please input a message of 1-19 bytes.\n");
-            }
-            return 102;
-        }
-        if (strlen (error_message) > 19)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Message d'erreur trop long. Entrez un message de 1-19 caractères.\n");
-                ladmin_log
-                    ("Message d'erreur trop long. Entrez un message de 1-19 caractères.\n");
-            }
-            else
-            {
-                printf
-                    ("Error message is too long. Please input a message of 1-19 bytes.\n");
-                ladmin_log
-                    ("Error message is too long. Please input a message of 1-19 bytes.\n");
-            }
-            return 102;
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour changer un statut.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to change a state.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7936;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOL (login_fd, 26) = state;
-    memcpy (WFIFOP (login_fd, 30), error_message, 20);
-    WFIFOSET (login_fd, 50);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-------------------------------------------------------
-// Sub-function: Asking to modify the state of an account
-//-------------------------------------------------------
-int changestate (char *param)
-{
-    char name[1023], error_message[1023];
-    int  state;
-
-    memset (name, '\0', sizeof (name));
-    memset (error_message, '\0', sizeof (error_message));
-
-    if (sscanf (param, "\"%[^\"]\" %d %[^\r\n]", name, &state, error_message)
-        < 2
-        && sscanf (param, "'%[^']' %d %[^\r\n]", name, &state,
-                   error_message) < 2
-        && sscanf (param, "%s %d %[^\r\n]", name, &state, error_message) < 2)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un statut svp.\n");
-            printf ("<exemples> state nomtest 5\n");
-            printf ("           state nomtest 7 fin de votre ban\n");
-            printf ("           block <nom compte>\n");
-            printf ("           unblock <nom compte>\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'state').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a state.\n");
-            printf ("<examples> state testname 5\n");
-            printf ("           state testname 7 end of your ban\n");
-            printf ("           block <account name>\n");
-            printf ("           unblock <account name>\n");
-            ladmin_log
-                ("Incomplete parameters to change the state of an account ('state' command).\n");
-        }
-        return 136;
-    }
-
-    return changestatesub (name, state, error_message);
-}
-
-//-------------------------------------------
-// Sub-function: Asking to unblock an account
-//-------------------------------------------
-int unblockaccount (char *param)
-{
-    char name[1023];
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemples> state nomtest 5\n");
-            printf ("           state nomtest 7 fin de votre ban\n");
-            printf ("           block <nom compte>\n");
-            printf ("           unblock <nom compte>\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'unblock').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<examples> state testname 5\n");
-            printf ("           state testname 7 end of your ban\n");
-            printf ("           block <account name>\n");
-            printf ("           unblock <account name>\n");
-            ladmin_log
-                ("Incomplete parameters to change the state of an account ('unblock' command).\n");
-        }
-        return 136;
-    }
-
-    return changestatesub (name, 0, "-");   // state 0, no error message
-}
-
-//-------------------------------------------
-// Sub-function: Asking to unblock an account
-//-------------------------------------------
-int blockaccount (char *param)
-{
-    char name[1023];
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemples> state nomtest 5\n");
-            printf ("           state nomtest 7 fin de votre ban\n");
-            printf ("           block <nom compte>\n");
-            printf ("           unblock <nom compte>\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'block').\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<examples> state testname 5\n");
-            printf ("           state testname 7 end of your ban\n");
-            printf ("           block <account name>\n");
-            printf ("           unblock <account name>\n");
-            ladmin_log
-                ("Incomplete parameters to change the state of an account ('block' command).\n");
-        }
-        return 136;
-    }
-
-    return changestatesub (name, 5, "-");   // state 5, no error message
-}
-
-//---------------------------------------------------------------------
-// Sub-function: Add/substract time to the validity limit of an account
-//---------------------------------------------------------------------
-int timeaddaccount (char *param)
-{
-    char name[1023], modif[1023];
-    int  year, month, day, hour, minute, second;
-    char *p_modif;
-    int  value, i;
-
-    memset (name, '\0', sizeof (name));
-    memset (modif, '\0', sizeof (modif));
-    year = month = day = hour = minute = second = 0;
-
-    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
-        sscanf (param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
-        sscanf (param, "%s %[^\r\n]", name, modif) < 2)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte et un modificateur svp.\n");
-            printf ("  <exemple> timeadd nomtest +1m-2mn1s-6y\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour modifier une date limite d'utilisation (commande 'timeadd').\n");
-        }
-        else
-        {
-            printf ("Please input an account name and a modifier.\n");
-            printf ("  <example>: timeadd testname +1m-2mn1s-6y\n");
-            printf
-                ("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("             and 6 years at the same time.\n");
-            ladmin_log
-                ("Incomplete parameters to modify a limit time ('timeadd' command).\n");
-        }
-        return 136;
-    }
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    // lowercase for modif
-    for (i = 0; modif[i]; i++)
-        modif[i] = tolower (modif[i]);
-    p_modif = modif;
-    while (strlen (p_modif) > 0)
-    {
-        value = atoi (p_modif);
-        if (value == 0)
-        {
-            p_modif++;
-        }
-        else
-        {
-            if (p_modif[0] == '-' || p_modif[0] == '+')
-                p_modif++;
-            while (strlen (p_modif) > 0 && p_modif[0] >= '0'
-                   && p_modif[0] <= '9')
-            {
-                p_modif++;
-            }
-            if (p_modif[0] == 's')
-            {
-                second = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'm' && p_modif[1] == 'n')
-            {
-                minute = value;
-                p_modif += 2;
-            }
-            else if (p_modif[0] == 'h')
-            {
-                hour = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'd' || p_modif[0] == 'j')
-            {
-                day = value;
-                p_modif += 2;
-            }
-            else if (p_modif[0] == 'm')
-            {
-                month = value;
-                p_modif++;
-            }
-            else if (p_modif[0] == 'y' || p_modif[0] == 'a')
-            {
-                year = value;
-                p_modif++;
-            }
-            else
-            {
-                p_modif++;
-            }
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        printf (" année:   %d\n", year);
-        printf (" mois:    %d\n", month);
-        printf (" jour:    %d\n", day);
-        printf (" heure:   %d\n", hour);
-        printf (" minute:  %d\n", minute);
-        printf (" seconde: %d\n", second);
-    }
-    else
-    {
-        printf (" year:   %d\n", year);
-        printf (" month:  %d\n", month);
-        printf (" day:    %d\n", day);
-        printf (" hour:   %d\n", hour);
-        printf (" minute: %d\n", minute);
-        printf (" second: %d\n", second);
-    }
-
-    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
-        && second == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Vous devez entrer un ajustement avec cette commande, svp:\n");
-            printf ("  Valeur d'ajustement (-1, 1, +1, etc...)\n");
-            printf ("  Elément modifié:\n");
-            printf ("    a ou y: année\n");
-            printf ("    m:      mois\n");
-            printf ("    j ou d: jour\n");
-            printf ("    h:      heure\n");
-            printf ("    mn:     minute\n");
-            printf ("    s:      seconde\n");
-            printf ("  <exemple> timeadd nomtest +1m-2mn1s-6y\n");
-            printf
-                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
-            printf ("            et 6 ans dans le même temps.\n");
-            ladmin_log
-                ("Aucun ajustement n'est pas un ajustement (commande 'timeadd').\n");
-        }
-        else
-        {
-            printf ("Please give an adjustment with this command:\n");
-            printf ("  Adjustment value (-1, 1, +1, etc...)\n");
-            printf ("  Modified element:\n");
-            printf ("    a or y: year\n");
-            printf ("    m:      month\n");
-            printf ("    j or d: day\n");
-            printf ("    h:      hour\n");
-            printf ("    mn:     minute\n");
-            printf ("    s:      second\n");
-            printf ("  <example> timeadd testname +1m-2mn1s-6y\n");
-            printf
-                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
-            printf ("            and 6 years at the same time.\n");
-            ladmin_log
-                ("No adjustment isn't an adjustment ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (year > 127 || year < -127)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement d'années correct (de -127 à 127), svp.\n");
-            ladmin_log
-                ("Ajustement de l'année hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the years (from -127 to 127).\n");
-            ladmin_log
-                ("Abnormal adjustement for the year ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (month > 255 || month < -255)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de mois correct (de -255 à 255), svp.\n");
-            ladmin_log ("Ajustement du mois hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the months (from -255 to 255).\n");
-            ladmin_log
-                ("Abnormal adjustement for the month ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (day > 32767 || day < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n");
-            ladmin_log ("Ajustement des jours hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the days (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the days ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (hour > 32767 || hour < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des heures hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the hours ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (minute > 32767 || minute < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des minutes hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the minutes ('timeadd' command).\n");
-        }
-        return 137;
-    }
-    if (second > 32767 || second < -32767)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n");
-            ladmin_log
-                ("Ajustement des secondes hors norme ('timeadd' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
-            ladmin_log
-                ("Abnormal adjustement for the seconds ('timeadd' command).\n");
-        }
-        return 137;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour modifier une date limite d'utilisation.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to modify a time limit.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7950;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOW (login_fd, 26) = (short) year;
-    WFIFOW (login_fd, 28) = (short) month;
-    WFIFOW (login_fd, 30) = (short) day;
-    WFIFOW (login_fd, 32) = (short) hour;
-    WFIFOW (login_fd, 34) = (short) minute;
-    WFIFOW (login_fd, 36) = (short) second;
-    WFIFOSET (login_fd, 38);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//-------------------------------------------------
-// Sub-function: Set a validity limit of an account
-//-------------------------------------------------
-int timesetaccount (char *param)
-{
-    char name[1023], date[1023], time[1023];
-    int  year, month, day, hour, minute, second;
-    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-    struct tm *tmtime;
-
-    memset (name, '\0', sizeof (name));
-    memset (date, '\0', sizeof (date));
-    memset (time, '\0', sizeof (time));
-    year = month = day = hour = minute = second = 0;
-    connect_until_time = 0;
-    tmtime = localtime (&connect_until_time);   // initialize
-
-    if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 &&   // if date = 0, time can be void
-        sscanf (param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 &&  // if date = 0, time can be void
-        sscanf (param, "%s %s %[^\r\n]", name, date, time) < 2)
-    {                           // if date = 0, time can be void
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte, une date et une heure svp.\n");
-            printf
-                ("<exemple>: timeset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
-            printf
-                ("           timeset <nom_du_compte> 0    (0 = illimité)\n");
-            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Nombre incorrect de paramètres pour fixer une date limite d'utilisation (commande 'timeset').\n");
-        }
-        else
-        {
-            printf ("Please input an account name, a date and a hour.\n");
-            printf
-                ("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
-            printf
-                ("           timeset <account_name> 0   (0 = unlimited)\n");
-            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
-            ladmin_log
-                ("Incomplete parameters to set a limit time ('timeset' command).\n");
-        }
-        return 136;
-    }
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (time[0] == '\0')
-        strcpy (time, "23:59:59");
-
-    if (atoi (date) != 0 &&
-        ((sscanf (date, "%d/%d/%d", &year, &month, &day) < 3 &&
-          sscanf (date, "%d-%d-%d", &year, &month, &day) < 3 &&
-          sscanf (date, "%d.%d.%d", &year, &month, &day) < 3 &&
-          sscanf (date, "%d'%d'%d", &year, &month, &day) < 3) ||
-         sscanf (time, "%d:%d:%d", &hour, &minute, &second) < 3))
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n");
-            ladmin_log
-                ("Format incorrect pour la date/heure ('timeset' command).\n");
-        }
-        else
-        {
-            printf
-                ("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
-            ladmin_log
-                ("Invalid format for the date/time ('timeset' command).\n");
-        }
-        return 102;
-    }
-
-    if (atoi (date) == 0)
-    {
-        connect_until_time = 0;
-    }
-    else
-    {
-        if (year < 70)
-        {
-            year = year + 100;
-        }
-        if (year >= 1900)
-        {
-            year = year - 1900;
-        }
-        if (month < 1 || month > 12)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez un mois correct svp (entre 1 et 12).\n");
-                ladmin_log ("Mois incorrect pour la date ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the month (from 1 to 12).\n");
-                ladmin_log ("Invalid month for the date ('timeset' command).\n");
-            }
-            return 102;
-        }
-        month = month - 1;
-        if (day < 1 || day > 31)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez un jour correct svp (entre 1 et 31).\n");
-                ladmin_log ("Jour incorrect pour la date ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the day (from 1 to 31).\n");
-                ladmin_log ("Invalid day for the date ('timeset' command).\n");
-            }
-            return 102;
-        }
-        if (((month == 3 || month == 5 || month == 8 || month == 10)
-             && day > 30) || (month == 1 && day > 29))
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez un jour correct en fonction du mois (%d) svp.\n",
-                     month);
-                ladmin_log
-                    ("Jour incorrect pour ce mois correspondant ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for a day of this month (%d).\n",
-                     month);
-                ladmin_log ("Invalid day for this month ('timeset' command).\n");
-            }
-            return 102;
-        }
-        if (hour < 0 || hour > 23)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Entrez une heure correcte svp (entre 0 et 23).\n");
-                ladmin_log
-                    ("Heure incorrecte pour l'heure ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the hour (from 0 to 23).\n");
-                ladmin_log ("Invalid hour for the time ('timeset' command).\n");
-            }
-            return 102;
-        }
-        if (minute < 0 || minute > 59)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez des minutes correctes svp (entre 0 et 59).\n");
-                ladmin_log
-                    ("Minute incorrecte pour l'heure ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the minutes (from 0 to 59).\n");
-                ladmin_log ("Invalid minute for the time ('timeset' command).\n");
-            }
-            return 102;
-        }
-        if (second < 0 || second > 59)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf
-                    ("Entrez des secondes correctes svp (entre 0 et 59).\n");
-                ladmin_log
-                    ("Seconde incorrecte pour l'heure ('timeset' command).\n");
-            }
-            else
-            {
-                printf
-                    ("Please give a correct value for the seconds (from 0 to 59).\n");
-                ladmin_log ("Invalid second for the time ('timeset' command).\n");
-            }
-            return 102;
-        }
-        tmtime->tm_year = year;
-        tmtime->tm_mon = month;
-        tmtime->tm_mday = day;
-        tmtime->tm_hour = hour;
-        tmtime->tm_min = minute;
-        tmtime->tm_sec = second;
-        tmtime->tm_isdst = -1;  // -1: no winter/summer time modification
-        connect_until_time = timegm (tmtime);
-        if (connect_until_time == -1)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Date incorrecte.\n");
-                printf
-                    ("Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n");
-                ladmin_log ("Date incorrecte. ('timeset' command).\n");
-            }
-            else
-            {
-                printf ("Invalid date.\n");
-                printf
-                    ("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
-                ladmin_log ("Invalid date. ('timeset' command).\n");
-            }
-            return 102;
-        }
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour fixer une date limite d'utilisation.\n");
-    }
-    else
-    {
-        ladmin_log ("Request to login-server to set a time limit.\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7948;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOL (login_fd, 26) = (int) connect_until_time;
-    WFIFOSET (login_fd, 30);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//------------------------------------------------------------------------------
-// Sub-function: Asking to displaying information about an account (by its name)
-//------------------------------------------------------------------------------
-int whoaccount (char *param)
-{
-    char name[1023];
-
-    memset (name, '\0', sizeof (name));
-
-    if (strlen (param) == 0 ||
-        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
-         sscanf (param, "'%[^']'", name) < 1 &&
-         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("Entrez un nom de compte svp.\n");
-            printf ("<exemple> who nomtest\n");
-            ladmin_log ("Aucun nom n'a été donné pour trouver le compte.\n");
-        }
-        else
-        {
-            printf ("Please input an account name.\n");
-            printf ("<example> who testname\n");
-            ladmin_log ("No name was given to found the account.\n");
-        }
-        return 136;
-    }
-    if (verify_accountname (name) == 0)
-    {
-        return 102;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour obtenir le information d'un compte (par le nom).\n");
-    }
-    else
-    {
-        ladmin_log
-            ("Request to login-server to obtain information about an account (by its name).\n");
-    }
-
-    WFIFOW (login_fd, 0) = 0x7952;
-    memcpy (WFIFOP (login_fd, 2), name, 24);
-    WFIFOSET (login_fd, 26);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//--------------------------------------------------------
-// Sub-function: Asking of the version of the login-server
-//--------------------------------------------------------
-int checkloginversion (void)
-{
-    if (defaultlanguage == 'F')
-        ladmin_log
-            ("Envoi d'un requête au serveur de logins pour obtenir sa version.\n");
-    else
-        ladmin_log ("Request to login-server to obtain its version.\n");
-
-    WFIFOW (login_fd, 0) = 0x7530;
-    WFIFOSET (login_fd, 2);
-    bytes_to_read = 1;
-
-    return 0;
-}
-
-//---------------------------------------------
-// Prompt function
-// this function wait until user type a command
-// and analyse the command.
-//---------------------------------------------
-int prompt (void)
-{
-    int  i, j;
-    char buf[1024];
-    char *p;
-
-    // while we don't wait new packets
-    while (bytes_to_read == 0)
-    {
-        // for help with the console colors look here:
-        // http://www.edoceo.com/liberum/?doc=printf-with-color
-        // some code explanation (used here):
-        // \033[2J : clear screen and go up/left (0, 0 position)
-        // \033[K  : clear line from actual position to end of the line
-        // \033[0m : reset color parameter
-        // \033[1m : use bold for font
-        Iprintf ("\n");
-        if (defaultlanguage == 'F')
-        {
-            Iprintf
-                ("\033[32mPour afficher les commandes, tapez 'Entrée'.\033[0m\n");
-        }
-        else
-            Iprintf ("\033[32mTo list the commands, type 'enter'.\033[0m\n");
-        Iprintf ("\033[0;36mLadmin-> \033[0m");
-        Iprintf ("\033[1m");
-        fflush (stdout);
-
-        // get command and parameter
-        memset (buf, '\0', sizeof (buf));
-        fflush (stdin);
-        if (!fgets (buf, 1023, stdin))
-            exit (0);
-        buf[1023] = '\0';
-
-        Iprintf ("\033[0m");
-        fflush (stdout);
-
-        if (!eathena_interactive_session && !strlen (buf))
-            exit (0);
-
-        // remove final \n
-        if ((p = strrchr (buf, '\n')) != NULL)
-            p[0] = '\0';
-        // remove all control char
-        for (i = 0; buf[i]; i++)
-            if (buf[i] < 32)
-            {
-                // remove cursor control.
-                if (buf[i] == 27 && buf[i + 1] == '[' && (buf[i + 2] == 'H' ||  // home position (cursor)
-                                                          buf[i + 2] == 'J' ||  // clear screen
-                                                          buf[i + 2] == 'A' ||  // up 1 line
-                                                          buf[i + 2] == 'B' ||  // down 1 line
-                                                          buf[i + 2] == 'C' ||  // right 1 position
-                                                          buf[i + 2] == 'D' ||  // left 1 position
-                                                          buf[i + 2] == 'G'))
-                {               // center cursor (windows)
-                    for (j = i; buf[j]; j++)
-                        buf[j] = buf[j + 3];
-                }
-                else if (buf[i] == 27 && buf[i + 1] == '['
-                         && buf[i + 2] == '2' && buf[i + 3] == 'J')
-                {               // clear screen
-                    for (j = i; buf[j]; j++)
-                        buf[j] = buf[j + 4];
-                }
-                else if (buf[i] == 27 && buf[i + 1] == '[' && buf[i + 3] == '~' && (buf[i + 2] == '1' ||    // home (windows)
-                                                                                    buf[i + 2] == '2' ||    // insert (windows)
-                                                                                    buf[i + 2] == '3' ||    // del (windows)
-                                                                                    buf[i + 2] == '4' ||    // end (windows)
-                                                                                    buf[i + 2] == '5' ||    // pgup (windows)
-                                                                                    buf
-                                                                                    [i
-                                                                                     +
-                                                                                     2]
-                                                                                    ==
-                                                                                    '6'))
-                {               // pgdown (windows)
-                    for (j = i; buf[j]; j++)
-                        buf[j] = buf[j + 4];
-                }
-                else
-                {
-                    // remove other control char.
-                    for (j = i; buf[j]; j++)
-                        buf[j] = buf[j + 1];
-                }
-                i--;
-            }
-
-        // extract command name and parameters
-        memset (command, '\0', sizeof (command));
-        memset (parameters, '\0', sizeof (parameters));
-        sscanf (buf, "%1023s %[^\n]", command, parameters);
-        command[1023] = '\0';
-        parameters[1023] = '\0';
-
-        // lowercase for command line
-        for (i = 0; command[i]; i++)
-            command[i] = tolower (command[i]);
-
-        if (command[0] == '?' || strlen (command) == 0)
-        {
-            if (defaultlanguage == 'F')
-            {
-                strcpy (buf, "aide");
-                strcpy (command, "aide");
-            }
-            else
-            {
-                strcpy (buf, "help");
-                strcpy (command, "help");
-            }
-        }
-
-        // Analyse of the command
-        check_command (command);    // give complete name to the command
-
-        if (strlen (parameters) == 0)
-        {
-            if (defaultlanguage == 'F')
-            {
-                ladmin_log ("Commande: '%s' (sans paramètre)\n",
-                            command, parameters);
-            }
-            else
-            {
-                ladmin_log ("Command: '%s' (without parameters)\n",
-                            command, parameters);
-            }
-        }
-        else
-        {
-            if (defaultlanguage == 'F')
-            {
-                ladmin_log ("Commande: '%s', paramètres: '%s'\n",
-                            command, parameters);
-            }
-            else
-            {
-                ladmin_log ("Command: '%s', parameters: '%s'\n",
-                            command, parameters);
-            }
-        }
-
-        // Analyse of the command
-// help
-        if (strcmp (command, "aide") == 0)
-        {
-            display_help (parameters, 1);   // 1: french
-        }
-        else if (strcmp (command, "help") == 0)
-        {
-            display_help (parameters, 0);   // 0: english
-// general commands
-        }
-        else if (strcmp (command, "add") == 0)
-        {
-            addaccount (parameters, 0); // 0: no email
-        }
-        else if (strcmp (command, "ban") == 0)
-        {
-            banaccount (parameters);
-        }
-        else if (strcmp (command, "banadd") == 0)
-        {
-            banaddaccount (parameters);
-        }
-        else if (strcmp (command, "banset") == 0)
-        {
-            bansetaccount (parameters);
-        }
-        else if (strcmp (command, "block") == 0)
-        {
-            blockaccount (parameters);
-        }
-        else if (strcmp (command, "check") == 0)
-        {
-            checkaccount (parameters);
-        }
-        else if (strcmp (command, "create") == 0)
-        {
-            addaccount (parameters, 1); // 1: with email
-        }
-        else if (strcmp (command, "delete") == 0)
-        {
-            delaccount (parameters);
-        }
-        else if (strcmp (command, "email") == 0)
-        {
-            changeemail (parameters);
-        }
-        else if (strcmp (command, "getcount") == 0)
-        {
-            getlogincount ();
-        }
-        else if (strcmp (command, "gm") == 0)
-        {
-            changegmlevel (parameters);
-        }
-        else if (strcmp (command, "id") == 0)
-        {
-            idaccount (parameters);
-        }
-        else if (strcmp (command, "info") == 0)
-        {
-            infoaccount (atoi (parameters));
-        }
-        else if (strcmp (command, "kami") == 0)
-        {
-            sendbroadcast (0, parameters);  // flag for normal
-        }
-        else if (strcmp (command, "kamib") == 0)
-        {
-            sendbroadcast (0x10, parameters);   // flag for blue
-        }
-        else if (strcmp (command, "language") == 0)
-        {
-            changelanguage (parameters);
-        }
-        else if (strcmp (command, "itemfrob") == 0)
-        {
-            itemfrob (parameters);  // 0: to list all
-        }
-        else if (strcmp (command, "list") == 0)
-        {
-            listaccount (parameters, 0);    // 0: to list all
-        }
-        else if (strcmp (command, "listban") == 0)
-        {
-            listaccount (parameters, 3);    // 3: to list only accounts with state or bannished
-        }
-        else if (strcmp (command, "listgm") == 0)
-        {
-            listaccount (parameters, 1);    // 1: to list only GM
-        }
-        else if (strcmp (command, "listok") == 0)
-        {
-            listaccount (parameters, 4);    // 4: to list only accounts without state and not bannished
-        }
-        else if (strcmp (command, "memo") == 0)
-        {
-            changememo (parameters);
-        }
-        else if (strcmp (command, "name") == 0)
-        {
-            nameaccount (atoi (parameters));
-        }
-        else if (strcmp (command, "password") == 0)
-        {
-            changepasswd (parameters);
-        }
-        else if (strcmp (command, "reloadgm") == 0)
-        {
-            reloadGM ();
-        }
-        else if (strcmp (command, "search") == 0)
-        {                       // no regex in C version
-            listaccount (parameters, 2);    // 2: to list with pattern
-        }
-        else if (strcmp (command, "sex") == 0)
-        {
-            changesex (parameters);
-        }
-        else if (strcmp (command, "state") == 0)
-        {
-            changestate (parameters);
-        }
-        else if (strcmp (command, "timeadd") == 0)
-        {
-            timeaddaccount (parameters);
-        }
-        else if (strcmp (command, "timeset") == 0)
-        {
-            timesetaccount (parameters);
-        }
-        else if (strcmp (command, "unban") == 0)
-        {
-            unbanaccount (parameters);
-        }
-        else if (strcmp (command, "unblock") == 0)
-        {
-            unblockaccount (parameters);
-        }
-        else if (strcmp (command, "version") == 0)
-        {
-            checkloginversion ();
-        }
-        else if (strcmp (command, "who") == 0)
-        {
-            whoaccount (parameters);
-// quit
-        }
-        else if (strcmp (command, "quit") == 0 ||
-                 strcmp (command, "exit") == 0 ||
-                 strcmp (command, "end") == 0)
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Au revoir.\n");
-            }
-            else
-            {
-                printf ("Bye.\n");
-            }
-            exit (0);
-// unknown command
-        }
-        else
-        {
-            if (defaultlanguage == 'F')
-            {
-                printf ("Commande inconnue [%s].\n", buf);
-                ladmin_log ("Commande inconnue [%s].\n", buf);
-            }
-            else
-            {
-                printf ("Unknown command [%s].\n", buf);
-                ladmin_log ("Unknown command [%s].\n", buf);
-            }
-        }
-    }
-
-    return 0;
-}
-
-//-------------------------------------------------------------
-// Function: Parse receiving informations from the login-server
-//-------------------------------------------------------------
-void parse_fromlogin (int fd)
-{
-    struct char_session_data *sd;
-
-    if (session[fd]->eof)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf
-                ("Impossible de se connecter au serveur de login [%s:%d] !\n",
-                 loginserverip, loginserverport);
-            ladmin_log
-                ("Impossible de se connecter au serveur de login [%s:%d] !\n",
-                  loginserverip, loginserverport);
-        }
-        else
-        {
-            printf
-                ("Impossible to have a connection with the login-server [%s:%d] !\n",
-                 loginserverip, loginserverport);
-            ladmin_log
-                ("Impossible to have a connection with the login-server [%s:%d] !\n",
-                  loginserverip, loginserverport);
-        }
-        close (fd);
-        delete_session (fd);
-        exit (0);
-    }
-
-//  printf("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
-    sd = (struct char_session_data *)session[fd]->session_data;
-
-    while (RFIFOREST (fd) >= 2)
-    {
-        switch (RFIFOW (fd, 0))
-        {
-            case 0x7919:       // answer of a connection request
-                if (RFIFOREST (fd) < 3)
-                    return;
-                if (RFIFOB (fd, 2) != 0)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Erreur de login:\n");
-                        printf (" - mot de passe incorrect,\n");
-                        printf
-                            (" - système d'administration non activé, ou\n");
-                        printf (" - IP non autorisée.\n");
-                        ladmin_log
-                            ("Erreur de login: mot de passe incorrect, système d'administration non activé, ou IP non autorisée.\n");
-                    }
-                    else
-                    {
-                        printf ("Error at login:\n");
-                        printf (" - incorrect password,\n");
-                        printf
-                            (" - administration system not activated, or\n");
-                        printf (" - unauthorised IP.\n");
-                        ladmin_log
-                            ("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n");
-                    }
-                    session[fd]->eof = 1;
-                    //bytes_to_read = 1; // not stop at prompt
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Connexion établie.\n");
-                        ladmin_log ("Connexion établie.\n");
-                        printf
-                            ("Lecture de la version du serveur de login...\n");
-                        ladmin_log
-                            ("Lecture de la version du serveur de login...\n");
-                    }
-                    else
-                    {
-                        Iprintf ("Established connection.\n");
-                        ladmin_log ("Established connection.\n");
-                        Iprintf
-                            ("Reading of the version of the login-server...\n");
-                        ladmin_log
-                            ("Reading of the version of the login-server...\n");
-                    }
-                    //bytes_to_read = 1; // unchanged
-                    checkloginversion ();
-                }
-                RFIFOSKIP (fd, 3);
-                break;
-
-#ifdef PASSWORDENC
-            case 0x01dc:       // answer of a coding key request
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    char md5str[64] =
-                        "", md5bin[32], md5key[RFIFOW (fd, 2) - 4 + 1];
-                    memcpy (md5key, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
-                    md5key[sizeof (md5key) - 1] = '0';
-                    if (passenc == 1)
-                    {
-                        strncpy (md5str, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
-                        strcat (md5str, loginserveradminpassword);
-                    }
-                    else if (passenc == 2)
-                    {
-                        strncpy (md5str, loginserveradminpassword,
-                                 sizeof (loginserveradminpassword));
-                        strcat (md5str, RFIFOP (fd, 4));
-                    }
-                    MD5_to_bin(MD5_from_cstring(md5str), md5bin);
-                    WFIFOW (login_fd, 0) = 0x7918;  // Request for administation login (encrypted password)
-                    WFIFOW (login_fd, 2) = passenc; // Encrypted type
-                    memcpy (WFIFOP (login_fd, 4), md5bin, 16);
-                    WFIFOSET (login_fd, 20);
-                    if (defaultlanguage == 'F')
-                    {
-                        Iprintf ("Réception de la clef MD5.\n");
-                        ladmin_log ("Réception de la clef MD5.\n");
-                        Iprintf ("Envoi du mot de passe crypté...\n");
-                        ladmin_log ("Envoi du mot de passe crypté...\n");
-                    }
-                    else
-                    {
-                        Iprintf ("Receiving of the MD5 key.\n");
-                        ladmin_log ("Receiving of the MD5 key.\n");
-                        Iprintf ("Sending of the encrypted password...\n");
-                        ladmin_log ("Sending of the encrypted password...\n");
-                    }
-                }
-                bytes_to_read = 1;
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-#endif
-
-            case 0x7531:       // Displaying of the version of the login-server
-                if (RFIFOREST (fd) < 10)
-                    return;
-                Iprintf ("  Login-Server [%s:%d]\n", loginserverip,
-                         loginserverport);
-                if (((int) RFIFOB (login_fd, 5)) == 0)
-                {
-                    Iprintf ("  eAthena version stable-%d.%d",
-                             (int) RFIFOB (login_fd, 2),
-                             (int) RFIFOB (login_fd, 3));
-                }
-                else
-                {
-                    Iprintf ("  eAthena version dev-%d.%d",
-                             (int) RFIFOB (login_fd, 2),
-                             (int) RFIFOB (login_fd, 3));
-                }
-                if (((int) RFIFOB (login_fd, 4)) == 0)
-                    Iprintf (" revision %d", (int) RFIFOB (login_fd, 4));
-                if (((int) RFIFOB (login_fd, 6)) == 0)
-                {
-                    Iprintf ("%d.\n", RFIFOW (login_fd, 8));
-                }
-                else
-                    Iprintf ("-mod%d.\n", RFIFOW (login_fd, 8));
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 10);
-                break;
-
-            case 0x7925:       // Itemfrob-OK
-                RFIFOSKIP (fd, 2);
-                bytes_to_read = 0;
-                break;
-
-            case 0x7921:       // Displaying of the list of accounts
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                if (RFIFOW (fd, 2) < 5)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        ladmin_log
-                            ("  Réception d'une liste des comptes vide.\n");
-                        if (list_count == 0)
-                            printf ("Aucun compte trouvé.\n");
-                        else if (list_count == 1)
-                            printf ("1 compte trouvé.\n");
-                        else
-                            printf ("%d comptes trouvés.\n", list_count);
-                    }
-                    else
-                    {
-                        ladmin_log ("  Receiving of a void accounts list.\n");
-                        if (list_count == 0)
-                        {
-                            Iprintf ("No account found.\n");
-                        }
-                        else if (list_count == 1)
-                        {
-                            Iprintf ("1 account found.\n");
-                        }
-                        else
-                            Iprintf ("%d accounts found.\n", list_count);
-                    }
-                    bytes_to_read = 0;
-                }
-                else
-                {
-                    int  i;
-                    if (defaultlanguage == 'F')
-                        ladmin_log ("  Réception d'une liste des comptes.\n");
-                    else
-                        ladmin_log ("  Receiving of a accounts list.\n");
-                    for (i = 4; i < RFIFOW (fd, 2); i += 38)
-                    {
-                        int  j;
-                        char userid[24];
-                        char lower_userid[24];
-                        memcpy (userid, RFIFOP (fd, i + 5), sizeof (userid));
-                        userid[sizeof (userid) - 1] = '\0';
-                        memset (lower_userid, '\0', sizeof (lower_userid));
-                        for (j = 0; userid[j]; j++)
-                            lower_userid[j] = tolower (userid[j]);
-                        list_first = RFIFOL (fd, i) + 1;
-                        // here are checks...
-                        if (list_type == 0 ||
-                            (list_type == 1 && RFIFOB (fd, i + 4) > 0) ||
-                            (list_type == 2
-                             && strstr (lower_userid, parameters) != NULL)
-                            || (list_type == 3 && RFIFOL (fd, i + 34) != 0)
-                            || (list_type == 4 && RFIFOL (fd, i + 34) == 0))
-                        {
-                            printf ("%10d ", RFIFOL (fd, i));
-                            if (RFIFOB (fd, i + 4) == 0)
-                                printf ("   ");
-                            else
-                                printf ("%2d ", (int) RFIFOB (fd, i + 4));
-                            printf ("%-24s", userid);
-                            if (defaultlanguage == 'F')
-                            {
-                                if (RFIFOB (fd, i + 29) == 0)
-                                    printf ("%-5s ", "Femme");
-                                else if (RFIFOB (fd, i + 29) == 1)
-                                    printf ("%-5s ", "Male");
-                                else
-                                    printf ("%-5s ", "Servr");
-                            }
-                            else
-                            {
-                                if (RFIFOB (fd, i + 29) == 0)
-                                    printf ("%-5s ", "Femal");
-                                else if (RFIFOB (fd, i + 29) == 1)
-                                    printf ("%-5s ", "Male");
-                                else
-                                    printf ("%-5s ", "Servr");
-                            }
-                            printf ("%6d ", RFIFOL (fd, i + 30));
-                            switch (RFIFOL (fd, i + 34))
-                            {
-                                case 0:
-                                    if (defaultlanguage == 'F')
-                                        printf ("%-27s\n", "Compte Ok");
-                                    else
-                                        printf ("%-27s\n", "Account OK");
-                                    break;
-                                case 1:
-                                    printf ("%-27s\n", "Unregistered ID");
-                                    break;
-                                case 2:
-                                    printf ("%-27s\n", "Incorrect Password");
-                                    break;
-                                case 3:
-                                    printf ("%-27s\n", "This ID is expired");
-                                    break;
-                                case 4:
-                                    printf ("%-27s\n",
-                                            "Rejected from Server");
-                                    break;
-                                case 5:
-                                    printf ("%-27s\n", "Blocked by the GM Team");   // You have been blocked by the GM Team
-                                    break;
-                                case 6:
-                                    printf ("%-27s\n", "Your EXE file is too old"); // Your Game's EXE file is not the latest version
-                                    break;
-                                case 7:
-                                    printf ("%-27s\n", "Banishement or");
-                                    printf ("                                                   Prohibited to login until...\n");   // You are Prohibited to log in until %s
-                                    break;
-                                case 8:
-                                    printf ("%-27s\n",
-                                            "Server is over populated");
-                                    break;
-                                case 9:
-                                    printf ("%-27s\n", "No MSG");
-                                    break;
-                                default:   // 100
-                                    printf ("%-27s\n", "This ID is totally erased");    // This ID has been totally erased
-                                    break;
-                            }
-                            list_count++;
-                        }
-                    }
-                    // asking of the following acounts
-                    if (defaultlanguage == 'F')
-                        ladmin_log
-                            ("Envoi d'un requête au serveur de logins pour obtenir la liste des comptes de %d à %d (complément).\n",
-                              list_first, list_last);
-                    else
-                        ladmin_log
-                            ("Request to login-server to obtain the list of accounts from %d to %d (complement).\n",
-                              list_first, list_last);
-                    WFIFOW (login_fd, 0) = 0x7920;
-                    WFIFOL (login_fd, 2) = list_first;
-                    WFIFOL (login_fd, 6) = list_last;
-                    WFIFOSET (login_fd, 10);
-                    bytes_to_read = 1;
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-            case 0x7931:       // Answer of login-server about an account creation
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec à la création du compte [%s]. Un compte identique existe déjà.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec à la création du compte [%s]. Un compte identique existe déjà.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] creation failed. Same account already exists.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] creation failed. Same account already exists.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Compte [%s] créé avec succès [id: %d].\n",
-                                RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log ("Compte [%s] créé avec succès [id: %d].\n",
-                                     RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] is successfully created [id: %d].\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s] is successfully created [id: %d].\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7933:       // Answer of login-server about an account deletion
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de la suppression du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec de la suppression du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] deletion failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] deletion failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Compte [%s][id: %d] SUPPRIME avec succès.\n",
-                                RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Compte [%s][id: %d] SUPPRIME avec succès.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] is successfully DELETED.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] is successfully DELETED.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7935:       // answer of the change of an account password
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de la modification du mot de passe du compte [%s].\n",
-                             RFIFOP (fd, 6));
-                        printf ("Le compte [%s] n'existe pas.\n",
-                                RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec de la modification du mot de passe du compte. Le compte [%s] n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf ("Account [%s] password changing failed.\n",
-                                RFIFOP (fd, 6));
-                        printf ("Account [%s] doesn't exist.\n",
-                                RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account password changing failed. The compte [%s] doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Modification du mot de passe du compte [%s][id: %d] réussie.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Modification du mot de passe du compte [%s][id: %d] réussie.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] password successfully changed.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] password successfully changed.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7937:       // answer of the change of an account state
-                if (RFIFOREST (fd) < 34)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement du statut du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement du statut du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] state changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] state changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    char tmpstr[256];
-                    if (defaultlanguage == 'F')
-                    {
-                        sprintf (tmpstr,
-                                 "Statut du compte [%s] changé avec succès en [",
-                                 RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        sprintf (tmpstr,
-                                 "Account [%s] state successfully changed in [",
-                                 RFIFOP (fd, 6));
-                    }
-                    switch (RFIFOL (fd, 30))
-                    {
-                        case 0:
-                            if (defaultlanguage == 'F')
-                                strcat (tmpstr, "0: Compte Ok");
-                            else
-                                strcat (tmpstr, "0: Account OK");
-                            break;
-                        case 1:
-                            strcat (tmpstr, "1: Unregistered ID");
-                            break;
-                        case 2:
-                            strcat (tmpstr, "2: Incorrect Password");
-                            break;
-                        case 3:
-                            strcat (tmpstr, "3: This ID is expired");
-                            break;
-                        case 4:
-                            strcat (tmpstr, "4: Rejected from Server");
-                            break;
-                        case 5:
-                            strcat (tmpstr,
-                                    "5: You have been blocked by the GM Team");
-                            break;
-                        case 6:
-                            strcat (tmpstr,
-                                    "6: [Your Game's EXE file is not the latest version");
-                            break;
-                        case 7:
-                            strcat (tmpstr,
-                                    "7: You are Prohibited to log in until...");
-                            break;
-                        case 8:
-                            strcat (tmpstr,
-                                    "8: Server is jammed due to over populated");
-                            break;
-                        case 9:
-                            strcat (tmpstr, "9: No MSG");
-                            break;
-                        default:   // 100
-                            strcat (tmpstr, "100: This ID is totally erased");
-                            break;
-                    }
-                    strcat (tmpstr, "]");
-                    printf ("%s\n", tmpstr);
-                    ladmin_log ("%s%s", tmpstr, "\n");
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 34);
-                break;
-
-            case 0x7939:       // answer of the number of online players
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    // Get length of the received packet
-                    int  i;
-                    char name[20];
-                    if (defaultlanguage == 'F')
-                    {
-                        ladmin_log
-                            ("  Réception du nombre de joueurs en ligne.\n");
-                    }
-                    else
-                    {
-                        ladmin_log
-                            ("  Receiving of the number of online players.\n");
-                    }
-                    // Read information of the servers
-                    if (RFIFOW (fd, 2) < 5)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("  Aucun serveur n'est connecté au login serveur.\n");
-                        }
-                        else
-                        {
-                            printf
-                                ("  No server is connected to the login-server.\n");
-                        }
-                    }
-                    else
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("  Nombre de joueurs en ligne (serveur: nb):\n");
-                        }
-                        else
-                        {
-                            printf
-                                ("  Number of online players (server: number).\n");
-                        }
-                        // Displaying of result
-                        for (i = 4; i < RFIFOW (fd, 2); i += 32)
-                        {
-                            memcpy (name, RFIFOP (fd, i + 6), sizeof (name));
-                            name[sizeof (name) - 1] = '\0';
-                            printf ("    %-20s : %5d\n", name,
-                                    RFIFOW (fd, i + 26));
-                        }
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-            case 0x793b:       // answer of the check of a password
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Le compte [%s] n'existe pas ou le mot de passe est incorrect.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Le compte [%s] n'existe pas ou le mot de passe est incorrect.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("The account [%s] doesn't exist or the password is incorrect.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("The account [%s] doesn't exist or the password is incorrect.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Le mot de passe donné correspond bien au compte [%s][id: %d].\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Le mot de passe donné correspond bien au compte [%s][id: %d].\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("The proposed password is correct for the account [%s][id: %d].\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("The proposed password is correct for the account [%s][id: %d].\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x793d:       // answer of the change of an account sex
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de la modification du sexe du compte [%s].\n",
-                             RFIFOP (fd, 6));
-                        printf
-                            ("Le compte [%s] n'existe pas ou le sexe est déjà celui demandé.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec de la modification du sexe du compte. Le compte [%s] n'existe pas ou le sexe est déjà celui demandé.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf ("Account [%s] sex changing failed.\n",
-                                RFIFOP (fd, 6));
-                        printf
-                            ("Account [%s] doesn't exist or the sex is already the good sex.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Sexe du compte [%s][id: %d] changé avec succès.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Sexe du compte [%s][id: %d] changé avec succès.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] sex successfully changed.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] sex successfully changed.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x793f:       // answer of the change of an account GM level
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de la modification du niveau de GM du compte [%s].\n",
-                             RFIFOP (fd, 6));
-                        printf
-                            ("Le compte [%s] n'existe pas, le niveau de GM est déjà celui demandé\n",
-                             RFIFOP (fd, 6));
-                        printf
-                            ("ou il est impossible de modifier le fichier des comptes GM.\n");
-                        ladmin_log
-                            ("Echec de la modification du niveau de GM du compte. Le compte [%s] n'existe pas, le niveau de GM est déjà celui demandé ou il est impossible de modifier le fichier des comptes GM.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf ("Account [%s] GM level changing failed.\n",
-                                RFIFOP (fd, 6));
-                        printf
-                            ("Account [%s] doesn't exist, the GM level is already the good GM level\n",
-                             RFIFOP (fd, 6));
-                        printf
-                            ("or it's impossible to modify the GM accounts file.\n");
-                        ladmin_log
-                            ("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Niveau de GM du compte [%s][id: %d] changé avec succès.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Niveau de GM du compte [%s][id: %d] changé avec succès.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] GM level successfully changed.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] GM level successfully changed.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7941:       // answer of the change of an account email
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de la modification de l'e-mail du compte [%s].\n",
-                             RFIFOP (fd, 6));
-                        printf ("Le compte [%s] n'existe pas.\n",
-                                RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec de la modification de l'e-mail du compte. Le compte [%s] n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf ("Account [%s] e-mail changing failed.\n",
-                                RFIFOP (fd, 6));
-                        printf ("Account [%s] doesn't exist.\n",
-                                RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account e-mail changing failed. The compte [%s] doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Modification de l'e-mail du compte [%s][id: %d] réussie.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Modification de l'e-mail du compte [%s][id: %d] réussie.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] e-mail successfully changed.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] e-mail successfully changed.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7943:       // answer of the change of an account memo
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement du mémo du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement du mémo du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] memo changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] memo changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Mémo du compte [%s][id: %d] changé avec succès.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Mémo du compte [%s][id: %d] changé avec succès.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s][id: %d] memo successfully changed.\n",
-                             RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Account [%s][id: %d] memo successfully changed.\n",
-                              RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7945:       // answer of an account id search
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Impossible de trouver l'id du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Impossible de trouver l'id du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Unable to find the account [%s] id. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Unable to find the account [%s] id. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Le compte [%s] a pour id: %d.\n",
-                                RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log ("Le compte [%s] a pour id: %d.\n",
-                                    RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf ("The account [%s] have the id: %d.\n",
-                                RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        ladmin_log ("The account [%s] have the id: %d.\n",
-                                     RFIFOP (fd, 6), RFIFOL (fd, 2));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7947:       // answer of an account name search
-                if (RFIFOREST (fd) < 30)
-                    return;
-                if (strcmp (RFIFOP (fd, 6), "") == 0)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas.\n",
-                             RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas.\n",
-                              RFIFOL (fd, 2));
-                    }
-                    else
-                    {
-                        printf
-                            ("Unable to find the account [%d] name. Account doesn't exist.\n",
-                             RFIFOL (fd, 2));
-                        ladmin_log
-                            ("Unable to find the account [%d] name. Account doesn't exist.\n",
-                              RFIFOL (fd, 2));
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf ("Le compte [id: %d] a pour nom: %s.\n",
-                                RFIFOL (fd, 2), RFIFOP (fd, 6));
-                        ladmin_log ("Le compte [id: %d] a pour nom: %s.\n",
-                                     RFIFOL (fd, 2), RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf ("The account [id: %d] have the name: %s.\n",
-                                RFIFOL (fd, 2), RFIFOP (fd, 6));
-                        ladmin_log ("The account [id: %d] have the name: %s.\n",
-                                     RFIFOL (fd, 2), RFIFOP (fd, 6));
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x7949:       // answer of an account validity limit set
-                if (RFIFOREST (fd) < 34)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    time_t timestamp = RFIFOL (fd, 30);
-                    if (timestamp == 0)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès en [illimité].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès en [illimité].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                        else
-                        {
-                            printf
-                                ("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                    }
-                    else
-                    {
-                        char tmpstr[128];
-                        strftime (tmpstr, 24, date_format,
-                                  localtime (&timestamp));
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                        else
-                        {
-                            printf
-                                ("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 34);
-                break;
-
-            case 0x794b:       // answer of an account ban set
-                if (RFIFOREST (fd) < 34)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    time_t timestamp = RFIFOL (fd, 30);
-                    if (timestamp == 0)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                        else
-                        {
-                            printf
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                    }
-                    else
-                    {
-                        char tmpstr[128];
-                        strftime (tmpstr, 24, date_format,
-                                  localtime (&timestamp));
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                        else
-                        {
-                            printf
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 34);
-                break;
-
-            case 0x794d:       // answer of an account ban date/time changing
-                if (RFIFOREST (fd) < 34)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    time_t timestamp = RFIFOL (fd, 30);
-                    if (timestamp == 0)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                        else
-                        {
-                            printf
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            ladmin_log
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                    }
-                    else
-                    {
-                        char tmpstr[128];
-                        strftime (tmpstr, 24, date_format,
-                                  localtime (&timestamp));
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                        else
-                        {
-                            printf
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 34);
-                break;
-
-            case 0x794f:       // answer of a broadcast
-                if (RFIFOREST (fd) < 4)
-                    return;
-                if (RFIFOW (fd, 2) == (unsigned short) -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec de l'envoi du message. Aucun server de char en ligne.\n");
-                        ladmin_log
-                            ("Echec de l'envoi du message. Aucun server de char en ligne.\n");
-                    }
-                    else
-                    {
-                        printf
-                            ("Message sending failed. No online char-server.\n");
-                        ladmin_log
-                            ("Message sending failed. No online char-server.\n");
-                    }
-                }
-                else
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Message transmis au server de logins avec succès.\n");
-                        ladmin_log
-                            ("Message transmis au server de logins avec succès.\n");
-                    }
-                    else
-                    {
-                        printf
-                            ("Message successfully sended to login-server.\n");
-                        ladmin_log
-                            ("Message successfully sended to login-server.\n");
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 4);
-                break;
-
-            case 0x7951:       // answer of an account validity limit changing
-                if (RFIFOREST (fd) < 34)
-                    return;
-                if (RFIFOL (fd, 2) == -1)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        printf
-                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
-                              RFIFOP (fd, 6));
-                    }
-                    else
-                    {
-                        printf
-                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
-                             RFIFOP (fd, 6));
-                        ladmin_log
-                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
-                              RFIFOP (fd, 6));
-                    }
-                }
-                else
-                {
-                    time_t timestamp = RFIFOL (fd, 30);
-                    if (timestamp == 0)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Limite de validité du compte [%s][id: %d] inchangée.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            printf
-                                ("Le compte a une validité illimitée ou\n");
-                            printf
-                                ("la modification est impossible avec les ajustements demandés.\n");
-                            ladmin_log
-                                ("Limite de validité du compte [%s][id: %d] inchangée. Le compte a une validité illimitée ou la modification est impossible avec les ajustements demandés.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                        else
-                        {
-                            printf
-                                ("Validity limit of the account [%s][id: %d] unchanged.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
-                            printf
-                                ("The account have an unlimited validity limit or\n");
-                            printf
-                                ("the changing is impossible with the proposed adjustments.\n");
-                            ladmin_log
-                                ("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
-                        }
-                    }
-                    else
-                    {
-                        char tmpstr[128];
-                        strftime (tmpstr, 24, date_format,
-                                  localtime (&timestamp));
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                        else
-                        {
-                            printf
-                                ("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
-                            ladmin_log
-                                ("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
-                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
-                                 tmpstr);
-                        }
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 34);
-                break;
-
-            case 0x7953:       // answer of a request about informations of an account (by account name/id)
-                if (RFIFOREST (fd) < 150
-                    || RFIFOREST (fd) < (150 + RFIFOW (fd, 148)))
-                    return;
-                {
-                    char userid[24], error_message[20], lastlogin[24],
-                        last_ip[16], email[40], memo[255];
-                    time_t ban_until_time;  // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-                    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-                    memcpy (userid, RFIFOP (fd, 7), sizeof (userid));
-                    userid[sizeof (userid) - 1] = '\0';
-                    memcpy (error_message, RFIFOP (fd, 40),
-                            sizeof (error_message));
-                    error_message[sizeof (error_message) - 1] = '\0';
-                    memcpy (lastlogin, RFIFOP (fd, 60), sizeof (lastlogin));
-                    lastlogin[sizeof (lastlogin) - 1] = '\0';
-                    memcpy (last_ip, RFIFOP (fd, 84), sizeof (last_ip));
-                    last_ip[sizeof (last_ip) - 1] = '\0';
-                    memcpy (email, RFIFOP (fd, 100), sizeof (email));
-                    email[sizeof (email) - 1] = '\0';
-                    connect_until_time = (time_t) RFIFOL (fd, 140);
-                    ban_until_time = (time_t) RFIFOL (fd, 144);
-                    memset (memo, '\0', sizeof (memo));
-                    strncpy (memo, RFIFOP (fd, 150), RFIFOW (fd, 148));
-                    if (RFIFOL (fd, 2) == -1)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Impossible de trouver le compte [%s]. Le compte n'existe pas.\n",
-                                 parameters);
-                            ladmin_log
-                                ("Impossible de trouver le compte [%s]. Le compte n'existe pas.\n",
-                                  parameters);
-                        }
-                        else
-                        {
-                            printf
-                                ("Unabled to find the account [%s]. Account doesn't exist.\n",
-                                 parameters);
-                            ladmin_log
-                                ("Unabled to find the account [%s]. Account doesn't exist.\n",
-                                  parameters);
-                        }
-                    }
-                    else if (strlen (userid) == 0)
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            printf
-                                ("Impossible de trouver le compte [id: %s]. Le compte n'existe pas.\n",
-                                 parameters);
-                            ladmin_log
-                                ("Impossible de trouver le compte [id: %s]. Le compte n'existe pas.\n",
-                                  parameters);
-                        }
-                        else
-                        {
-                            printf
-                                ("Unabled to find the account [id: %s]. Account doesn't exist.\n",
-                                 parameters);
-                            ladmin_log
-                                ("Unabled to find the account [id: %s]. Account doesn't exist.\n",
-                                  parameters);
-                        }
-                    }
-                    else
-                    {
-                        if (defaultlanguage == 'F')
-                        {
-                            ladmin_log
-                                ("Réception d'information concernant un compte.\n");
-                            printf
-                                ("Le compte a les caractéristiques suivantes:\n");
-                        }
-                        else
-                        {
-                            ladmin_log
-                                ("Receiving information about an account.\n");
-                            printf ("The account is set with:\n");
-                        }
-                        if (RFIFOB (fd, 6) == 0)
-                        {
-                            printf (" Id:     %d (non-GM)\n", RFIFOL (fd, 2));
-                        }
-                        else
-                        {
-                            if (defaultlanguage == 'F')
-                            {
-                                printf (" Id:     %d (GM niveau %d)\n",
-                                        RFIFOL (fd, 2), (int) RFIFOB (fd, 6));
-                            }
-                            else
-                            {
-                                printf (" Id:     %d (GM level %d)\n",
-                                        RFIFOL (fd, 2), (int) RFIFOB (fd, 6));
-                            }
-                        }
-                        if (defaultlanguage == 'F')
-                        {
-                            printf (" Nom:    '%s'\n", userid);
-                            if (RFIFOB (fd, 31) == 0)
-                                printf (" Sexe:   Femme\n");
-                            else if (RFIFOB (fd, 31) == 1)
-                                printf (" Sexe:   Male\n");
-                            else
-                                printf (" Sexe:   Serveur\n");
-                        }
-                        else
-                        {
-                            printf (" Name:   '%s'\n", userid);
-                            if (RFIFOB (fd, 31) == 0)
-                                printf (" Sex:    Female\n");
-                            else if (RFIFOB (fd, 31) == 1)
-                                printf (" Sex:    Male\n");
-                            else
-                                printf (" Sex:    Server\n");
-                        }
-                        printf (" E-mail: %s\n", email);
-                        switch (RFIFOL (fd, 36))
-                        {
-                            case 0:
-                                if (defaultlanguage == 'F')
-                                    printf (" Statut: 0 [Compte Ok]\n");
-                                else
-                                    printf (" Statut: 0 [Account OK]\n");
-                                break;
-                            case 1:
-                                printf (" Statut: 1 [Unregistered ID]\n");
-                                break;
-                            case 2:
-                                printf (" Statut: 2 [Incorrect Password]\n");
-                                break;
-                            case 3:
-                                printf (" Statut: 3 [This ID is expired]\n");
-                                break;
-                            case 4:
-                                printf
-                                    (" Statut: 4 [Rejected from Server]\n");
-                                break;
-                            case 5:
-                                printf
-                                    (" Statut: 5 [You have been blocked by the GM Team]\n");
-                                break;
-                            case 6:
-                                printf
-                                    (" Statut: 6 [Your Game's EXE file is not the latest version]\n");
-                                break;
-                            case 7:
-                                printf
-                                    (" Statut: 7 [You are Prohibited to log in until %s]\n",
-                                     error_message);
-                                break;
-                            case 8:
-                                printf
-                                    (" Statut: 8 [Server is jammed due to over populated]\n");
-                                break;
-                            case 9:
-                                printf (" Statut: 9 [No MSG]\n");
-                                break;
-                            default:   // 100
-                                printf
-                                    (" Statut: %d [This ID is totally erased]\n",
-                                     RFIFOL (fd, 36));
-                                break;
-                        }
-                        if (defaultlanguage == 'F')
-                        {
-                            if (ban_until_time == 0)
-                            {
-                                printf (" Banissement: non banni.\n");
-                            }
-                            else
-                            {
-                                char tmpstr[128];
-                                strftime (tmpstr, 24, date_format,
-                                          localtime (&ban_until_time));
-                                printf (" Banissement: jusqu'au %s.\n",
-                                        tmpstr);
-                            }
-                            if (RFIFOL (fd, 32) > 1)
-                                printf (" Compteur: %d connexions.\n",
-                                        RFIFOL (fd, 32));
-                            else
-                                printf (" Compteur: %d connexion.\n",
-                                        RFIFOL (fd, 32));
-                            printf (" Dernière connexion le: %s (ip: %s)\n",
-                                    lastlogin, last_ip);
-                            if (connect_until_time == 0)
-                            {
-                                printf (" Limite de validité: illimité.\n");
-                            }
-                            else
-                            {
-                                char tmpstr[128];
-                                strftime (tmpstr, 24, date_format,
-                                          localtime (&connect_until_time));
-                                printf (" Limite de validité: jusqu'au %s.\n",
-                                        tmpstr);
-                            }
-                        }
-                        else
-                        {
-                            if (ban_until_time == 0)
-                            {
-                                printf (" Banishment: not banished.\n");
-                            }
-                            else
-                            {
-                                char tmpstr[128];
-                                strftime (tmpstr, 24, date_format,
-                                          localtime (&ban_until_time));
-                                printf (" Banishment: until %s.\n", tmpstr);
-                            }
-                            if (RFIFOL (fd, 32) > 1)
-                                printf (" Count:  %d connections.\n",
-                                        RFIFOL (fd, 32));
-                            else
-                                printf (" Count:  %d connection.\n",
-                                        RFIFOL (fd, 32));
-                            printf (" Last connection at: %s (ip: %s)\n",
-                                    lastlogin, last_ip);
-                            if (connect_until_time == 0)
-                            {
-                                printf (" Validity limit: unlimited.\n");
-                            }
-                            else
-                            {
-                                char tmpstr[128];
-                                strftime (tmpstr, 24, date_format,
-                                          localtime (&connect_until_time));
-                                printf (" Validity limit: until %s.\n",
-                                        tmpstr);
-                            }
-                        }
-                        printf (" Memo:   '%s'\n", memo);
-                    }
-                }
-                bytes_to_read = 0;
-                RFIFOSKIP (fd, 150 + RFIFOW (fd, 148));
-                break;
-
-            default:
-                printf
-                    ("Remote administration has been disconnected (unknown packet).\n");
-                ladmin_log ("'End of connection, unknown packet.\n");
-                session[fd]->eof = 1;
-                return;
-        }
-    }
-
-    // if we don't wait new packets, do the prompt
-    prompt ();
-}
-
-//------------------------------------
-// Function to connect to login-server
-//------------------------------------
-int Connect_login_server (void)
-{
-    if (defaultlanguage == 'F')
-    {
-        Iprintf ("Essai de connection au server de logins...\n");
-        ladmin_log ("Essai de connection au server de logins...\n");
-    }
-    else
-    {
-        Iprintf ("Attempt to connect to login-server...\n");
-        ladmin_log ("Attempt to connect to login-server...\n");
-    }
-
-    if ((login_fd = make_connection (login_ip, loginserverport)) < 0)
-        return 0;
-
-#ifdef PASSWORDENC
-    if (passenc == 0)
-    {
-#endif
-        WFIFOW (login_fd, 0) = 0x7918;  // Request for administation login
-        WFIFOW (login_fd, 2) = 0;   // no encrypted
-        memcpy (WFIFOP (login_fd, 4), loginserveradminpassword, 24);
-        WFIFOSET (login_fd, 28);
-        bytes_to_read = 1;
-
-        if (defaultlanguage == 'F')
-        {
-            Iprintf ("Envoi du mot de passe...\n");
-            ladmin_log ("Envoi du mot de passe...\n");
-        }
-        else
-        {
-            Iprintf ("Sending of the password...\n");
-            ladmin_log ("Sending of the password...\n");
-        }
-#ifdef PASSWORDENC
-    }
-    else
-    {
-        WFIFOW (login_fd, 0) = 0x791a;  // Sending request about the coding key
-        WFIFOSET (login_fd, 2);
-        bytes_to_read = 1;
-        if (defaultlanguage == 'F')
-        {
-            Iprintf ("Demande de la clef MD5...\n");
-            ladmin_log ("Demande de la clef MD5...\n");
-        }
-        else
-        {
-            Iprintf ("Request about the MD5 key...\n");
-            ladmin_log ("Request about the MD5 key...\n");
-        }
-    }
-#endif
-
-    return 0;
-}
-
-//-------------------------------------------------
-// Return numerical value of a switch configuration
-// on/off, english, français, deutsch, español
-//-------------------------------------------------
-int config_switch (const char *str)
-{
-    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
-        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
-        || strcasecmp (str, "si") == 0)
-        return 1;
-    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
-        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
-        return 0;
-
-    return atoi (str);
-}
-
-//-----------------------------------
-// Reading general configuration file
-//-----------------------------------
-int ladmin_config_read (const char *cfgName)
-{
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        if (defaultlanguage == 'F')
-        {
-            printf ("\033[0mFichier de configuration (%s) non trouvé.\n",
-                    cfgName);
-        }
-        else
-        {
-            printf ("\033[0mConfiguration file (%s) not found.\n", cfgName);
-        }
-        return 1;
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        Iprintf
-            ("\033[0m---Début de lecture du fichier de configuration Ladmin (%s)\n",
-             cfgName);
-    }
-    else
-    {
-        Iprintf
-            ("\033[0m---Start reading of Ladmin configuration file (%s)\n",
-             cfgName);
-    }
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        line[sizeof (line) - 1] = '\0';
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
-        {
-            remove_control_chars (w1);
-            remove_control_chars (w2);
-
-            if (strcasecmp (w1, "login_ip") == 0)
-            {
-                struct hostent *h = gethostbyname (w2);
-                if (h != NULL)
-                {
-                    if (defaultlanguage == 'F')
-                    {
-                        Iprintf
-                            ("Adresse du serveur de logins: %s -> %d.%d.%d.%d\n",
-                             w2, (unsigned char) h->h_addr[0],
-                             (unsigned char) h->h_addr[1],
-                             (unsigned char) h->h_addr[2],
-                             (unsigned char) h->h_addr[3]);
-                    }
-                    else
-                    {
-                        Iprintf
-                            ("Login server IP address: %s -> %d.%d.%d.%d\n",
-                             w2, (unsigned char) h->h_addr[0],
-                             (unsigned char) h->h_addr[1],
-                             (unsigned char) h->h_addr[2],
-                             (unsigned char) h->h_addr[3]);
-                    }
-                    sprintf (loginserverip, "%d.%d.%d.%d",
-                             (unsigned char) h->h_addr[0],
-                             (unsigned char) h->h_addr[1],
-                             (unsigned char) h->h_addr[2],
-                             (unsigned char) h->h_addr[3]);
-                }
-                else
-                    memcpy (loginserverip, w2, 16);
-            }
-            else if (strcasecmp (w1, "login_port") == 0)
-            {
-                loginserverport = atoi (w2);
-            }
-            else if (strcasecmp (w1, "admin_pass") == 0)
-            {
-                strncpy (loginserveradminpassword, w2,
-                         sizeof (loginserveradminpassword));
-                loginserveradminpassword[sizeof (loginserveradminpassword) -
-                                         1] = '\0';
-#ifdef PASSWORDENC
-            }
-            else if (strcasecmp (w1, "passenc") == 0)
-            {
-                passenc = atoi (w2);
-                if (passenc < 0 || passenc > 2)
-                    passenc = 0;
-#endif
-            }
-            else if (strcasecmp (w1, "defaultlanguage") == 0)
-            {
-                if (w2[0] == 'F' || w2[0] == 'E')
-                    defaultlanguage = w2[0];
-            }
-            else if (strcasecmp (w1, "ladmin_log_filename") == 0)
-            {
-                strncpy (ladmin_log_filename, w2,
-                         sizeof (ladmin_log_filename));
-                ladmin_log_filename[sizeof (ladmin_log_filename) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "date_format") == 0)
-            {                   // note: never have more than 19 char for the date!
-                switch (atoi (w2))
-                {
-                    case 0:
-                        strcpy (date_format, "%d-%m-%Y %H:%M:%S");  // 31-12-2004 23:59:59
-                        break;
-                    case 1:
-                        strcpy (date_format, "%m-%d-%Y %H:%M:%S");  // 12-31-2004 23:59:59
-                        break;
-                    case 2:
-                        strcpy (date_format, "%Y-%d-%m %H:%M:%S");  // 2004-31-12 23:59:59
-                        break;
-                    case 3:
-                        strcpy (date_format, "%Y-%m-%d %H:%M:%S");  // 2004-12-31 23:59:59
-                        break;
-                }
-            }
-            else if (strcasecmp (w1, "import") == 0)
-            {
-                ladmin_config_read (w2);
-            }
-        }
-    }
-    fclose_ (fp);
-
-    login_ip = inet_addr (loginserverip);
-
-    if (defaultlanguage == 'F')
-    {
-        Iprintf ("---Lecture du fichier de configuration Ladmin terminée.\n");
-    }
-    else
-    {
-        Iprintf ("---End reading of Ladmin configuration file.\n");
-    }
-
-    return 0;
-}
-
-//--------------------------------------
-// Function called at exit of the server
-//--------------------------------------
-void term_func (void)
-{
-
-    if (already_exit_function == 0)
-    {
-        delete_session (login_fd);
-
-        if (defaultlanguage == 'F')
-        {
-            Iprintf
-                ("\033[0m----Fin de Ladmin (fin normale avec fermeture de tous les fichiers).\n");
-            ladmin_log
-                ("----Fin de Ladmin (fin normale avec fermeture de tous les fichiers).\n");
-        }
-        else
-        {
-            Iprintf
-                ("\033[0m----End of Ladmin (normal end with closing of all files).\n");
-            ladmin_log
-                ("----End of Ladmin (normal end with closing of all files).\n");
-        }
-
-        already_exit_function = 1;
-    }
-}
-
-//------------------------
-// Main function of ladmin
-//------------------------
-int do_init (int argc, char **argv)
-{
-    eathena_interactive_session = isatty (0);
-    // read ladmin configuration
-    ladmin_config_read ((argc > 1) ? argv[1] : LADMIN_CONF_NAME);
-
-    ladmin_log ("");
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log ("Fichier de configuration lu.\n");
-    }
-    else
-    {
-        ladmin_log ("Configuration file readed.\n");
-    }
-
-    srand (time (NULL));
-
-    set_defaultparse (parse_fromlogin);
-
-    if (defaultlanguage == 'F')
-    {
-        Iprintf ("Outil d'administration à distance de eAthena.\n");
-        Iprintf ("(pour eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION,
-                 ATHENA_MINOR_VERSION, ATHENA_REVISION);
-    }
-    else
-    {
-        Iprintf ("EAthena login-server administration tool.\n");
-        Iprintf ("(for eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION,
-                 ATHENA_MINOR_VERSION, ATHENA_REVISION);
-    }
-
-    if (defaultlanguage == 'F')
-    {
-        ladmin_log ("Ladmin est prêt.\n");
-        Iprintf ("Ladmin est \033[1;32mprêt\033[0m.\n\n");
-    }
-    else
-    {
-        ladmin_log ("Ladmin is ready.\n");
-        Iprintf ("Ladmin is \033[1;32mready\033[0m.\n\n");
-    }
-
-    Connect_login_server ();
-
-    return 0;
-}
diff --git a/src/ladmin/ladmin.cpp b/src/ladmin/ladmin.cpp
new file mode 100644
index 0000000..01eb244
--- /dev/null
+++ b/src/ladmin/ladmin.cpp
@@ -0,0 +1,6476 @@
+// $Id: ladmin.c,v 1.1.1.1 2004/09/10 17:26:52 MagicalTux Exp $
+///////////////////////////////////////////////////////////////////////////
+// EAthena login-server remote administration tool
+// Ladamin in C by [Yor]
+// if you modify this software, modify ladmin in tool too.
+///////////////////////////////////////////////////////////////////////////
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/time.h>           // gettimeofday
+#include <time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>             // close
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>             // str*
+#include <arpa/inet.h>          // inet_addr
+#include <netdb.h>              // gethostbyname
+#include <stdarg.h>             // valist
+#include <ctype.h>              // tolower
+
+#include "../common/core.hpp"
+#include "../common/socket.hpp"
+#include "ladmin.hpp"
+#include "../common/version.hpp"
+#include "../common/mmo.hpp"
+
+#ifdef PASSWORDENC
+#include "../common/md5calc.hpp"
+#endif
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+int eathena_interactive_session; // from core.c
+#define Iprintf if (eathena_interactive_session) printf
+
+//-------------------------------INSTRUCTIONS------------------------------
+// Set the variables below:
+//   IP of the login server.
+//   Port where the login-server listens incoming packets.
+//   Password of administration (same of config_athena.conf).
+//   Displayed language of the sofware (if not correct, english is used).
+// IMPORTANT:
+//   Be sure that you authorize remote administration in login-server
+//   (see login_athena.conf, 'admin_state' parameter)
+//-------------------------------------------------------------------------
+char loginserverip[16] = "127.0.0.1";   // IP of login-server
+int  loginserverport = 6900;    // Port of login-server
+char loginserveradminpassword[24] = "admin";    // Administration password
+#ifdef PASSWORDENC
+int  passenc = 2;               // Encoding type of the password
+#else
+int  passenc = 0;               // Encoding type of the password
+#endif
+char defaultlanguage = 'E';     // Default language (F: Français/E: English)
+                                             // (if it's not 'F', default is English)
+char ladmin_log_filename[1024] = "log/ladmin.log";
+char date_format[32] = "%Y-%m-%d %H:%M:%S";
+//-------------------------------------------------------------------------
+//  LIST of COMMANDs that you can type at the prompt:
+//    To use these commands you can only type only the first letters.
+//    You must type a minimum of letters (you can not type 'a',
+//      because ladmin doesn't know if it's for 'aide' or for 'add')
+//    <Example> q <= quit, li <= list, pass <= passwd, etc.
+//
+//  Note: every time you must give a account_name, you can use "" or '' (spaces can be included)
+//
+//  aide/help/?
+//    Display the description of the commands
+//  aide/help/? [command]
+//    Display the description of the specified command
+//
+//  add <account_name> <sex> <password>
+//    Create an account with the default email (a@a.com).
+//    Concerning the sex, only the first letter is used (F or M).
+//    The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.
+//    When the password is omitted, the input is done without displaying of the pressed keys.
+//    <example> add testname Male testpass
+//
+//  ban/banish yyyy/mm/dd hh:mm:ss <account name>
+//    Changes the final date of a banishment of an account.
+//    Like banset, but <account name> is at end.
+//
+//  banadd <account_name> <modifier>
+//    Adds or substracts time from the final date of a banishment of an account.
+//    Modifier is done as follows:
+//      Adjustment value (-1, 1, +1, etc...)
+//      Modified element:
+//        a or y: year
+//        m:  month
+//        j or d: day
+//        h:  hour
+//        mn: minute
+//        s:  second
+//    <example> banadd testname +1m-2mn1s-6y
+//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
+//  NOTE: If you modify the final date of a non-banished account,
+//        you fix the final date to (actual time +- adjustments)
+//
+//  banset <account_name> yyyy/mm/dd [hh:mm:ss]
+//    Changes the final date of a banishment of an account.
+//    Default time [hh:mm:ss]: 23:59:59.
+//  banset <account_name> 0
+//    Set a non-banished account (0 = unbanished).
+//
+//  block <account name>
+//    Set state 5 (You have been blocked by the GM Team) to an account.
+//    Like state <account name> 5.
+//
+//  check <account_name> <password>
+//    Check the validity of a password for an account
+//    NOTE: Server will never sends back a password.
+//          It's the only method you have to know if a password is correct.
+//          The other method is to have a ('physical') access to the accounts file.
+//
+//  create <account_name> <sex> <email> <password>
+//    Like the 'add' command, but with e-mail moreover.
+//    <example> create testname Male my@mail.com testpass
+//
+//  del <account name>
+//    Remove an account.
+//    This order requires confirmation. After confirmation, the account is deleted.
+//
+//  email <account_name> <email>
+//    Modify the e-mail of an account.
+//
+//  getcount
+//    Give the number of players online on all char-servers.
+//
+//  gm <account_name> [GM_level]
+//    Modify the GM level of an account.
+//    Default value remove GM level (GM level = 0).
+//    <example> gm testname 80
+//
+//  id <account name>
+//    Give the id of an account.
+//
+//  info <account_id>
+//    Display complete information of an account.
+//
+//  kami <message>
+//    Sends a broadcast message on all map-server (in yellow).
+//  kamib <message>
+//    Sends a broadcast message on all map-server (in blue).
+//
+//  language <language>
+//    Change the language of displaying.
+//
+//  list/ls [start_id [end_id]]
+//    Display a list of accounts.
+//    'start_id', 'end_id': indicate end and start identifiers.
+//    Research by name is not possible with this command.
+//    <example> list 10 9999999
+//
+//  listBan/lsBan [start_id [end_id]]
+//    Like list/ls, but only for accounts with state or banished
+//
+//  listGM/lsGM [start_id [end_id]]
+//    Like list/ls, but only for GM accounts
+//
+//  listOK/lsOK [start_id [end_id]]
+//    Like list/ls, but only for accounts without state and not banished
+//
+//  memo <account_name> <memo>
+//    Modify the memo of an account.
+//    'memo': it can have until 253 characters (with spaces or not).
+//
+//  name <account_id>
+//    Give the name of an account.
+//
+//  passwd <account_name> <new_password>
+//    Change the password of an account.
+//    When new password is omitted, the input is done without displaying of the pressed keys.
+//
+//  quit/end/exit
+//    End of the program of administration
+//
+//  reloadGM
+//    Reload GM configuration file
+//
+//  search <expression>
+//    Seek accounts.
+//    Displays the accounts whose names correspond.
+//  search -r/-e/--expr/--regex <expression>
+//    Seek accounts by regular expression.
+//    Displays the accounts whose names correspond.
+//
+//  sex <account_name> <sex>
+//    Modify the sex of an account.
+//    <example> sex testname Male
+//
+//  state <account_name> <new_state> <error_message_#7>
+//    Change the state of an account.
+//    'new_state': state is the state of the packet 0x006a + 1. The possibilities are:
+//                 0 = Account ok            6 = Your Game's EXE file is not the latest version
+//                 1 = Unregistered ID       7 = You are Prohibited to log in until %s
+//                 2 = Incorrect Password    8 = Server is jammed due to over populated
+//                 3 = This ID is expired    9 = No MSG
+//                 4 = Rejected from Server  100 = This ID has been totally erased
+//                 5 = You have been blocked by the GM Team
+//                 all other values are 'No MSG', then use state 9 please.
+//    'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
+//
+//  timeadd <account_name> <modifier>
+//    Adds or substracts time from the validity limit of an account.
+//    Modifier is done as follows:
+//      Adjustment value (-1, 1, +1, etc...)
+//      Modified element:
+//        a or y: year
+//        m:  month
+//        j or d: day
+//        h:  hour
+//        mn: minute
+//        s:  second
+//    <example> timeadd testname +1m-2mn1s-6y
+//              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
+//  NOTE: You can not modify a unlimited validity limit.
+//        If you want modify it, you want probably create a limited validity limit.
+//        So, at first, you must set the validity limit to a date/time.
+//
+//  timeset <account_name> yyyy/mm/dd [hh:mm:ss]
+//    Changes the validity limit of an account.
+//    Default time [hh:mm:ss]: 23:59:59.
+//  timeset <account_name> 0
+//    Gives an unlimited validity limit (0 = unlimited).
+//
+//  unban/unbanish <account name>
+//    Unban an account.
+//    Like banset <account name> 0.
+//
+//  unblock <account name>
+//    Set state 0 (Account ok) to an account.
+//    Like state <account name> 0.
+//
+//  version
+//    Display the version of the login-server.
+//
+//  who <account name>
+//    Displays complete information of an account.
+//
+//-------------------------------------------------------------------------
+int  login_fd;
+int  login_ip;
+int  bytes_to_read = 0;         // flag to know if we waiting bytes from login-server
+char command[1024];
+char parameters[1024];
+int  list_first, list_last, list_type, list_count;  // parameter to display a list of accounts
+int  already_exit_function = 0; // sometimes, the exit function is called twice... so, don't log twice the message
+
+//------------------------------
+// Writing function of logs file
+//------------------------------
+int ladmin_log (const char *fmt, ...)
+{
+    FILE *logfp;
+    va_list ap;
+    struct timeval tv;
+    char tmpstr[2048];
+
+    va_start (ap, fmt);
+
+    logfp = fopen_ (ladmin_log_filename, "a");
+    if (logfp)
+    {
+        if (fmt[0] == '\0')     // jump a line if no message
+            fprintf (logfp, "\n");
+        else
+        {
+            gettimeofday (&tv, NULL);
+            strftime (tmpstr, 24, date_format, localtime (&(tv.tv_sec)));
+            sprintf (tmpstr + strlen (tmpstr), ".%03d: %s",
+                     (int) tv.tv_usec / 1000, fmt);
+            vfprintf (logfp, tmpstr, ap);
+        }
+        fclose_ (logfp);
+    }
+
+    va_end (ap);
+    return 0;
+}
+
+//-----------------------------------------------------
+// Function to suppress control characters in a string.
+//-----------------------------------------------------
+int remove_control_chars (unsigned char *str)
+{
+    int  i;
+    int  change = 0;
+
+    for (i = 0; str[i]; i++)
+    {
+        if (str[i] < 32)
+        {
+            str[i] = '_';
+            change = 1;
+        }
+    }
+
+    return change;
+}
+
+//---------------------------------------------
+// Function to return ordonal text of a number.
+//---------------------------------------------
+const char *makeordinal (int number)
+{
+    if (defaultlanguage == 'F')
+    {
+        if (number == 0)
+            return "";
+        else if (number == 1)
+            return "er";
+        else
+            return "ème";
+    }
+    else
+    {
+        if ((number % 10) < 4 && (number % 10) != 0
+            && (number < 10 || number > 20))
+        {
+            if ((number % 10) == 1)
+                return "st";
+            else if ((number % 10) == 2)
+                return "nd";
+            else
+                return "rd";
+        }
+        else
+        {
+            return "th";
+        }
+    }
+    return "";
+}
+
+//-----------------------------------------------------------------------------------------
+// Function to test of the validity of an account name (return 0 if incorrect, and 1 if ok)
+//-----------------------------------------------------------------------------------------
+int verify_accountname (char *account_name)
+{
+    int  i;
+
+    for (i = 0; account_name[i]; i++)
+    {
+        if (account_name[i] < 32)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
+                     i + 1, makeordinal (i + 1));
+                ladmin_log
+                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
+                      i + 1, makeordinal (i + 1));
+            }
+            else
+            {
+                printf
+                    ("Illegal character found in the account name (%d%s character).\n",
+                     i + 1, makeordinal (i + 1));
+                ladmin_log
+                    ("Illegal character found in the account name (%d%s character).\n",
+                      i + 1, makeordinal (i + 1));
+            }
+            return 0;
+        }
+    }
+
+    if (strlen (account_name) < 4)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
+            ladmin_log
+                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
+        }
+        else
+        {
+            printf
+                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
+            ladmin_log
+                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
+        }
+        return 0;
+    }
+
+    if (strlen (account_name) > 23)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n");
+            ladmin_log
+                ("Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n");
+        }
+        else
+        {
+            printf
+                ("Account name is too long. Please input an account name of 4-23 bytes.\n");
+            ladmin_log
+                ("Account name is too long. Please input an account name of 4-23 bytes.\n");
+        }
+        return 0;
+    }
+
+    return 1;
+}
+
+//---------------------------------------------------
+// E-mail check: return 0 (not correct) or 1 (valid).
+//---------------------------------------------------
+int e_mail_check (unsigned char *email)
+{
+    char ch;
+    unsigned char *last_arobas;
+
+    // athena limits
+    if (strlen (email) < 3 || strlen (email) > 39)
+        return 0;
+
+    // part of RFC limits (official reference of e-mail description)
+    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
+        return 0;
+
+    if (email[strlen (email) - 1] == '.')
+        return 0;
+
+    last_arobas = strrchr (email, '@');
+
+    if (strstr (last_arobas, "@.") != NULL ||
+        strstr (last_arobas, "..") != NULL)
+        return 0;
+
+    for (ch = 1; ch < 32; ch++)
+    {
+        if (strchr (last_arobas, ch) != NULL)
+        {
+            return 0;
+            break;
+        }
+    }
+
+    if (strchr (last_arobas, ' ') != NULL ||
+        strchr (last_arobas, ';') != NULL)
+        return 0;
+
+    // all correct
+    return 1;
+}
+
+//----------------------------------
+// Sub-function: Input of a password
+//----------------------------------
+int typepasswd (char *password)
+{
+    char password1[1023], password2[1023];
+    int  letter;
+    int  i;
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Aucun mot de passe n'a été donné. Demande d'un mot de passe.\n");
+    }
+    else
+    {
+        ladmin_log ("No password was given. Request to obtain a password.\n");
+    }
+
+    memset (password1, '\0', sizeof (password1));
+    memset (password2, '\0', sizeof (password2));
+    if (defaultlanguage == 'F')
+        printf ("\033[1;36m Entrez le mot de passe > \033[0;32;42m");
+    else
+        printf ("\033[1;36m Type the password > \033[0;32;42m");
+    i = 0;
+    while ((letter = getchar ()) != '\n')
+        password1[i++] = letter;
+    if (defaultlanguage == 'F')
+        printf
+            ("\033[0m\033[1;36m Ré-entrez le mot de passe > \033[0;32;42m");
+    else
+        printf ("\033[0m\033[1;36m Verify the password > \033[0;32;42m");
+    i = 0;
+    while ((letter = getchar ()) != '\n')
+        password2[i++] = letter;
+
+    printf ("\033[0m");
+    fflush (stdout);
+    fflush (stdin);
+
+    if (strcmp (password1, password2) != 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n");
+            ladmin_log
+                ("Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n");
+            ladmin_log ("  Premier mot de passe: %s, second mot de passe: %s.\n",
+                         password1, password2);
+        }
+        else
+        {
+            printf
+                ("Password verification failed. Please input same password.\n");
+            ladmin_log
+                ("Password verification failed. Please input same password.\n");
+            ladmin_log ("  First password: %s, second password: %s.\n",
+                        password1, password2);
+        }
+        return 0;
+    }
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log ("Mot de passe saisi: %s.\n", password1);
+    }
+    else
+    {
+        ladmin_log ("Typed password: %s.\n", password1);
+    }
+    strcpy (password, password1);
+    return 1;
+}
+
+//------------------------------------------------------------------------------------
+// Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
+//------------------------------------------------------------------------------------
+int verify_password (char *password)
+{
+    int  i;
+
+    for (i = 0; password[i]; i++)
+    {
+        if (password[i] < 32)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Caractère interdit trouvé dans le mot de passe (%d%s caractère).\n",
+                     i + 1, makeordinal (i + 1));
+                ladmin_log
+                    ("Caractère interdit trouvé dans le nom du compte (%d%s caractère).\n",
+                      i + 1, makeordinal (i + 1));
+            }
+            else
+            {
+                printf
+                    ("Illegal character found in the password (%d%s character).\n",
+                     i + 1, makeordinal (i + 1));
+                ladmin_log
+                    ("Illegal character found in the password (%d%s character).\n",
+                      i + 1, makeordinal (i + 1));
+            }
+            return 0;
+        }
+    }
+
+    if (strlen (password) < 4)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
+            ladmin_log
+                ("Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n");
+        }
+        else
+        {
+            printf
+                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
+            ladmin_log
+                ("Account name is too short. Please input an account name of 4-23 bytes.\n");
+        }
+        return 0;
+    }
+
+    if (strlen (password) > 23)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n");
+            ladmin_log
+                ("Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n");
+        }
+        else
+        {
+            printf
+                ("Password is too long. Please input a password of 4-23 bytes.\n");
+            ladmin_log
+                ("Password is too long. Please input a password of 4-23 bytes.\n");
+        }
+        return 0;
+    }
+
+    return 1;
+}
+
+//------------------------------------------------------------------
+// Sub-function: Check the name of a command (return complete name)
+//-----------------------------------------------------------------
+int check_command (char *command)
+{
+// help
+    if (strncmp (command, "aide", 2) == 0 && strncmp (command, "aide", strlen (command)) == 0)  // not 1 letter command: 'aide' or 'add'?
+        strcpy (command, "aide");
+    else if (strncmp (command, "help", 1) == 0
+             && strncmp (command, "help", strlen (command)) == 0)
+        strcpy (command, "help");
+// general commands
+    else if (strncmp (command, "add", 2) == 0 && strncmp (command, "add", strlen (command)) == 0)   // not 1 letter command: 'aide' or 'add'?
+        strcpy (command, "add");
+    else if ((strncmp (command, "ban", 3) == 0
+              && strncmp (command, "ban", strlen (command)) == 0)
+             || (strncmp (command, "banish", 4) == 0
+                 && strncmp (command, "banish", strlen (command)) == 0))
+        strcpy (command, "ban");
+    else if ((strncmp (command, "banadd", 4) == 0 && strncmp (command, "banadd", strlen (command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
+             strcmp (command, "ba") == 0)
+        strcpy (command, "banadd");
+    else if ((strncmp (command, "banset", 4) == 0 && strncmp (command, "banset", strlen (command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
+             strcmp (command, "bs") == 0)
+        strcpy (command, "banset");
+    else if (strncmp (command, "block", 2) == 0
+             && strncmp (command, "block", strlen (command)) == 0)
+        strcpy (command, "block");
+    else if (strncmp (command, "check", 2) == 0 && strncmp (command, "check", strlen (command)) == 0)   // not 1 letter command: 'check' or 'create'?
+        strcpy (command, "check");
+    else if (strncmp (command, "create", 2) == 0 && strncmp (command, "create", strlen (command)) == 0) // not 1 letter command: 'check' or 'create'?
+        strcpy (command, "create");
+    else if (strncmp (command, "delete", 1) == 0
+             && strncmp (command, "delete", strlen (command)) == 0)
+        strcpy (command, "delete");
+    else if ((strncmp (command, "email", 2) == 0 && strncmp (command, "email", strlen (command)) == 0) ||   // not 1 letter command: 'email', 'end' or 'exit'?
+             (strncmp (command, "e-mail", 2) == 0
+              && strncmp (command, "e-mail", strlen (command)) == 0))
+        strcpy (command, "email");
+    else if (strncmp (command, "getcount", 2) == 0 && strncmp (command, "getcount", strlen (command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
+        strcpy (command, "getcount");
+//  else if (strncmp(command, "gm", 2) == 0 && strncmp(command, "gm", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
+//      strcpy(command, "gm");
+//  else if (strncmp(command, "id", 2) == 0 && strncmp(command, "id", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
+//      strcpy(command, "id");
+    else if (strncmp (command, "info", 2) == 0 && strncmp (command, "info", strlen (command)) == 0) // not 1 letter command: 'id' or 'info'?
+        strcpy (command, "info");
+//  else if (strncmp(command, "kami", 4) == 0 && strncmp(command, "kami", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
+//      strcpy(command, "kami");
+//  else if (strncmp(command, "kamib", 5) == 0 && strncmp(command, "kamib", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
+//      strcpy(command, "kamib");
+    else if ((strncmp (command, "language", 2) == 0 && strncmp (command, "language", strlen (command)) == 0))   // not 1 letter command: 'language' or 'list'?
+        strcpy (command, "language");
+    else if ((strncmp (command, "list", 2) == 0 && strncmp (command, "list", strlen (command)) == 0) || // 'list' is default list command // not 1 letter command: 'language' or 'list'?
+             strcmp (command, "ls") == 0)
+        strcpy (command, "list");
+    else if (strncmp (command, "itemfrob", 6) == 0)
+        strcpy (command, "itemfrob");
+    else if ((strncmp (command, "listban", 5) == 0
+              && strncmp (command, "listban", strlen (command)) == 0)
+             || (strncmp (command, "lsban", 3) == 0
+                 && strncmp (command, "lsban", strlen (command)) == 0)
+             || strcmp (command, "lb") == 0)
+        strcpy (command, "listban");
+    else if ((strncmp (command, "listgm", 5) == 0
+              && strncmp (command, "listgm", strlen (command)) == 0)
+             || (strncmp (command, "lsgm", 3) == 0
+                 && strncmp (command, "lsgm", strlen (command)) == 0)
+             || strcmp (command, "lg") == 0)
+        strcpy (command, "listgm");
+    else if ((strncmp (command, "listok", 5) == 0
+              && strncmp (command, "listok", strlen (command)) == 0)
+             || (strncmp (command, "lsok", 3) == 0
+                 && strncmp (command, "lsok", strlen (command)) == 0)
+             || strcmp (command, "lo") == 0)
+        strcpy (command, "listok");
+    else if (strncmp (command, "memo", 1) == 0
+             && strncmp (command, "memo", strlen (command)) == 0)
+        strcpy (command, "memo");
+    else if (strncmp (command, "name", 1) == 0
+             && strncmp (command, "name", strlen (command)) == 0)
+        strcpy (command, "name");
+    else if ((strncmp (command, "password", 1) == 0
+              && strncmp (command, "password", strlen (command)) == 0)
+             || strcmp (command, "passwd") == 0)
+        strcpy (command, "password");
+    else if (strncmp (command, "reloadgm", 1) == 0
+             && strncmp (command, "reloadgm", strlen (command)) == 0)
+        strcpy (command, "reloadgm");
+    else if (strncmp (command, "search", 3) == 0 && strncmp (command, "search", strlen (command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
+        strcpy (command, "search"); // not 2 letters command: 'search' or 'sex'?
+//  else if (strncmp(command, "sex", 3) == 0 && strncmp(command, "sex", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
+//      strcpy(command, "sex"); // not 2 letters command: 'search' or 'sex'?
+    else if (strncmp (command, "state", 2) == 0 && strncmp (command, "state", strlen (command)) == 0)   // not 1 letter command: 'search', 'state' or 'sex'?
+        strcpy (command, "state");
+    else if ((strncmp (command, "timeadd", 5) == 0 && strncmp (command, "timeadd", strlen (command)) == 0) ||   // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
+             strcmp (command, "ta") == 0)
+        strcpy (command, "timeadd");
+    else if ((strncmp (command, "timeset", 5) == 0 && strncmp (command, "timeset", strlen (command)) == 0) ||   // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
+             strcmp (command, "ts") == 0)
+        strcpy (command, "timeset");
+    else if ((strncmp (command, "unban", 5) == 0
+              && strncmp (command, "unban", strlen (command)) == 0)
+             || (strncmp (command, "unbanish", 4) == 0
+                 && strncmp (command, "unbanish", strlen (command)) == 0))
+        strcpy (command, "unban");
+    else if (strncmp (command, "unblock", 4) == 0
+             && strncmp (command, "unblock", strlen (command)) == 0)
+        strcpy (command, "unblock");
+    else if (strncmp (command, "version", 1) == 0
+             && strncmp (command, "version", strlen (command)) == 0)
+        strcpy (command, "version");
+    else if (strncmp (command, "who", 1) == 0
+             && strncmp (command, "who", strlen (command)) == 0)
+        strcpy (command, "who");
+// quit
+    else if (strncmp (command, "quit", 1) == 0
+             && strncmp (command, "quit", strlen (command)) == 0)
+        strcpy (command, "quit");
+    else if (strncmp (command, "exit", 2) == 0 && strncmp (command, "exit", strlen (command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
+        strcpy (command, "exit");
+    else if (strncmp (command, "end", 2) == 0 && strncmp (command, "end", strlen (command)) == 0)   // not 1 letter command: 'email', 'end' or 'exit'?
+        strcpy (command, "end");
+
+    return 0;
+}
+
+//-----------------------------------------
+// Sub-function: Display commands of ladmin
+//-----------------------------------------
+void display_help (char *param, int language)
+{
+    char command[1023];
+    int  i;
+
+    memset (command, '\0', sizeof (command));
+
+    if (sscanf (param, "%s ", command) < 1 || strlen (command) == 0)
+        strcpy (command, "");   // any value that is not a command
+
+    if (command[0] == '?')
+    {
+        if (defaultlanguage == 'F')
+            strcpy (command, "aide");
+        else
+            strcpy (command, "help");
+    }
+
+    // lowercase for command
+    for (i = 0; command[i]; i++)
+        command[i] = tolower (command[i]);
+
+    // Analyse of the command
+    check_command (command);    // give complete name to the command
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log ("Affichage des commandes ou d'une commande.\n");
+    }
+    else
+    {
+        ladmin_log ("Displaying of the commands or a command.\n");
+    }
+
+    if (language == 1)
+    {
+        if (strcmp (command, "aide") == 0)
+        {
+            printf ("aide/help/?\n");
+            printf ("  Affiche la description des commandes\n");
+            printf ("aide/help/? [commande]\n");
+            printf ("  Affiche la description de la commande specifiée\n");
+        }
+        else if (strcmp (command, "help") == 0)
+        {
+            printf ("aide/help/?\n");
+            printf ("  Display the description of the commands\n");
+            printf ("aide/help/? [command]\n");
+            printf ("  Display the description of the specified command\n");
+// general commands
+        }
+        else if (strcmp (command, "add") == 0)
+        {
+            printf ("add <nomcompte> <sexe> <motdepasse>\n");
+            printf ("  Crée un compte avec l'email par défaut (a@a.com).\n");
+            printf
+                ("  Concernant le sexe, seule la première lettre compte (F ou M).\n");
+            printf
+                ("  L'e-mail est a@a.com (e-mail par défaut). C'est comme n'avoir aucun e-mail.\n");
+            printf
+                ("  Lorsque motdepasse est omis, la saisie se fait sans que la frappe se voit.\n");
+            printf ("  <exemple> add testname Male testpass\n");
+        }
+        else if (strcmp (command, "ban") == 0)
+        {
+            printf ("ban/banish aaaa/mm/jj hh:mm:ss <nom compte>\n");
+            printf ("  Change la date de fin de bannissement d'un compte.\n");
+            printf ("  Comme banset, mais <nom compte> est à la fin.\n");
+        }
+        else if (strcmp (command, "banadd") == 0)
+        {
+            printf ("banadd <nomcompte> <Modificateur>\n");
+            printf
+                ("  Ajoute ou soustrait du temps à la date de banissement d'un compte.\n");
+            printf ("  Les modificateurs sont construits comme suit:\n");
+            printf ("    Valeur d'ajustement (-1, 1, +1, etc...)\n");
+            printf ("    Elément modifié:\n");
+            printf ("      a ou y: année\n");
+            printf ("      m:      mois\n");
+            printf ("      j ou d: jour\n");
+            printf ("      h:      heure\n");
+            printf ("      mn:     minute\n");
+            printf ("      s:      seconde\n");
+            printf ("  <exemple> banadd testname +1m-2mn1s-6a\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            printf
+                ("NOTE: Si vous modifez la date de banissement d'un compte non bani,\n");
+            printf
+                ("      vous indiquez comme date (le moment actuel +- les ajustements)\n");
+        }
+        else if (strcmp (command, "banset") == 0)
+        {
+            printf ("banset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf ("  Change la date de fin de bannissement d'un compte.\n");
+            printf ("  Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            printf ("banset <nomcompte> 0\n");
+            printf ("  Débanni un compte (0 = de-banni).\n");
+        }
+        else if (strcmp (command, "block") == 0)
+        {
+            printf ("block <nom compte>\n");
+            printf
+                ("  Place le status d'un compte à 5 (You have been blocked by the GM Team).\n");
+            printf
+                ("  La commande est l'équivalent de state <nom_compte> 5.\n");
+        }
+        else if (strcmp (command, "check") == 0)
+        {
+            printf ("check <nomcompte> <motdepasse>\n");
+            printf
+                ("  Vérifie la validité d'un mot de passe pour un compte\n");
+            printf ("  NOTE: Le serveur n'enverra jamais un mot de passe.\n");
+            printf
+                ("        C'est la seule méthode que vous possédez pour savoir\n");
+            printf
+                ("        si un mot de passe est le bon. L'autre méthode est\n");
+            printf
+                ("        d'avoir un accès ('physique') au fichier des comptes.\n");
+        }
+        else if (strcmp (command, "create") == 0)
+        {
+            printf ("create <nomcompte> <sexe> <email> <motdepasse>\n");
+            printf ("  Comme la commande add, mais avec l'e-mail en plus.\n");
+            printf
+                ("  <exemple> create testname Male mon@mail.com testpass\n");
+        }
+        else if (strcmp (command, "delete") == 0)
+        {
+            printf ("del <nom compte>\n");
+            printf ("  Supprime un compte.\n");
+            printf
+                ("  La commande demande confirmation. Après confirmation, le compte est détruit.\n");
+        }
+        else if (strcmp (command, "email") == 0)
+        {
+            printf ("email <nomcompte> <email>\n");
+            printf ("  Modifie l'e-mail d'un compte.\n");
+        }
+        else if (strcmp (command, "getcount") == 0)
+        {
+            printf ("getcount\n");
+            printf
+                ("  Donne le nombre de joueurs en ligne par serveur de char.\n");
+        }
+        else if (strcmp (command, "gm") == 0)
+        {
+            printf ("gm <nomcompte> [Niveau_GM]\n");
+            printf ("  Modifie le niveau de GM d'un compte.\n");
+            printf
+                ("  Valeur par défaut: 0 (suppression du niveau de GM).\n");
+            printf ("  <exemple> gm nomtest 80\n");
+        }
+        else if (strcmp (command, "id") == 0)
+        {
+            printf ("id <nom compte>\n");
+            printf ("  Donne l'id d'un compte.\n");
+        }
+        else if (strcmp (command, "info") == 0)
+        {
+            printf ("info <idcompte>\n");
+            printf ("  Affiche les informations sur un compte.\n");
+        }
+        else if (strcmp (command, "kami") == 0)
+        {
+            printf ("kami <message>\n");
+            printf
+                ("  Envoi un message général sur tous les serveurs de map (en jaune).\n");
+        }
+        else if (strcmp (command, "kamib") == 0)
+        {
+            printf ("kamib <message>\n");
+            printf
+                ("  Envoi un message général sur tous les serveurs de map (en bleu).\n");
+        }
+        else if (strcmp (command, "language") == 0)
+        {
+            printf ("language <langue>\n");
+            printf ("  Change la langue d'affichage.\n");
+            printf ("  Langues possibles: 'Français' ou 'English'.\n");
+        }
+        else if (strcmp (command, "list") == 0)
+        {
+            printf ("list/ls [Premier_id [Dernier_id]]\n");
+            printf ("  Affiche une liste de comptes.\n");
+            printf
+                ("  'Premier_id', 'Dernier_id': indique les identifiants de départ et de fin.\n");
+            printf
+                ("  La recherche par nom n'est pas possible avec cette commande.\n");
+            printf ("  <example> list 10 9999999\n");
+        }
+        else if (strcmp (command, "itemfrob") == 0)
+        {
+            printf ("Not localised yet.\n");
+        }
+        else if (strcmp (command, "listban") == 0)
+        {
+            printf ("listBan/lsBan [Premier_id [Dernier_id]]\n");
+            printf
+                ("  Comme list/ls, mais seulement pour les comptes avec statut ou bannis.\n");
+        }
+        else if (strcmp (command, "listgm") == 0)
+        {
+            printf ("listGM/lsGM [Premier_id [Dernier_id]]\n");
+            printf ("  Comme list/ls, mais seulement pour les comptes GM.\n");
+        }
+        else if (strcmp (command, "listok") == 0)
+        {
+            printf ("listOK/lsOK [Premier_id [Dernier_id]]\n");
+            printf
+                ("  Comme list/ls, mais seulement pour les comptes sans statut et non bannis.\n");
+        }
+        else if (strcmp (command, "memo") == 0)
+        {
+            printf ("memo <nomcompte> <memo>\n");
+            printf ("  Modifie le mémo d'un compte.\n");
+            printf
+                ("  'memo': Il peut avoir jusqu'à 253 caractères (avec des espaces ou non).\n");
+        }
+        else if (strcmp (command, "name") == 0)
+        {
+            printf ("name <idcompte>\n");
+            printf ("  Donne le nom d'un compte.\n");
+        }
+        else if (strcmp (command, "password") == 0)
+        {
+            printf ("passwd <nomcompte> <nouveaumotdepasse>\n");
+            printf ("  Change le mot de passe d'un compte.\n");
+            printf ("  Lorsque nouveaumotdepasse est omis,\n");
+            printf ("  la saisie se fait sans que la frappe ne se voit.\n");
+        }
+        else if (strcmp (command, "reloadgm") == 0)
+        {
+            printf ("reloadGM\n");
+            printf ("  Reload GM configuration file\n");
+        }
+        else if (strcmp (command, "search") == 0)
+        {
+            printf ("search <expression>\n");
+            printf ("  Cherche des comptes.\n");
+            printf ("  Affiche les comptes dont les noms correspondent.\n");
+//          printf("search -r/-e/--expr/--regex <expression>\n");
+//          printf("  Cherche des comptes par expression regulière.\n");
+//          printf("  Affiche les comptes dont les noms correspondent.\n");
+        }
+        else if (strcmp (command, "sex") == 0)
+        {
+            printf ("sex <nomcompte> <sexe>\n");
+            printf ("  Modifie le sexe d'un compte.\n");
+            printf ("  <exemple> sex testname Male\n");
+        }
+        else if (strcmp (command, "state") == 0)
+        {
+            printf ("state <nomcompte> <nouveaustatut> <message_erreur_7>\n");
+            printf ("  Change le statut d'un compte.\n");
+            printf
+                ("  'nouveaustatut': Le statut est le même que celui du packet 0x006a + 1.\n");
+            printf ("               les possibilités sont:\n");
+            printf ("               0 = Compte ok\n");
+            printf ("               1 = Unregistered ID\n");
+            printf ("               2 = Incorrect Password\n");
+            printf ("               3 = This ID is expired\n");
+            printf ("               4 = Rejected from Server\n");
+            printf
+                ("               5 = You have been blocked by the GM Team\n");
+            printf
+                ("               6 = Your Game's EXE file is not the latest version\n");
+            printf
+                ("               7 = You are Prohibited to log in until...\n");
+            printf
+                ("               8 = Server is jammed due to over populated\n");
+            printf ("               9 = No MSG\n");
+            printf ("               100 = This ID has been totally erased\n");
+            printf
+                ("               all other values are 'No MSG', then use state 9 please.\n");
+            printf ("  'message_erreur_7': message du code erreur 6 =\n");
+            printf
+                ("                      = Your are Prohibited to log in until... (packet 0x006a)\n");
+        }
+        else if (strcmp (command, "timeadd") == 0)
+        {
+            printf ("timeadd <nomcompte> <modificateur>\n");
+            printf
+                ("  Ajoute/soustrait du temps à la limite de validité d'un compte.\n");
+            printf ("  Le modificateur est composé comme suit:\n");
+            printf ("    Valeur modificatrice (-1, 1, +1, etc...)\n");
+            printf ("    Elément modifié:\n");
+            printf ("      a ou y: année\n");
+            printf ("      m:      mois\n");
+            printf ("      j ou d: jour\n");
+            printf ("      h:      heure\n");
+            printf ("      mn:     minute\n");
+            printf ("      s:      seconde\n");
+            printf ("  <exemple> timeadd testname +1m-2mn1s-6a\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            printf
+                ("NOTE: Vous ne pouvez pas modifier une limite de validité illimitée. Si vous\n");
+            printf
+                ("      désirez le faire, c'est que vous voulez probablement créer un limite de\n");
+            printf
+                ("      validité limitée. Donc, en premier, fixé une limite de valitidé.\n");
+        }
+        else if (strcmp (command, "timeadd") == 0)
+        {
+            printf ("timeset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf ("  Change la limite de validité d'un compte.\n");
+            printf ("  Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            printf ("timeset <nomcompte> 0\n");
+            printf
+                ("  Donne une limite de validité illimitée (0 = illimitée).\n");
+        }
+        else if (strcmp (command, "unban") == 0)
+        {
+            printf ("unban/unbanish <nom compte>\n");
+            printf ("  Ote le banissement d'un compte.\n");
+            printf
+                ("  La commande est l'équivalent de banset <nom_compte> 0.\n");
+        }
+        else if (strcmp (command, "unblock") == 0)
+        {
+            printf ("unblock <nom compte>\n");
+            printf ("  Place le status d'un compte à 0 (Compte ok).\n");
+            printf
+                ("  La commande est l'équivalent de state <nom_compte> 0.\n");
+        }
+        else if (strcmp (command, "version") == 0)
+        {
+            printf ("version\n");
+            printf ("  Affiche la version du login-serveur.\n");
+        }
+        else if (strcmp (command, "who") == 0)
+        {
+            printf ("who <nom compte>\n");
+            printf ("  Affiche les informations sur un compte.\n");
+// quit
+        }
+        else if (strcmp (command, "quit") == 0 ||
+                 strcmp (command, "exit") == 0 ||
+                 strcmp (command, "end") == 0)
+        {
+            printf ("quit/end/exit\n");
+            printf ("  Fin du programme d'administration.\n");
+// unknown command
+        }
+        else
+        {
+            if (strlen (command) > 0)
+                printf
+                    ("Commande inconnue [%s] pour l'aide. Affichage de toutes les commandes.\n",
+                     command);
+            printf
+                (" aide/help/?                             -- Affiche cet aide\n");
+            printf
+                (" aide/help/? [commande]                  -- Affiche l'aide de la commande\n");
+            printf
+                (" add <nomcompte> <sexe> <motdepasse>     -- Crée un compte (sans email)\n");
+            printf
+                (" ban/banish aaaa/mm/jj hh:mm:ss <nom compte> -- Fixe la date finale de banismnt\n");
+            printf
+                (" banadd/ba <nomcompte> <modificateur>    -- Ajout/soustrait du temps à la\n");
+            printf
+                ("   exemple: ba moncompte +1m-2mn1s-2y       date finale de banissement\n");
+            printf
+                (" banset/bs <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la date fin de banisemnt\n");
+            printf
+                (" banset/bs <nomcompte> 0                 -- Dé-banis un compte.\n");
+            printf
+                (" block <nom compte>  -- Mets le status d'un compte à 5 (blocked by the GM Team)\n");
+            printf
+                (" check <nomcompte> <motdepasse>          -- Vérifie un mot de passe d'un compte\n");
+            printf
+                (" create <nomcompte> <sexe> <email> <motdepasse> -- Crée un compte (avec email)\n");
+            printf
+                (" del <nom compte>                        -- Supprime un compte\n");
+            printf
+                (" email <nomcompte> <email>               -- Modifie l'e-mail d'un compte\n");
+            printf
+                (" getcount                                -- Donne le nb de joueurs en ligne\n");
+            printf
+                ("  gm <nomcompte> [Niveau_GM]              -- Modifie le niveau de GM d'un compte\n");
+            printf
+                (" id <nom compte>                         -- Donne l'id d'un compte\n");
+            printf
+                (" info <idcompte>                         -- Affiche les infos sur un compte\n");
+            printf
+                (" kami <message>                          -- Envoi un message général (en jaune)\n");
+            printf
+                (" kamib <message>                         -- Envoi un message général (en bleu)\n");
+            printf
+                (" language <langue>                       -- Change la langue d'affichage.\n");
+            printf
+                (" list/ls [Premier_id [Dernier_id] ]      -- Affiche une liste de comptes\n");
+            printf
+                (" listBan/lsBan [Premier_id [Dernier_id] ] -- Affiche une liste de comptes\n");
+            printf
+                ("                                             avec un statut ou bannis\n");
+            printf
+                (" listGM/lsGM [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes GM\n");
+            printf
+                (" listOK/lsOK [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes\n");
+            printf
+                ("                                            sans status et non bannis\n");
+            printf
+                (" memo <nomcompte> <memo>                 -- Modifie le memo d'un compte\n");
+            printf
+                (" name <idcompte>                         -- Donne le nom d'un compte\n");
+            printf
+                (" passwd <nomcompte> <nouveaumotdepasse>  -- Change le mot de passe d'un compte\n");
+            printf
+                (" quit/end/exit                           -- Fin du programme d'administation\n");
+            printf
+                (" reloadGM                              -- Recharger le fichier de config des GM\n");
+            printf
+                (" search <expression>                     -- Cherche des comptes\n");
+//          printf(" search -e/-r/--expr/--regex <expression> -- Cherche des comptes par REGEX\n");
+            printf
+                (" sex <nomcompte> <sexe>                  -- Modifie le sexe d'un compte\n");
+            printf
+                (" state <nomcompte> <nouveaustatut> <messageerr7> -- Change le statut d'1 compte\n");
+            printf
+                (" timeadd/ta <nomcompte> <modificateur>   -- Ajout/soustrait du temps à la\n");
+            printf
+                ("   exemple: ta moncompte +1m-2mn1s-2y       limite de validité\n");
+            printf
+                (" timeset/ts <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la limite de validité\n");
+            printf
+                (" timeset/ts <nomcompte> 0                -- limite de validité = illimitée\n");
+            printf
+                (" unban/unbanish <nom compte>             -- Ote le banissement d'un compte\n");
+            printf
+                (" unblock <nom compte>             -- Mets le status d'un compte à 0 (Compte ok)\n");
+            printf
+                (" version                                 -- Donne la version du login-serveur\n");
+            printf
+                (" who <nom compte>                        -- Affiche les infos sur un compte\n");
+            printf
+                (" Note: Pour les noms de compte avec des espaces, tapez \"<nom compte>\" (ou ').\n");
+        }
+    }
+    else
+    {
+        if (strcmp (command, "aide") == 0)
+        {
+            printf ("aide/help/?\n");
+            printf ("  Display the description of the commands\n");
+            printf ("aide/help/? [command]\n");
+            printf ("  Display the description of the specified command\n");
+        }
+        else if (strcmp (command, "help") == 0)
+        {
+            printf ("aide/help/?\n");
+            printf ("  Display the description of the commands\n");
+            printf ("aide/help/? [command]\n");
+            printf ("  Display the description of the specified command\n");
+// general commands
+        }
+        else if (strcmp (command, "add") == 0)
+        {
+            printf ("add <account_name> <sex> <password>\n");
+            printf
+                ("  Create an account with the default email (a@a.com).\n");
+            printf
+                ("  Concerning the sex, only the first letter is used (F or M).\n");
+            printf
+                ("  The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n");
+            printf ("  When the password is omitted,\n");
+            printf
+                ("  the input is done without displaying of the pressed keys.\n");
+            printf ("  <example> add testname Male testpass\n");
+        }
+        else if (strcmp (command, "ban") == 0)
+        {
+            printf ("ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
+            printf
+                ("  Changes the final date of a banishment of an account.\n");
+            printf ("  Like banset, but <account name> is at end.\n");
+        }
+        else if (strcmp (command, "banadd") == 0)
+        {
+            printf ("banadd <account_name> <modifier>\n");
+            printf
+                ("  Adds or substracts time from the final date of a banishment of an account.\n");
+            printf ("  Modifier is done as follows:\n");
+            printf ("    Adjustment value (-1, 1, +1, etc...)\n");
+            printf ("    Modified element:\n");
+            printf ("      a or y: year\n");
+            printf ("      m:  month\n");
+            printf ("      j or d: day\n");
+            printf ("      h:  hour\n");
+            printf ("      mn: minute\n");
+            printf ("      s:  second\n");
+            printf ("  <example> banadd testname +1m-2mn1s-6y\n");
+            printf
+                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("            and 6 years at the same time.\n");
+            printf
+                ("NOTE: If you modify the final date of a non-banished account,\n");
+            printf
+                ("      you fix the final date to (actual time +- adjustments)\n");
+        }
+        else if (strcmp (command, "banset") == 0)
+        {
+            printf ("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf
+                ("  Changes the final date of a banishment of an account.\n");
+            printf ("  Default time [hh:mm:ss]: 23:59:59.\n");
+            printf ("banset <account_name> 0\n");
+            printf ("  Set a non-banished account (0 = unbanished).\n");
+        }
+        else if (strcmp (command, "block") == 0)
+        {
+            printf ("block <account name>\n");
+            printf
+                ("  Set state 5 (You have been blocked by the GM Team) to an account.\n");
+            printf ("  This command works like state <account_name> 5.\n");
+        }
+        else if (strcmp (command, "check") == 0)
+        {
+            printf ("check <account_name> <password>\n");
+            printf ("  Check the validity of a password for an account.\n");
+            printf ("  NOTE: Server will never sends back a password.\n");
+            printf
+                ("        It's the only method you have to know if a password is correct.\n");
+            printf
+                ("        The other method is to have a ('physical') access to the accounts file.\n");
+        }
+        else if (strcmp (command, "create") == 0)
+        {
+            printf ("create <account_name> <sex> <email> <password>\n");
+            printf ("  Like the 'add' command, but with e-mail moreover.\n");
+            printf
+                ("  <example> create testname Male my@mail.com testpass\n");
+        }
+        else if (strcmp (command, "delete") == 0)
+        {
+            printf ("del <account name>\n");
+            printf ("  Remove an account.\n");
+            printf
+                ("  This order requires confirmation. After confirmation, the account is deleted.\n");
+        }
+        else if (strcmp (command, "email") == 0)
+        {
+            printf ("email <account_name> <email>\n");
+            printf ("  Modify the e-mail of an account.\n");
+        }
+        else if (strcmp (command, "getcount") == 0)
+        {
+            printf ("getcount\n");
+            printf
+                ("  Give the number of players online on all char-servers.\n");
+        }
+        else if (strcmp (command, "gm") == 0)
+        {
+            printf ("gm <account_name> [GM_level]\n");
+            printf ("  Modify the GM level of an account.\n");
+            printf ("  Default value remove GM level (GM level = 0).\n");
+            printf ("  <example> gm testname 80\n");
+        }
+        else if (strcmp (command, "id") == 0)
+        {
+            printf ("id <account name>\n");
+            printf ("  Give the id of an account.\n");
+        }
+        else if (strcmp (command, "info") == 0)
+        {
+            printf ("info <account_id>\n");
+            printf ("  Display complete information of an account.\n");
+        }
+        else if (strcmp (command, "kami") == 0)
+        {
+            printf ("kami <message>\n");
+            printf
+                ("  Sends a broadcast message on all map-server (in yellow).\n");
+        }
+        else if (strcmp (command, "kamib") == 0)
+        {
+            printf ("kamib <message>\n");
+            printf
+                ("  Sends a broadcast message on all map-server (in blue).\n");
+        }
+        else if (strcmp (command, "language") == 0)
+        {
+            printf ("language <language>\n");
+            printf ("  Change the language of displaying.\n");
+            printf ("  Possible languages: Français or English.\n");
+        }
+        else if (strcmp (command, "list") == 0)
+        {
+            printf ("list/ls [start_id [end_id]]\n");
+            printf ("  Display a list of accounts.\n");
+            printf
+                ("  'start_id', 'end_id': indicate end and start identifiers.\n");
+            printf
+                ("  Research by name is not possible with this command.\n");
+            printf ("  <example> list 10 9999999\n");
+        }
+        else if (strcmp (command, "itemfrob") == 0)
+        {
+            printf ("itemfrob <source-id> <dest-id>\n");
+            printf ("  Translates item IDs for all accounts.\n");
+            printf
+                ("  Any items matching the source item ID will be mapped to the dest-id.\n");
+            printf ("  <example> itemfrob 500 700\n");
+        }
+        else if (strcmp (command, "listban") == 0)
+        {
+            printf ("listBan/lsBan [start_id [end_id]]\n");
+            printf
+                ("  Like list/ls, but only for accounts with state or banished.\n");
+        }
+        else if (strcmp (command, "listgm") == 0)
+        {
+            printf ("listGM/lsGM [start_id [end_id]]\n");
+            printf ("  Like list/ls, but only for GM accounts.\n");
+        }
+        else if (strcmp (command, "listok") == 0)
+        {
+            printf ("listOK/lsOK [start_id [end_id]]\n");
+            printf
+                ("  Like list/ls, but only for accounts without state and not banished.\n");
+        }
+        else if (strcmp (command, "memo") == 0)
+        {
+            printf ("memo <account_name> <memo>\n");
+            printf ("  Modify the memo of an account.\n");
+            printf
+                ("  'memo': it can have until 253 characters (with spaces or not).\n");
+        }
+        else if (strcmp (command, "name") == 0)
+        {
+            printf ("name <account_id>\n");
+            printf ("  Give the name of an account.\n");
+        }
+        else if (strcmp (command, "password") == 0)
+        {
+            printf ("passwd <account_name> <new_password>\n");
+            printf ("  Change the password of an account.\n");
+            printf ("  When new password is omitted,\n");
+            printf
+                ("  the input is done without displaying of the pressed keys.\n");
+        }
+        else if (strcmp (command, "reloadgm") == 0)
+        {
+            printf ("reloadGM\n");
+            printf ("  Reload GM configuration file\n");
+        }
+        else if (strcmp (command, "search") == 0)
+        {
+            printf ("search <expression>\n");
+            printf ("  Seek accounts.\n");
+            printf ("  Displays the accounts whose names correspond.\n");
+//          printf("search -r/-e/--expr/--regex <expression>\n");
+//          printf("  Seek accounts by regular expression.\n");
+//          printf("  Displays the accounts whose names correspond.\n");
+        }
+        else if (strcmp (command, "sex") == 0)
+        {
+            printf ("sex <account_name> <sex>\n");
+            printf ("  Modify the sex of an account.\n");
+            printf ("  <example> sex testname Male\n");
+        }
+        else if (strcmp (command, "state") == 0)
+        {
+            printf ("state <account_name> <new_state> <error_message_#7>\n");
+            printf ("  Change the state of an account.\n");
+            printf
+                ("  'new_state': state is the state of the packet 0x006a + 1.\n");
+            printf ("               The possibilities are:\n");
+            printf ("               0 = Account ok\n");
+            printf ("               1 = Unregistered ID\n");
+            printf ("               2 = Incorrect Password\n");
+            printf ("               3 = This ID is expired\n");
+            printf ("               4 = Rejected from Server\n");
+            printf
+                ("               5 = You have been blocked by the GM Team\n");
+            printf
+                ("               6 = Your Game's EXE file is not the latest version\n");
+            printf
+                ("               7 = You are Prohibited to log in until...\n");
+            printf
+                ("               8 = Server is jammed due to over populated\n");
+            printf ("               9 = No MSG\n");
+            printf ("               100 = This ID has been totally erased\n");
+            printf
+                ("               all other values are 'No MSG', then use state 9 please.\n");
+            printf ("  'error_message_#7': message of the code error 6\n");
+            printf
+                ("                      = Your are Prohibited to log in until... (packet 0x006a)\n");
+        }
+        else if (strcmp (command, "timeadd") == 0)
+        {
+            printf ("timeadd <account_name> <modifier>\n");
+            printf
+                ("  Adds or substracts time from the validity limit of an account.\n");
+            printf ("  Modifier is done as follows:\n");
+            printf ("    Adjustment value (-1, 1, +1, etc...)\n");
+            printf ("    Modified element:\n");
+            printf ("      a or y: year\n");
+            printf ("      m:  month\n");
+            printf ("      j or d: day\n");
+            printf ("      h:  hour\n");
+            printf ("      mn: minute\n");
+            printf ("      s:  second\n");
+            printf ("  <example> timeadd testname +1m-2mn1s-6y\n");
+            printf
+                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("            and 6 years at the same time.\n");
+            printf ("NOTE: You can not modify a unlimited validity limit.\n");
+            printf
+                ("      If you want modify it, you want probably create a limited validity limit.\n");
+            printf
+                ("      So, at first, you must set the validity limit to a date/time.\n");
+        }
+        else if (strcmp (command, "timeadd") == 0)
+        {
+            printf ("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf ("  Changes the validity limit of an account.\n");
+            printf ("  Default time [hh:mm:ss]: 23:59:59.\n");
+            printf ("timeset <account_name> 0\n");
+            printf ("  Gives an unlimited validity limit (0 = unlimited).\n");
+        }
+        else if (strcmp (command, "unban") == 0)
+        {
+            printf ("unban/unbanish <account name>\n");
+            printf ("  Remove the banishment of an account.\n");
+            printf ("  This command works like banset <account_name> 0.\n");
+        }
+        else if (strcmp (command, "unblock") == 0)
+        {
+            printf ("unblock <account name>\n");
+            printf ("  Set state 0 (Account ok) to an account.\n");
+            printf ("  This command works like state <account_name> 0.\n");
+        }
+        else if (strcmp (command, "version") == 0)
+        {
+            printf ("version\n");
+            printf ("  Display the version of the login-server.\n");
+        }
+        else if (strcmp (command, "who") == 0)
+        {
+            printf ("who <account name>\n");
+            printf ("  Displays complete information of an account.\n");
+// quit
+        }
+        else if (strcmp (command, "quit") == 0 ||
+                 strcmp (command, "exit") == 0 ||
+                 strcmp (command, "end") == 0)
+        {
+            printf ("quit/end/exit\n");
+            printf ("  End of the program of administration.\n");
+// unknown command
+        }
+        else
+        {
+            if (strlen (command) > 0)
+                printf
+                    ("Unknown command [%s] for help. Displaying of all commands.\n",
+                     command);
+            printf
+                (" aide/help/?                          -- Display this help\n");
+            printf
+                (" aide/help/? [command]                -- Display the help of the command\n");
+            printf
+                (" add <account_name> <sex> <password>  -- Create an account with default email\n");
+            printf
+                (" ban/banish yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n");
+            printf
+                (" banadd/ba <account_name> <modifier>  -- Add or substract time from the final\n");
+            printf
+                ("   example: ba apple +1m-2mn1s-2y        date of a banishment of an account\n");
+            printf
+                (" banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n");
+            printf
+                (" banset/bs <account_name> 0           -- Un-banish an account\n");
+            printf
+                (" block <account name>     -- Set state 5 (blocked by the GM Team) to an account\n");
+            printf
+                (" check <account_name> <password>      -- Check the validity of a password\n");
+            printf
+                (" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n");
+            printf
+                (" del <account name>                   -- Remove an account\n");
+            printf
+                (" email <account_name> <email>         -- Modify an email of an account\n");
+            printf
+                (" getcount                             -- Give the number of players online\n");
+            printf
+                (" gm <account_name> [GM_level]         -- Modify the GM level of an account\n");
+            printf
+                (" id <account name>                    -- Give the id of an account\n");
+            printf
+                (" info <account_id>                    -- Display all information of an account\n");
+            printf
+                (" itemfrob <source-id> <dest-id>       -- Map all items from one item ID to another\n");
+            printf
+                (" kami <message>                       -- Sends a broadcast message (in yellow)\n");
+            printf
+                (" kamib <message>                      -- Sends a broadcast message (in blue)\n");
+            printf
+                (" language <language>                  -- Change the language of displaying.\n");
+            printf
+                (" list/ls [First_id [Last_id]]         -- Display a list of accounts\n");
+            printf
+                (" listBan/lsBan [First_id [Last_id] ]  -- Display a list of accounts\n");
+            printf
+                ("                                         with state or banished\n");
+            printf
+                (" listGM/lsGM [First_id [Last_id]]     -- Display a list of GM accounts\n");
+            printf
+                (" listOK/lsOK [First_id [Last_id] ]    -- Display a list of accounts\n");
+            printf
+                ("                                         without state and not banished\n");
+            printf
+                (" memo <account_name> <memo>           -- Modify the memo of an account\n");
+            printf
+                (" name <account_id>                    -- Give the name of an account\n");
+            printf
+                (" passwd <account_name> <new_password> -- Change the password of an account\n");
+            printf
+                (" quit/end/exit                        -- End of the program of administation\n");
+            printf
+                (" reloadGM                             -- Reload GM configuration file\n");
+            printf
+                (" search <expression>                  -- Seek accounts\n");
+//          printf(" search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression\n");
+            printf
+                (" sex <nomcompte> <sexe>               -- Modify the sex of an account\n");
+            printf
+                (" state <account_name> <new_state> <error_message_#7> -- Change the state\n");
+            printf
+                (" timeadd/ta <account_name> <modifier> -- Add or substract time from the\n");
+            printf
+                ("   example: ta apple +1m-2mn1s-2y        validity limit of an account\n");
+            printf
+                (" timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n");
+            printf
+                (" timeset/ts <account_name> 0          -- Give a unlimited validity limit\n");
+            printf
+                (" unban/unbanish <account name>        -- Remove the banishment of an account\n");
+            printf
+                (" unblock <account name>               -- Set state 0 (Account ok) to an account\n");
+            printf
+                (" version                              -- Gives the version of the login-server\n");
+            printf
+                (" who <account name>                   -- Display all information of an account\n");
+            printf
+                (" who <account name>                   -- Display all information of an account\n");
+            printf
+                (" Note: To use spaces in an account name, type \"<account name>\" (or ').\n");
+        }
+    }
+}
+
+//-----------------------------
+// Sub-function: add an account
+//-----------------------------
+int addaccount (char *param, int emailflag)
+{
+    char name[1023], sex[1023], email[1023], password[1023];
+//  int i;
+
+    memset (name, '\0', sizeof (name));
+    memset (sex, '\0', sizeof (sex));
+    memset (email, '\0', sizeof (email));
+    memset (password, '\0', sizeof (password));
+
+    if (emailflag == 0)
+    {                           // add command
+        if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, sex, password) < 2 &&    // password can be void
+            sscanf (param, "'%[^']' %s %[^\r\n]", name, sex, password) < 2 &&   // password can be void
+            sscanf (param, "%s %s %[^\r\n]", name, sex, password) < 2)
+        {                       // password can be void
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez un nom de compte, un sexe et un mot de passe svp.\n");
+                printf ("<exemple> add nomtest Male motdepassetest\n");
+                ladmin_log
+                    ("Nombre incorrect de paramètres pour créer un compte (commande 'add').\n");
+            }
+            else
+            {
+                printf
+                    ("Please input an account name, a sex and a password.\n");
+                printf ("<example> add testname Male testpass\n");
+                ladmin_log
+                    ("Incomplete parameters to create an account ('add' command).\n");
+            }
+            return 136;
+        }
+        strcpy (email, "a@a.com");  // default email
+    }
+    else
+    {                           // 1: create command
+        if (sscanf (param, "\"%[^\"]\" %s %s %[^\r\n]", name, sex, email, password) < 3 &&  // password can be void
+            sscanf (param, "'%[^']' %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
+            sscanf (param, "%s %s %s %[^\r\n]", name, sex, email,
+                    password) < 3)
+        {                       // password can be void
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez un nom de compte, un sexe et un mot de passe svp.\n");
+                printf
+                    ("<exemple> create nomtest Male mo@mail.com motdepassetest\n");
+                ladmin_log
+                    ("Nombre incorrect de paramètres pour créer un compte (commande 'create').\n");
+            }
+            else
+            {
+                printf
+                    ("Please input an account name, a sex and a password.\n");
+                printf
+                    ("<example> create testname Male my@mail.com testpass\n");
+                ladmin_log
+                    ("Incomplete parameters to create an account ('create' command).\n");
+            }
+            return 136;
+        }
+    }
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+/*	for(i = 0; name[i]; i++) {
+		if (strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_", name[i]) == NULL) {
+			if (defaultlanguage == 'F') {
+				printf("Caractère interdit (%c) trouvé dans le nom du compte (%d%s caractère).\n", name[i], i+1, makeordinal(i+1));
+				ladmin_log("Caractère interdit (%c) trouvé dans le nom du compte (%d%s caractère).\n", name[i], i+1, makeordinal(i+1));
+			} else {
+				printf("Illegal character (%c) found in the account name (%d%s character).\n", name[i], i+1, makeordinal(i+1));
+				ladmin_log("Illegal character (%c) found in the account name (%d%s character).\n", name[i], i+1, makeordinal(i+1));
+			}
+			return 101;
+		}
+	}*/
+
+    sex[0] = toupper (sex[0]);
+    if (strchr ("MF", sex[0]) == NULL)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Sexe incorrect [%s]. Entrez M ou F svp.\n", sex);
+            ladmin_log ("Sexe incorrect [%s]. Entrez M ou F svp.\n",
+                        sex);
+        }
+        else
+        {
+            printf ("Illegal gender [%s]. Please input M or F.\n", sex);
+            ladmin_log ("Illegal gender [%s]. Please input M or F.\n",
+                        sex);
+        }
+        return 103;
+    }
+
+    if (strlen (email) < 3)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
+                    email);
+            ladmin_log
+                ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
+                  email);
+        }
+        else
+        {
+            printf ("Email is too short [%s]. Please input a valid e-mail.\n",
+                    email);
+            ladmin_log
+                ("Email is too short [%s]. Please input a valid e-mail.\n",
+                  email);
+        }
+        return 109;
+    }
+    if (strlen (email) > 39)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
+                 email);
+            ladmin_log
+                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
+                  email);
+        }
+        else
+        {
+            printf
+                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
+                 email);
+            ladmin_log
+                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
+                  email);
+        }
+        return 109;
+    }
+    if (e_mail_check (email) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
+                    email);
+            ladmin_log ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
+                         email);
+        }
+        else
+        {
+            printf ("Invalid email [%s]. Please input a valid e-mail.\n",
+                    email);
+            ladmin_log ("Invalid email [%s]. Please input a valid e-mail.\n",
+                         email);
+        }
+        return 109;
+    }
+
+    if (strlen (password) == 0)
+    {
+        if (typepasswd (password) == 0)
+            return 108;
+    }
+    if (verify_password (password) == 0)
+        return 104;
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour créer un compte.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to create an account.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7930;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    memcpy (WFIFOP (login_fd, 26), password, 24);
+    WFIFOB (login_fd, 50) = sex[0];
+    memcpy (WFIFOP (login_fd, 51), email, 40);
+    WFIFOSET (login_fd, 91);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//---------------------------------------------------------------------------------
+// Sub-function: Add/substract time to the final date of a banishment of an account
+//---------------------------------------------------------------------------------
+int banaddaccount (char *param)
+{
+    char name[1023], modif[1023];
+    int  year, month, day, hour, minute, second;
+    char *p_modif;
+    int  value, i;
+
+    memset (name, '\0', sizeof (name));
+    memset (modif, '\0', sizeof (modif));
+    year = month = day = hour = minute = second = 0;
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
+        sscanf (param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
+        sscanf (param, "%s %[^\r\n]", name, modif) < 2)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un modificateur svp.\n");
+            printf ("  <exemple> banadd nomtest +1m-2mn1s-6y\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour modifier la fin de ban d'un compte (commande 'banadd').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a modifier.\n");
+            printf ("  <example>: banadd testname +1m-2mn1s-6y\n");
+            printf
+                ("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("             and 6 years at the same time.\n");
+            ladmin_log
+                ("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n");
+        }
+        return 136;
+    }
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    // lowercase for modif
+    for (i = 0; modif[i]; i++)
+        modif[i] = tolower (modif[i]);
+    p_modif = modif;
+    while (strlen (p_modif) > 0)
+    {
+        value = atoi (p_modif);
+        if (value == 0)
+        {
+            p_modif++;
+        }
+        else
+        {
+            if (p_modif[0] == '-' || p_modif[0] == '+')
+                p_modif++;
+            while (strlen (p_modif) > 0 && p_modif[0] >= '0'
+                   && p_modif[0] <= '9')
+            {
+                p_modif++;
+            }
+            if (p_modif[0] == 's')
+            {
+                second = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'm' && p_modif[1] == 'n')
+            {
+                minute = value;
+                p_modif += 2;
+            }
+            else if (p_modif[0] == 'h')
+            {
+                hour = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'd' || p_modif[0] == 'j')
+            {
+                day = value;
+                p_modif += 2;
+            }
+            else if (p_modif[0] == 'm')
+            {
+                month = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'y' || p_modif[0] == 'a')
+            {
+                year = value;
+                p_modif++;
+            }
+            else
+            {
+                p_modif++;
+            }
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        printf (" année:   %d\n", year);
+        printf (" mois:    %d\n", month);
+        printf (" jour:    %d\n", day);
+        printf (" heure:   %d\n", hour);
+        printf (" minute:  %d\n", minute);
+        printf (" seconde: %d\n", second);
+    }
+    else
+    {
+        printf (" year:   %d\n", year);
+        printf (" month:  %d\n", month);
+        printf (" day:    %d\n", day);
+        printf (" hour:   %d\n", hour);
+        printf (" minute: %d\n", minute);
+        printf (" second: %d\n", second);
+    }
+
+    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
+        && second == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Vous devez entrer un ajustement avec cette commande, svp:\n");
+            printf ("  Valeur d'ajustement (-1, 1, +1, etc...)\n");
+            printf ("  Element modifié:\n");
+            printf ("    a ou y: année\n");
+            printf ("    m:      mois\n");
+            printf ("    j ou d: jour\n");
+            printf ("    h:      heure\n");
+            printf ("    mn:     minute\n");
+            printf ("    s:      seconde\n");
+            printf ("  <exemple> banadd nomtest +1m-2mn1s-6y\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            ladmin_log
+                ("Aucun ajustement n'est pas un ajustement (commande 'banadd').\n");
+        }
+        else
+        {
+            printf ("Please give an adjustment with this command:\n");
+            printf ("  Adjustment value (-1, 1, +1, etc...)\n");
+            printf ("  Modified element:\n");
+            printf ("    a or y: year\n");
+            printf ("    m: month\n");
+            printf ("    j or d: day\n");
+            printf ("    h: hour\n");
+            printf ("    mn: minute\n");
+            printf ("    s: second\n");
+            printf ("  <example> banadd testname +1m-2mn1s-6y\n");
+            printf
+                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("            and 6 years at the same time.\n");
+            ladmin_log
+                ("No adjustment isn't an adjustment ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (year > 127 || year < -127)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement d'années correct (de -127 à 127), svp.\n");
+            ladmin_log
+                ("Ajustement de l'année hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the years (from -127 to 127).\n");
+            ladmin_log
+                ("Abnormal adjustement for the year ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (month > 255 || month < -255)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de mois correct (de -255 à 255), svp.\n");
+            ladmin_log ("Ajustement du mois hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the months (from -255 to 255).\n");
+            ladmin_log
+                ("Abnormal adjustement for the month ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (day > 32767 || day < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n");
+            ladmin_log ("Ajustement des jours hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the days (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the days ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (hour > 32767 || hour < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des heures hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the hours ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (minute > 32767 || minute < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des minutes hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the minutes ('banadd' command).\n");
+        }
+        return 137;
+    }
+    if (second > 32767 || second < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des secondes hors norme (commande 'banadd').\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the seconds ('banadd' command).\n");
+        }
+        return 137;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour modifier la date d'un bannissement.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to modify a ban date/time.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x794c;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOW (login_fd, 26) = (short) year;
+    WFIFOW (login_fd, 28) = (short) month;
+    WFIFOW (login_fd, 30) = (short) day;
+    WFIFOW (login_fd, 32) = (short) hour;
+    WFIFOW (login_fd, 34) = (short) minute;
+    WFIFOW (login_fd, 36) = (short) second;
+    WFIFOSET (login_fd, 38);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-----------------------------------------------------------------------
+// Sub-function of sub-function banaccount, unbanaccount or bansetaccount
+// Set the final date of a banishment of an account
+//-----------------------------------------------------------------------
+int bansetaccountsub (char *name, char *date, char *time)
+{
+    int  year, month, day, hour, minute, second;
+    time_t ban_until_time;      // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
+    struct tm *tmtime;
+
+    year = month = day = hour = minute = second = 0;
+    ban_until_time = 0;
+    tmtime = localtime (&ban_until_time);   // initialize
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (atoi (date) != 0 &&
+        ((sscanf (date, "%d/%d/%d", &year, &month, &day) < 3 &&
+          sscanf (date, "%d-%d-%d", &year, &month, &day) < 3 &&
+          sscanf (date, "%d.%d.%d", &year, &month, &day) < 3) ||
+         sscanf (time, "%d:%d:%d", &hour, &minute, &second) < 3))
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez une date et une heure svp (format: aaaa/mm/jj hh:mm:ss).\n");
+            printf
+                ("Vous pouvez aussi mettre 0 à la place si vous utilisez la commande 'banset'.\n");
+            ladmin_log
+                ("Format incorrect pour la date/heure (commande'banset' ou 'ban').\n");
+        }
+        else
+        {
+            printf
+                ("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
+            printf
+                ("You can imput 0 instead of if you use 'banset' command.\n");
+            ladmin_log
+                ("Invalid format for the date/time ('banset' or 'ban' command).\n");
+        }
+        return 102;
+    }
+
+    if (atoi (date) == 0)
+    {
+        ban_until_time = 0;
+    }
+    else
+    {
+        if (year < 70)
+        {
+            year = year + 100;
+        }
+        if (year >= 1900)
+        {
+            year = year - 1900;
+        }
+        if (month < 1 || month > 12)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez un mois correct svp (entre 1 et 12).\n");
+                ladmin_log
+                    ("Mois incorrect pour la date (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the month (from 1 to 12).\n");
+                ladmin_log
+                    ("Invalid month for the date ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        month = month - 1;
+        if (day < 1 || day > 31)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez un jour correct svp (entre 1 et 31).\n");
+                ladmin_log
+                    ("Jour incorrect pour la date (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the day (from 1 to 31).\n");
+                ladmin_log
+                    ("Invalid day for the date ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        if (((month == 3 || month == 5 || month == 8 || month == 10)
+             && day > 30) || (month == 1 && day > 29))
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez un jour correct en fonction du mois (%d) svp.\n",
+                     month);
+                ladmin_log
+                    ("Jour incorrect pour ce mois correspondant (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for a day of this month (%d).\n",
+                     month);
+                ladmin_log
+                    ("Invalid day for this month ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        if (hour < 0 || hour > 23)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez une heure correcte svp (entre 0 et 23).\n");
+                ladmin_log
+                    ("Heure incorrecte pour l'heure (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the hour (from 0 to 23).\n");
+                ladmin_log
+                    ("Invalid hour for the time ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        if (minute < 0 || minute > 59)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez des minutes correctes svp (entre 0 et 59).\n");
+                ladmin_log
+                    ("Minute incorrecte pour l'heure (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the minutes (from 0 to 59).\n");
+                ladmin_log
+                    ("Invalid minute for the time ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        if (second < 0 || second > 59)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez des secondes correctes svp (entre 0 et 59).\n");
+                ladmin_log
+                    ("Seconde incorrecte pour l'heure (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the seconds (from 0 to 59).\n");
+                ladmin_log
+                    ("Invalid second for the time ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+        tmtime->tm_year = year;
+        tmtime->tm_mon = month;
+        tmtime->tm_mday = day;
+        tmtime->tm_hour = hour;
+        tmtime->tm_min = minute;
+        tmtime->tm_sec = second;
+        tmtime->tm_isdst = -1;  // -1: no winter/summer time modification
+        ban_until_time = timegm (tmtime);
+        if (ban_until_time == -1)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Date incorrecte.\n");
+                printf
+                    ("Entrez une date et une heure svp (format: aaaa/mm/jj hh:mm:ss).\n");
+                printf
+                    ("Vous pouvez aussi mettre 0 à la place si vous utilisez la commande 'banset'.\n");
+                ladmin_log ("Date incorrecte. (command 'banset' ou 'ban').\n");
+            }
+            else
+            {
+                printf ("Invalid date.\n");
+                printf
+                    ("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
+                printf
+                    ("You can imput 0 instead of if you use 'banset' command.\n");
+                ladmin_log ("Invalid date. ('banset' or 'ban' command).\n");
+            }
+            return 102;
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour fixer un ban.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to set a ban.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x794a;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOL (login_fd, 26) = (int) ban_until_time;
+    WFIFOSET (login_fd, 30);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//---------------------------------------------------------------------
+// Sub-function: Set the final date of a banishment of an account (ban)
+//---------------------------------------------------------------------
+int banaccount (char *param)
+{
+    char name[1023], date[1023], time[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (date, '\0', sizeof (date));
+    memset (time, '\0', sizeof (time));
+
+    if (sscanf (param, "%s %s \"%[^\"]\"", date, time, name) < 3 &&
+        sscanf (param, "%s %s '%[^']'", date, time, name) < 3 &&
+        sscanf (param, "%s %s %[^\r\n]", date, time, name) < 3)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte, une date et une heure svp.\n");
+            printf
+                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
+            printf
+                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
+            printf ("           unban/unbanish <nom du compte>\n");
+            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour fixer un ban (commande 'banset' ou 'ban').\n");
+        }
+        else
+        {
+            printf ("Please input an account name, a date and a hour.\n");
+            printf
+                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf
+                ("           banset <account_name> 0   (0 = un-banished)\n");
+            printf
+                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
+            printf ("           unban/unbanish <account name>\n");
+            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
+        }
+        return 136;
+    }
+
+    return bansetaccountsub (name, date, time);
+}
+
+//------------------------------------------------------------------------
+// Sub-function: Set the final date of a banishment of an account (banset)
+//------------------------------------------------------------------------
+int bansetaccount (char *param)
+{
+    char name[1023], date[1023], time[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (date, '\0', sizeof (date));
+    memset (time, '\0', sizeof (time));
+
+    if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 &&   // if date = 0, time can be void
+        sscanf (param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 &&  // if date = 0, time can be void
+        sscanf (param, "%s %s %[^\r\n]", name, date, time) < 2)
+    {                           // if date = 0, time can be void
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte, une date et une heure svp.\n");
+            printf
+                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
+            printf
+                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
+            printf ("           unban/unbanish <nom du compte>\n");
+            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour fixer un ban (commande 'banset' ou 'ban').\n");
+        }
+        else
+        {
+            printf ("Please input an account name, a date and a hour.\n");
+            printf
+                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf
+                ("           banset <account_name> 0   (0 = un-banished)\n");
+            printf
+                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
+            printf ("           unban/unbanish <account name>\n");
+            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
+        }
+        return 136;
+    }
+
+    if (time[0] == '\0')
+        strcpy (time, "23:59:59");
+
+    return bansetaccountsub (name, date, time);
+}
+
+//-------------------------------------------------
+// Sub-function: unbanishment of an account (unban)
+//-------------------------------------------------
+int unbanaccount (char *param)
+{
+    char name[1023];
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf
+                ("<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf ("           banset <nom_du_compte> 0    (0 = dé-bani)\n");
+            printf
+                ("           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n");
+            printf ("           unban/unbanish <nom du compte>\n");
+            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour fixer un ban (commande 'unban').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf
+                ("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf
+                ("           banset <account_name> 0   (0 = un-banished)\n");
+            printf
+                ("           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
+            printf ("           unban/unbanish <account name>\n");
+            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Incomplete parameters to set a ban ('unban' command).\n");
+        }
+        return 136;
+    }
+
+    return bansetaccountsub (name, "0", "");
+}
+
+//---------------------------------------------------------
+// Sub-function: Asking to check the validity of a password
+// (Note: never send back a password with login-server!! security of passwords)
+//---------------------------------------------------------
+int checkaccount (char *param)
+{
+    char name[1023], password[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (password, '\0', sizeof (password));
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&    // password can be void
+        sscanf (param, "'%[^']' %[^\r\n]", name, password) < 1 &&   // password can be void
+        sscanf (param, "%s %[^\r\n]", name, password) < 1)
+    {                           // password can be void
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemple> check testname motdepasse\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour tester le mot d'un passe d'un compte (commande 'check').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<example> check testname password\n");
+            ladmin_log
+                ("Incomplete parameters to check the password of an account ('check' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (strlen (password) == 0)
+    {
+        if (typepasswd (password) == 0)
+            return 134;
+    }
+    if (verify_password (password) == 0)
+        return 131;
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour test un mot de passe.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to check a password.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x793a;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    memcpy (WFIFOP (login_fd, 26), password, 24);
+    WFIFOSET (login_fd, 50);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//------------------------------------------------
+// Sub-function: Asking for deletion of an account
+//------------------------------------------------
+int delaccount (char *param)
+{
+    char name[1023];
+    char letter;
+    char confirm[1023];
+    int  i;
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemple> del nomtestasupprimer\n");
+            ladmin_log
+                ("Aucun nom donné pour supprimer un compte (commande 'delete').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<example> del testnametodelete\n");
+            ladmin_log
+                ("No name given to delete an account ('delete' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    memset (confirm, '\0', sizeof (confirm));
+    while ((confirm[0] != 'o' || defaultlanguage != 'F') && confirm[0] != 'n'
+           && (confirm[0] != 'y' || defaultlanguage == 'F'))
+    {
+        if (defaultlanguage == 'F')
+            printf
+                ("\033[1;36m ** Etes-vous vraiment sûr de vouloir SUPPRIMER le compte [$userid]? (o/n) > \033[0m");
+        else
+            printf
+                ("\033[1;36m ** Are you really sure to DELETE account [$userid]? (y/n) > \033[0m");
+        fflush (stdout);
+        memset (confirm, '\0', sizeof (confirm));
+        i = 0;
+        while ((letter = getchar ()) != '\n')
+            confirm[i++] = letter;
+    }
+
+    if (confirm[0] == 'n')
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Suppression annulée.\n");
+            ladmin_log
+                ("Suppression annulée par l'utilisateur (commande 'delete').\n");
+        }
+        else
+        {
+            printf ("Deletion canceled.\n");
+            ladmin_log ("Deletion canceled by user ('delete' command).\n");
+        }
+        return 121;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour détruire un compte.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to delete an acount.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7932;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOSET (login_fd, 26);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//----------------------------------------------------------
+// Sub-function: Asking to modification of an account e-mail
+//----------------------------------------------------------
+int changeemail (char *param)
+{
+    char name[1023], email[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (email, '\0', sizeof (email));
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, email) < 2 &&
+        sscanf (param, "'%[^']' %[^\r\n]", name, email) < 2 &&
+        sscanf (param, "%s %[^\r\n]", name, email) < 2)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et une email svp.\n");
+            printf ("<exemple> email testname nouveauemail\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer l'email d'un compte (commande 'email').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and an email.\n");
+            printf ("<example> email testname newemail\n");
+            ladmin_log
+                ("Incomplete parameters to change the email of an account ('email' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (strlen (email) < 3)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
+                    email);
+            ladmin_log
+                ("Email trop courte [%s]. Entrez une e-mail valide svp.\n",
+                  email);
+        }
+        else
+        {
+            printf ("Email is too short [%s]. Please input a valid e-mail.\n",
+                    email);
+            ladmin_log
+                ("Email is too short [%s]. Please input a valid e-mail.\n",
+                  email);
+        }
+        return 109;
+    }
+    if (strlen (email) > 39)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
+                 email);
+            ladmin_log
+                ("Email trop longue [%s]. Entrez une e-mail de 39 caractères maximum svp.\n",
+                  email);
+        }
+        else
+        {
+            printf
+                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
+                 email);
+            ladmin_log
+                ("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n",
+                  email);
+        }
+        return 109;
+    }
+    if (e_mail_check (email) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
+                    email);
+            ladmin_log ("Email incorrecte [%s]. Entrez une e-mail valide svp.\n",
+                         email);
+        }
+        else
+        {
+            printf ("Invalid email [%s]. Please input a valid e-mail.\n",
+                    email);
+            ladmin_log ("Invalid email [%s]. Please input a valid e-mail.\n",
+                         email);
+        }
+        return 109;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer une email.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change an email.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7940;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    memcpy (WFIFOP (login_fd, 26), email, 40);
+    WFIFOSET (login_fd, 66);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-----------------------------------------------------
+// Sub-function: Asking of the number of online players
+//-----------------------------------------------------
+int getlogincount (void)
+{
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour obtenir le nombre de joueurs en jeu.\n");
+    }
+    else
+    {
+        ladmin_log
+            ("Request to login-server to obtain the # of online players.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7938;
+    WFIFOSET (login_fd, 2);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//----------------------------------------------------------
+// Sub-function: Asking to modify the GM level of an account
+//----------------------------------------------------------
+int changegmlevel (char *param)
+{
+    char name[1023];
+    int  GM_level;
+
+    memset (name, '\0', sizeof (name));
+    GM_level = 0;
+
+    if (sscanf (param, "\"%[^\"]\" %d", name, &GM_level) < 1 &&
+        sscanf (param, "'%[^']' %d", name, &GM_level) < 1 &&
+        sscanf (param, "%s %d", name, &GM_level) < 1)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un niveau de GM svp.\n");
+            printf ("<exemple> gm nomtest 80\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le Niveau de GM d'un compte (commande 'gm').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a GM level.\n");
+            printf ("<example> gm testname 80\n");
+            ladmin_log
+                ("Incomplete parameters to change the GM level of an account ('gm' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (GM_level < 0 || GM_level > 99)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Niveau de GM incorrect [%d]. Entrez une valeur de 0 à 99 svp.\n",
+                 GM_level);
+            ladmin_log
+                ("Niveau de GM incorrect [%d]. La valeur peut être de 0 à 99.\n",
+                  GM_level);
+        }
+        else
+        {
+            printf
+                ("Illegal GM level [%d]. Please input a value from 0 to 99.\n",
+                 GM_level);
+            ladmin_log
+                ("Illegal GM level [%d]. The value can be from 0 to 99.\n",
+                  GM_level);
+        }
+        return 103;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer un niveau de GM.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change a GM level.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x793e;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOB (login_fd, 26) = GM_level;
+    WFIFOSET (login_fd, 27);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//---------------------------------------------
+// Sub-function: Asking to obtain an account id
+//---------------------------------------------
+int idaccount (char *param)
+{
+    char name[1023];
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemple> id nomtest\n");
+            ladmin_log
+                ("Aucun nom donné pour rechecher l'id d'un compte (commande 'id').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<example> id testname\n");
+            ladmin_log
+                ("No name given to search an account id ('id' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour connaître l'id d'un compte.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to know an account id.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7944;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOSET (login_fd, 26);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//----------------------------------------------------------------------------
+// Sub-function: Asking to displaying information about an account (by its id)
+//----------------------------------------------------------------------------
+int infoaccount (int account_id)
+{
+    if (account_id < 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un id ayant une valeur positive svp.\n");
+            ladmin_log
+                ("Une valeur négative a été donné pour trouver le compte.\n");
+        }
+        else
+        {
+            printf ("Please input a positive value for the id.\n");
+            ladmin_log ("Negative value was given to found the account.\n");
+        }
+        return 136;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour obtenir le information d'un compte (par l'id).\n");
+    }
+    else
+    {
+        ladmin_log
+            ("Request to login-server to obtain information about an account (by its id).\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7954;
+    WFIFOL (login_fd, 2) = account_id;
+    WFIFOSET (login_fd, 6);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//---------------------------------------
+// Sub-function: Send a broadcast message
+//---------------------------------------
+int sendbroadcast (short type, char *message)
+{
+    if (strlen (message) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un message svp.\n");
+            if (type == 0)
+            {
+                printf ("<exemple> kami un message\n");
+            }
+            else
+            {
+                printf ("<exemple> kamib un message\n");
+            }
+            ladmin_log ("Le message est vide (commande 'kami(b)').\n");
+        }
+        else
+        {
+            printf ("Please input a message.\n");
+            if (type == 0)
+            {
+                printf ("<example> kami a message\n");
+            }
+            else
+            {
+                printf ("<example> kamib a message\n");
+            }
+            ladmin_log ("The message is void ('kami(b)' command).\n");
+        }
+        return 136;
+    }
+
+    WFIFOW (login_fd, 0) = 0x794e;
+    WFIFOW (login_fd, 2) = type;
+    WFIFOL (login_fd, 4) = strlen (message) + 1;
+    memcpy (WFIFOP (login_fd, 8), message, strlen (message) + 1);
+    WFIFOSET (login_fd, 8 + strlen (message) + 1);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//--------------------------------------------
+// Sub-function: Change language of displaying
+//--------------------------------------------
+int changelanguage (char *language)
+{
+    if (strlen (language) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez une langue svp.\n");
+            printf ("<exemple> language english\n");
+            printf ("          language français\n");
+            ladmin_log ("La langue est vide (commande 'language').\n");
+        }
+        else
+        {
+            printf ("Please input a language.\n");
+            printf ("<example> language english\n");
+            printf ("          language français\n");
+            ladmin_log ("The language is void ('language' command).\n");
+        }
+        return 136;
+    }
+
+    language[0] = toupper (language[0]);
+    if (language[0] == 'F' || language[0] == 'E')
+    {
+        defaultlanguage = language[0];
+        if (defaultlanguage == 'F')
+        {
+            printf ("Changement de la langue d'affichage en Français.\n");
+            ladmin_log ("Changement de la langue d'affichage en Français.\n");
+        }
+        else
+        {
+            printf ("Displaying language changed to English.\n");
+            ladmin_log ("Displaying language changed to English.\n");
+        }
+    }
+    else
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Langue non paramétrée (langues possibles: 'Français' ou 'English').\n");
+            ladmin_log
+                ("Langue non paramétrée (Français ou English nécessaire).\n");
+        }
+        else
+        {
+            printf
+                ("Undefined language (possible languages: Français or English).\n");
+            ladmin_log ("Undefined language (must be Français or English).\n");
+        }
+    }
+
+    return 0;
+}
+
+//--------------------------------------------------------
+// Sub-function: Asking to Displaying of the accounts list
+//--------------------------------------------------------
+int listaccount (char *param, int type)
+{
+//int list_first, list_last, list_type; // parameter to display a list of accounts
+    int  i;
+
+    list_type = type;
+
+    // set default values
+    list_first = 0;
+    list_last = 0;
+
+    if (list_type == 1)
+    {                           // if listgm
+        // get all accounts = use default
+    }
+    else if (list_type == 2)
+    {                           // if search
+        for (i = 0; param[i]; i++)
+            param[i] = tolower (param[i]);
+        // get all accounts = use default
+    }
+    else if (list_type == 3)
+    {                           // if listban
+        // get all accounts = use default
+    }
+    else if (list_type == 4)
+    {                           // if listok
+        // get all accounts = use default
+    }
+    else
+    {                           // if list (list_type == 0)
+        switch (sscanf (param, "%d %d", &list_first, &list_last))
+        {
+            case 0:
+                // get all accounts = use default
+                break;
+            case 1:
+                list_last = 0;
+                // use tests of the following value
+            default:
+                if (list_first < 0)
+                    list_first = 0;
+                if (list_last < list_first || list_last < 0)
+                    list_last = 0;
+                break;
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour obtenir la liste des comptes de %d à %d.\n",
+              list_first, list_last);
+    }
+    else
+    {
+        ladmin_log
+            ("Request to login-server to obtain the list of accounts from %d to %d.\n",
+              list_first, list_last);
+    }
+
+    WFIFOW (login_fd, 0) = 0x7920;
+    WFIFOL (login_fd, 2) = list_first;
+    WFIFOL (login_fd, 6) = list_last;
+    WFIFOSET (login_fd, 10);
+    bytes_to_read = 1;
+
+    //          0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
+    if (defaultlanguage == 'F')
+    {
+        Iprintf
+            (" id_compte GM nom_utilisateur         sexe   count statut\n");
+    }
+    else
+    {
+        Iprintf
+            ("account_id GM user_name               sex    count state\n");
+    }
+    Iprintf
+        ("-------------------------------------------------------------------------------\n");
+    list_count = 0;
+
+    return 0;
+}
+
+//--------------------------------------------------------
+// Sub-function: Frobnicate items
+//--------------------------------------------------------
+int itemfrob (char *param)
+{
+    int  source_id, dest_id;
+
+    if (sscanf (param, "%d %d", &source_id, &dest_id) < 2)
+    {
+        printf ("You must provide the source and destination item IDs.\n");
+        return 1;
+    }
+
+    WFIFOW (login_fd, 0) = 0x7924;
+    WFIFOL (login_fd, 2) = source_id;
+    WFIFOL (login_fd, 6) = dest_id;
+    WFIFOSET (login_fd, 10);
+    bytes_to_read = 1;          // all logging is done to the three main servers
+
+    return 0;
+}
+
+//--------------------------------------------
+// Sub-function: Asking to modify a memo field
+//--------------------------------------------
+int changememo (char *param)
+{
+    char name[1023], memo[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (memo, '\0', sizeof (memo));
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, memo) < 1 &&    // memo can be void
+        sscanf (param, "'%[^']' %[^\r\n]", name, memo) < 1 &&   // memo can be void
+        sscanf (param, "%s %[^\r\n]", name, memo) < 1)
+    {                           // memo can be void
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un mémo svp.\n");
+            printf ("<exemple> memo nomtest nouveau memo\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le mémo d'un compte (commande 'email').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a memo.\n");
+            printf ("<example> memo testname new memo\n");
+            ladmin_log
+                ("Incomplete parameters to change the memo of an account ('email' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (strlen (memo) > 254)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Mémo trop long (%d caractères).\n", strlen (memo));
+            printf ("Entrez un mémo de 254 caractères maximum svp.\n");
+            ladmin_log
+                ("Mémo trop long (%d caractères). Entrez un mémo de 254 caractères maximum svp.\n",
+                  strlen (memo));
+        }
+        else
+        {
+            printf ("Memo is too long (%d characters).\n", strlen (memo));
+            printf ("Please input a memo of 254 bytes at the maximum.\n");
+            ladmin_log
+                ("Email is too long (%d characters). Please input a memo of 254 bytes at the maximum.\n",
+                  strlen (memo));
+        }
+        return 102;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer un mémo.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change a memo.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7942;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOW (login_fd, 26) = strlen (memo);
+    if (strlen (memo) > 0)
+        memcpy (WFIFOP (login_fd, 28), memo, strlen (memo));
+    WFIFOSET (login_fd, 28 + strlen (memo));
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-----------------------------------------------
+// Sub-function: Asking to obtain an account name
+//-----------------------------------------------
+int nameaccount (int id)
+{
+    if (id < 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un id ayant une valeur positive svp.\n");
+            ladmin_log
+                ("Id négatif donné pour rechecher le nom d'un compte (commande 'name').\n");
+        }
+        else
+        {
+            printf ("Please input a positive value for the id.\n");
+            ladmin_log
+                ("Negativ id given to search an account name ('name' command).\n");
+        }
+        return 136;
+    }
+
+    if (defaultlanguage == 'F')
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour connaître le nom d'un compte.\n");
+    else
+        ladmin_log ("Request to login-server to know an account name.\n");
+
+    WFIFOW (login_fd, 0) = 0x7946;
+    WFIFOL (login_fd, 2) = id;
+    WFIFOSET (login_fd, 6);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//------------------------------------------
+// Sub-function: Asking to modify a password
+// (Note: never send back a password with login-server!! security of passwords)
+//------------------------------------------
+int changepasswd (char *param)
+{
+    char name[1023], password[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (password, '\0', sizeof (password));
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&
+        sscanf (param, "'%[^']' %[^\r\n]", name, password) < 1 &&
+        sscanf (param, "%s %[^\r\n]", name, password) < 1)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemple> passwd nomtest nouveaumotdepasse\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le mot d'un passe d'un compte (commande 'password').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<example> passwd testname newpassword\n");
+            ladmin_log
+                ("Incomplete parameters to change the password of an account ('password' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (strlen (password) == 0)
+    {
+        if (typepasswd (password) == 0)
+            return 134;
+    }
+    if (verify_password (password) == 0)
+        return 131;
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer un mot de passe.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change a password.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7934;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    memcpy (WFIFOP (login_fd, 26), password, 24);
+    WFIFOSET (login_fd, 50);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Sub-function: Request to login-server to reload GM configuration file
+// this function have no answer
+//----------------------------------------------------------------------
+int reloadGM (void)
+{
+    WFIFOW (login_fd, 0) = 0x7955;
+    WFIFOSET (login_fd, 2);
+    bytes_to_read = 0;
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Demande de recharger le fichier de configuration des GM envoyée.\n");
+        printf
+            ("Demande de recharger le fichier de configuration des GM envoyée.\n");
+        printf ("Vérifiez les comptes GM actuels (après rechargement):\n");
+    }
+    else
+    {
+        ladmin_log ("Request to reload the GM configuration file sended.\n");
+        printf ("Request to reload the GM configuration file sended.\n");
+        printf ("Check the actual GM accounts (after reloading):\n");
+    }
+    listaccount (parameters, 1);    // 1: to list only GM
+
+    return 180;
+}
+
+//-----------------------------------------------------
+// Sub-function: Asking to modify the sex of an account
+//-----------------------------------------------------
+int changesex (char *param)
+{
+    char name[1023], sex[1023];
+
+    memset (name, '\0', sizeof (name));
+    memset (sex, '\0', sizeof (sex));
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, sex) < 2 &&
+        sscanf (param, "'%[^']' %[^\r\n]", name, sex) < 2 &&
+        sscanf (param, "%s %[^\r\n]", name, sex) < 2)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un sexe svp.\n");
+            printf ("<exemple> sex nomtest Male\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le sexe d'un compte (commande 'sex').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a sex.\n");
+            printf ("<example> sex testname Male\n");
+            ladmin_log
+                ("Incomplete parameters to change the sex of an account ('sex' command).\n");
+        }
+        return 136;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    sex[0] = toupper (sex[0]);
+    if (strchr ("MF", sex[0]) == NULL)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Sexe incorrect [%s]. Entrez M ou F svp.\n", sex);
+            ladmin_log ("Sexe incorrect [%s]. Entrez M ou F svp.\n",
+                        sex);
+        }
+        else
+        {
+            printf ("Illegal gender [%s]. Please input M or F.\n", sex);
+            ladmin_log ("Illegal gender [%s]. Please input M or F.\n",
+                        sex);
+        }
+        return 103;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer un sexe.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change a sex.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x793c;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOB (login_fd, 26) = sex[0];
+    WFIFOSET (login_fd, 27);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-------------------------------------------------------------------------
+// Sub-function of sub-function changestate, blockaccount or unblockaccount
+// Asking to modify the state of an account
+//-------------------------------------------------------------------------
+int changestatesub (char *name, int state, char *error_message7)
+{
+    char error_message[1023];   // need to use, because we can modify error_message7
+
+    memset (error_message, '\0', sizeof (error_message));
+    strncpy (error_message, error_message7, sizeof (error_message) - 1);
+
+    if ((state < 0 || state > 9) && state != 100)
+    {                           // Valid values: 0: ok, or value of the 0x006a packet + 1
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez une des statuts suivantes svp:\n");
+            printf
+                ("  0 = Compte ok             6 = Your Game's EXE file is not the latest version\n");
+        }
+        else
+        {
+            printf ("Please input one of these states:\n");
+            printf
+                ("  0 = Account ok            6 = Your Game's EXE file is not the latest version\n");
+        }
+        printf
+            ("  1 = Unregistered ID       7 = You are Prohibited to log in until + message\n");
+        printf
+            ("  2 = Incorrect Password    8 = Server is jammed due to over populated\n");
+        printf ("  3 = This ID is expired    9 = No MSG\n");
+        printf
+            ("  4 = Rejected from Server  100 = This ID has been totally erased\n");
+        printf ("  5 = You have been blocked by the GM Team\n");
+        if (defaultlanguage == 'F')
+        {
+            printf ("<exemples> state nomtest 5\n");
+            printf ("           state nomtest 7 fin de votre ban\n");
+            printf ("           block <nom compte>\n");
+            printf ("           unblock <nom compte>\n");
+            ladmin_log
+                ("Valeur incorrecte pour le statut d'un compte (commande 'state', 'block' ou 'unblock').\n");
+        }
+        else
+        {
+            printf ("<examples> state testname 5\n");
+            printf ("           state testname 7 end of your ban\n");
+            printf ("           block <account name>\n");
+            printf ("           unblock <account name>\n");
+            ladmin_log
+                ("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n");
+        }
+        return 151;
+    }
+
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (state != 7)
+    {
+        strcpy (error_message, "-");
+    }
+    else
+    {
+        if (strlen (error_message) < 1)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Message d'erreur trop court. Entrez un message de 1-19 caractères.\n");
+                ladmin_log
+                    ("Message d'erreur trop court. Entrez un message de 1-19 caractères.\n");
+            }
+            else
+            {
+                printf
+                    ("Error message is too short. Please input a message of 1-19 bytes.\n");
+                ladmin_log
+                    ("Error message is too short. Please input a message of 1-19 bytes.\n");
+            }
+            return 102;
+        }
+        if (strlen (error_message) > 19)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Message d'erreur trop long. Entrez un message de 1-19 caractères.\n");
+                ladmin_log
+                    ("Message d'erreur trop long. Entrez un message de 1-19 caractères.\n");
+            }
+            else
+            {
+                printf
+                    ("Error message is too long. Please input a message of 1-19 bytes.\n");
+                ladmin_log
+                    ("Error message is too long. Please input a message of 1-19 bytes.\n");
+            }
+            return 102;
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour changer un statut.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to change a state.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7936;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOL (login_fd, 26) = state;
+    memcpy (WFIFOP (login_fd, 30), error_message, 20);
+    WFIFOSET (login_fd, 50);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-------------------------------------------------------
+// Sub-function: Asking to modify the state of an account
+//-------------------------------------------------------
+int changestate (char *param)
+{
+    char name[1023], error_message[1023];
+    int  state;
+
+    memset (name, '\0', sizeof (name));
+    memset (error_message, '\0', sizeof (error_message));
+
+    if (sscanf (param, "\"%[^\"]\" %d %[^\r\n]", name, &state, error_message)
+        < 2
+        && sscanf (param, "'%[^']' %d %[^\r\n]", name, &state,
+                   error_message) < 2
+        && sscanf (param, "%s %d %[^\r\n]", name, &state, error_message) < 2)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un statut svp.\n");
+            printf ("<exemples> state nomtest 5\n");
+            printf ("           state nomtest 7 fin de votre ban\n");
+            printf ("           block <nom compte>\n");
+            printf ("           unblock <nom compte>\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'state').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a state.\n");
+            printf ("<examples> state testname 5\n");
+            printf ("           state testname 7 end of your ban\n");
+            printf ("           block <account name>\n");
+            printf ("           unblock <account name>\n");
+            ladmin_log
+                ("Incomplete parameters to change the state of an account ('state' command).\n");
+        }
+        return 136;
+    }
+
+    return changestatesub (name, state, error_message);
+}
+
+//-------------------------------------------
+// Sub-function: Asking to unblock an account
+//-------------------------------------------
+int unblockaccount (char *param)
+{
+    char name[1023];
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemples> state nomtest 5\n");
+            printf ("           state nomtest 7 fin de votre ban\n");
+            printf ("           block <nom compte>\n");
+            printf ("           unblock <nom compte>\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'unblock').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<examples> state testname 5\n");
+            printf ("           state testname 7 end of your ban\n");
+            printf ("           block <account name>\n");
+            printf ("           unblock <account name>\n");
+            ladmin_log
+                ("Incomplete parameters to change the state of an account ('unblock' command).\n");
+        }
+        return 136;
+    }
+
+    return changestatesub (name, 0, "-");   // state 0, no error message
+}
+
+//-------------------------------------------
+// Sub-function: Asking to unblock an account
+//-------------------------------------------
+int blockaccount (char *param)
+{
+    char name[1023];
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemples> state nomtest 5\n");
+            printf ("           state nomtest 7 fin de votre ban\n");
+            printf ("           block <nom compte>\n");
+            printf ("           unblock <nom compte>\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour changer le statut d'un compte (commande 'block').\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<examples> state testname 5\n");
+            printf ("           state testname 7 end of your ban\n");
+            printf ("           block <account name>\n");
+            printf ("           unblock <account name>\n");
+            ladmin_log
+                ("Incomplete parameters to change the state of an account ('block' command).\n");
+        }
+        return 136;
+    }
+
+    return changestatesub (name, 5, "-");   // state 5, no error message
+}
+
+//---------------------------------------------------------------------
+// Sub-function: Add/substract time to the validity limit of an account
+//---------------------------------------------------------------------
+int timeaddaccount (char *param)
+{
+    char name[1023], modif[1023];
+    int  year, month, day, hour, minute, second;
+    char *p_modif;
+    int  value, i;
+
+    memset (name, '\0', sizeof (name));
+    memset (modif, '\0', sizeof (modif));
+    year = month = day = hour = minute = second = 0;
+
+    if (sscanf (param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
+        sscanf (param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
+        sscanf (param, "%s %[^\r\n]", name, modif) < 2)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte et un modificateur svp.\n");
+            printf ("  <exemple> timeadd nomtest +1m-2mn1s-6y\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour modifier une date limite d'utilisation (commande 'timeadd').\n");
+        }
+        else
+        {
+            printf ("Please input an account name and a modifier.\n");
+            printf ("  <example>: timeadd testname +1m-2mn1s-6y\n");
+            printf
+                ("             this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("             and 6 years at the same time.\n");
+            ladmin_log
+                ("Incomplete parameters to modify a limit time ('timeadd' command).\n");
+        }
+        return 136;
+    }
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    // lowercase for modif
+    for (i = 0; modif[i]; i++)
+        modif[i] = tolower (modif[i]);
+    p_modif = modif;
+    while (strlen (p_modif) > 0)
+    {
+        value = atoi (p_modif);
+        if (value == 0)
+        {
+            p_modif++;
+        }
+        else
+        {
+            if (p_modif[0] == '-' || p_modif[0] == '+')
+                p_modif++;
+            while (strlen (p_modif) > 0 && p_modif[0] >= '0'
+                   && p_modif[0] <= '9')
+            {
+                p_modif++;
+            }
+            if (p_modif[0] == 's')
+            {
+                second = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'm' && p_modif[1] == 'n')
+            {
+                minute = value;
+                p_modif += 2;
+            }
+            else if (p_modif[0] == 'h')
+            {
+                hour = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'd' || p_modif[0] == 'j')
+            {
+                day = value;
+                p_modif += 2;
+            }
+            else if (p_modif[0] == 'm')
+            {
+                month = value;
+                p_modif++;
+            }
+            else if (p_modif[0] == 'y' || p_modif[0] == 'a')
+            {
+                year = value;
+                p_modif++;
+            }
+            else
+            {
+                p_modif++;
+            }
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        printf (" année:   %d\n", year);
+        printf (" mois:    %d\n", month);
+        printf (" jour:    %d\n", day);
+        printf (" heure:   %d\n", hour);
+        printf (" minute:  %d\n", minute);
+        printf (" seconde: %d\n", second);
+    }
+    else
+    {
+        printf (" year:   %d\n", year);
+        printf (" month:  %d\n", month);
+        printf (" day:    %d\n", day);
+        printf (" hour:   %d\n", hour);
+        printf (" minute: %d\n", minute);
+        printf (" second: %d\n", second);
+    }
+
+    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
+        && second == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Vous devez entrer un ajustement avec cette commande, svp:\n");
+            printf ("  Valeur d'ajustement (-1, 1, +1, etc...)\n");
+            printf ("  Elément modifié:\n");
+            printf ("    a ou y: année\n");
+            printf ("    m:      mois\n");
+            printf ("    j ou d: jour\n");
+            printf ("    h:      heure\n");
+            printf ("    mn:     minute\n");
+            printf ("    s:      seconde\n");
+            printf ("  <exemple> timeadd nomtest +1m-2mn1s-6y\n");
+            printf
+                ("            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n");
+            printf ("            et 6 ans dans le même temps.\n");
+            ladmin_log
+                ("Aucun ajustement n'est pas un ajustement (commande 'timeadd').\n");
+        }
+        else
+        {
+            printf ("Please give an adjustment with this command:\n");
+            printf ("  Adjustment value (-1, 1, +1, etc...)\n");
+            printf ("  Modified element:\n");
+            printf ("    a or y: year\n");
+            printf ("    m:      month\n");
+            printf ("    j or d: day\n");
+            printf ("    h:      hour\n");
+            printf ("    mn:     minute\n");
+            printf ("    s:      second\n");
+            printf ("  <example> timeadd testname +1m-2mn1s-6y\n");
+            printf
+                ("            this example adds 1 month and 1 second, and substracts 2 minutes\n");
+            printf ("            and 6 years at the same time.\n");
+            ladmin_log
+                ("No adjustment isn't an adjustment ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (year > 127 || year < -127)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement d'années correct (de -127 à 127), svp.\n");
+            ladmin_log
+                ("Ajustement de l'année hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the years (from -127 to 127).\n");
+            ladmin_log
+                ("Abnormal adjustement for the year ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (month > 255 || month < -255)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de mois correct (de -255 à 255), svp.\n");
+            ladmin_log ("Ajustement du mois hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the months (from -255 to 255).\n");
+            ladmin_log
+                ("Abnormal adjustement for the month ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (day > 32767 || day < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n");
+            ladmin_log ("Ajustement des jours hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the days (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the days ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (hour > 32767 || hour < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des heures hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the hours ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (minute > 32767 || minute < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des minutes hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the minutes ('timeadd' command).\n");
+        }
+        return 137;
+    }
+    if (second > 32767 || second < -32767)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n");
+            ladmin_log
+                ("Ajustement des secondes hors norme ('timeadd' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
+            ladmin_log
+                ("Abnormal adjustement for the seconds ('timeadd' command).\n");
+        }
+        return 137;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour modifier une date limite d'utilisation.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to modify a time limit.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7950;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOW (login_fd, 26) = (short) year;
+    WFIFOW (login_fd, 28) = (short) month;
+    WFIFOW (login_fd, 30) = (short) day;
+    WFIFOW (login_fd, 32) = (short) hour;
+    WFIFOW (login_fd, 34) = (short) minute;
+    WFIFOW (login_fd, 36) = (short) second;
+    WFIFOSET (login_fd, 38);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//-------------------------------------------------
+// Sub-function: Set a validity limit of an account
+//-------------------------------------------------
+int timesetaccount (char *param)
+{
+    char name[1023], date[1023], time[1023];
+    int  year, month, day, hour, minute, second;
+    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+    struct tm *tmtime;
+
+    memset (name, '\0', sizeof (name));
+    memset (date, '\0', sizeof (date));
+    memset (time, '\0', sizeof (time));
+    year = month = day = hour = minute = second = 0;
+    connect_until_time = 0;
+    tmtime = localtime (&connect_until_time);   // initialize
+
+    if (sscanf (param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 &&   // if date = 0, time can be void
+        sscanf (param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 &&  // if date = 0, time can be void
+        sscanf (param, "%s %s %[^\r\n]", name, date, time) < 2)
+    {                           // if date = 0, time can be void
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte, une date et une heure svp.\n");
+            printf
+                ("<exemple>: timeset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n");
+            printf
+                ("           timeset <nom_du_compte> 0    (0 = illimité)\n");
+            printf ("           Heure par défaut [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Nombre incorrect de paramètres pour fixer une date limite d'utilisation (commande 'timeset').\n");
+        }
+        else
+        {
+            printf ("Please input an account name, a date and a hour.\n");
+            printf
+                ("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
+            printf
+                ("           timeset <account_name> 0   (0 = unlimited)\n");
+            printf ("           Default time [hh:mm:ss]: 23:59:59.\n");
+            ladmin_log
+                ("Incomplete parameters to set a limit time ('timeset' command).\n");
+        }
+        return 136;
+    }
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (time[0] == '\0')
+        strcpy (time, "23:59:59");
+
+    if (atoi (date) != 0 &&
+        ((sscanf (date, "%d/%d/%d", &year, &month, &day) < 3 &&
+          sscanf (date, "%d-%d-%d", &year, &month, &day) < 3 &&
+          sscanf (date, "%d.%d.%d", &year, &month, &day) < 3 &&
+          sscanf (date, "%d'%d'%d", &year, &month, &day) < 3) ||
+         sscanf (time, "%d:%d:%d", &hour, &minute, &second) < 3))
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n");
+            ladmin_log
+                ("Format incorrect pour la date/heure ('timeset' command).\n");
+        }
+        else
+        {
+            printf
+                ("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
+            ladmin_log
+                ("Invalid format for the date/time ('timeset' command).\n");
+        }
+        return 102;
+    }
+
+    if (atoi (date) == 0)
+    {
+        connect_until_time = 0;
+    }
+    else
+    {
+        if (year < 70)
+        {
+            year = year + 100;
+        }
+        if (year >= 1900)
+        {
+            year = year - 1900;
+        }
+        if (month < 1 || month > 12)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez un mois correct svp (entre 1 et 12).\n");
+                ladmin_log ("Mois incorrect pour la date ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the month (from 1 to 12).\n");
+                ladmin_log ("Invalid month for the date ('timeset' command).\n");
+            }
+            return 102;
+        }
+        month = month - 1;
+        if (day < 1 || day > 31)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez un jour correct svp (entre 1 et 31).\n");
+                ladmin_log ("Jour incorrect pour la date ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the day (from 1 to 31).\n");
+                ladmin_log ("Invalid day for the date ('timeset' command).\n");
+            }
+            return 102;
+        }
+        if (((month == 3 || month == 5 || month == 8 || month == 10)
+             && day > 30) || (month == 1 && day > 29))
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez un jour correct en fonction du mois (%d) svp.\n",
+                     month);
+                ladmin_log
+                    ("Jour incorrect pour ce mois correspondant ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for a day of this month (%d).\n",
+                     month);
+                ladmin_log ("Invalid day for this month ('timeset' command).\n");
+            }
+            return 102;
+        }
+        if (hour < 0 || hour > 23)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Entrez une heure correcte svp (entre 0 et 23).\n");
+                ladmin_log
+                    ("Heure incorrecte pour l'heure ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the hour (from 0 to 23).\n");
+                ladmin_log ("Invalid hour for the time ('timeset' command).\n");
+            }
+            return 102;
+        }
+        if (minute < 0 || minute > 59)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez des minutes correctes svp (entre 0 et 59).\n");
+                ladmin_log
+                    ("Minute incorrecte pour l'heure ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the minutes (from 0 to 59).\n");
+                ladmin_log ("Invalid minute for the time ('timeset' command).\n");
+            }
+            return 102;
+        }
+        if (second < 0 || second > 59)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf
+                    ("Entrez des secondes correctes svp (entre 0 et 59).\n");
+                ladmin_log
+                    ("Seconde incorrecte pour l'heure ('timeset' command).\n");
+            }
+            else
+            {
+                printf
+                    ("Please give a correct value for the seconds (from 0 to 59).\n");
+                ladmin_log ("Invalid second for the time ('timeset' command).\n");
+            }
+            return 102;
+        }
+        tmtime->tm_year = year;
+        tmtime->tm_mon = month;
+        tmtime->tm_mday = day;
+        tmtime->tm_hour = hour;
+        tmtime->tm_min = minute;
+        tmtime->tm_sec = second;
+        tmtime->tm_isdst = -1;  // -1: no winter/summer time modification
+        connect_until_time = timegm (tmtime);
+        if (connect_until_time == -1)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Date incorrecte.\n");
+                printf
+                    ("Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n");
+                ladmin_log ("Date incorrecte. ('timeset' command).\n");
+            }
+            else
+            {
+                printf ("Invalid date.\n");
+                printf
+                    ("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
+                ladmin_log ("Invalid date. ('timeset' command).\n");
+            }
+            return 102;
+        }
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour fixer une date limite d'utilisation.\n");
+    }
+    else
+    {
+        ladmin_log ("Request to login-server to set a time limit.\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7948;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOL (login_fd, 26) = (int) connect_until_time;
+    WFIFOSET (login_fd, 30);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//------------------------------------------------------------------------------
+// Sub-function: Asking to displaying information about an account (by its name)
+//------------------------------------------------------------------------------
+int whoaccount (char *param)
+{
+    char name[1023];
+
+    memset (name, '\0', sizeof (name));
+
+    if (strlen (param) == 0 ||
+        (sscanf (param, "\"%[^\"]\"", name) < 1 &&
+         sscanf (param, "'%[^']'", name) < 1 &&
+         sscanf (param, "%[^\r\n]", name) < 1) || strlen (name) == 0)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("Entrez un nom de compte svp.\n");
+            printf ("<exemple> who nomtest\n");
+            ladmin_log ("Aucun nom n'a été donné pour trouver le compte.\n");
+        }
+        else
+        {
+            printf ("Please input an account name.\n");
+            printf ("<example> who testname\n");
+            ladmin_log ("No name was given to found the account.\n");
+        }
+        return 136;
+    }
+    if (verify_accountname (name) == 0)
+    {
+        return 102;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour obtenir le information d'un compte (par le nom).\n");
+    }
+    else
+    {
+        ladmin_log
+            ("Request to login-server to obtain information about an account (by its name).\n");
+    }
+
+    WFIFOW (login_fd, 0) = 0x7952;
+    memcpy (WFIFOP (login_fd, 2), name, 24);
+    WFIFOSET (login_fd, 26);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//--------------------------------------------------------
+// Sub-function: Asking of the version of the login-server
+//--------------------------------------------------------
+int checkloginversion (void)
+{
+    if (defaultlanguage == 'F')
+        ladmin_log
+            ("Envoi d'un requête au serveur de logins pour obtenir sa version.\n");
+    else
+        ladmin_log ("Request to login-server to obtain its version.\n");
+
+    WFIFOW (login_fd, 0) = 0x7530;
+    WFIFOSET (login_fd, 2);
+    bytes_to_read = 1;
+
+    return 0;
+}
+
+//---------------------------------------------
+// Prompt function
+// this function wait until user type a command
+// and analyse the command.
+//---------------------------------------------
+int prompt (void)
+{
+    int  i, j;
+    char buf[1024];
+    char *p;
+
+    // while we don't wait new packets
+    while (bytes_to_read == 0)
+    {
+        // for help with the console colors look here:
+        // http://www.edoceo.com/liberum/?doc=printf-with-color
+        // some code explanation (used here):
+        // \033[2J : clear screen and go up/left (0, 0 position)
+        // \033[K  : clear line from actual position to end of the line
+        // \033[0m : reset color parameter
+        // \033[1m : use bold for font
+        Iprintf ("\n");
+        if (defaultlanguage == 'F')
+        {
+            Iprintf
+                ("\033[32mPour afficher les commandes, tapez 'Entrée'.\033[0m\n");
+        }
+        else
+            Iprintf ("\033[32mTo list the commands, type 'enter'.\033[0m\n");
+        Iprintf ("\033[0;36mLadmin-> \033[0m");
+        Iprintf ("\033[1m");
+        fflush (stdout);
+
+        // get command and parameter
+        memset (buf, '\0', sizeof (buf));
+        fflush (stdin);
+        if (!fgets (buf, 1023, stdin))
+            exit (0);
+        buf[1023] = '\0';
+
+        Iprintf ("\033[0m");
+        fflush (stdout);
+
+        if (!eathena_interactive_session && !strlen (buf))
+            exit (0);
+
+        // remove final \n
+        if ((p = strrchr (buf, '\n')) != NULL)
+            p[0] = '\0';
+        // remove all control char
+        for (i = 0; buf[i]; i++)
+            if (buf[i] < 32)
+            {
+                // remove cursor control.
+                if (buf[i] == 27 && buf[i + 1] == '[' && (buf[i + 2] == 'H' ||  // home position (cursor)
+                                                          buf[i + 2] == 'J' ||  // clear screen
+                                                          buf[i + 2] == 'A' ||  // up 1 line
+                                                          buf[i + 2] == 'B' ||  // down 1 line
+                                                          buf[i + 2] == 'C' ||  // right 1 position
+                                                          buf[i + 2] == 'D' ||  // left 1 position
+                                                          buf[i + 2] == 'G'))
+                {               // center cursor (windows)
+                    for (j = i; buf[j]; j++)
+                        buf[j] = buf[j + 3];
+                }
+                else if (buf[i] == 27 && buf[i + 1] == '['
+                         && buf[i + 2] == '2' && buf[i + 3] == 'J')
+                {               // clear screen
+                    for (j = i; buf[j]; j++)
+                        buf[j] = buf[j + 4];
+                }
+                else if (buf[i] == 27 && buf[i + 1] == '[' && buf[i + 3] == '~' && (buf[i + 2] == '1' ||    // home (windows)
+                                                                                    buf[i + 2] == '2' ||    // insert (windows)
+                                                                                    buf[i + 2] == '3' ||    // del (windows)
+                                                                                    buf[i + 2] == '4' ||    // end (windows)
+                                                                                    buf[i + 2] == '5' ||    // pgup (windows)
+                                                                                    buf
+                                                                                    [i
+                                                                                     +
+                                                                                     2]
+                                                                                    ==
+                                                                                    '6'))
+                {               // pgdown (windows)
+                    for (j = i; buf[j]; j++)
+                        buf[j] = buf[j + 4];
+                }
+                else
+                {
+                    // remove other control char.
+                    for (j = i; buf[j]; j++)
+                        buf[j] = buf[j + 1];
+                }
+                i--;
+            }
+
+        // extract command name and parameters
+        memset (command, '\0', sizeof (command));
+        memset (parameters, '\0', sizeof (parameters));
+        sscanf (buf, "%1023s %[^\n]", command, parameters);
+        command[1023] = '\0';
+        parameters[1023] = '\0';
+
+        // lowercase for command line
+        for (i = 0; command[i]; i++)
+            command[i] = tolower (command[i]);
+
+        if (command[0] == '?' || strlen (command) == 0)
+        {
+            if (defaultlanguage == 'F')
+            {
+                strcpy (buf, "aide");
+                strcpy (command, "aide");
+            }
+            else
+            {
+                strcpy (buf, "help");
+                strcpy (command, "help");
+            }
+        }
+
+        // Analyse of the command
+        check_command (command);    // give complete name to the command
+
+        if (strlen (parameters) == 0)
+        {
+            if (defaultlanguage == 'F')
+            {
+                ladmin_log ("Commande: '%s' (sans paramètre)\n",
+                            command, parameters);
+            }
+            else
+            {
+                ladmin_log ("Command: '%s' (without parameters)\n",
+                            command, parameters);
+            }
+        }
+        else
+        {
+            if (defaultlanguage == 'F')
+            {
+                ladmin_log ("Commande: '%s', paramètres: '%s'\n",
+                            command, parameters);
+            }
+            else
+            {
+                ladmin_log ("Command: '%s', parameters: '%s'\n",
+                            command, parameters);
+            }
+        }
+
+        // Analyse of the command
+// help
+        if (strcmp (command, "aide") == 0)
+        {
+            display_help (parameters, 1);   // 1: french
+        }
+        else if (strcmp (command, "help") == 0)
+        {
+            display_help (parameters, 0);   // 0: english
+// general commands
+        }
+        else if (strcmp (command, "add") == 0)
+        {
+            addaccount (parameters, 0); // 0: no email
+        }
+        else if (strcmp (command, "ban") == 0)
+        {
+            banaccount (parameters);
+        }
+        else if (strcmp (command, "banadd") == 0)
+        {
+            banaddaccount (parameters);
+        }
+        else if (strcmp (command, "banset") == 0)
+        {
+            bansetaccount (parameters);
+        }
+        else if (strcmp (command, "block") == 0)
+        {
+            blockaccount (parameters);
+        }
+        else if (strcmp (command, "check") == 0)
+        {
+            checkaccount (parameters);
+        }
+        else if (strcmp (command, "create") == 0)
+        {
+            addaccount (parameters, 1); // 1: with email
+        }
+        else if (strcmp (command, "delete") == 0)
+        {
+            delaccount (parameters);
+        }
+        else if (strcmp (command, "email") == 0)
+        {
+            changeemail (parameters);
+        }
+        else if (strcmp (command, "getcount") == 0)
+        {
+            getlogincount ();
+        }
+        else if (strcmp (command, "gm") == 0)
+        {
+            changegmlevel (parameters);
+        }
+        else if (strcmp (command, "id") == 0)
+        {
+            idaccount (parameters);
+        }
+        else if (strcmp (command, "info") == 0)
+        {
+            infoaccount (atoi (parameters));
+        }
+        else if (strcmp (command, "kami") == 0)
+        {
+            sendbroadcast (0, parameters);  // flag for normal
+        }
+        else if (strcmp (command, "kamib") == 0)
+        {
+            sendbroadcast (0x10, parameters);   // flag for blue
+        }
+        else if (strcmp (command, "language") == 0)
+        {
+            changelanguage (parameters);
+        }
+        else if (strcmp (command, "itemfrob") == 0)
+        {
+            itemfrob (parameters);  // 0: to list all
+        }
+        else if (strcmp (command, "list") == 0)
+        {
+            listaccount (parameters, 0);    // 0: to list all
+        }
+        else if (strcmp (command, "listban") == 0)
+        {
+            listaccount (parameters, 3);    // 3: to list only accounts with state or bannished
+        }
+        else if (strcmp (command, "listgm") == 0)
+        {
+            listaccount (parameters, 1);    // 1: to list only GM
+        }
+        else if (strcmp (command, "listok") == 0)
+        {
+            listaccount (parameters, 4);    // 4: to list only accounts without state and not bannished
+        }
+        else if (strcmp (command, "memo") == 0)
+        {
+            changememo (parameters);
+        }
+        else if (strcmp (command, "name") == 0)
+        {
+            nameaccount (atoi (parameters));
+        }
+        else if (strcmp (command, "password") == 0)
+        {
+            changepasswd (parameters);
+        }
+        else if (strcmp (command, "reloadgm") == 0)
+        {
+            reloadGM ();
+        }
+        else if (strcmp (command, "search") == 0)
+        {                       // no regex in C version
+            listaccount (parameters, 2);    // 2: to list with pattern
+        }
+        else if (strcmp (command, "sex") == 0)
+        {
+            changesex (parameters);
+        }
+        else if (strcmp (command, "state") == 0)
+        {
+            changestate (parameters);
+        }
+        else if (strcmp (command, "timeadd") == 0)
+        {
+            timeaddaccount (parameters);
+        }
+        else if (strcmp (command, "timeset") == 0)
+        {
+            timesetaccount (parameters);
+        }
+        else if (strcmp (command, "unban") == 0)
+        {
+            unbanaccount (parameters);
+        }
+        else if (strcmp (command, "unblock") == 0)
+        {
+            unblockaccount (parameters);
+        }
+        else if (strcmp (command, "version") == 0)
+        {
+            checkloginversion ();
+        }
+        else if (strcmp (command, "who") == 0)
+        {
+            whoaccount (parameters);
+// quit
+        }
+        else if (strcmp (command, "quit") == 0 ||
+                 strcmp (command, "exit") == 0 ||
+                 strcmp (command, "end") == 0)
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Au revoir.\n");
+            }
+            else
+            {
+                printf ("Bye.\n");
+            }
+            exit (0);
+// unknown command
+        }
+        else
+        {
+            if (defaultlanguage == 'F')
+            {
+                printf ("Commande inconnue [%s].\n", buf);
+                ladmin_log ("Commande inconnue [%s].\n", buf);
+            }
+            else
+            {
+                printf ("Unknown command [%s].\n", buf);
+                ladmin_log ("Unknown command [%s].\n", buf);
+            }
+        }
+    }
+
+    return 0;
+}
+
+//-------------------------------------------------------------
+// Function: Parse receiving informations from the login-server
+//-------------------------------------------------------------
+void parse_fromlogin (int fd)
+{
+    struct char_session_data *sd;
+
+    if (session[fd]->eof)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf
+                ("Impossible de se connecter au serveur de login [%s:%d] !\n",
+                 loginserverip, loginserverport);
+            ladmin_log
+                ("Impossible de se connecter au serveur de login [%s:%d] !\n",
+                  loginserverip, loginserverport);
+        }
+        else
+        {
+            printf
+                ("Impossible to have a connection with the login-server [%s:%d] !\n",
+                 loginserverip, loginserverport);
+            ladmin_log
+                ("Impossible to have a connection with the login-server [%s:%d] !\n",
+                  loginserverip, loginserverport);
+        }
+        close (fd);
+        delete_session (fd);
+        exit (0);
+    }
+
+//  printf("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
+    sd = (struct char_session_data *)session[fd]->session_data;
+
+    while (RFIFOREST (fd) >= 2)
+    {
+        switch (RFIFOW (fd, 0))
+        {
+            case 0x7919:       // answer of a connection request
+                if (RFIFOREST (fd) < 3)
+                    return;
+                if (RFIFOB (fd, 2) != 0)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Erreur de login:\n");
+                        printf (" - mot de passe incorrect,\n");
+                        printf
+                            (" - système d'administration non activé, ou\n");
+                        printf (" - IP non autorisée.\n");
+                        ladmin_log
+                            ("Erreur de login: mot de passe incorrect, système d'administration non activé, ou IP non autorisée.\n");
+                    }
+                    else
+                    {
+                        printf ("Error at login:\n");
+                        printf (" - incorrect password,\n");
+                        printf
+                            (" - administration system not activated, or\n");
+                        printf (" - unauthorised IP.\n");
+                        ladmin_log
+                            ("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n");
+                    }
+                    session[fd]->eof = 1;
+                    //bytes_to_read = 1; // not stop at prompt
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Connexion établie.\n");
+                        ladmin_log ("Connexion établie.\n");
+                        printf
+                            ("Lecture de la version du serveur de login...\n");
+                        ladmin_log
+                            ("Lecture de la version du serveur de login...\n");
+                    }
+                    else
+                    {
+                        Iprintf ("Established connection.\n");
+                        ladmin_log ("Established connection.\n");
+                        Iprintf
+                            ("Reading of the version of the login-server...\n");
+                        ladmin_log
+                            ("Reading of the version of the login-server...\n");
+                    }
+                    //bytes_to_read = 1; // unchanged
+                    checkloginversion ();
+                }
+                RFIFOSKIP (fd, 3);
+                break;
+
+#ifdef PASSWORDENC
+            case 0x01dc:       // answer of a coding key request
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    char md5str[64] =
+                        "", md5bin[32], md5key[RFIFOW (fd, 2) - 4 + 1];
+                    memcpy (md5key, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
+                    md5key[sizeof (md5key) - 1] = '0';
+                    if (passenc == 1)
+                    {
+                        strncpy (md5str, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
+                        strcat (md5str, loginserveradminpassword);
+                    }
+                    else if (passenc == 2)
+                    {
+                        strncpy (md5str, loginserveradminpassword,
+                                 sizeof (loginserveradminpassword));
+                        strcat (md5str, RFIFOP (fd, 4));
+                    }
+                    MD5_to_bin(MD5_from_cstring(md5str), md5bin);
+                    WFIFOW (login_fd, 0) = 0x7918;  // Request for administation login (encrypted password)
+                    WFIFOW (login_fd, 2) = passenc; // Encrypted type
+                    memcpy (WFIFOP (login_fd, 4), md5bin, 16);
+                    WFIFOSET (login_fd, 20);
+                    if (defaultlanguage == 'F')
+                    {
+                        Iprintf ("Réception de la clef MD5.\n");
+                        ladmin_log ("Réception de la clef MD5.\n");
+                        Iprintf ("Envoi du mot de passe crypté...\n");
+                        ladmin_log ("Envoi du mot de passe crypté...\n");
+                    }
+                    else
+                    {
+                        Iprintf ("Receiving of the MD5 key.\n");
+                        ladmin_log ("Receiving of the MD5 key.\n");
+                        Iprintf ("Sending of the encrypted password...\n");
+                        ladmin_log ("Sending of the encrypted password...\n");
+                    }
+                }
+                bytes_to_read = 1;
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+#endif
+
+            case 0x7531:       // Displaying of the version of the login-server
+                if (RFIFOREST (fd) < 10)
+                    return;
+                Iprintf ("  Login-Server [%s:%d]\n", loginserverip,
+                         loginserverport);
+                if (((int) RFIFOB (login_fd, 5)) == 0)
+                {
+                    Iprintf ("  eAthena version stable-%d.%d",
+                             (int) RFIFOB (login_fd, 2),
+                             (int) RFIFOB (login_fd, 3));
+                }
+                else
+                {
+                    Iprintf ("  eAthena version dev-%d.%d",
+                             (int) RFIFOB (login_fd, 2),
+                             (int) RFIFOB (login_fd, 3));
+                }
+                if (((int) RFIFOB (login_fd, 4)) == 0)
+                    Iprintf (" revision %d", (int) RFIFOB (login_fd, 4));
+                if (((int) RFIFOB (login_fd, 6)) == 0)
+                {
+                    Iprintf ("%d.\n", RFIFOW (login_fd, 8));
+                }
+                else
+                    Iprintf ("-mod%d.\n", RFIFOW (login_fd, 8));
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 10);
+                break;
+
+            case 0x7925:       // Itemfrob-OK
+                RFIFOSKIP (fd, 2);
+                bytes_to_read = 0;
+                break;
+
+            case 0x7921:       // Displaying of the list of accounts
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                if (RFIFOW (fd, 2) < 5)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        ladmin_log
+                            ("  Réception d'une liste des comptes vide.\n");
+                        if (list_count == 0)
+                            printf ("Aucun compte trouvé.\n");
+                        else if (list_count == 1)
+                            printf ("1 compte trouvé.\n");
+                        else
+                            printf ("%d comptes trouvés.\n", list_count);
+                    }
+                    else
+                    {
+                        ladmin_log ("  Receiving of a void accounts list.\n");
+                        if (list_count == 0)
+                        {
+                            Iprintf ("No account found.\n");
+                        }
+                        else if (list_count == 1)
+                        {
+                            Iprintf ("1 account found.\n");
+                        }
+                        else
+                            Iprintf ("%d accounts found.\n", list_count);
+                    }
+                    bytes_to_read = 0;
+                }
+                else
+                {
+                    int  i;
+                    if (defaultlanguage == 'F')
+                        ladmin_log ("  Réception d'une liste des comptes.\n");
+                    else
+                        ladmin_log ("  Receiving of a accounts list.\n");
+                    for (i = 4; i < RFIFOW (fd, 2); i += 38)
+                    {
+                        int  j;
+                        char userid[24];
+                        char lower_userid[24];
+                        memcpy (userid, RFIFOP (fd, i + 5), sizeof (userid));
+                        userid[sizeof (userid) - 1] = '\0';
+                        memset (lower_userid, '\0', sizeof (lower_userid));
+                        for (j = 0; userid[j]; j++)
+                            lower_userid[j] = tolower (userid[j]);
+                        list_first = RFIFOL (fd, i) + 1;
+                        // here are checks...
+                        if (list_type == 0 ||
+                            (list_type == 1 && RFIFOB (fd, i + 4) > 0) ||
+                            (list_type == 2
+                             && strstr (lower_userid, parameters) != NULL)
+                            || (list_type == 3 && RFIFOL (fd, i + 34) != 0)
+                            || (list_type == 4 && RFIFOL (fd, i + 34) == 0))
+                        {
+                            printf ("%10d ", RFIFOL (fd, i));
+                            if (RFIFOB (fd, i + 4) == 0)
+                                printf ("   ");
+                            else
+                                printf ("%2d ", (int) RFIFOB (fd, i + 4));
+                            printf ("%-24s", userid);
+                            if (defaultlanguage == 'F')
+                            {
+                                if (RFIFOB (fd, i + 29) == 0)
+                                    printf ("%-5s ", "Femme");
+                                else if (RFIFOB (fd, i + 29) == 1)
+                                    printf ("%-5s ", "Male");
+                                else
+                                    printf ("%-5s ", "Servr");
+                            }
+                            else
+                            {
+                                if (RFIFOB (fd, i + 29) == 0)
+                                    printf ("%-5s ", "Femal");
+                                else if (RFIFOB (fd, i + 29) == 1)
+                                    printf ("%-5s ", "Male");
+                                else
+                                    printf ("%-5s ", "Servr");
+                            }
+                            printf ("%6d ", RFIFOL (fd, i + 30));
+                            switch (RFIFOL (fd, i + 34))
+                            {
+                                case 0:
+                                    if (defaultlanguage == 'F')
+                                        printf ("%-27s\n", "Compte Ok");
+                                    else
+                                        printf ("%-27s\n", "Account OK");
+                                    break;
+                                case 1:
+                                    printf ("%-27s\n", "Unregistered ID");
+                                    break;
+                                case 2:
+                                    printf ("%-27s\n", "Incorrect Password");
+                                    break;
+                                case 3:
+                                    printf ("%-27s\n", "This ID is expired");
+                                    break;
+                                case 4:
+                                    printf ("%-27s\n",
+                                            "Rejected from Server");
+                                    break;
+                                case 5:
+                                    printf ("%-27s\n", "Blocked by the GM Team");   // You have been blocked by the GM Team
+                                    break;
+                                case 6:
+                                    printf ("%-27s\n", "Your EXE file is too old"); // Your Game's EXE file is not the latest version
+                                    break;
+                                case 7:
+                                    printf ("%-27s\n", "Banishement or");
+                                    printf ("                                                   Prohibited to login until...\n");   // You are Prohibited to log in until %s
+                                    break;
+                                case 8:
+                                    printf ("%-27s\n",
+                                            "Server is over populated");
+                                    break;
+                                case 9:
+                                    printf ("%-27s\n", "No MSG");
+                                    break;
+                                default:   // 100
+                                    printf ("%-27s\n", "This ID is totally erased");    // This ID has been totally erased
+                                    break;
+                            }
+                            list_count++;
+                        }
+                    }
+                    // asking of the following acounts
+                    if (defaultlanguage == 'F')
+                        ladmin_log
+                            ("Envoi d'un requête au serveur de logins pour obtenir la liste des comptes de %d à %d (complément).\n",
+                              list_first, list_last);
+                    else
+                        ladmin_log
+                            ("Request to login-server to obtain the list of accounts from %d to %d (complement).\n",
+                              list_first, list_last);
+                    WFIFOW (login_fd, 0) = 0x7920;
+                    WFIFOL (login_fd, 2) = list_first;
+                    WFIFOL (login_fd, 6) = list_last;
+                    WFIFOSET (login_fd, 10);
+                    bytes_to_read = 1;
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+            case 0x7931:       // Answer of login-server about an account creation
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec à la création du compte [%s]. Un compte identique existe déjà.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec à la création du compte [%s]. Un compte identique existe déjà.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] creation failed. Same account already exists.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] creation failed. Same account already exists.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Compte [%s] créé avec succès [id: %d].\n",
+                                RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log ("Compte [%s] créé avec succès [id: %d].\n",
+                                     RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] is successfully created [id: %d].\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s] is successfully created [id: %d].\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7933:       // Answer of login-server about an account deletion
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de la suppression du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec de la suppression du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] deletion failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] deletion failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Compte [%s][id: %d] SUPPRIME avec succès.\n",
+                                RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Compte [%s][id: %d] SUPPRIME avec succès.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] is successfully DELETED.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] is successfully DELETED.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7935:       // answer of the change of an account password
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de la modification du mot de passe du compte [%s].\n",
+                             RFIFOP (fd, 6));
+                        printf ("Le compte [%s] n'existe pas.\n",
+                                RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec de la modification du mot de passe du compte. Le compte [%s] n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf ("Account [%s] password changing failed.\n",
+                                RFIFOP (fd, 6));
+                        printf ("Account [%s] doesn't exist.\n",
+                                RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account password changing failed. The compte [%s] doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Modification du mot de passe du compte [%s][id: %d] réussie.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Modification du mot de passe du compte [%s][id: %d] réussie.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] password successfully changed.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] password successfully changed.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7937:       // answer of the change of an account state
+                if (RFIFOREST (fd) < 34)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement du statut du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement du statut du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] state changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] state changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    char tmpstr[256];
+                    if (defaultlanguage == 'F')
+                    {
+                        sprintf (tmpstr,
+                                 "Statut du compte [%s] changé avec succès en [",
+                                 RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        sprintf (tmpstr,
+                                 "Account [%s] state successfully changed in [",
+                                 RFIFOP (fd, 6));
+                    }
+                    switch (RFIFOL (fd, 30))
+                    {
+                        case 0:
+                            if (defaultlanguage == 'F')
+                                strcat (tmpstr, "0: Compte Ok");
+                            else
+                                strcat (tmpstr, "0: Account OK");
+                            break;
+                        case 1:
+                            strcat (tmpstr, "1: Unregistered ID");
+                            break;
+                        case 2:
+                            strcat (tmpstr, "2: Incorrect Password");
+                            break;
+                        case 3:
+                            strcat (tmpstr, "3: This ID is expired");
+                            break;
+                        case 4:
+                            strcat (tmpstr, "4: Rejected from Server");
+                            break;
+                        case 5:
+                            strcat (tmpstr,
+                                    "5: You have been blocked by the GM Team");
+                            break;
+                        case 6:
+                            strcat (tmpstr,
+                                    "6: [Your Game's EXE file is not the latest version");
+                            break;
+                        case 7:
+                            strcat (tmpstr,
+                                    "7: You are Prohibited to log in until...");
+                            break;
+                        case 8:
+                            strcat (tmpstr,
+                                    "8: Server is jammed due to over populated");
+                            break;
+                        case 9:
+                            strcat (tmpstr, "9: No MSG");
+                            break;
+                        default:   // 100
+                            strcat (tmpstr, "100: This ID is totally erased");
+                            break;
+                    }
+                    strcat (tmpstr, "]");
+                    printf ("%s\n", tmpstr);
+                    ladmin_log ("%s%s", tmpstr, "\n");
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 34);
+                break;
+
+            case 0x7939:       // answer of the number of online players
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    // Get length of the received packet
+                    int  i;
+                    char name[20];
+                    if (defaultlanguage == 'F')
+                    {
+                        ladmin_log
+                            ("  Réception du nombre de joueurs en ligne.\n");
+                    }
+                    else
+                    {
+                        ladmin_log
+                            ("  Receiving of the number of online players.\n");
+                    }
+                    // Read information of the servers
+                    if (RFIFOW (fd, 2) < 5)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("  Aucun serveur n'est connecté au login serveur.\n");
+                        }
+                        else
+                        {
+                            printf
+                                ("  No server is connected to the login-server.\n");
+                        }
+                    }
+                    else
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("  Nombre de joueurs en ligne (serveur: nb):\n");
+                        }
+                        else
+                        {
+                            printf
+                                ("  Number of online players (server: number).\n");
+                        }
+                        // Displaying of result
+                        for (i = 4; i < RFIFOW (fd, 2); i += 32)
+                        {
+                            memcpy (name, RFIFOP (fd, i + 6), sizeof (name));
+                            name[sizeof (name) - 1] = '\0';
+                            printf ("    %-20s : %5d\n", name,
+                                    RFIFOW (fd, i + 26));
+                        }
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+            case 0x793b:       // answer of the check of a password
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Le compte [%s] n'existe pas ou le mot de passe est incorrect.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Le compte [%s] n'existe pas ou le mot de passe est incorrect.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("The account [%s] doesn't exist or the password is incorrect.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("The account [%s] doesn't exist or the password is incorrect.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Le mot de passe donné correspond bien au compte [%s][id: %d].\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Le mot de passe donné correspond bien au compte [%s][id: %d].\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("The proposed password is correct for the account [%s][id: %d].\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("The proposed password is correct for the account [%s][id: %d].\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x793d:       // answer of the change of an account sex
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de la modification du sexe du compte [%s].\n",
+                             RFIFOP (fd, 6));
+                        printf
+                            ("Le compte [%s] n'existe pas ou le sexe est déjà celui demandé.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec de la modification du sexe du compte. Le compte [%s] n'existe pas ou le sexe est déjà celui demandé.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf ("Account [%s] sex changing failed.\n",
+                                RFIFOP (fd, 6));
+                        printf
+                            ("Account [%s] doesn't exist or the sex is already the good sex.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Sexe du compte [%s][id: %d] changé avec succès.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Sexe du compte [%s][id: %d] changé avec succès.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] sex successfully changed.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] sex successfully changed.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x793f:       // answer of the change of an account GM level
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de la modification du niveau de GM du compte [%s].\n",
+                             RFIFOP (fd, 6));
+                        printf
+                            ("Le compte [%s] n'existe pas, le niveau de GM est déjà celui demandé\n",
+                             RFIFOP (fd, 6));
+                        printf
+                            ("ou il est impossible de modifier le fichier des comptes GM.\n");
+                        ladmin_log
+                            ("Echec de la modification du niveau de GM du compte. Le compte [%s] n'existe pas, le niveau de GM est déjà celui demandé ou il est impossible de modifier le fichier des comptes GM.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf ("Account [%s] GM level changing failed.\n",
+                                RFIFOP (fd, 6));
+                        printf
+                            ("Account [%s] doesn't exist, the GM level is already the good GM level\n",
+                             RFIFOP (fd, 6));
+                        printf
+                            ("or it's impossible to modify the GM accounts file.\n");
+                        ladmin_log
+                            ("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Niveau de GM du compte [%s][id: %d] changé avec succès.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Niveau de GM du compte [%s][id: %d] changé avec succès.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] GM level successfully changed.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] GM level successfully changed.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7941:       // answer of the change of an account email
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de la modification de l'e-mail du compte [%s].\n",
+                             RFIFOP (fd, 6));
+                        printf ("Le compte [%s] n'existe pas.\n",
+                                RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec de la modification de l'e-mail du compte. Le compte [%s] n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf ("Account [%s] e-mail changing failed.\n",
+                                RFIFOP (fd, 6));
+                        printf ("Account [%s] doesn't exist.\n",
+                                RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account e-mail changing failed. The compte [%s] doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Modification de l'e-mail du compte [%s][id: %d] réussie.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Modification de l'e-mail du compte [%s][id: %d] réussie.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] e-mail successfully changed.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] e-mail successfully changed.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7943:       // answer of the change of an account memo
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement du mémo du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement du mémo du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] memo changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] memo changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Mémo du compte [%s][id: %d] changé avec succès.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Mémo du compte [%s][id: %d] changé avec succès.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s][id: %d] memo successfully changed.\n",
+                             RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Account [%s][id: %d] memo successfully changed.\n",
+                              RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7945:       // answer of an account id search
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Impossible de trouver l'id du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Impossible de trouver l'id du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Unable to find the account [%s] id. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Unable to find the account [%s] id. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Le compte [%s] a pour id: %d.\n",
+                                RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log ("Le compte [%s] a pour id: %d.\n",
+                                    RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf ("The account [%s] have the id: %d.\n",
+                                RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        ladmin_log ("The account [%s] have the id: %d.\n",
+                                     RFIFOP (fd, 6), RFIFOL (fd, 2));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7947:       // answer of an account name search
+                if (RFIFOREST (fd) < 30)
+                    return;
+                if (strcmp (RFIFOP (fd, 6), "") == 0)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas.\n",
+                             RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Impossible de trouver le nom du compte [%d]. Le compte n'existe pas.\n",
+                              RFIFOL (fd, 2));
+                    }
+                    else
+                    {
+                        printf
+                            ("Unable to find the account [%d] name. Account doesn't exist.\n",
+                             RFIFOL (fd, 2));
+                        ladmin_log
+                            ("Unable to find the account [%d] name. Account doesn't exist.\n",
+                              RFIFOL (fd, 2));
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf ("Le compte [id: %d] a pour nom: %s.\n",
+                                RFIFOL (fd, 2), RFIFOP (fd, 6));
+                        ladmin_log ("Le compte [id: %d] a pour nom: %s.\n",
+                                     RFIFOL (fd, 2), RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf ("The account [id: %d] have the name: %s.\n",
+                                RFIFOL (fd, 2), RFIFOP (fd, 6));
+                        ladmin_log ("The account [id: %d] have the name: %s.\n",
+                                     RFIFOL (fd, 2), RFIFOP (fd, 6));
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x7949:       // answer of an account validity limit set
+                if (RFIFOREST (fd) < 34)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    time_t timestamp = RFIFOL (fd, 30);
+                    if (timestamp == 0)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès en [illimité].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès en [illimité].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                        else
+                        {
+                            printf
+                                ("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                    }
+                    else
+                    {
+                        char tmpstr[128];
+                        strftime (tmpstr, 24, date_format,
+                                  localtime (&timestamp));
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                        else
+                        {
+                            printf
+                                ("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 34);
+                break;
+
+            case 0x794b:       // answer of an account ban set
+                if (RFIFOREST (fd) < 34)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    time_t timestamp = RFIFOL (fd, 30);
+                    if (timestamp == 0)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                        else
+                        {
+                            printf
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                    }
+                    else
+                    {
+                        char tmpstr[128];
+                        strftime (tmpstr, 24, date_format,
+                                  localtime (&timestamp));
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                        else
+                        {
+                            printf
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 34);
+                break;
+
+            case 0x794d:       // answer of an account ban date/time changing
+                if (RFIFOREST (fd) < 34)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement de la date finale de banissement du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] final date of banishment changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    time_t timestamp = RFIFOL (fd, 30);
+                    if (timestamp == 0)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès en [dé-bannie].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                        else
+                        {
+                            printf
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            ladmin_log
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                    }
+                    else
+                    {
+                        char tmpstr[128];
+                        strftime (tmpstr, 24, date_format,
+                                  localtime (&timestamp));
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Date finale de banissement du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                        else
+                        {
+                            printf
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 34);
+                break;
+
+            case 0x794f:       // answer of a broadcast
+                if (RFIFOREST (fd) < 4)
+                    return;
+                if (RFIFOW (fd, 2) == (unsigned short) -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec de l'envoi du message. Aucun server de char en ligne.\n");
+                        ladmin_log
+                            ("Echec de l'envoi du message. Aucun server de char en ligne.\n");
+                    }
+                    else
+                    {
+                        printf
+                            ("Message sending failed. No online char-server.\n");
+                        ladmin_log
+                            ("Message sending failed. No online char-server.\n");
+                    }
+                }
+                else
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Message transmis au server de logins avec succès.\n");
+                        ladmin_log
+                            ("Message transmis au server de logins avec succès.\n");
+                    }
+                    else
+                    {
+                        printf
+                            ("Message successfully sended to login-server.\n");
+                        ladmin_log
+                            ("Message successfully sended to login-server.\n");
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 4);
+                break;
+
+            case 0x7951:       // answer of an account validity limit changing
+                if (RFIFOREST (fd) < 34)
+                    return;
+                if (RFIFOL (fd, 2) == -1)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        printf
+                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Echec du changement de la validité du compte [%s]. Le compte n'existe pas.\n",
+                              RFIFOP (fd, 6));
+                    }
+                    else
+                    {
+                        printf
+                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
+                             RFIFOP (fd, 6));
+                        ladmin_log
+                            ("Account [%s] validity limit changing failed. Account doesn't exist.\n",
+                              RFIFOP (fd, 6));
+                    }
+                }
+                else
+                {
+                    time_t timestamp = RFIFOL (fd, 30);
+                    if (timestamp == 0)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Limite de validité du compte [%s][id: %d] inchangée.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            printf
+                                ("Le compte a une validité illimitée ou\n");
+                            printf
+                                ("la modification est impossible avec les ajustements demandés.\n");
+                            ladmin_log
+                                ("Limite de validité du compte [%s][id: %d] inchangée. Le compte a une validité illimitée ou la modification est impossible avec les ajustements demandés.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                        else
+                        {
+                            printf
+                                ("Validity limit of the account [%s][id: %d] unchanged.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2));
+                            printf
+                                ("The account have an unlimited validity limit or\n");
+                            printf
+                                ("the changing is impossible with the proposed adjustments.\n");
+                            ladmin_log
+                                ("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2));
+                        }
+                    }
+                    else
+                    {
+                        char tmpstr[128];
+                        strftime (tmpstr, 24, date_format,
+                                  localtime (&timestamp));
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Limite de validité du compte [%s][id: %d] changée avec succès pour être jusqu'au %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                        else
+                        {
+                            printf
+                                ("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                 RFIFOP (fd, 6), RFIFOL (fd, 2), tmpstr);
+                            ladmin_log
+                                ("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n",
+                                  RFIFOP (fd, 6), RFIFOL (fd, 2),
+                                 tmpstr);
+                        }
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 34);
+                break;
+
+            case 0x7953:       // answer of a request about informations of an account (by account name/id)
+                if (RFIFOREST (fd) < 150
+                    || RFIFOREST (fd) < (150 + RFIFOW (fd, 148)))
+                    return;
+                {
+                    char userid[24], error_message[20], lastlogin[24],
+                        last_ip[16], email[40], memo[255];
+                    time_t ban_until_time;  // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
+                    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+                    memcpy (userid, RFIFOP (fd, 7), sizeof (userid));
+                    userid[sizeof (userid) - 1] = '\0';
+                    memcpy (error_message, RFIFOP (fd, 40),
+                            sizeof (error_message));
+                    error_message[sizeof (error_message) - 1] = '\0';
+                    memcpy (lastlogin, RFIFOP (fd, 60), sizeof (lastlogin));
+                    lastlogin[sizeof (lastlogin) - 1] = '\0';
+                    memcpy (last_ip, RFIFOP (fd, 84), sizeof (last_ip));
+                    last_ip[sizeof (last_ip) - 1] = '\0';
+                    memcpy (email, RFIFOP (fd, 100), sizeof (email));
+                    email[sizeof (email) - 1] = '\0';
+                    connect_until_time = (time_t) RFIFOL (fd, 140);
+                    ban_until_time = (time_t) RFIFOL (fd, 144);
+                    memset (memo, '\0', sizeof (memo));
+                    strncpy (memo, RFIFOP (fd, 150), RFIFOW (fd, 148));
+                    if (RFIFOL (fd, 2) == -1)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Impossible de trouver le compte [%s]. Le compte n'existe pas.\n",
+                                 parameters);
+                            ladmin_log
+                                ("Impossible de trouver le compte [%s]. Le compte n'existe pas.\n",
+                                  parameters);
+                        }
+                        else
+                        {
+                            printf
+                                ("Unabled to find the account [%s]. Account doesn't exist.\n",
+                                 parameters);
+                            ladmin_log
+                                ("Unabled to find the account [%s]. Account doesn't exist.\n",
+                                  parameters);
+                        }
+                    }
+                    else if (strlen (userid) == 0)
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            printf
+                                ("Impossible de trouver le compte [id: %s]. Le compte n'existe pas.\n",
+                                 parameters);
+                            ladmin_log
+                                ("Impossible de trouver le compte [id: %s]. Le compte n'existe pas.\n",
+                                  parameters);
+                        }
+                        else
+                        {
+                            printf
+                                ("Unabled to find the account [id: %s]. Account doesn't exist.\n",
+                                 parameters);
+                            ladmin_log
+                                ("Unabled to find the account [id: %s]. Account doesn't exist.\n",
+                                  parameters);
+                        }
+                    }
+                    else
+                    {
+                        if (defaultlanguage == 'F')
+                        {
+                            ladmin_log
+                                ("Réception d'information concernant un compte.\n");
+                            printf
+                                ("Le compte a les caractéristiques suivantes:\n");
+                        }
+                        else
+                        {
+                            ladmin_log
+                                ("Receiving information about an account.\n");
+                            printf ("The account is set with:\n");
+                        }
+                        if (RFIFOB (fd, 6) == 0)
+                        {
+                            printf (" Id:     %d (non-GM)\n", RFIFOL (fd, 2));
+                        }
+                        else
+                        {
+                            if (defaultlanguage == 'F')
+                            {
+                                printf (" Id:     %d (GM niveau %d)\n",
+                                        RFIFOL (fd, 2), (int) RFIFOB (fd, 6));
+                            }
+                            else
+                            {
+                                printf (" Id:     %d (GM level %d)\n",
+                                        RFIFOL (fd, 2), (int) RFIFOB (fd, 6));
+                            }
+                        }
+                        if (defaultlanguage == 'F')
+                        {
+                            printf (" Nom:    '%s'\n", userid);
+                            if (RFIFOB (fd, 31) == 0)
+                                printf (" Sexe:   Femme\n");
+                            else if (RFIFOB (fd, 31) == 1)
+                                printf (" Sexe:   Male\n");
+                            else
+                                printf (" Sexe:   Serveur\n");
+                        }
+                        else
+                        {
+                            printf (" Name:   '%s'\n", userid);
+                            if (RFIFOB (fd, 31) == 0)
+                                printf (" Sex:    Female\n");
+                            else if (RFIFOB (fd, 31) == 1)
+                                printf (" Sex:    Male\n");
+                            else
+                                printf (" Sex:    Server\n");
+                        }
+                        printf (" E-mail: %s\n", email);
+                        switch (RFIFOL (fd, 36))
+                        {
+                            case 0:
+                                if (defaultlanguage == 'F')
+                                    printf (" Statut: 0 [Compte Ok]\n");
+                                else
+                                    printf (" Statut: 0 [Account OK]\n");
+                                break;
+                            case 1:
+                                printf (" Statut: 1 [Unregistered ID]\n");
+                                break;
+                            case 2:
+                                printf (" Statut: 2 [Incorrect Password]\n");
+                                break;
+                            case 3:
+                                printf (" Statut: 3 [This ID is expired]\n");
+                                break;
+                            case 4:
+                                printf
+                                    (" Statut: 4 [Rejected from Server]\n");
+                                break;
+                            case 5:
+                                printf
+                                    (" Statut: 5 [You have been blocked by the GM Team]\n");
+                                break;
+                            case 6:
+                                printf
+                                    (" Statut: 6 [Your Game's EXE file is not the latest version]\n");
+                                break;
+                            case 7:
+                                printf
+                                    (" Statut: 7 [You are Prohibited to log in until %s]\n",
+                                     error_message);
+                                break;
+                            case 8:
+                                printf
+                                    (" Statut: 8 [Server is jammed due to over populated]\n");
+                                break;
+                            case 9:
+                                printf (" Statut: 9 [No MSG]\n");
+                                break;
+                            default:   // 100
+                                printf
+                                    (" Statut: %d [This ID is totally erased]\n",
+                                     RFIFOL (fd, 36));
+                                break;
+                        }
+                        if (defaultlanguage == 'F')
+                        {
+                            if (ban_until_time == 0)
+                            {
+                                printf (" Banissement: non banni.\n");
+                            }
+                            else
+                            {
+                                char tmpstr[128];
+                                strftime (tmpstr, 24, date_format,
+                                          localtime (&ban_until_time));
+                                printf (" Banissement: jusqu'au %s.\n",
+                                        tmpstr);
+                            }
+                            if (RFIFOL (fd, 32) > 1)
+                                printf (" Compteur: %d connexions.\n",
+                                        RFIFOL (fd, 32));
+                            else
+                                printf (" Compteur: %d connexion.\n",
+                                        RFIFOL (fd, 32));
+                            printf (" Dernière connexion le: %s (ip: %s)\n",
+                                    lastlogin, last_ip);
+                            if (connect_until_time == 0)
+                            {
+                                printf (" Limite de validité: illimité.\n");
+                            }
+                            else
+                            {
+                                char tmpstr[128];
+                                strftime (tmpstr, 24, date_format,
+                                          localtime (&connect_until_time));
+                                printf (" Limite de validité: jusqu'au %s.\n",
+                                        tmpstr);
+                            }
+                        }
+                        else
+                        {
+                            if (ban_until_time == 0)
+                            {
+                                printf (" Banishment: not banished.\n");
+                            }
+                            else
+                            {
+                                char tmpstr[128];
+                                strftime (tmpstr, 24, date_format,
+                                          localtime (&ban_until_time));
+                                printf (" Banishment: until %s.\n", tmpstr);
+                            }
+                            if (RFIFOL (fd, 32) > 1)
+                                printf (" Count:  %d connections.\n",
+                                        RFIFOL (fd, 32));
+                            else
+                                printf (" Count:  %d connection.\n",
+                                        RFIFOL (fd, 32));
+                            printf (" Last connection at: %s (ip: %s)\n",
+                                    lastlogin, last_ip);
+                            if (connect_until_time == 0)
+                            {
+                                printf (" Validity limit: unlimited.\n");
+                            }
+                            else
+                            {
+                                char tmpstr[128];
+                                strftime (tmpstr, 24, date_format,
+                                          localtime (&connect_until_time));
+                                printf (" Validity limit: until %s.\n",
+                                        tmpstr);
+                            }
+                        }
+                        printf (" Memo:   '%s'\n", memo);
+                    }
+                }
+                bytes_to_read = 0;
+                RFIFOSKIP (fd, 150 + RFIFOW (fd, 148));
+                break;
+
+            default:
+                printf
+                    ("Remote administration has been disconnected (unknown packet).\n");
+                ladmin_log ("'End of connection, unknown packet.\n");
+                session[fd]->eof = 1;
+                return;
+        }
+    }
+
+    // if we don't wait new packets, do the prompt
+    prompt ();
+}
+
+//------------------------------------
+// Function to connect to login-server
+//------------------------------------
+int Connect_login_server (void)
+{
+    if (defaultlanguage == 'F')
+    {
+        Iprintf ("Essai de connection au server de logins...\n");
+        ladmin_log ("Essai de connection au server de logins...\n");
+    }
+    else
+    {
+        Iprintf ("Attempt to connect to login-server...\n");
+        ladmin_log ("Attempt to connect to login-server...\n");
+    }
+
+    if ((login_fd = make_connection (login_ip, loginserverport)) < 0)
+        return 0;
+
+#ifdef PASSWORDENC
+    if (passenc == 0)
+    {
+#endif
+        WFIFOW (login_fd, 0) = 0x7918;  // Request for administation login
+        WFIFOW (login_fd, 2) = 0;   // no encrypted
+        memcpy (WFIFOP (login_fd, 4), loginserveradminpassword, 24);
+        WFIFOSET (login_fd, 28);
+        bytes_to_read = 1;
+
+        if (defaultlanguage == 'F')
+        {
+            Iprintf ("Envoi du mot de passe...\n");
+            ladmin_log ("Envoi du mot de passe...\n");
+        }
+        else
+        {
+            Iprintf ("Sending of the password...\n");
+            ladmin_log ("Sending of the password...\n");
+        }
+#ifdef PASSWORDENC
+    }
+    else
+    {
+        WFIFOW (login_fd, 0) = 0x791a;  // Sending request about the coding key
+        WFIFOSET (login_fd, 2);
+        bytes_to_read = 1;
+        if (defaultlanguage == 'F')
+        {
+            Iprintf ("Demande de la clef MD5...\n");
+            ladmin_log ("Demande de la clef MD5...\n");
+        }
+        else
+        {
+            Iprintf ("Request about the MD5 key...\n");
+            ladmin_log ("Request about the MD5 key...\n");
+        }
+    }
+#endif
+
+    return 0;
+}
+
+//-------------------------------------------------
+// Return numerical value of a switch configuration
+// on/off, english, français, deutsch, español
+//-------------------------------------------------
+int config_switch (const char *str)
+{
+    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
+        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
+        || strcasecmp (str, "si") == 0)
+        return 1;
+    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
+        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
+        return 0;
+
+    return atoi (str);
+}
+
+//-----------------------------------
+// Reading general configuration file
+//-----------------------------------
+int ladmin_config_read (const char *cfgName)
+{
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        if (defaultlanguage == 'F')
+        {
+            printf ("\033[0mFichier de configuration (%s) non trouvé.\n",
+                    cfgName);
+        }
+        else
+        {
+            printf ("\033[0mConfiguration file (%s) not found.\n", cfgName);
+        }
+        return 1;
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        Iprintf
+            ("\033[0m---Début de lecture du fichier de configuration Ladmin (%s)\n",
+             cfgName);
+    }
+    else
+    {
+        Iprintf
+            ("\033[0m---Start reading of Ladmin configuration file (%s)\n",
+             cfgName);
+    }
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        line[sizeof (line) - 1] = '\0';
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
+        {
+            remove_control_chars (w1);
+            remove_control_chars (w2);
+
+            if (strcasecmp (w1, "login_ip") == 0)
+            {
+                struct hostent *h = gethostbyname (w2);
+                if (h != NULL)
+                {
+                    if (defaultlanguage == 'F')
+                    {
+                        Iprintf
+                            ("Adresse du serveur de logins: %s -> %d.%d.%d.%d\n",
+                             w2, (unsigned char) h->h_addr[0],
+                             (unsigned char) h->h_addr[1],
+                             (unsigned char) h->h_addr[2],
+                             (unsigned char) h->h_addr[3]);
+                    }
+                    else
+                    {
+                        Iprintf
+                            ("Login server IP address: %s -> %d.%d.%d.%d\n",
+                             w2, (unsigned char) h->h_addr[0],
+                             (unsigned char) h->h_addr[1],
+                             (unsigned char) h->h_addr[2],
+                             (unsigned char) h->h_addr[3]);
+                    }
+                    sprintf (loginserverip, "%d.%d.%d.%d",
+                             (unsigned char) h->h_addr[0],
+                             (unsigned char) h->h_addr[1],
+                             (unsigned char) h->h_addr[2],
+                             (unsigned char) h->h_addr[3]);
+                }
+                else
+                    memcpy (loginserverip, w2, 16);
+            }
+            else if (strcasecmp (w1, "login_port") == 0)
+            {
+                loginserverport = atoi (w2);
+            }
+            else if (strcasecmp (w1, "admin_pass") == 0)
+            {
+                strncpy (loginserveradminpassword, w2,
+                         sizeof (loginserveradminpassword));
+                loginserveradminpassword[sizeof (loginserveradminpassword) -
+                                         1] = '\0';
+#ifdef PASSWORDENC
+            }
+            else if (strcasecmp (w1, "passenc") == 0)
+            {
+                passenc = atoi (w2);
+                if (passenc < 0 || passenc > 2)
+                    passenc = 0;
+#endif
+            }
+            else if (strcasecmp (w1, "defaultlanguage") == 0)
+            {
+                if (w2[0] == 'F' || w2[0] == 'E')
+                    defaultlanguage = w2[0];
+            }
+            else if (strcasecmp (w1, "ladmin_log_filename") == 0)
+            {
+                strncpy (ladmin_log_filename, w2,
+                         sizeof (ladmin_log_filename));
+                ladmin_log_filename[sizeof (ladmin_log_filename) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "date_format") == 0)
+            {                   // note: never have more than 19 char for the date!
+                switch (atoi (w2))
+                {
+                    case 0:
+                        strcpy (date_format, "%d-%m-%Y %H:%M:%S");  // 31-12-2004 23:59:59
+                        break;
+                    case 1:
+                        strcpy (date_format, "%m-%d-%Y %H:%M:%S");  // 12-31-2004 23:59:59
+                        break;
+                    case 2:
+                        strcpy (date_format, "%Y-%d-%m %H:%M:%S");  // 2004-31-12 23:59:59
+                        break;
+                    case 3:
+                        strcpy (date_format, "%Y-%m-%d %H:%M:%S");  // 2004-12-31 23:59:59
+                        break;
+                }
+            }
+            else if (strcasecmp (w1, "import") == 0)
+            {
+                ladmin_config_read (w2);
+            }
+        }
+    }
+    fclose_ (fp);
+
+    login_ip = inet_addr (loginserverip);
+
+    if (defaultlanguage == 'F')
+    {
+        Iprintf ("---Lecture du fichier de configuration Ladmin terminée.\n");
+    }
+    else
+    {
+        Iprintf ("---End reading of Ladmin configuration file.\n");
+    }
+
+    return 0;
+}
+
+//--------------------------------------
+// Function called at exit of the server
+//--------------------------------------
+void term_func (void)
+{
+
+    if (already_exit_function == 0)
+    {
+        delete_session (login_fd);
+
+        if (defaultlanguage == 'F')
+        {
+            Iprintf
+                ("\033[0m----Fin de Ladmin (fin normale avec fermeture de tous les fichiers).\n");
+            ladmin_log
+                ("----Fin de Ladmin (fin normale avec fermeture de tous les fichiers).\n");
+        }
+        else
+        {
+            Iprintf
+                ("\033[0m----End of Ladmin (normal end with closing of all files).\n");
+            ladmin_log
+                ("----End of Ladmin (normal end with closing of all files).\n");
+        }
+
+        already_exit_function = 1;
+    }
+}
+
+//------------------------
+// Main function of ladmin
+//------------------------
+int do_init (int argc, char **argv)
+{
+    eathena_interactive_session = isatty (0);
+    // read ladmin configuration
+    ladmin_config_read ((argc > 1) ? argv[1] : LADMIN_CONF_NAME);
+
+    ladmin_log ("");
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log ("Fichier de configuration lu.\n");
+    }
+    else
+    {
+        ladmin_log ("Configuration file readed.\n");
+    }
+
+    srand (time (NULL));
+
+    set_defaultparse (parse_fromlogin);
+
+    if (defaultlanguage == 'F')
+    {
+        Iprintf ("Outil d'administration à distance de eAthena.\n");
+        Iprintf ("(pour eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION,
+                 ATHENA_MINOR_VERSION, ATHENA_REVISION);
+    }
+    else
+    {
+        Iprintf ("EAthena login-server administration tool.\n");
+        Iprintf ("(for eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION,
+                 ATHENA_MINOR_VERSION, ATHENA_REVISION);
+    }
+
+    if (defaultlanguage == 'F')
+    {
+        ladmin_log ("Ladmin est prêt.\n");
+        Iprintf ("Ladmin est \033[1;32mprêt\033[0m.\n\n");
+    }
+    else
+    {
+        ladmin_log ("Ladmin is ready.\n");
+        Iprintf ("Ladmin is \033[1;32mready\033[0m.\n\n");
+    }
+
+    Connect_login_server ();
+
+    return 0;
+}
diff --git a/src/ladmin/ladmin.h b/src/ladmin/ladmin.h
deleted file mode 100644
index dc1efe6..0000000
--- a/src/ladmin/ladmin.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// $Id: ladmin.h,v 1.1.1.1 2004/09/10 17:26:52 MagicalTux Exp $
-#ifndef _LADMIN_H_
-#define _LADMIN_H_
-
-#define LADMIN_CONF_NAME	"conf/ladmin_athena.conf"
-#define PASSWORDENC		3       // A definition is given when making an encryption password correspond.
-                            // It is 1 at the time of passwordencrypt.
-                            // It is made into 2 at the time of passwordencrypt2.
-                            // When it is made 3, it corresponds to both.
-
-#endif
diff --git a/src/ladmin/ladmin.hpp b/src/ladmin/ladmin.hpp
new file mode 100644
index 0000000..77d7fe4
--- /dev/null
+++ b/src/ladmin/ladmin.hpp
@@ -0,0 +1,11 @@
+// $Id: ladmin.h,v 1.1.1.1 2004/09/10 17:26:52 MagicalTux Exp $
+#ifndef LADMIN_HPP
+#define LADMIN_HPP
+
+#define LADMIN_CONF_NAME	"conf/ladmin_athena.conf"
+#define PASSWORDENC		3       // A definition is given when making an encryption password correspond.
+                            // It is 1 at the time of passwordencrypt.
+                            // It is made into 2 at the time of passwordencrypt2.
+                            // When it is made 3, it corresponds to both.
+
+#endif
diff --git a/src/login/login.c b/src/login/login.c
deleted file mode 100644
index cd46049..0000000
--- a/src/login/login.c
+++ /dev/null
@@ -1,5038 +0,0 @@
-// $Id: login.c,v 1.1.1.1 2004/09/10 17:26:53 MagicalTux Exp $
-// new version of the login-server by [Yor]
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <sys/time.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>           // for stat/lstat/fstat
-#include <unistd.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/wait.h>
-
-#include "../common/core.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "login.h"
-#include "../common/mmo.h"
-#include "../common/version.h"
-#include "../common/db.h"
-#include "../common/lock.h"
-#include "../common/mt_rand.h"
-
-#include "../common/md5calc.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-int  account_id_count = START_ACCOUNT_NUM;
-int  server_num;
-int  new_account_flag = 0;
-int  login_port = 6900;
-char lan_char_ip[16];
-int  subneti[4];
-int  subnetmaski[4];
-char update_host[128] = "";
-char main_server[20] = "";
-
-char account_filename[1024] = "save/account.txt";
-char GM_account_filename[1024] = "conf/GM_account.txt";
-char login_log_filename[1024] = "log/login.log";
-char login_log_unknown_packets_filename[1024] =
-    "log/login_unknown_packets.log";
-char date_format[32] = "%Y-%m-%d %H:%M:%S";
-int  save_unknown_packets = 0;
-long creation_time_GM_account_file;
-int  gm_account_filename_check_timer = 15;  // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15)
-
-int  display_parse_login = 0;   // 0: no, 1: yes
-int  display_parse_admin = 0;   // 0: no, 1: yes
-int  display_parse_fromchar = 0;    // 0: no, 1: yes (without packet 0x2714), 2: all packets
-
-struct mmo_char_server server[MAX_SERVERS];
-int  server_fd[MAX_SERVERS];
-int  server_freezeflag[MAX_SERVERS];    // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
-int  anti_freeze_enable = 0;
-int  ANTI_FREEZE_INTERVAL = 15;
-
-int  login_fd;
-
-enum
-{
-    ACO_DENY_ALLOW = 0,
-    ACO_ALLOW_DENY,
-    ACO_MUTUAL_FAILTURE,
-    ACO_STRSIZE = 128,
-};
-
-int  access_order = ACO_DENY_ALLOW;
-int  access_allownum = 0;
-int  access_denynum = 0;
-char *access_allow = NULL;
-char *access_deny = NULL;
-
-int  access_ladmin_allownum = 0;
-char *access_ladmin_allow = NULL;
-
-int  min_level_to_connect = 0;  // minimum level of player/GM (0: player, 1-99: gm) to connect on the server
-int  add_to_unlimited_account = 0;  // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account.
-int  start_limited_time = -1;   // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now)
-int  check_ip_flag = 1;         // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
-
-struct login_session_data
-{
-    int  md5keylen;
-    char md5key[20];
-};
-
-#define AUTH_FIFO_SIZE 256
-struct
-{
-    int  account_id, login_id1, login_id2;
-    int  ip, sex, delflag;
-} auth_fifo[AUTH_FIFO_SIZE];
-int  auth_fifo_pos = 0;
-
-struct auth_dat
-{
-    int  account_id, sex;
-    char userid[24], pass[40], lastlogin[24];
-    int  logincount;
-    int  state;                 // packet 0x006a value + 1 (0: compte OK)
-    char email[40];             // e-mail (by default: a@a.com)
-    char error_message[20];     // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
-    time_t ban_until_time;      // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-    char last_ip[16];           // save of last IP of connection
-    char memo[255];             // a memo field
-    int  account_reg2_num;
-    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
-}   *auth_dat;
-
-int  auth_num = 0, auth_max = 0;
-
-int  admin_state = 0;
-char admin_pass[24] = "";
-char gm_pass[64] = "";
-int  level_new_gm = 60;
-
-static struct dbt *gm_account_db;
-
-pid_t pid = 0; // For forked DB writes
-
-
-#define VERSION_2_UPDATEHOST 0x01   // client supports updatehost
-#define VERSION_2_SERVERORDER 0x02  // send servers in forward order
-//------------------------------
-// Writing function of logs file
-//------------------------------
-int login_log (char *fmt, ...)
-{
-    FILE *logfp;
-    va_list ap;
-    struct timeval tv;
-    char tmpstr[2048];
-
-    va_start (ap, fmt);
-
-    logfp = fopen_ (login_log_filename, "a");
-    if (logfp)
-    {
-        if (fmt[0] == '\0')     // jump a line if no message
-            fprintf (logfp, "\n");
-        else
-        {
-            gettimeofday (&tv, NULL);
-            strftime (tmpstr, 24, date_format, gmtime (&(tv.tv_sec)));
-            sprintf (tmpstr + strlen (tmpstr), ".%03d: %s",
-                     (int) tv.tv_usec / 1000, fmt);
-            vfprintf (logfp, tmpstr, ap);
-        }
-        fclose_ (logfp);
-    }
-
-    va_end (ap);
-    return 0;
-}
-
-//----------------------------------------------------------------------
-// Determine if an account (id) is a GM account
-// and returns its level (or 0 if it isn't a GM account or if not found)
-//----------------------------------------------------------------------
-int isGM (int account_id)
-{
-    struct gm_account *p = (struct gm_account*) numdb_search (gm_account_db, account_id);
-    if (p == NULL)
-        return 0;
-    return p->level;
-}
-
-//-------------------------------------------------------
-// Reading function of GM accounts file (and their level)
-//-------------------------------------------------------
-int read_gm_account (void)
-{
-    char line[512];
-    struct gm_account *p;
-    FILE *fp;
-    int  c = 0;
-    int  GM_level;
-    struct stat file_stat;
-
-    free (gm_account_db);
-    gm_account_db = numdb_init ();
-
-    // get last modify time/date
-    if (stat (GM_account_filename, &file_stat))
-        creation_time_GM_account_file = 0;  // error
-    else
-        creation_time_GM_account_file = file_stat.st_mtime;
-
-    if ((fp = fopen_ (GM_account_filename, "r")) == NULL)
-    {
-        printf ("read_gm_account: GM accounts file [%s] not found.\n",
-                GM_account_filename);
-        printf
-            ("                 Actually, there is no GM accounts on the server.\n");
-        login_log ("read_gm_account: GM accounts file [%s] not found.\n",
-                   GM_account_filename);
-        login_log
-            ("                 Actually, there is no GM accounts on the server.\n");
-        return 1;
-    }
-    // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???)
-    // int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
-    while (fgets (line, sizeof (line) - 1, fp) && c < 4000)
-    {
-        if ((line[0] == '/' && line[1] == '/') || line[0] == '\0'
-            || line[0] == '\n' || line[0] == '\r')
-            continue;
-        CREATE (p, struct gm_account, 1);
-        if (sscanf (line, "%d %d", &p->account_id, &p->level) != 2
-            && sscanf (line, "%d: %d", &p->account_id, &p->level) != 2)
-            printf
-                ("read_gm_account: file [%s], invalid 'id_acount level' format.\n",
-                 GM_account_filename);
-        else if (p->level <= 0)
-            printf
-                ("read_gm_account: file [%s] %dth account (invalid level [0 or negative]: %d).\n",
-                 GM_account_filename, c + 1, p->level);
-        else
-        {
-            if (p->level > 99)
-            {
-                printf
-                    ("read_gm_account: file [%s] %dth account (invalid level, but corrected: %d->99).\n",
-                     GM_account_filename, c + 1, p->level);
-                p->level = 99;
-            }
-            if ((GM_level = isGM (p->account_id)) > 0)
-            {                   // if it's not a new account
-                if (GM_level == p->level)
-                    printf
-                        ("read_gm_account: GM account %d defined twice (same level: %d).\n",
-                         p->account_id, p->level);
-                else
-                    printf
-                        ("read_gm_account: GM account %d defined twice (levels: %d and %d).\n",
-                         p->account_id, GM_level, p->level);
-            }
-            if (GM_level != p->level)
-            {                   // if new account or new level
-                numdb_insert (gm_account_db, p->account_id, p);
-                //printf("GM account:%d, level: %d->%d\n", p->account_id, GM_level, p->level);
-                if (GM_level == 0)
-                {               // if new account
-                    c++;
-                    if (c >= 4000)
-                    {
-                        printf
-                            ("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
-                        login_log
-                            ("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
-                    }
-                }
-            }
-        }
-    }
-    fclose_ (fp);
-
-    printf ("read_gm_account: file '%s' readed (%d GM accounts found).\n",
-            GM_account_filename, c);
-    login_log ("read_gm_account: file '%s' readed (%d GM accounts found).\n",
-               GM_account_filename, c);
-
-    return 0;
-}
-
-//--------------------------------------------------------------
-// Test of the IP mask
-// (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
-//--------------------------------------------------------------
-int check_ipmask (unsigned int ip, const unsigned char *str)
-{
-    unsigned int mask = 0, i = 0, m, ip2, a0, a1, a2, a3;
-    unsigned char *p = (unsigned char *) &ip2, *p2 = (unsigned char *) &mask;
-
-    if (sscanf (str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0)
-        return 0;
-    p[0] = a0;
-    p[1] = a1;
-    p[2] = a2;
-    p[3] = a3;
-
-    if (sscanf (str + i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4)
-    {
-        p2[0] = a0;
-        p2[1] = a1;
-        p2[2] = a2;
-        p2[3] = a3;
-        mask = ntohl (mask);
-    }
-    else if (sscanf (str + i, "%d", &m) == 1 && m >= 0 && m <= 32)
-    {
-        for (i = 0; i < m && i < 32; i++)
-            mask = (mask >> 1) | 0x80000000;
-    }
-    else
-    {
-        printf ("check_ipmask: invalid mask [%s].\n", str);
-        return 0;
-    }
-
-//  printf("Tested IP: %08x, network: %08x, network mask: %08x\n",
-//         (unsigned int)ntohl(ip), (unsigned int)ntohl(ip2), (unsigned int)mask);
-    return ((ntohl (ip) & mask) == (ntohl (ip2) & mask));
-}
-
-//---------------------
-// Access control by IP
-//---------------------
-int check_ip (unsigned int ip)
-{
-    int  i;
-    unsigned char *p = (unsigned char *) &ip;
-    char buf[32];
-    enum
-    { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
-
-    if (access_allownum == 0 && access_denynum == 0)
-        return 1;               // When there is no restriction, all IP are authorised.
-
-//  +   012.345.: front match form, or
-//      all: all IP are matched, or
-//      012.345.678.901/24: network form (mask with # of bits), or
-//      012.345.678.901/255.255.255.0: network form (mask with ip mask)
-//  +   Note about the DNS resolution (like www.ne.jp, etc.):
-//      There is no guarantee to have an answer.
-//      If we have an answer, there is no guarantee to have a 100% correct value.
-//      And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
-//      So, DNS notation isn't authorised for ip checking.
-    sprintf (buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
-
-    for (i = 0; i < access_allownum; i++)
-    {
-        const char *p = access_allow + i * ACO_STRSIZE;
-        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
-        {
-            flag = ACF_ALLOW;
-            if (access_order == ACO_ALLOW_DENY)
-                return 1;       // With 'allow, deny' (deny if not allow), allow has priority
-            break;
-        }
-    }
-
-    for (i = 0; i < access_denynum; i++)
-    {
-        const char *p = access_deny + i * ACO_STRSIZE;
-        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
-        {
-            flag = ACF_DENY;
-            return 0;           // At this point, if it's 'deny', we refuse connection.
-            break;
-        }
-    }
-
-    return (flag == ACF_ALLOW || access_order == ACO_DENY_ALLOW) ? 1 : 0;
-    // With 'mutual-failture', only 'allow' and non 'deny' IP are authorised.
-    //   A non 'allow' (even non 'deny') IP is not authorised. It's like: if allowed and not denied, it's authorised.
-    //   So, it's disapproval if you have no description at the time of 'mutual-failture'.
-    // With 'deny,allow' (allow if not deny), because here it's not deny, we authorise.
-}
-
-//--------------------------------
-// Access control by IP for ladmin
-//--------------------------------
-int check_ladminip (unsigned int ip)
-{
-    int  i;
-    unsigned char *p = (unsigned char *) &ip;
-    char buf[32];
-
-    if (access_ladmin_allownum == 0)
-        return 1;               // When there is no restriction, all IP are authorised.
-
-//  +   012.345.: front match form, or
-//      all: all IP are matched, or
-//      012.345.678.901/24: network form (mask with # of bits), or
-//      012.345.678.901/255.255.255.0: network form (mask with ip mask)
-//  +   Note about the DNS resolution (like www.ne.jp, etc.):
-//      There is no guarantee to have an answer.
-//      If we have an answer, there is no guarantee to have a 100% correct value.
-//      And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
-//      So, DNS notation isn't authorised for ip checking.
-    sprintf (buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
-
-    for (i = 0; i < access_ladmin_allownum; i++)
-    {
-        const char *p = access_ladmin_allow + i * ACO_STRSIZE;
-        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
-        {
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars (unsigned char *str)
-{
-    int  i;
-    int  change = 0;
-
-    for (i = 0; str[i]; i++)
-    {
-        if (str[i] < 32)
-        {
-            str[i] = '_';
-            change = 1;
-        }
-    }
-
-    return change;
-}
-
-//---------------------------------------------------
-// E-mail check: return 0 (not correct) or 1 (valid).
-//---------------------------------------------------
-int e_mail_check (unsigned char *email)
-{
-    char ch;
-    unsigned char *last_arobas;
-
-    // athena limits
-    if (strlen (email) < 3 || strlen (email) > 39)
-        return 0;
-
-    // part of RFC limits (official reference of e-mail description)
-    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
-        return 0;
-
-    if (email[strlen (email) - 1] == '.')
-        return 0;
-
-    last_arobas = strrchr (email, '@');
-
-    if (strstr (last_arobas, "@.") != NULL ||
-        strstr (last_arobas, "..") != NULL)
-        return 0;
-
-    for (ch = 1; ch < 32; ch++)
-    {
-        if (strchr (last_arobas, ch) != NULL)
-        {
-            return 0;
-            break;
-        }
-    }
-
-    if (strchr (last_arobas, ' ') != NULL ||
-        strchr (last_arobas, ';') != NULL)
-        return 0;
-
-    // all correct
-    return 1;
-}
-
-//-----------------------------------------------
-// Search an account id
-//   (return account index or -1 (if not found))
-//   If exact account name is not found,
-//   the function checks without case sensitive
-//   and returns index if only 1 account is found
-//   and similar to the searched name.
-//-----------------------------------------------
-int search_account_index (char *account_name)
-{
-    int  i, quantity, index;
-
-    quantity = 0;
-    index = -1;
-    for (i = 0; i < auth_num; i++)
-    {
-        // Without case sensitive check (increase the number of similar account names found)
-        if (strcasecmp (auth_dat[i].userid, account_name) == 0)
-        {
-            // Strict comparison (if found, we finish the function immediatly with correct value)
-            if (strcmp (auth_dat[i].userid, account_name) == 0)
-                return i;
-            quantity++;
-            index = i;
-        }
-    }
-    // Here, the exact account name is not found
-    // We return the found index of a similar account ONLY if there is 1 similar account
-    if (quantity == 1)
-        return index;
-
-    // Exact account name is not found and 0 or more than 1 similar accounts have been found ==> we say not found
-    return -1;
-}
-
-//--------------------------------------------------------
-// Create a string to save the account in the account file
-//--------------------------------------------------------
-int mmo_auth_tostr (char *str, struct auth_dat *p)
-{
-    int  i;
-    char *str_p = str;
-
-    str_p += sprintf (str_p, "%d\t%s\t%s\t%s\t%c\t%d\t%d\t"
-                      "%s\t%s\t%ld\t%s\t%s\t%ld\t",
-                      p->account_id, p->userid, p->pass, p->lastlogin,
-                      (p->sex == 2) ? 'S' : (p->sex ? 'M' : 'F'),
-                      p->logincount, p->state,
-                      p->email, p->error_message,
-                      p->connect_until_time, p->last_ip, p->memo,
-                      p->ban_until_time);
-
-    for (i = 0; i < p->account_reg2_num; i++)
-        if (p->account_reg2[i].str[0])
-            str_p +=
-                sprintf (str_p, "%s,%d ", p->account_reg2[i].str,
-                         p->account_reg2[i].value);
-
-    return 0;
-}
-
-//---------------------------------
-// Reading of the accounts database
-//---------------------------------
-int mmo_auth_init (void)
-{
-    FILE *fp;
-    int  account_id, logincount, state, n, i, j, v;
-    char line[2048], *p, userid[2048], pass[2048], lastlogin[2048], sex,
-        email[2048], error_message[2048], last_ip[2048], memo[2048];
-    time_t ban_until_time;
-    time_t connect_until_time;
-    char str[2048];
-    int  GM_count = 0;
-    int  server_count = 0;
-
-    CREATE (auth_dat, struct auth_dat, 256);
-    auth_max = 256;
-
-    fp = fopen_ (account_filename, "r");
-    if (fp == NULL)
-    {
-        // no account file -> no account -> no login, including char-server (ERROR)
-        printf
-            ("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n",
-             account_filename);
-        return 0;
-    }
-
-    while (fgets (line, sizeof (line) - 1, fp) != NULL)
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        line[sizeof (line) - 1] = '\0';
-        p = line;
-
-        // database version reading (v2)
-        if (((i = sscanf (line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
-                          "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n",
-                          &account_id, userid, pass, lastlogin, &sex,
-                          &logincount, &state, email, error_message,
-                          &connect_until_time, last_ip, memo, &ban_until_time,
-                          &n)) == 13 && line[n] == '\t')
-            ||
-            ((i =
-              sscanf (line,
-                      "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
-                      "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]%n", &account_id,
-                      userid, pass, lastlogin, &sex, &logincount, &state,
-                      email, error_message, &connect_until_time, last_ip,
-                      memo, &n)) == 12 && line[n] == '\t'))
-        {
-            n = n + 1;
-
-            // Some checks
-            if (account_id > END_ACCOUNT_NUM)
-            {
-                printf
-                    ("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n",
-                     END_ACCOUNT_NUM);
-                printf
-                    ("               account id #%d -> account not read (saved in log file).\033[0m\n",
-                     account_id);
-                login_log
-                    ("mmmo_auth_init: ******Error: an account has an id higher than %d.\n",
-                     END_ACCOUNT_NUM);
-                login_log
-                    ("               account id #%d -> account not read (saved in next line):\n",
-                     account_id);
-                login_log ("%s", line);
-                continue;
-            }
-            userid[23] = '\0';
-            remove_control_chars (userid);
-            for (j = 0; j < auth_num; j++)
-            {
-                if (auth_dat[j].account_id == account_id)
-                {
-                    printf
-                        ("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    printf
-                        ("               account id #%d -> new account not read (saved in log file).\033[0m\n",
-                         account_id);
-                    login_log
-                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    login_log
-                        ("               account id #%d -> new account not read (saved in next line):\n",
-                         account_id);
-                    login_log ("%s", line);
-                    break;
-                }
-                else if (strcmp (auth_dat[j].userid, userid) == 0)
-                {
-                    printf
-                        ("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
-                    printf ("               account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
-                    printf
-                        ("               Account saved in log file.\033[0m\n");
-                    login_log
-                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    login_log
-                        ("               account id #%d -> new account not read (saved in next line):\n",
-                         account_id);
-                    login_log ("%s", line);
-                    break;
-                }
-            }
-            if (j != auth_num)
-                continue;
-
-            if (auth_num >= auth_max)
-            {
-                auth_max += 256;
-                RECREATE (auth_dat, struct auth_dat, auth_max);
-            }
-
-            memset (&auth_dat[auth_num], '\0', sizeof (struct auth_dat));
-
-            auth_dat[auth_num].account_id = account_id;
-
-            strncpy (auth_dat[auth_num].userid, userid, 24);
-
-            memo[254] = '\0';
-            remove_control_chars (memo);
-            strncpy (auth_dat[auth_num].memo, memo, 255);
-
-            pass[39] = '\0';
-            remove_control_chars (pass);
-            // If a password is not encrypted, we encrypt it now.
-	    // A password beginning with ! and - in the memo field is our magic
-	    if (pass[0] != '!' && memo[0] == '-') {
-		strcpy(auth_dat[auth_num].pass, MD5_saltcrypt(pass, make_salt()));
-		auth_dat[auth_num].memo[0] = '!';
-		printf("encrypting pass: %s %s\n", pass, auth_dat[auth_num].pass);
-	    }
-	    else
-		strcpy(auth_dat[auth_num].pass, pass);
-
-            lastlogin[23] = '\0';
-            remove_control_chars (lastlogin);
-            strncpy (auth_dat[auth_num].lastlogin, lastlogin, 24);
-
-            auth_dat[auth_num].sex = (sex == 'S'
-                                      || sex == 's') ? 2 : (sex == 'M'
-                                                            || sex == 'm');
-
-            if (logincount >= 0)
-                auth_dat[auth_num].logincount = logincount;
-            else
-                auth_dat[auth_num].logincount = 0;
-
-            if (state > 255)
-                auth_dat[auth_num].state = 100;
-            else if (state < 0)
-                auth_dat[auth_num].state = 0;
-            else
-                auth_dat[auth_num].state = state;
-
-            if (e_mail_check (email) == 0)
-            {
-                printf
-                    ("Account %s (%d): invalid e-mail (replaced par a@a.com).\n",
-                     auth_dat[auth_num].userid,
-                     auth_dat[auth_num].account_id);
-                strncpy (auth_dat[auth_num].email, "a@a.com", 40);
-            }
-            else
-            {
-                remove_control_chars (email);
-                strncpy (auth_dat[auth_num].email, email, 40);
-            }
-
-            error_message[19] = '\0';
-            remove_control_chars (error_message);
-            if (error_message[0] == '\0' || state != 7)
-            {                   // 7, because state is packet 0x006a value + 1
-                strncpy (auth_dat[auth_num].error_message, "-", 20);
-            }
-            else
-            {
-                strncpy (auth_dat[auth_num].error_message, error_message, 20);
-            }
-
-            if (i == 13)
-                auth_dat[auth_num].ban_until_time = ban_until_time;
-            else
-                auth_dat[auth_num].ban_until_time = 0;
-
-            auth_dat[auth_num].connect_until_time = connect_until_time;
-
-            last_ip[15] = '\0';
-            remove_control_chars (last_ip);
-            strncpy (auth_dat[auth_num].last_ip, last_ip, 16);
-
-            for (j = 0; j < ACCOUNT_REG2_NUM; j++)
-            {
-                p += n;
-                if (sscanf (p, "%[^\t,],%d %n", str, &v, &n) != 2)
-                {
-                    // We must check if a str is void. If it's, we can continue to read other REG2.
-                    // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
-                    if (p[0] == ',' && sscanf (p, ",%d %n", &v, &n) == 1)
-                    {
-                        j--;
-                        continue;
-                    }
-                    else
-                        break;
-                }
-                str[31] = '\0';
-                remove_control_chars (str);
-                strncpy (auth_dat[auth_num].account_reg2[j].str, str, 32);
-                auth_dat[auth_num].account_reg2[j].value = v;
-            }
-            auth_dat[auth_num].account_reg2_num = j;
-
-            if (isGM (account_id) > 0)
-                GM_count++;
-            if (auth_dat[auth_num].sex == 2)
-                server_count++;
-
-            auth_num++;
-            if (account_id >= account_id_count)
-                account_id_count = account_id + 1;
-
-            // Old athena database version reading (v1)
-        }
-        else if ((i =
-                  sscanf (line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
-                          &account_id, userid, pass, lastlogin, &sex,
-                          &logincount, &state, &n)) >= 5)
-        {
-            if (account_id > END_ACCOUNT_NUM)
-            {
-                printf
-                    ("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n",
-                     END_ACCOUNT_NUM);
-                printf
-                    ("               account id #%d -> account not read (saved in log file).\033[0m\n",
-                     account_id);
-                login_log
-                    ("mmmo_auth_init: ******Error: an account has an id higher than %d.\n",
-                     END_ACCOUNT_NUM);
-                login_log
-                    ("               account id #%d -> account not read (saved in next line):\n",
-                     account_id);
-                login_log ("%s", line);
-                continue;
-            }
-            userid[23] = '\0';
-            remove_control_chars (userid);
-            for (j = 0; j < auth_num; j++)
-            {
-                if (auth_dat[j].account_id == account_id)
-                {
-                    printf
-                        ("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    printf
-                        ("               account id #%d -> new account not read (saved in log file).\033[0m\n",
-                         account_id);
-                    login_log
-                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    login_log
-                        ("               account id #%d -> new account not read (saved in next line):\n",
-                         account_id);
-                    login_log ("%s", line);
-                    break;
-                }
-                else if (strcmp (auth_dat[j].userid, userid) == 0)
-                {
-                    printf
-                        ("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
-                    printf ("               account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
-                    printf
-                        ("               Account saved in log file.\033[0m\n");
-                    login_log
-                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
-                    login_log
-                        ("               account id #%d -> new account not read (saved in next line):\n",
-                         account_id);
-                    login_log ("%s", line);
-                    break;
-                }
-            }
-            if (j != auth_num)
-                continue;
-
-            if (auth_num >= auth_max)
-            {
-                auth_max += 256;
-                RECREATE (auth_dat, struct auth_dat, auth_max);
-            }
-
-            memset (&auth_dat[auth_num], '\0', sizeof (struct auth_dat));
-
-            auth_dat[auth_num].account_id = account_id;
-
-            strncpy (auth_dat[auth_num].userid, userid, 24);
-
-            lastlogin[23] = '\0';
-            remove_control_chars (lastlogin);
-            strncpy (auth_dat[auth_num].lastlogin, lastlogin, 24);
-
-            auth_dat[auth_num].sex = (sex == 'S'
-                                      || sex == 's') ? 2 : (sex == 'M'
-                                                            || sex == 'm');
-
-            if (i >= 6)
-            {
-                if (logincount >= 0)
-                    auth_dat[auth_num].logincount = logincount;
-                else
-                    auth_dat[auth_num].logincount = 0;
-            }
-            else
-                auth_dat[auth_num].logincount = 0;
-
-            if (i >= 7)
-            {
-                if (state > 255)
-                    auth_dat[auth_num].state = 100;
-                else if (state < 0)
-                    auth_dat[auth_num].state = 0;
-                else
-                    auth_dat[auth_num].state = state;
-            }
-            else
-                auth_dat[auth_num].state = 0;
-
-            // Initialization of new data
-            strncpy (auth_dat[auth_num].email, "a@a.com", 40);
-            strncpy (auth_dat[auth_num].error_message, "-", 20);
-            auth_dat[auth_num].ban_until_time = 0;
-            auth_dat[auth_num].connect_until_time = 0;
-            strncpy (auth_dat[auth_num].last_ip, "-", 16);
-            strncpy (auth_dat[auth_num].memo, "!", 255);
-
-            for (j = 0; j < ACCOUNT_REG2_NUM; j++)
-            {
-                p += n;
-                if (sscanf (p, "%[^\t,],%d %n", str, &v, &n) != 2)
-                {
-                    // We must check if a str is void. If it's, we can continue to read other REG2.
-                    // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
-                    if (p[0] == ',' && sscanf (p, ",%d %n", &v, &n) == 1)
-                    {
-                        j--;
-                        continue;
-                    }
-                    else
-                        break;
-                }
-                str[31] = '\0';
-                remove_control_chars (str);
-                strncpy (auth_dat[auth_num].account_reg2[j].str, str, 32);
-                auth_dat[auth_num].account_reg2[j].value = v;
-            }
-            auth_dat[auth_num].account_reg2_num = j;
-
-            if (isGM (account_id) > 0)
-                GM_count++;
-            if (auth_dat[auth_num].sex == 2)
-                server_count++;
-
-            auth_num++;
-            if (account_id >= account_id_count)
-                account_id_count = account_id + 1;
-
-        }
-        else
-        {
-            i = 0;
-            if (sscanf (line, "%d\t%%newid%%\n%n", &account_id, &i) == 1 &&
-                i > 0 && account_id > account_id_count)
-                account_id_count = account_id;
-        }
-    }
-    fclose_ (fp);
-
-    if (auth_num == 0)
-    {
-        printf ("mmo_auth_init: No account found in %s.\n", account_filename);
-        sprintf (line, "No account found in %s.", account_filename);
-    }
-    else
-    {
-        if (auth_num == 1)
-        {
-            printf ("mmo_auth_init: 1 account read in %s,\n",
-                    account_filename);
-            sprintf (line, "1 account read in %s,", account_filename);
-        }
-        else
-        {
-            printf ("mmo_auth_init: %d accounts read in %s,\n", auth_num,
-                    account_filename);
-            sprintf (line, "%d accounts read in %s,", auth_num,
-                     account_filename);
-        }
-        if (GM_count == 0)
-        {
-            printf ("               of which is no GM account, and ");
-            sprintf (str, "%s of which is no GM account and", line);
-        }
-        else if (GM_count == 1)
-        {
-            printf ("               of which is 1 GM account, and ");
-            sprintf (str, "%s of which is 1 GM account and", line);
-        }
-        else
-        {
-            printf ("               of which is %d GM accounts, and ",
-                    GM_count);
-            sprintf (str, "%s of which is %d GM accounts and", line,
-                     GM_count);
-        }
-        if (server_count == 0)
-        {
-            printf ("no server account ('S').\n");
-            sprintf (line, "%s no server account ('S').", str);
-        }
-        else if (server_count == 1)
-        {
-            printf ("1 server account ('S').\n");
-            sprintf (line, "%s 1 server account ('S').", str);
-        }
-        else
-        {
-            printf ("%d server accounts ('S').\n", server_count);
-            sprintf (line, "%s %d server accounts ('S').", str, server_count);
-        }
-    }
-    login_log ("%s\n", line);
-
-    return 0;
-}
-
-//------------------------------------------
-// Writing of the accounts database file
-//   (accounts are sorted by id before save)
-//------------------------------------------
-void mmo_auth_sync (void)
-{
-    FILE *fp;
-    int  i, j, k, lock;
-    int  id[auth_num];
-    char line[65536];
-
-    // Sorting before save
-    for (i = 0; i < auth_num; i++)
-    {
-        id[i] = i;
-        for (j = 0; j < i; j++)
-        {
-            if (auth_dat[i].account_id < auth_dat[id[j]].account_id)
-            {
-                for (k = i; k > j; k--)
-                    id[k] = id[k - 1];
-                id[j] = i;      // id[i]
-                break;
-            }
-        }
-    }
-
-    // Data save
-    fp = lock_fopen (account_filename, &lock);
-    if (fp == NULL)
-        return;
-    fprintf (fp,
-             "// Accounts file: here are saved all information about the accounts.\n");
-    fprintf (fp,
-             "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n");
-    fprintf (fp, "// Some explanations:\n");
-    fprintf (fp,
-             "//   account name    : between 4 to 23 char for a normal account (standard client can't send less than 4 char).\n");
-    fprintf (fp, "//   account password: between 4 to 23 char\n");
-    fprintf (fp,
-             "//   sex             : M or F for normal accounts, S for server accounts\n");
-    fprintf (fp,
-             "//   state           : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n");
-    fprintf (fp,
-             "//   email           : between 3 to 39 char (a@a.com is like no email)\n");
-    fprintf (fp,
-             "//   error message   : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char\n");
-    fprintf (fp,
-             "//   valitidy time   : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
-    fprintf (fp, "//   memo field      : max 254 char\n");
-    fprintf (fp,
-             "//   ban time        : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
-    for (i = 0; i < auth_num; i++)
-    {
-        k = id[i];              // use of sorted index
-        if (auth_dat[k].account_id < 0)
-            continue;
-
-        mmo_auth_tostr (line, &auth_dat[k]);
-        fprintf (fp, "%s\n", line);
-    }
-    fprintf (fp, "%d\t%%newid%%\n", account_id_count);
-
-    lock_fclose (fp, account_filename, &lock);
-
-    return;
-}
-
-// We want to sync the DB to disk as little as possible as it's fairly
-// resource intensive. therefore most player-triggerable events that
-// update the account DB will not immideately trigger a save. Instead
-// we save periodicly on a timer.
-//-----------------------------------------------------
-void check_auth_sync (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    if (pid != 0)
-    {
-        int status;
-        pid_t temp = waitpid (pid, &status, WNOHANG);
-
-        // Need to check status too?
-        if (temp == 0)
-        {
-            return;
-        }
-    }
-
-    // This can take a lot of time. Fork a child to handle the work and return at once
-    // If we're unable to fork just continue running the function normally
-    if ((pid = fork ()) > 0)
-        return;
-
-    mmo_auth_sync ();
-
-    // If we're a child we should suicide now.
-    if (pid == 0)
-        _exit (0);
-
-    return;
-}
-
-//--------------------------------------------------------------------
-// Packet send to all char-servers, except one (wos: without our self)
-//--------------------------------------------------------------------
-int charif_sendallwos (int sfd, unsigned char *buf, unsigned int len)
-{
-    int  i, c;
-
-    for (i = 0, c = 0; i < MAX_SERVERS; i++)
-    {
-        int  fd;
-        if ((fd = server_fd[i]) >= 0 && fd != sfd)
-        {
-            memcpy (WFIFOP (fd, 0), buf, len);
-            WFIFOSET (fd, len);
-            c++;
-        }
-    }
-    return c;
-}
-
-//-----------------------------------------------------
-// Send GM accounts to all char-server
-//-----------------------------------------------------
-void send_GM_accounts (void)
-{
-    int  i;
-    char buf[32000];
-    int  GM_value;
-    int  len;
-
-    len = 4;
-    WBUFW (buf, 0) = 0x2732;
-    for (i = 0; i < auth_num; i++)
-        // send only existing accounts. We can not create a GM account when server is online.
-        if ((GM_value = isGM (auth_dat[i].account_id)) > 0)
-        {
-            WBUFL (buf, len) = auth_dat[i].account_id;
-            WBUFB (buf, len + 4) = (unsigned char) GM_value;
-            len += 5;
-        }
-    WBUFW (buf, 2) = len;
-    charif_sendallwos (-1, buf, len);
-
-    return;
-}
-
-//-----------------------------------------------------
-// Check if GM file account have been changed
-//-----------------------------------------------------
-void check_GM_file (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct stat file_stat;
-    long new_time;
-
-    // if we would not check
-    if (gm_account_filename_check_timer < 1)
-        return;
-
-    // get last modify time/date
-    if (stat (GM_account_filename, &file_stat))
-        new_time = 0;           // error
-    else
-        new_time = file_stat.st_mtime;
-
-    if (new_time != creation_time_GM_account_file)
-    {
-        read_gm_account ();
-        send_GM_accounts ();
-    }
-}
-
-//-------------------------------------
-// Account creation (with e-mail check)
-//-------------------------------------
-int mmo_auth_new (struct mmo_account *account, char sex, char *email)
-{
-    time_t timestamp, timestamp_temp;
-    struct tm *tmtime;
-    int  i = auth_num;
-
-    if (auth_num >= auth_max)
-    {
-        auth_max += 256;
-        RECREATE (auth_dat, struct auth_dat, auth_max);
-    }
-
-    memset (&auth_dat[i], '\0', sizeof (struct auth_dat));
-
-    while (isGM (account_id_count) > 0)
-        account_id_count++;
-
-    auth_dat[i].account_id = account_id_count++;
-
-    strncpy (auth_dat[i].userid, account->userid, 24);
-    auth_dat[i].userid[23] = '\0';
-
-    strcpy(auth_dat[i].pass, MD5_saltcrypt(account->passwd, make_salt()));
-    auth_dat[i].pass[39] = '\0';
-
-    memcpy (auth_dat[i].lastlogin, "-", 2);
-
-    auth_dat[i].sex = (sex == 'M');
-
-    auth_dat[i].logincount = 0;
-
-    auth_dat[i].state = 0;
-
-    if (e_mail_check (email) == 0)
-        strncpy (auth_dat[i].email, "a@a.com", 40);
-    else
-        strncpy (auth_dat[i].email, email, 40);
-
-    strncpy (auth_dat[i].error_message, "-", 20);
-
-    auth_dat[i].ban_until_time = 0;
-
-    if (start_limited_time < 0)
-        auth_dat[i].connect_until_time = 0; // unlimited
-    else
-    {                           // limited time
-        timestamp = time (NULL) + start_limited_time;
-        // double conversion to be sure that it is possible
-        tmtime = gmtime (&timestamp);
-        timestamp_temp = mktime (tmtime);
-        if (timestamp_temp != -1 && (timestamp_temp + 3600) >= timestamp)   // check possible value and overflow (and avoid summer/winter hour)
-            auth_dat[i].connect_until_time = timestamp_temp;
-        else
-            auth_dat[i].connect_until_time = 0; // unlimited
-    }
-
-    strncpy (auth_dat[i].last_ip, "-", 16);
-
-    strncpy (auth_dat[i].memo, "!", 255);
-
-    auth_dat[i].account_reg2_num = 0;
-
-    auth_num++;
-
-    return (account_id_count - 1);
-}
-
-//---------------------------------------
-// Check/authentification of a connection
-//---------------------------------------
-int mmo_auth (struct mmo_account *account, int fd)
-{
-    int  i;
-    struct timeval tv;
-    char tmpstr[256];
-    int  len, newaccount = 0;
-#ifdef PASSWDENC
-    char md5str[64], md5bin[32];
-#endif
-    char ip[16];
-    unsigned char *sin_addr =
-        (unsigned char *) &session[fd]->client_addr.sin_addr;
-
-    sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2],
-             sin_addr[3]);
-
-    len = strlen (account->userid) - 2;
-    // Account creation with _M/_F
-    if (account->passwdenc == 0 && account->userid[len] == '_' &&
-        (account->userid[len + 1] == 'F' || account->userid[len + 1] == 'M')
-        && new_account_flag == 1 && account_id_count <= END_ACCOUNT_NUM
-        && len >= 4 && strlen (account->passwd) >= 4)
-    {
-        if (new_account_flag == 1)
-            newaccount = 1;
-        account->userid[len] = '\0';
-    }
-
-    // Strict account search
-    for (i = 0; i < auth_num; i++)
-    {
-        if (strcmp (account->userid, auth_dat[i].userid) == 0)
-            break;
-    }
-    // if there is no creation request and strict account search fails, we do a no sensitive case research for index
-    if (newaccount == 0 && i == auth_num)
-    {
-        i = search_account_index (account->userid);
-        if (i == -1)
-            i = auth_num;
-        else
-            memcpy (account->userid, auth_dat[i].userid, 24);   // for the possible tests/checks afterwards (copy correcte sensitive case).
-    }
-
-    if (i != auth_num)
-    {
-        int  encpasswdok = 0;
-        struct login_session_data *ld;
-        if (newaccount)
-        {
-            login_log
-                ("Attempt of creation of an already existant account (account: %s_%c, ip: %s)\n",
-                 account->userid, account->userid[len + 1], ip);
-            return 9;           // 9 = Account already exists
-        }
-        ld = (struct login_session_data*) session[fd]->session_data;
-#ifdef PASSWORDENC
-        if (account->passwdenc > 0)
-        {
-            int  j = account->passwdenc;
-            if (!ld)
-            {
-                login_log ("Md5 key not created (account: %s, ip: %s)\n",
-                           account->userid, ip);
-                return 1;       // 1 = Incorrect Password
-            }
-            if (j > 2)
-                j = 1;
-            do
-            {
-                if (j == 1)
-                {
-                    strncpy (md5str, ld->md5key, sizeof (ld->md5key));  // 20
-                    strcat (md5str, auth_dat[i].pass);  // 24
-                }
-                else if (j == 2)
-                {
-                    strncpy (md5str, auth_dat[i].pass, sizeof (auth_dat[i].pass));  // 24
-                    strcat (md5str, ld->md5key);    // 20
-                }
-                else
-                    md5str[0] = '\0';
-                md5str[sizeof (md5str) - 1] = '\0'; // 64
-                MD5_String2binary (md5str, md5bin);
-                encpasswdok = (memcmp (account->passwd, md5bin, 16) == 0);
-            }
-            while (j < 2 && !encpasswdok && (j++) != account->passwdenc);
-//          printf("key[%s] md5 [%s] ", md5key, md5);
-//          printf("client [%s] accountpass [%s]\n", account->passwd, auth_dat[i].pass);
-        }
-#endif
-        if ((!pass_ok (account->passwd, auth_dat[i].pass)) && !encpasswdok)
-        {
-            if (account->passwdenc == 0)
-                login_log
-                    ("Invalid password (account: %s, ip: %s)\n",
-                     account->userid, ip);
-
-#ifdef PASSWORDENC
-            else
-            {
-                char logbuf[512], *p = logbuf;
-                int  j;
-                p += sprintf (p,
-                              "Invalid password (account: %s, received md5[",
-                              account->userid);
-                for (j = 0; j < 16; j++)
-                    p += sprintf (p, "%02x",
-                                  ((unsigned char *) account->passwd)[j]);
-                p += sprintf (p, "] calculated md5[");
-                for (j = 0; j < 16; j++)
-                    p += sprintf (p, "%02x", ((unsigned char *) md5bin)[j]);
-                p += sprintf (p, "] md5 key[");
-                for (j = 0; j < ld->md5keylen; j++)
-                    p += sprintf (p, "%02x",
-                                  ((unsigned char *) ld->md5key)[j]);
-                p += sprintf (p, "], ip: %s)\n", ip);
-                login_log (logbuf);
-            }
-#endif
-            return 1;           // 1 = Incorrect Password
-        }
-
-        if (auth_dat[i].state)
-        {
-            login_log
-                ("Connection refused (account: %s, state: %d, ip: %s)\n",
-                 account->userid, auth_dat[i].state,
-                 ip);
-            switch (auth_dat[i].state)
-            {                   // packet 0x006a value + 1
-                case 1:        // 0 = Unregistered ID
-                case 2:        // 1 = Incorrect Password
-                case 3:        // 2 = This ID is expired
-                case 4:        // 3 = Rejected from Server
-                case 5:        // 4 = You have been blocked by the GM Team
-                case 6:        // 5 = Your Game's EXE file is not the latest version
-                case 7:        // 6 = Your are Prohibited to log in until %s
-                case 8:        // 7 = Server is jammed due to over populated
-                case 9:        // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
-                case 100:      // 99 = This ID has been totally erased
-                    return auth_dat[i].state - 1;
-                    break;
-                default:
-                    return 99;  // 99 = ID has been totally erased
-                    break;
-            }
-        }
-
-        if (auth_dat[i].ban_until_time != 0)
-        {                       // if account is banned
-            strftime (tmpstr, 20, date_format,
-                      gmtime (&auth_dat[i].ban_until_time));
-            tmpstr[19] = '\0';
-            if (auth_dat[i].ban_until_time > time (NULL))
-            {                   // always banned
-                login_log
-                    ("Connection refused (account: %s, banned until %s, ip: %s)\n",
-                     account->userid, tmpstr, ip);
-                return 6;       // 6 = Your are Prohibited to log in until %s
-            }
-            else
-            {                   // ban is finished
-                login_log
-                    ("End of ban (account: %s, previously banned until %s -> not more banned, ip: %s)\n",
-                     account->userid, tmpstr, ip);
-                auth_dat[i].ban_until_time = 0; // reset the ban time
-            }
-        }
-
-        if (auth_dat[i].connect_until_time != 0
-            && auth_dat[i].connect_until_time < time (NULL))
-        {
-            login_log
-                ("Connection refused (account: %s, expired ID, ip: %s)\n",
-                 account->userid, ip);
-            return 2;           // 2 = This ID is expired
-        }
-
-        login_log ("Authentification accepted (account: %s (id: %d), ip: %s)\n",
-                   account->userid, auth_dat[i].account_id, ip);
-    }
-    else
-    {
-        if (newaccount == 0)
-        {
-            login_log
-                ("Unknown account (account: %s, ip: %s)\n",
-                 account->userid, ip);
-            return 0;           // 0 = Unregistered ID
-        }
-        else
-        {
-            int  new_id =
-                mmo_auth_new (account, account->userid[len + 1], "a@a.com");
-            login_log
-                ("Account creation and authentification accepted (account %s (id: %d), sex: %c, connection with _F/_M, ip: %s)\n",
-                 account->userid, new_id,
-                 account->userid[len + 1], ip);
-        }
-    }
-
-    gettimeofday (&tv, NULL);
-    strftime (tmpstr, 24, date_format, gmtime (&(tv.tv_sec)));
-    sprintf (tmpstr + strlen (tmpstr), ".%03d", (int) tv.tv_usec / 1000);
-
-    account->account_id = auth_dat[i].account_id;
-    account->login_id1 = mt_random ();
-    account->login_id2 = mt_random ();
-    memcpy (account->lastlogin, auth_dat[i].lastlogin, 24);
-    memcpy (auth_dat[i].lastlogin, tmpstr, 24);
-    account->sex = auth_dat[i].sex;
-    strncpy (auth_dat[i].last_ip, ip, 16);
-    auth_dat[i].logincount++;
-
-    return -1;                  // account OK
-}
-
-//-------------------------------
-// Char-server anti-freeze system
-//-------------------------------
-void char_anti_freeze_system (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  i;
-
-    //printf("Entering in char_anti_freeze_system function to check freeze of servers.\n");
-    for (i = 0; i < MAX_SERVERS; i++)
-    {
-        if (server_fd[i] >= 0)
-        {                       // if char-server is online
-            //printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
-            if (server_freezeflag[i]-- < 1)
-            {                   // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
-                printf
-                    ("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n",
-                     i, server[i].name);
-                login_log
-                    ("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n",
-                     i, server[i].name);
-                session[server_fd[i]]->eof = 1;
-            }
-        }
-    }
-}
-
-//--------------------------------
-// Packet parsing for char-servers
-//--------------------------------
-void parse_fromchar (int fd)
-{
-    int  i, j, id;
-    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
-    char ip[16];
-
-    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-
-    for (id = 0; id < MAX_SERVERS; id++)
-        if (server_fd[id] == fd)
-            break;
-    if (id == MAX_SERVERS || session[fd]->eof)
-    {
-        if (id < MAX_SERVERS)
-        {
-            printf ("Char-server '%s' has disconnected.\n", server[id].name);
-            login_log ("Char-server '%s' has disconnected (ip: %s).\n",
-                       server[id].name, ip);
-            server_fd[id] = -1;
-            memset (&server[id], 0, sizeof (struct mmo_char_server));
-        }
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    while (RFIFOREST (fd) >= 2)
-    {
-        if (display_parse_fromchar == 2 || (display_parse_fromchar == 1 && RFIFOW (fd, 0) != 0x2714))   // 0x2714 is done very often (number of players)
-            printf
-                ("parse_fromchar: connection #%d, packet: 0x%x (with being read: %d bytes).\n",
-                 fd, RFIFOW (fd, 0), RFIFOREST (fd));
-
-        switch (RFIFOW (fd, 0))
-        {
-                // request from map-server via char-server to reload GM accounts (by Yor).
-            case 0x2709:
-                login_log
-                    ("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n",
-                     server[id].name, ip);
-                read_gm_account ();
-                // send GM accounts to all char-servers
-                send_GM_accounts ();
-                RFIFOSKIP (fd, 2);
-                break;
-
-            case 0x2712:       // request from char-server to authentify an account
-                if (RFIFOREST (fd) < 19)
-                    return;
-                {
-                    int  acc;
-                    acc = RFIFOL (fd, 2);   // speed up
-                    for (i = 0; i < AUTH_FIFO_SIZE; i++)
-                    {
-                        if (auth_fifo[i].account_id == acc &&
-                            auth_fifo[i].login_id1 == RFIFOL (fd, 6) &&
-#if CMP_AUTHFIFO_LOGIN2 != 0
-                            auth_fifo[i].login_id2 == RFIFOL (fd, 10) &&    // relate to the versions higher than 18
-#endif
-                            auth_fifo[i].sex == RFIFOB (fd, 14) &&
-                            (!check_ip_flag
-                             || auth_fifo[i].ip == RFIFOL (fd, 15))
-                            && !auth_fifo[i].delflag)
-                        {
-                            int  p, k;
-                            auth_fifo[i].delflag = 1;
-                            login_log
-                                ("Char-server '%s': authentification of the account %d accepted (ip: %s).\n",
-                                 server[id].name, acc, ip);
-//                  printf("%d\n", i);
-                            for (k = 0; k < auth_num; k++)
-                            {
-                                if (auth_dat[k].account_id == acc)
-                                {
-                                    WFIFOW (fd, 0) = 0x2729;    // Sending of the account_reg2
-                                    WFIFOL (fd, 4) = acc;
-                                    for (p = 8, j = 0;
-                                         j < auth_dat[k].account_reg2_num;
-                                         p += 36, j++)
-                                    {
-                                        memcpy (WFIFOP (fd, p),
-                                                auth_dat[k].
-                                                account_reg2[j].str, 32);
-                                        WFIFOL (fd, p + 32) =
-                                            auth_dat[k].account_reg2[j].value;
-                                    }
-                                    WFIFOW (fd, 2) = p;
-                                    WFIFOSET (fd, p);
-//                          printf("parse_fromchar: Sending of account_reg2: login->char (auth fifo)\n");
-                                    WFIFOW (fd, 0) = 0x2713;
-                                    WFIFOL (fd, 2) = acc;
-                                    WFIFOB (fd, 6) = 0;
-                                    memcpy (WFIFOP (fd, 7), auth_dat[k].email,
-                                            40);
-                                    WFIFOL (fd, 47) =
-                                        (unsigned long)
-                                        auth_dat[k].connect_until_time;
-                                    WFIFOSET (fd, 51);
-                                    break;
-                                }
-                            }
-                            break;
-                        }
-                    }
-                    // authentification not found
-                    if (i == AUTH_FIFO_SIZE)
-                    {
-                        login_log
-                            ("Char-server '%s': authentification of the account %d REFUSED (ip: %s).\n",
-                             server[id].name, acc, ip);
-                        WFIFOW (fd, 0) = 0x2713;
-                        WFIFOL (fd, 2) = acc;
-                        WFIFOB (fd, 6) = 1;
-                        // It is unnecessary to send email
-                        // It is unnecessary to send validity date of the account
-                        WFIFOSET (fd, 51);
-                    }
-                }
-                RFIFOSKIP (fd, 19);
-                break;
-
-            case 0x2714:
-                if (RFIFOREST (fd) < 6)
-                    return;
-                //printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2));
-                server[id].users = RFIFOL (fd, 2);
-                if (anti_freeze_enable)
-                    server_freezeflag[id] = 5;  // Char anti-freeze system. Counter. 5 ok, 4...0 freezed
-                RFIFOSKIP (fd, 6);
-                break;
-
-                // we receive a e-mail creation of an account with a default e-mail (no answer)
-            case 0x2715:
-            {
-                int  acc;
-                char email[40];
-                if (RFIFOREST (fd) < 46)
-                    return;
-                acc = RFIFOL (fd, 2);   // speed up
-                memcpy (email, RFIFOP (fd, 6), 40);
-                email[39] = '\0';
-                remove_control_chars (email);
-                //printf("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6));
-                if (e_mail_check (email) == 0)
-                    login_log
-                        ("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n",
-                         server[id].name, acc, ip);
-                else
-                {
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc
-                            && (strcmp (auth_dat[i].email, "a@a.com") == 0
-                                || auth_dat[i].email[0] == '\0'))
-                        {
-                            memcpy (auth_dat[i].email, email, 40);
-                            login_log
-                                ("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n",
-                                 server[id].name, acc, email, ip);
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                        login_log
-                            ("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n",
-                             server[id].name, acc, ip);
-                }
-                RFIFOSKIP (fd, 46);
-                break;
-
-                // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
-            }
-            case 0x2716:
-                if (RFIFOREST (fd) < 6)
-                    return;
-                //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
-                for (i = 0; i < auth_num; i++)
-                {
-                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
-                    {
-                        login_log
-                            ("Char-server '%s': e-mail of the account %d found (ip: %s).\n",
-                             server[id].name, RFIFOL (fd, 2), ip);
-                        WFIFOW (fd, 0) = 0x2717;
-                        WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].email, 40);
-                        WFIFOL (fd, 46) =
-                            (unsigned long) auth_dat[i].connect_until_time;
-                        WFIFOSET (fd, 50);
-                        break;
-                    }
-                }
-                if (i == auth_num)
-                {
-                    login_log
-                        ("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n",
-                         server[id].name, RFIFOL (fd, 2), ip);
-                }
-                RFIFOSKIP (fd, 6);
-                break;
-
-            case 0x2720:       // To become GM request
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    int  acc;
-                    unsigned char buf[10];
-                    FILE *fp;
-                    acc = RFIFOL (fd, 4);
-                    //printf("parse_fromchar: Request to become a GM acount from %d account.\n", acc);
-                    WBUFW (buf, 0) = 0x2721;
-                    WBUFL (buf, 2) = acc;
-                    WBUFL (buf, 6) = 0;
-                    if (strcmp (RFIFOP (fd, 8), gm_pass) == 0)
-                    {
-                        // only non-GM can become GM
-                        if (isGM (acc) == 0)
-                        {
-                            // if we autorise creation
-                            if (level_new_gm > 0)
-                            {
-                                // if we can open the file to add the new GM
-                                if ((fp =
-                                     fopen_ (GM_account_filename,
-                                             "a")) != NULL)
-                                {
-                                    char tmpstr[24];
-                                    struct timeval tv;
-                                    gettimeofday (&tv, NULL);
-                                    strftime (tmpstr, 23, date_format,
-                                              gmtime (&(tv.tv_sec)));
-                                    fprintf (fp,
-                                             "\n// %s: @GM command on account %d\n%d %d\n",
-                                             tmpstr,
-                                             acc, acc, level_new_gm);
-                                    fclose_ (fp);
-                                    WBUFL (buf, 6) = level_new_gm;
-                                    read_gm_account ();
-                                    send_GM_accounts ();
-                                    printf
-                                        ("GM Change of the account %d: level 0 -> %d.\n",
-                                         acc, level_new_gm);
-                                    login_log
-                                        ("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n",
-                                         server[id].name, acc,
-                                         level_new_gm, ip);
-                                }
-                                else
-                                {
-                                    printf
-                                        ("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n",
-                                         acc);
-                                    login_log
-                                        ("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n",
-                                         server[id].name, acc, ip);
-                                }
-                            }
-                            else
-                            {
-                                printf
-                                    ("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n",
-                                     acc);
-                                login_log
-                                    ("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n",
-                                     server[id].name, acc, ip);
-                            }
-                        }
-                        else
-                        {
-                            printf
-                                ("Error of GM change (suggested account: %d (already GM), correct password).\n",
-                                 acc);
-                            login_log
-                                ("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n",
-                                 server[id].name, acc, ip);
-                        }
-                    }
-                    else
-                    {
-                        printf
-                            ("Error of GM change (suggested account: %d, invalid password).\n",
-                             acc);
-                        login_log
-                            ("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n",
-                             server[id].name, acc, ip);
-                    }
-                    charif_sendallwos (-1, buf, 10);
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                return;
-
-                // Map server send information to change an email of an account via char-server
-            case 0x2722:       // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
-                if (RFIFOREST (fd) < 86)
-                    return;
-                {
-                    int  acc;
-                    char actual_email[40], new_email[40];
-                    acc = RFIFOL (fd, 2);
-                    memcpy (actual_email, RFIFOP (fd, 6), 40);
-                    actual_email[39] = '\0';
-                    remove_control_chars (actual_email);
-                    memcpy (new_email, RFIFOP (fd, 46), 40);
-                    new_email[39] = '\0';
-                    remove_control_chars (new_email);
-                    if (e_mail_check (actual_email) == 0)
-                        login_log
-                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n",
-                             server[id].name, acc, ip);
-                    else if (e_mail_check (new_email) == 0)
-                        login_log
-                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n",
-                             server[id].name, acc, ip);
-                    else if (strcasecmp (new_email, "a@a.com") == 0)
-                        login_log
-                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n",
-                             server[id].name, acc, ip);
-                    else
-                    {
-                        for (i = 0; i < auth_num; i++)
-                        {
-                            if (auth_dat[i].account_id == acc)
-                            {
-                                if (strcasecmp (auth_dat[i].email, actual_email)
-                                    == 0)
-                                {
-                                    memcpy (auth_dat[i].email, new_email, 40);
-                                    login_log
-                                        ("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n",
-                                         server[id].name, acc,
-                                         auth_dat[i].userid, new_email, ip);
-                                }
-                                else
-                                    login_log
-                                        ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n",
-                                         server[id].name, acc,
-                                         auth_dat[i].userid,
-                                         auth_dat[i].email, actual_email, ip);
-                                break;
-                            }
-                        }
-                        if (i == auth_num)
-                            login_log
-                                ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n",
-                                 server[id].name, acc, ip);
-                    }
-                }
-                RFIFOSKIP (fd, 86);
-                break;
-
-                // Receiving of map-server via char-server a status change resquest (by Yor)
-            case 0x2724:
-                if (RFIFOREST (fd) < 10)
-                    return;
-                {
-                    int  acc, statut;
-                    acc = RFIFOL (fd, 2);
-                    statut = RFIFOL (fd, 6);
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            if (auth_dat[i].state != statut)
-                            {
-                                login_log
-                                    ("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n",
-                                     server[id].name, acc, statut,
-                                     ip);
-                                if (statut != 0)
-                                {
-                                    unsigned char buf[16];
-                                    WBUFW (buf, 0) = 0x2731;
-                                    WBUFL (buf, 2) = acc;
-                                    WBUFB (buf, 6) = 0; // 0: change of statut, 1: ban
-                                    WBUFL (buf, 7) = statut;    // status or final date of a banishment
-                                    charif_sendallwos (-1, buf, 11);
-                                    for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                        if (auth_fifo[j].account_id == acc)
-                                            auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                                }
-                                auth_dat[i].state = statut;
-                            }
-                            else
-                                login_log
-                                    ("Char-server '%s':  Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n",
-                                     server[id].name, acc, statut,
-                                     ip);
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                    {
-                        login_log
-                            ("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n",
-                             server[id].name, acc, statut, ip);
-                    }
-                    RFIFOSKIP (fd, 10);
-                }
-                return;
-
-            case 0x2725:       // Receiving of map-server via char-server a ban resquest (by Yor)
-                if (RFIFOREST (fd) < 18)
-                    return;
-                {
-                    int  acc;
-                    acc = RFIFOL (fd, 2);
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            time_t timestamp;
-                            struct tm *tmtime;
-                            if (auth_dat[i].ban_until_time == 0
-                                || auth_dat[i].ban_until_time < time (NULL))
-                                timestamp = time (NULL);
-                            else
-                                timestamp = auth_dat[i].ban_until_time;
-                            tmtime = gmtime (&timestamp);
-                            tmtime->tm_year =
-                                tmtime->tm_year + (short) RFIFOW (fd, 6);
-                            tmtime->tm_mon =
-                                tmtime->tm_mon + (short) RFIFOW (fd, 8);
-                            tmtime->tm_mday =
-                                tmtime->tm_mday + (short) RFIFOW (fd, 10);
-                            tmtime->tm_hour =
-                                tmtime->tm_hour + (short) RFIFOW (fd, 12);
-                            tmtime->tm_min =
-                                tmtime->tm_min + (short) RFIFOW (fd, 14);
-                            tmtime->tm_sec =
-                                tmtime->tm_sec + (short) RFIFOW (fd, 16);
-                            timestamp = timegm (tmtime);
-                            if (timestamp != -1)
-                            {
-                                if (timestamp <= time (NULL))
-                                    timestamp = 0;
-                                if (auth_dat[i].ban_until_time != timestamp)
-                                {
-                                    if (timestamp != 0)
-                                    {
-                                        unsigned char buf[16];
-                                        char tmpstr[2048];
-                                        strftime (tmpstr, 24, date_format,
-                                                  gmtime (&timestamp));
-                                        login_log
-                                            ("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n",
-                                             server[id].name, acc,
-                                             timestamp,
-                                             (timestamp ==
-                                              0 ? "no banishment" : tmpstr),
-                                             ip);
-                                        WBUFW (buf, 0) = 0x2731;
-                                        WBUFL (buf, 2) =
-                                            auth_dat[i].account_id;
-                                        WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
-                                        WBUFL (buf, 7) = timestamp; // status or final date of a banishment
-                                        charif_sendallwos (-1, buf, 11);
-                                        for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                            if (auth_fifo[j].account_id ==
-                                                acc)
-                                                auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                                    }
-                                    else
-                                    {
-                                        login_log
-                                            ("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n",
-                                             server[id].name, acc,
-                                             ip);
-                                    }
-                                    auth_dat[i].ban_until_time = timestamp;
-                                }
-                                else
-                                {
-                                    login_log
-                                        ("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s).\n",
-                                         server[id].name, acc, ip);
-                                }
-                            }
-                            else
-                            {
-                                login_log
-                                    ("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n",
-                                     server[id].name, acc, ip);
-                            }
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                    {
-                        login_log
-                            ("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n",
-                             server[id].name, acc, ip);
-                    }
-                    RFIFOSKIP (fd, 18);
-                }
-                return;
-
-            case 0x2727:       // Change of sex (sex is reversed)
-                if (RFIFOREST (fd) < 6)
-                    return;
-                {
-                    int  acc, sex;
-                    acc = RFIFOL (fd, 2);
-                    for (i = 0; i < auth_num; i++)
-                    {
-//                  printf("%d,", auth_dat[i].account_id);
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            if (auth_dat[i].sex == 2)
-                                login_log
-                                    ("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n",
-                                     server[id].name, acc,
-                                     auth_dat[i].sex, ip);
-                            else
-                            {
-                                unsigned char buf[16];
-                                if (auth_dat[i].sex == 0)
-                                    sex = 1;
-                                else
-                                    sex = 0;
-                                login_log
-                                    ("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n",
-                                     server[id].name, acc,
-                                     (sex == 2) ? 'S' : (sex ? 'M' : 'F'),
-                                     ip);
-                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                    if (auth_fifo[j].account_id == acc)
-                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                                auth_dat[i].sex = sex;
-                                WBUFW (buf, 0) = 0x2723;
-                                WBUFL (buf, 2) = acc;
-                                WBUFB (buf, 6) = sex;
-                                charif_sendallwos (-1, buf, 7);
-                            }
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                    {
-                        login_log
-                            ("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n",
-                             server[id].name, acc, ip);
-                    }
-                    RFIFOSKIP (fd, 6);
-                }
-                return;
-
-            case 0x2728:       // We receive account_reg2 from a char-server, and we send them to other char-servers.
-                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
-                    return;
-                {
-                    int  acc, p;
-                    acc = RFIFOL (fd, 4);
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            unsigned char buf[RFIFOW (fd, 2) + 1];
-                            login_log
-                                ("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n",
-                                 server[id].name, acc, ip);
-                            for (p = 8, j = 0;
-                                 p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
-                                 p += 36, j++)
-                            {
-                                memcpy (auth_dat[i].account_reg2[j].str,
-                                        RFIFOP (fd, p), 32);
-                                auth_dat[i].account_reg2[j].str[31] = '\0';
-                                remove_control_chars (auth_dat[i].account_reg2
-                                                      [j].str);
-                                auth_dat[i].account_reg2[j].value =
-                                    RFIFOL (fd, p + 32);
-                            }
-                            auth_dat[i].account_reg2_num = j;
-                            // Sending information towards the other char-servers.
-                            memcpy (WBUFP (buf, 0), RFIFOP (fd, 0),
-                                    RFIFOW (fd, 2));
-                            WBUFW (buf, 0) = 0x2729;
-                            charif_sendallwos (fd, buf, WBUFW (buf, 2));
-//                      printf("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc);
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                    {
-//                  printf("parse_fromchar: receiving (from the char-server) of account_reg2 (unknwon account id: %d).\n", acc);
-                        login_log
-                            ("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n",
-                             server[id].name, acc, ip);
-                    }
-                }
-                RFIFOSKIP (fd, RFIFOW (fd, 2));
-                break;
-
-            case 0x272a:       // Receiving of map-server via char-server a unban resquest (by Yor)
-                if (RFIFOREST (fd) < 6)
-                    return;
-                {
-                    int  acc;
-                    acc = RFIFOL (fd, 2);
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            if (auth_dat[i].ban_until_time != 0)
-                            {
-                                auth_dat[i].ban_until_time = 0;
-                                login_log
-                                    ("Char-server '%s': UnBan request (account: %d, ip: %s).\n",
-                                     server[id].name, acc, ip);
-                            }
-                            else
-                            {
-                                login_log
-                                    ("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n",
-                                     server[id].name, acc, ip);
-                            }
-                            break;
-                        }
-                    }
-                    if (i == auth_num)
-                    {
-                        login_log
-                            ("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n",
-                             server[id].name, acc, ip);
-                    }
-                    RFIFOSKIP (fd, 6);
-                }
-                return;
-
-                // request from char-server to change account password
-            case 0x2740:       // 0x2740 <account_id>.L <actual_password>.24B <new_password>.24B
-                if (RFIFOREST (fd) < 54)
-                    return;
-                {
-                    int  acc;
-                    char actual_pass[24], new_pass[24];
-                    acc = RFIFOL (fd, 2);
-                    memcpy (actual_pass, RFIFOP (fd, 6), 24);
-                    actual_pass[23] = '\0';
-                    remove_control_chars (actual_pass);
-                    memcpy (new_pass, RFIFOP (fd, 30), 24);
-                    new_pass[23] = '\0';
-                    remove_control_chars (new_pass);
-
-                    int  status = 0;
-
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        if (auth_dat[i].account_id == acc)
-                        {
-                            if (pass_ok (actual_pass, auth_dat[i].pass))
-                            {
-                                if (strlen (new_pass) < 4)
-                                    status = 3;
-                                else
-                                {
-                                    status = 1;
-                                    strcpy (auth_dat[i].pass, MD5_saltcrypt(new_pass, make_salt()));
-                                    login_log
-                                        ("Char-server '%s': Change pass success (account: %d (%s), ip: %s.\n",
-                                         server[id].name, acc,
-                                         auth_dat[i].userid, ip);
-                                }
-                            }
-                            else
-                            {
-                                status = 2;
-                                login_log
-                                    ("Char-server '%s': Attempt to modify a pass failed, wrong password. (account: %d (%s), ip: %s).\n",
-                                     server[id].name, acc,
-                                     auth_dat[i].userid, ip);
-                            }
-                            break;
-                        }
-                    }
-                    WFIFOW (fd, 0) = 0x2741;
-                    WFIFOL (fd, 2) = acc;
-                    WFIFOB (fd, 6) = status;    // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short
-                    WFIFOSET (fd, 7);
-                }
-
-                RFIFOSKIP (fd, 54);
-                break;
-
-            default:
-            {
-                FILE *logfp;
-                char tmpstr[24];
-                struct timeval tv;
-                logfp = fopen_ (login_log_unknown_packets_filename, "a");
-                if (logfp)
-                {
-                    gettimeofday (&tv, NULL);
-                    strftime (tmpstr, 23, date_format, gmtime (&(tv.tv_sec)));
-                    fprintf (logfp,
-                             "%s.%03d: receiving of an unknown packet -> disconnection\n",
-                             tmpstr, (int) tv.tv_usec / 1000);
-                    fprintf (logfp,
-                             "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
-                             fd, ip, RFIFOW (fd, 0), RFIFOREST (fd));
-                    fprintf (logfp, "Detail (in hex):\n");
-                    fprintf (logfp,
-                             "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-                    memset (tmpstr, '\0', sizeof (tmpstr));
-                    for (i = 0; i < RFIFOREST (fd); i++)
-                    {
-                        if ((i & 15) == 0)
-                            fprintf (logfp, "%04X ", i);
-                        fprintf (logfp, "%02x ", RFIFOB (fd, i));
-                        if (RFIFOB (fd, i) > 0x1f)
-                            tmpstr[i % 16] = RFIFOB (fd, i);
-                        else
-                            tmpstr[i % 16] = '.';
-                        if ((i - 7) % 16 == 0)  // -8 + 1
-                            fprintf (logfp, " ");
-                        else if ((i + 1) % 16 == 0)
-                        {
-                            fprintf (logfp, " %s\n", tmpstr);
-                            memset (tmpstr, '\0', sizeof (tmpstr));
-                        }
-                    }
-                    if (i % 16 != 0)
-                    {
-                        for (j = i; j % 16 != 0; j++)
-                        {
-                            fprintf (logfp, "   ");
-                            if ((j - 7) % 16 == 0)  // -8 + 1
-                                fprintf (logfp, " ");
-                        }
-                        fprintf (logfp, " %s\n", tmpstr);
-                    }
-                    fprintf (logfp, "\n");
-                    fclose_ (logfp);
-                }
-            }
-                printf
-                    ("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n",
-                     RFIFOW (fd, 0));
-                session[fd]->eof = 1;
-                printf
-                    ("Char-server has been disconnected (unknown packet).\n");
-                return;
-        }
-    }
-    return;
-}
-
-//---------------------------------------
-// Packet parsing for administation login
-//---------------------------------------
-void parse_admin (int fd)
-{
-    int  i, j;
-    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
-    char *account_name;
-    char ip[16];
-
-    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-
-    if (session[fd]->eof)
-    {
-        close (fd);
-        delete_session (fd);
-        printf ("Remote administration has disconnected (session #%d).\n",
-                fd);
-        return;
-    }
-
-    while (RFIFOREST (fd) >= 2)
-    {
-        if (display_parse_admin == 1)
-            printf
-                ("parse_admin: connection #%d, packet: 0x%x (with being read: %d).\n",
-                 fd, RFIFOW (fd, 0), RFIFOREST (fd));
-
-        switch (RFIFOW (fd, 0))
-        {
-            case 0x7530:       // Request of the server version
-                login_log ("'ladmin': Sending of the server version (ip: %s)\n",
-                           ip);
-                WFIFOW (fd, 0) = 0x7531;
-                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
-                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
-                WFIFOB (fd, 4) = ATHENA_REVISION;
-                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
-                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
-                WFIFOB (fd, 7) = ATHENA_SERVER_LOGIN;
-                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
-                WFIFOSET (fd, 10);
-                RFIFOSKIP (fd, 2);
-                break;
-
-            case 0x7532:       // Request of end of connection
-                login_log ("'ladmin': End of connection (ip: %s)\n",
-                           ip);
-                RFIFOSKIP (fd, 2);
-                session[fd]->eof = 1;
-                break;
-
-            case 0x7920:       // Request of an accounts list
-                if (RFIFOREST (fd) < 10)
-                    return;
-                {
-                    int  st, ed, len;
-                    int  id[auth_num];
-                    st = RFIFOL (fd, 2);
-                    ed = RFIFOL (fd, 6);
-                    RFIFOSKIP (fd, 10);
-                    WFIFOW (fd, 0) = 0x7921;
-                    if (st < 0)
-                        st = 0;
-                    if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
-                        ed = END_ACCOUNT_NUM;
-                    login_log
-                        ("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n",
-                         st, ed, ip);
-                    // Sort before send
-                    for (i = 0; i < auth_num; i++)
-                    {
-                        int  k;
-                        id[i] = i;
-                        for (j = 0; j < i; j++)
-                        {
-                            if (auth_dat[id[i]].account_id <
-                                auth_dat[id[j]].account_id)
-                            {
-                                for (k = i; k > j; k--)
-                                {
-                                    id[k] = id[k - 1];
-                                }
-                                id[j] = i;  // id[i]
-                                break;
-                            }
-                        }
-                    }
-                    // Sending accounts information
-                    len = 4;
-                    for (i = 0; i < auth_num && len < 30000; i++)
-                    {
-                        int  account_id = auth_dat[id[i]].account_id;   // use sorted index
-                        if (account_id >= st && account_id <= ed)
-                        {
-                            j = id[i];
-                            WFIFOL (fd, len) = account_id;
-                            WFIFOB (fd, len + 4) =
-                                (unsigned char) isGM (account_id);
-                            memcpy (WFIFOP (fd, len + 5), auth_dat[j].userid,
-                                    24);
-                            WFIFOB (fd, len + 29) = auth_dat[j].sex;
-                            WFIFOL (fd, len + 30) = auth_dat[j].logincount;
-                            if (auth_dat[j].state == 0 && auth_dat[j].ban_until_time != 0)  // if no state and banished
-                                WFIFOL (fd, len + 34) = 7;  // 6 = Your are Prohibited to log in until %s
-                            else
-                                WFIFOL (fd, len + 34) = auth_dat[j].state;
-                            len += 38;
-                        }
-                    }
-                    WFIFOW (fd, 2) = len;
-                    WFIFOSET (fd, len);
-                }
-                break;
-
-            case 0x7924:
-            {                   // [Fate] Itemfrob package: change item IDs
-                if (RFIFOREST (fd) < 10)
-                    return;
-                charif_sendallwos (-1, RFIFOP (fd, 0), 10); // forward package to char servers
-                RFIFOSKIP (fd, 10);
-                WFIFOW (fd, 0) = 0x7925;
-                WFIFOSET (fd, 2);
-                break;
-            }
-
-            case 0x7930:       // Request for an account creation
-                if (RFIFOREST (fd) < 91)
-                    return;
-                {
-                    struct mmo_account ma;
-                    ma.userid = RFIFOP (fd, 2);
-                    ma.passwd = RFIFOP (fd, 26);
-                    memcpy (ma.lastlogin, "-", 2);
-                    ma.sex = RFIFOB (fd, 50);
-                    WFIFOW (fd, 0) = 0x7931;
-                    WFIFOL (fd, 2) = -1;
-                    memcpy (WFIFOP (fd, 6), RFIFOP (fd, 2), 24);
-                    if (strlen (ma.userid) > 23 || strlen (ma.passwd) > 23)
-                    {
-                        login_log
-                            ("'ladmin': Attempt to create an invalid account (account or pass is too long, ip: %s)\n",
-                             ip);
-                    }
-                    else if (strlen (ma.userid) < 4 || strlen (ma.passwd) < 4)
-                    {
-                        login_log
-                            ("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n",
-                             ip);
-                    }
-                    else if (ma.sex != 'F' && ma.sex != 'M')
-                    {
-                        login_log
-                            ("'ladmin': Attempt to create an invalid account (account: %s, invalid sex, ip: %s)\n",
-                             ma.userid, ip);
-                    }
-                    else if (account_id_count > END_ACCOUNT_NUM)
-                    {
-                        login_log
-                            ("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, sex: %c, ip: %s)\n",
-                             ma.userid, ma.sex, ip);
-                    }
-                    else
-                    {
-                        remove_control_chars (ma.userid);
-                        remove_control_chars (ma.passwd);
-                        for (i = 0; i < auth_num; i++)
-                        {
-                            if (strncmp (auth_dat[i].userid, ma.userid, 24) ==
-                                0)
-                            {
-                                login_log
-                                    ("'ladmin': Attempt to create an already existing account (account: %s ip: %s)\n",
-                                     auth_dat[i].userid, ip);
-                                break;
-                            }
-                        }
-                        if (i == auth_num)
-                        {
-                            int  new_id;
-                            char email[40];
-                            memcpy (email, RFIFOP (fd, 51), 40);
-                            email[39] = '\0';
-                            remove_control_chars (email);
-                            new_id = mmo_auth_new (&ma, ma.sex, email);
-                            login_log
-                                ("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n",
-                                 ma.userid, new_id,
-                                 ma.sex, auth_dat[i].email, ip);
-                            WFIFOL (fd, 2) = new_id;
-                        }
-                    }
-                    WFIFOSET (fd, 30);
-                    RFIFOSKIP (fd, 91);
-                }
-                break;
-
-            case 0x7932:       // Request for an account deletion
-                if (RFIFOREST (fd) < 26)
-                    return;
-                WFIFOW (fd, 0) = 0x7933;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    // Char-server is notified of deletion (for characters deletion).
-                    unsigned char buf[65535];
-                    WBUFW (buf, 0) = 0x2730;
-                    WBUFL (buf, 2) = auth_dat[i].account_id;
-                    charif_sendallwos (-1, buf, 6);
-                    // send answer
-                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                    WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    // save deleted account in log file
-                    login_log
-                        ("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n",
-                         auth_dat[i].userid, auth_dat[i].account_id,
-                         ip);
-                    mmo_auth_tostr (buf, &auth_dat[i]);
-                    login_log ("%s\n", buf);
-                    // delete account
-                    memset (auth_dat[i].userid, '\0',
-                            sizeof (auth_dat[i].userid));
-                    auth_dat[i].account_id = -1;
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 6), account_name, 24);
-                    login_log
-                        ("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 26);
-                break;
-
-            case 0x7934:       // Request to change a password
-                if (RFIFOREST (fd) < 50)
-                    return;
-                WFIFOW (fd, 0) = 0x7935;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                    strcpy (auth_dat[i].pass, MD5_saltcrypt(RFIFOP (fd, 26), make_salt()));
-                    auth_dat[i].pass[39] = '\0';
-                    WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    login_log
-                        ("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n",
-                         auth_dat[i].userid, auth_dat[i].pass, ip);
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 6), account_name, 24);
-                    login_log
-                        ("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 50);
-                break;
-
-            case 0x7936:       // Request to modify a state
-                if (RFIFOREST (fd) < 50)
-                    return;
-                {
-                    char error_message[20];
-                    int  statut;
-                    WFIFOW (fd, 0) = 0x7937;
-                    WFIFOL (fd, 2) = -1;
-                    account_name = RFIFOP (fd, 2);
-                    account_name[23] = '\0';
-                    remove_control_chars (account_name);
-                    statut = RFIFOL (fd, 26);
-                    memcpy (error_message, RFIFOP (fd, 30), 20);
-                    error_message[19] = '\0';
-                    remove_control_chars (error_message);
-                    if (statut != 7 || error_message[0] == '\0')
-                    {           // 7: // 6 = Your are Prohibited to log in until %s
-                        strcpy (error_message, "-");
-                    }
-                    i = search_account_index (account_name);
-                    if (i != -1)
-                    {
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                        if (auth_dat[i].state == statut
-                            && strcmp (auth_dat[i].error_message,
-                                       error_message) == 0)
-                            login_log
-                                ("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n",
-                                 account_name, statut, ip);
-                        else
-                        {
-                            if (statut == 7)
-                                login_log
-                                    ("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n",
-                                     auth_dat[i].userid, statut,
-                                     error_message, ip);
-                            else
-                                login_log
-                                    ("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n",
-                                     auth_dat[i].userid, statut, ip);
-                            if (auth_dat[i].state == 0)
-                            {
-                                unsigned char buf[16];
-                                WBUFW (buf, 0) = 0x2731;
-                                WBUFL (buf, 2) = auth_dat[i].account_id;
-                                WBUFB (buf, 6) = 0; // 0: change of statut, 1: ban
-                                WBUFL (buf, 7) = statut;    // status or final date of a banishment
-                                charif_sendallwos (-1, buf, 11);
-                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                    if (auth_fifo[j].account_id ==
-                                        auth_dat[i].account_id)
-                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                            }
-                            auth_dat[i].state = statut;
-                            memcpy (auth_dat[i].error_message, error_message,
-                                    20);
-                        }
-                    }
-                    else
-                    {
-                        memcpy (WFIFOP (fd, 6), account_name, 24);
-                        login_log
-                            ("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n",
-                             account_name, statut, ip);
-                    }
-                    WFIFOL (fd, 30) = statut;
-                }
-                WFIFOSET (fd, 34);
-                RFIFOSKIP (fd, 50);
-                break;
-
-            case 0x7938:       // Request for servers list and # of online players
-                login_log ("'ladmin': Sending of servers list (ip: %s)\n", ip);
-                server_num = 0;
-                for (i = 0; i < MAX_SERVERS; i++)
-                {
-                    if (server_fd[i] >= 0)
-                    {
-                        WFIFOL (fd, 4 + server_num * 32) = server[i].ip;
-                        WFIFOW (fd, 4 + server_num * 32 + 4) = server[i].port;
-                        memcpy (WFIFOP (fd, 4 + server_num * 32 + 6),
-                                server[i].name, 20);
-                        WFIFOW (fd, 4 + server_num * 32 + 26) =
-                            server[i].users;
-                        WFIFOW (fd, 4 + server_num * 32 + 28) =
-                            server[i].maintenance;
-                        WFIFOW (fd, 4 + server_num * 32 + 30) = server[i].is_new;
-                        server_num++;
-                    }
-                }
-                WFIFOW (fd, 0) = 0x7939;
-                WFIFOW (fd, 2) = 4 + 32 * server_num;
-                WFIFOSET (fd, 4 + 32 * server_num);
-                RFIFOSKIP (fd, 2);
-                break;
-
-            case 0x793a:       // Request to password check
-                if (RFIFOREST (fd) < 50)
-                    return;
-                WFIFOW (fd, 0) = 0x793b;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-		    if ( pass_ok(RFIFOP (fd, 26), auth_dat[i].pass) )
-                    {
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                        login_log
-                            ("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n",
-                             auth_dat[i].userid, auth_dat[i].pass,
-                             ip);
-                    }
-                    else
-                    {
-                        char pass[24];
-                        memcpy (pass, RFIFOP (fd, 26), 24);
-                        pass[23] = '\0';
-                        remove_control_chars (pass);
-                        login_log
-                            ("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n",
-                             auth_dat[i].userid, pass, ip);
-                    }
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 6), account_name, 24);
-                    login_log
-                        ("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 50);
-                break;
-
-            case 0x793c:       // Request to modify sex
-                if (RFIFOREST (fd) < 27)
-                    return;
-                WFIFOW (fd, 0) = 0x793d;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                memcpy (WFIFOP (fd, 6), account_name, 24);
-                {
-                    char sex;
-                    sex = RFIFOB (fd, 26);
-                    if (sex != 'F' && sex != 'M')
-                    {
-                        if (sex > 31)
-                            login_log
-                                ("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n",
-                                 account_name, sex, ip);
-                        else
-                            login_log
-                                ("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n",
-                                 account_name, ip);
-                    }
-                    else
-                    {
-                        i = search_account_index (account_name);
-                        if (i != -1)
-                        {
-                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                            if (auth_dat[i].sex !=
-                                ((sex == 'S' || sex == 's') ? 2 : (sex == 'M'
-                                                                   || sex ==
-                                                                   'm')))
-                            {
-                                unsigned char buf[16];
-                                WFIFOL (fd, 2) = auth_dat[i].account_id;
-                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                    if (auth_fifo[j].account_id ==
-                                        auth_dat[i].account_id)
-                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                                auth_dat[i].sex = (sex == 'S'
-                                                   || sex ==
-                                                   's') ? 2 : (sex == 'M'
-                                                               || sex == 'm');
-                                login_log
-                                    ("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n",
-                                     auth_dat[i].userid, sex, ip);
-                                // send to all char-server the change
-                                WBUFW (buf, 0) = 0x2723;
-                                WBUFL (buf, 2) = auth_dat[i].account_id;
-                                WBUFB (buf, 6) = auth_dat[i].sex;
-                                charif_sendallwos (-1, buf, 7);
-                            }
-                            else
-                            {
-                                login_log
-                                    ("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n",
-                                     auth_dat[i].userid, sex, ip);
-                            }
-                        }
-                        else
-                        {
-                            login_log
-                                ("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n",
-                                 account_name, sex, ip);
-                        }
-                    }
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 27);
-                break;
-
-            case 0x793e:       // Request to modify GM level
-                if (RFIFOREST (fd) < 27)
-                    return;
-                WFIFOW (fd, 0) = 0x793f;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                memcpy (WFIFOP (fd, 6), account_name, 24);
-                {
-                    char new_gm_level;
-                    new_gm_level = RFIFOB (fd, 26);
-                    if (new_gm_level < 0 || new_gm_level > 99)
-                    {
-                        login_log
-                            ("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n",
-                             account_name, (int) new_gm_level, ip);
-                    }
-                    else
-                    {
-                        i = search_account_index (account_name);
-                        if (i != -1)
-                        {
-                            int  acc = auth_dat[i].account_id;
-                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                            if (isGM (acc) != new_gm_level)
-                            {
-                                // modification of the file
-                                FILE *fp, *fp2;
-                                int  lock;
-                                char line[512];
-                                int  GM_account, GM_level;
-                                int  modify_flag;
-                                char tmpstr[24];
-                                struct timeval tv;
-                                if ((fp2 =
-                                     lock_fopen (GM_account_filename,
-                                                 &lock)) != NULL)
-                                {
-                                    if ((fp =
-                                         fopen_ (GM_account_filename,
-                                                 "r")) != NULL)
-                                    {
-                                        gettimeofday (&tv, NULL);
-                                        strftime (tmpstr, 23, date_format,
-                                                  gmtime (&(tv.tv_sec)));
-                                        modify_flag = 0;
-                                        // read/write GM file
-                                        while (fgets
-                                               (line, sizeof (line) - 1, fp))
-                                        {
-                                            while (line[0] != '\0'
-                                                   && (line[strlen (line) - 1]
-                                                       == '\n'
-                                                       || line[strlen (line) -
-                                                               1] == '\r'))
-                                                line[strlen (line) - 1] =
-                                                    '\0';
-                                            if ((line[0] == '/'
-                                                 && line[1] == '/')
-                                                || line[0] == '\0')
-                                                fprintf (fp2, "%s\n",
-                                                         line);
-                                            else
-                                            {
-                                                if (sscanf
-                                                    (line, "%d %d",
-                                                     &GM_account,
-                                                     &GM_level) != 2
-                                                    && sscanf (line, "%d: %d",
-                                                               &GM_account,
-                                                               &GM_level) !=
-                                                    2)
-                                                    fprintf (fp2,
-                                                             "%s\n",
-                                                             line);
-                                                else if (GM_account != acc)
-                                                    fprintf (fp2,
-                                                             "%s\n",
-                                                             line);
-                                                else if (new_gm_level < 1)
-                                                {
-                                                    fprintf (fp2,
-                                                             "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n",
-                                                             tmpstr,
-                                                             acc,
-                                                             auth_dat
-                                                             [i].userid,
-                                                             GM_level, acc,
-                                                             new_gm_level);
-                                                    modify_flag = 1;
-                                                }
-                                                else
-                                                {
-                                                    fprintf (fp2,
-                                                             "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n",
-                                                             tmpstr,
-                                                             acc,
-                                                             auth_dat
-                                                             [i].userid,
-                                                             GM_level, acc,
-                                                             new_gm_level);
-                                                    modify_flag = 1;
-                                                }
-                                            }
-                                        }
-                                        if (modify_flag == 0)
-                                            fprintf (fp2,
-                                                     "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n",
-                                                     tmpstr, acc,
-                                                     auth_dat[i].userid, acc,
-                                                     new_gm_level);
-                                        fclose_ (fp);
-                                    }
-                                    else
-                                    {
-                                        login_log
-                                            ("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n",
-                                             auth_dat[i].userid, acc,
-                                             (int) new_gm_level, ip);
-                                    }
-                                    lock_fclose(fp2, GM_account_filename, &lock);
-                                    WFIFOL (fd, 2) = acc;
-                                    login_log
-                                        ("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n",
-                                         auth_dat[i].userid, acc,
-                                            (int) new_gm_level, ip);
-                                    // read and send new GM informations
-                                    read_gm_account ();
-                                    send_GM_accounts ();
-                                }
-                                else
-                                {
-                                    login_log
-                                        ("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n",
-                                         auth_dat[i].userid, acc,
-                                         (int) new_gm_level, ip);
-                                }
-                            }
-                            else
-                            {
-                                login_log
-                                    ("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n",
-                                     auth_dat[i].userid, acc,
-                                     (int) new_gm_level, ip);
-                            }
-                        }
-                        else
-                        {
-                            login_log
-                                ("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n",
-                                 account_name, (int) new_gm_level,
-                                 ip);
-                        }
-                    }
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 27);
-                break;
-
-            case 0x7940:       // Request to modify e-mail
-                if (RFIFOREST (fd) < 66)
-                    return;
-                WFIFOW (fd, 0) = 0x7941;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                memcpy (WFIFOP (fd, 6), account_name, 24);
-                {
-                    char email[40];
-                    memcpy (email, RFIFOP (fd, 26), 40);
-                    if (e_mail_check (email) == 0)
-                    {
-                        login_log
-                            ("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n",
-                             account_name, ip);
-                    }
-                    else
-                    {
-                        remove_control_chars (email);
-                        i = search_account_index (account_name);
-                        if (i != -1)
-                        {
-                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                            memcpy (auth_dat[i].email, email, 40);
-                            WFIFOL (fd, 2) = auth_dat[i].account_id;
-                            login_log
-                                ("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n",
-                                 auth_dat[i].userid, email, ip);
-                        }
-                        else
-                        {
-                            login_log
-                                ("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n",
-                                 account_name, email, ip);
-                        }
-                    }
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 66);
-                break;
-
-            case 0x7942:       // Request to modify memo field
-                if (RFIFOREST (fd) < 28
-                    || RFIFOREST (fd) < (28 + RFIFOW (fd, 26)))
-                    return;
-                WFIFOW (fd, 0) = 0x7943;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    int  size_of_memo = sizeof (auth_dat[i].memo);
-                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                    memset (auth_dat[i].memo, '\0', size_of_memo);
-                    if (RFIFOW (fd, 26) == 0)
-                    {
-                        strncpy (auth_dat[i].memo, "!", size_of_memo);
-                    }
-                    else if (RFIFOW (fd, 26) > size_of_memo - 1)
-                    {
-                        memcpy (auth_dat[i].memo, RFIFOP (fd, 28),
-                                size_of_memo - 1);
-                    }
-                    else
-                    {
-                        memcpy (auth_dat[i].memo, RFIFOP (fd, 28),
-                                RFIFOW (fd, 26));
-                    }
-                    auth_dat[i].memo[size_of_memo - 1] = '\0';
-                    remove_control_chars (auth_dat[i].memo);
-                    WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    login_log
-                        ("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n",
-                         auth_dat[i].userid, auth_dat[i].memo, ip);
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 6), account_name, 24);
-                    login_log
-                        ("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 28 + RFIFOW (fd, 26));
-                break;
-
-            case 0x7944:       // Request to found an account id
-                if (RFIFOREST (fd) < 26)
-                    return;
-                WFIFOW (fd, 0) = 0x7945;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                    WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    login_log
-                        ("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n",
-                         auth_dat[i].userid, auth_dat[i].account_id,
-                         ip);
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 6), account_name, 24);
-                    login_log
-                        ("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 26);
-                break;
-
-            case 0x7946:       // Request to found an account name
-                if (RFIFOREST (fd) < 6)
-                    return;
-                WFIFOW (fd, 0) = 0x7947;
-                WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                memset (WFIFOP (fd, 6), '\0', 24);
-                for (i = 0; i < auth_num; i++)
-                {
-                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
-                    {
-                        strncpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        login_log
-                            ("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n",
-                             auth_dat[i].userid, RFIFOL (fd, 2), ip);
-                        break;
-                    }
-                }
-                if (i == auth_num)
-                {
-                    login_log
-                        ("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n",
-                         RFIFOL (fd, 2), ip);
-                    strncpy (WFIFOP (fd, 6), "", 24);
-                }
-                WFIFOSET (fd, 30);
-                RFIFOSKIP (fd, 6);
-                break;
-
-            case 0x7948:       // Request to change the validity limit (timestamp) (absolute value)
-                if (RFIFOREST (fd) < 30)
-                    return;
-                {
-                    time_t timestamp;
-                    char tmpstr[2048];
-                    WFIFOW (fd, 0) = 0x7949;
-                    WFIFOL (fd, 2) = -1;
-                    account_name = RFIFOP (fd, 2);
-                    account_name[23] = '\0';
-                    remove_control_chars (account_name);
-                    timestamp = (time_t) RFIFOL (fd, 26);
-                    strftime (tmpstr, 24, date_format, gmtime (&timestamp));
-                    i = search_account_index (account_name);
-                    if (i != -1)
-                    {
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        login_log
-                            ("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n",
-                             auth_dat[i].userid, timestamp,
-                             (timestamp == 0 ? "unlimited" : tmpstr), ip);
-                        auth_dat[i].connect_until_time = timestamp;
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    }
-                    else
-                    {
-                        memcpy (WFIFOP (fd, 6), account_name, 24);
-                        login_log
-                            ("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", account_name, timestamp,
-                             (timestamp == 0 ? "unlimited" : tmpstr), ip);
-                    }
-                    WFIFOL (fd, 30) = timestamp;
-                }
-                WFIFOSET (fd, 34);
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x794a:       // Request to change the final date of a banishment (timestamp) (absolute value)
-                if (RFIFOREST (fd) < 30)
-                    return;
-                {
-                    time_t timestamp;
-                    char tmpstr[2048];
-                    WFIFOW (fd, 0) = 0x794b;
-                    WFIFOL (fd, 2) = -1;
-                    account_name = RFIFOP (fd, 2);
-                    account_name[23] = '\0';
-                    remove_control_chars (account_name);
-                    timestamp = (time_t) RFIFOL (fd, 26);
-                    if (timestamp <= time (NULL))
-                        timestamp = 0;
-                    strftime (tmpstr, 24, date_format, gmtime (&timestamp));
-                    i = search_account_index (account_name);
-                    if (i != -1)
-                    {
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                        login_log
-                            ("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n",
-                             auth_dat[i].userid, timestamp,
-                             (timestamp == 0 ? "no banishment" : tmpstr), ip);
-                        if (auth_dat[i].ban_until_time != timestamp)
-                        {
-                            if (timestamp != 0)
-                            {
-                                unsigned char buf[16];
-                                WBUFW (buf, 0) = 0x2731;
-                                WBUFL (buf, 2) = auth_dat[i].account_id;
-                                WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
-                                WBUFL (buf, 7) = timestamp; // status or final date of a banishment
-                                charif_sendallwos (-1, buf, 11);
-                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                    if (auth_fifo[j].account_id ==
-                                        auth_dat[i].account_id)
-                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                            }
-                            auth_dat[i].ban_until_time = timestamp;
-                        }
-                    }
-                    else
-                    {
-                        memcpy (WFIFOP (fd, 6), account_name, 24);
-                        login_log
-                            ("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n",
-                             account_name, timestamp,
-                             (timestamp == 0 ? "no banishment" : tmpstr), ip);
-                    }
-                    WFIFOL (fd, 30) = timestamp;
-                }
-                WFIFOSET (fd, 34);
-                RFIFOSKIP (fd, 30);
-                break;
-
-            case 0x794c:       // Request to change the final date of a banishment (timestamp) (relative change)
-                if (RFIFOREST (fd) < 38)
-                    return;
-                {
-                    time_t timestamp;
-                    struct tm *tmtime;
-                    char tmpstr[2048];
-                    WFIFOW (fd, 0) = 0x794d;
-                    WFIFOL (fd, 2) = -1;
-                    account_name = RFIFOP (fd, 2);
-                    account_name[23] = '\0';
-                    remove_control_chars (account_name);
-                    i = search_account_index (account_name);
-                    if (i != -1)
-                    {
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        if (auth_dat[i].ban_until_time == 0
-                            || auth_dat[i].ban_until_time < time (NULL))
-                            timestamp = time (NULL);
-                        else
-                            timestamp = auth_dat[i].ban_until_time;
-                        tmtime = gmtime (&timestamp);
-                        tmtime->tm_year =
-                            tmtime->tm_year + (short) RFIFOW (fd, 26);
-                        tmtime->tm_mon =
-                            tmtime->tm_mon + (short) RFIFOW (fd, 28);
-                        tmtime->tm_mday =
-                            tmtime->tm_mday + (short) RFIFOW (fd, 30);
-                        tmtime->tm_hour =
-                            tmtime->tm_hour + (short) RFIFOW (fd, 32);
-                        tmtime->tm_min =
-                            tmtime->tm_min + (short) RFIFOW (fd, 34);
-                        tmtime->tm_sec =
-                            tmtime->tm_sec + (short) RFIFOW (fd, 36);
-                        timestamp = mktime (tmtime);
-                        if (timestamp != -1)
-                        {
-                            if (timestamp <= time (NULL))
-                                timestamp = 0;
-                            strftime (tmpstr, 24, date_format,
-                                      gmtime (&timestamp));
-                            login_log
-                                ("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n",
-                                 auth_dat[i].userid,
-                                 (short) RFIFOW (fd, 26), (short) RFIFOW (fd,
-                                                                          28),
-                                 (short) RFIFOW (fd, 30), (short) RFIFOW (fd,
-                                                                          32),
-                                 (short) RFIFOW (fd, 34), (short) RFIFOW (fd,
-                                                                          36),
-                                 timestamp,
-                                 (timestamp == 0 ? "no banishment" : tmpstr),
-                                 ip);
-                            if (auth_dat[i].ban_until_time != timestamp)
-                            {
-                                if (timestamp != 0)
-                                {
-                                    unsigned char buf[16];
-                                    WBUFW (buf, 0) = 0x2731;
-                                    WBUFL (buf, 2) = auth_dat[i].account_id;
-                                    WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
-                                    WBUFL (buf, 7) = timestamp; // status or final date of a banishment
-                                    charif_sendallwos (-1, buf, 11);
-                                    for (j = 0; j < AUTH_FIFO_SIZE; j++)
-                                        if (auth_fifo[j].account_id ==
-                                            auth_dat[i].account_id)
-                                            auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
-                                }
-                                auth_dat[i].ban_until_time = timestamp;
-                            }
-                        }
-                        else
-                        {
-                            strftime (tmpstr, 24, date_format,
-                                      gmtime (&auth_dat[i].ban_until_time));
-                            login_log
-                                ("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
-                                 auth_dat[i].userid,
-                                 auth_dat[i].ban_until_time,
-                                 (auth_dat[i].ban_until_time ==
-                                  0 ? "no banishment" : tmpstr),
-                                 (short) RFIFOW (fd, 26), (short) RFIFOW (fd,
-                                                                          28),
-                                 (short) RFIFOW (fd, 30), (short) RFIFOW (fd,
-                                                                          32),
-                                 (short) RFIFOW (fd, 34), (short) RFIFOW (fd,
-                                                                          36),
-                                 ip);
-                        }
-                        WFIFOL (fd, 30) =
-                            (unsigned long) auth_dat[i].ban_until_time;
-                    }
-                    else
-                    {
-                        memcpy (WFIFOP (fd, 6), account_name, 24);
-                        login_log
-                            ("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n",
-                             account_name, ip);
-                        WFIFOL (fd, 30) = 0;
-                    }
-                }
-                WFIFOSET (fd, 34);
-                RFIFOSKIP (fd, 38);
-                break;
-
-            case 0x794e:       // Request to send a broadcast message
-                if (RFIFOREST (fd) < 8
-                    || RFIFOREST (fd) < (8 + RFIFOL (fd, 4)))
-                    return;
-                WFIFOW (fd, 0) = 0x794f;
-                WFIFOW (fd, 2) = -1;
-                if (RFIFOL (fd, 4) < 1)
-                {
-                    login_log
-                        ("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n",
-                         ip);
-                }
-                else
-                {
-                    // at least 1 char-server
-                    for (i = 0; i < MAX_SERVERS; i++)
-                        if (server_fd[i] >= 0)
-                            break;
-                    if (i == MAX_SERVERS)
-                    {
-                        login_log
-                            ("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n",
-                             ip);
-                    }
-                    else
-                    {
-                        char buf[32000];
-                        char message[32000];
-                        WFIFOW (fd, 2) = 0;
-                        memset (message, '\0', sizeof (message));
-                        memcpy (message, RFIFOP (fd, 8), RFIFOL (fd, 4));
-                        message[sizeof (message) - 1] = '\0';
-                        remove_control_chars (message);
-                        if (RFIFOW (fd, 2) == 0)
-                            login_log
-                                ("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n",
-                                 message, ip);
-                        else
-                            login_log
-                                ("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n",
-                                 message, ip);
-                        // send same message to all char-servers (no answer)
-                        memcpy (WBUFP (buf, 0), RFIFOP (fd, 0),
-                                8 + RFIFOL (fd, 4));
-                        WBUFW (buf, 0) = 0x2726;
-                        charif_sendallwos (-1, buf, 8 + RFIFOL (fd, 4));
-                    }
-                }
-                WFIFOSET (fd, 4);
-                RFIFOSKIP (fd, 8 + RFIFOL (fd, 4));
-                break;
-
-            case 0x7950:       // Request to change the validity limite (timestamp) (relative change)
-                if (RFIFOREST (fd) < 38)
-                    return;
-                {
-                    time_t timestamp;
-                    struct tm *tmtime;
-                    char tmpstr[2048];
-                    char tmpstr2[2048];
-                    WFIFOW (fd, 0) = 0x7951;
-                    WFIFOL (fd, 2) = -1;
-                    account_name = RFIFOP (fd, 2);
-                    account_name[23] = '\0';
-                    remove_control_chars (account_name);
-                    i = search_account_index (account_name);
-                    if (i != -1)
-                    {
-                        WFIFOL (fd, 2) = auth_dat[i].account_id;
-                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
-                        timestamp = auth_dat[i].connect_until_time;
-                        if (add_to_unlimited_account == 0 && timestamp == 0)
-                        {
-                            login_log
-                                ("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n",
-                                 auth_dat[i].userid, ip);
-                            WFIFOL (fd, 30) = 0;
-                        }
-                        else
-                        {
-                            if (timestamp == 0 || timestamp < time (NULL))
-                                timestamp = time (NULL);
-                            tmtime = gmtime (&timestamp);
-                            tmtime->tm_year =
-                                tmtime->tm_year + (short) RFIFOW (fd, 26);
-                            tmtime->tm_mon =
-                                tmtime->tm_mon + (short) RFIFOW (fd, 28);
-                            tmtime->tm_mday =
-                                tmtime->tm_mday + (short) RFIFOW (fd, 30);
-                            tmtime->tm_hour =
-                                tmtime->tm_hour + (short) RFIFOW (fd, 32);
-                            tmtime->tm_min =
-                                tmtime->tm_min + (short) RFIFOW (fd, 34);
-                            tmtime->tm_sec =
-                                tmtime->tm_sec + (short) RFIFOW (fd, 36);
-                            timestamp = mktime (tmtime);
-                            if (timestamp != -1)
-                            {
-                                strftime (tmpstr, 24, date_format,
-                                          gmtime (&auth_dat
-                                                  [i].connect_until_time));
-                                strftime (tmpstr2, 24, date_format,
-                                          gmtime (&timestamp));
-                                login_log
-                                    ("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n",
-                                     auth_dat[i].userid,
-                                     auth_dat[i].connect_until_time,
-                                     (auth_dat[i].connect_until_time ==
-                                      0 ? "unlimited" : tmpstr),
-                                     (short) RFIFOW (fd, 26),
-                                     (short) RFIFOW (fd, 28),
-                                     (short) RFIFOW (fd, 30),
-                                     (short) RFIFOW (fd, 32),
-                                     (short) RFIFOW (fd, 34),
-                                     (short) RFIFOW (fd, 36), timestamp,
-                                     (timestamp == 0 ? "unlimited" : tmpstr2),
-                                     ip);
-                                auth_dat[i].connect_until_time = timestamp;
-                                WFIFOL (fd, 30) =
-                                    (unsigned long)
-                                    auth_dat[i].connect_until_time;
-                            }
-                            else
-                            {
-                                strftime (tmpstr, 24, date_format,
-                                          gmtime (&auth_dat
-                                                  [i].connect_until_time));
-                                login_log
-                                    ("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
-                                     auth_dat[i].userid,
-                                     auth_dat[i].connect_until_time,
-                                     (auth_dat[i].connect_until_time ==
-                                      0 ? "unlimited" : tmpstr),
-                                     (short) RFIFOW (fd, 26),
-                                     (short) RFIFOW (fd, 28),
-                                     (short) RFIFOW (fd, 30),
-                                     (short) RFIFOW (fd, 32),
-                                     (short) RFIFOW (fd, 34),
-                                     (short) RFIFOW (fd, 36), ip);
-                                WFIFOL (fd, 30) = 0;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        memcpy (WFIFOP (fd, 6), account_name, 24);
-                        login_log
-                            ("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n",
-                             account_name, ip);
-                        WFIFOL (fd, 30) = 0;
-                    }
-                }
-                WFIFOSET (fd, 34);
-                RFIFOSKIP (fd, 38);
-                break;
-
-            case 0x7952:       // Request about informations of an account (by account name)
-                if (RFIFOREST (fd) < 26)
-                    return;
-                WFIFOW (fd, 0) = 0x7953;
-                WFIFOL (fd, 2) = -1;
-                account_name = RFIFOP (fd, 2);
-                account_name[23] = '\0';
-                remove_control_chars (account_name);
-                i = search_account_index (account_name);
-                if (i != -1)
-                {
-                    WFIFOL (fd, 2) = auth_dat[i].account_id;
-                    WFIFOB (fd, 6) =
-                        (unsigned char) isGM (auth_dat[i].account_id);
-                    memcpy (WFIFOP (fd, 7), auth_dat[i].userid, 24);
-                    WFIFOB (fd, 31) = auth_dat[i].sex;
-                    WFIFOL (fd, 32) = auth_dat[i].logincount;
-                    WFIFOL (fd, 36) = auth_dat[i].state;
-                    memcpy (WFIFOP (fd, 40), auth_dat[i].error_message, 20);
-                    memcpy (WFIFOP (fd, 60), auth_dat[i].lastlogin, 24);
-                    memcpy (WFIFOP (fd, 84), auth_dat[i].last_ip, 16);
-                    memcpy (WFIFOP (fd, 100), auth_dat[i].email, 40);
-                    WFIFOL (fd, 140) =
-                        (unsigned long) auth_dat[i].connect_until_time;
-                    WFIFOL (fd, 144) =
-                        (unsigned long) auth_dat[i].ban_until_time;
-                    WFIFOW (fd, 148) = strlen (auth_dat[i].memo);
-                    if (auth_dat[i].memo[0])
-                    {
-                        memcpy (WFIFOP (fd, 150), auth_dat[i].memo,
-                                strlen (auth_dat[i].memo));
-                    }
-                    login_log
-                        ("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n",
-                         auth_dat[i].userid, auth_dat[i].account_id,
-                         ip);
-                    WFIFOSET (fd, 150 + strlen (auth_dat[i].memo));
-                }
-                else
-                {
-                    memcpy (WFIFOP (fd, 7), account_name, 24);
-                    WFIFOW (fd, 148) = 0;
-                    login_log
-                        ("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n",
-                         account_name, ip);
-                    WFIFOSET (fd, 150);
-                }
-                RFIFOSKIP (fd, 26);
-                break;
-
-            case 0x7954:       // Request about information of an account (by account id)
-                if (RFIFOREST (fd) < 6)
-                    return;
-                WFIFOW (fd, 0) = 0x7953;
-                WFIFOL (fd, 2) = RFIFOL (fd, 2);
-                memset (WFIFOP (fd, 7), '\0', 24);
-                for (i = 0; i < auth_num; i++)
-                {
-                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
-                    {
-                        login_log
-                            ("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n",
-                             auth_dat[i].userid, RFIFOL (fd, 2), ip);
-                        WFIFOB (fd, 6) =
-                            (unsigned char) isGM (auth_dat[i].account_id);
-                        memcpy (WFIFOP (fd, 7), auth_dat[i].userid, 24);
-                        WFIFOB (fd, 31) = auth_dat[i].sex;
-                        WFIFOL (fd, 32) = auth_dat[i].logincount;
-                        WFIFOL (fd, 36) = auth_dat[i].state;
-                        memcpy (WFIFOP (fd, 40), auth_dat[i].error_message,
-                                20);
-                        memcpy (WFIFOP (fd, 60), auth_dat[i].lastlogin, 24);
-                        memcpy (WFIFOP (fd, 84), auth_dat[i].last_ip, 16);
-                        memcpy (WFIFOP (fd, 100), auth_dat[i].email, 40);
-                        WFIFOL (fd, 140) =
-                            (unsigned long) auth_dat[i].connect_until_time;
-                        WFIFOL (fd, 144) =
-                            (unsigned long) auth_dat[i].ban_until_time;
-                        WFIFOW (fd, 148) = strlen (auth_dat[i].memo);
-                        if (auth_dat[i].memo[0])
-                        {
-                            memcpy (WFIFOP (fd, 150), auth_dat[i].memo,
-                                    strlen (auth_dat[i].memo));
-                        }
-                        WFIFOSET (fd, 150 + strlen (auth_dat[i].memo));
-                        break;
-                    }
-                }
-                if (i == auth_num)
-                {
-                    login_log
-                        ("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n",
-                         RFIFOL (fd, 2), ip);
-                    strncpy (WFIFOP (fd, 7), "", 24);
-                    WFIFOW (fd, 148) = 0;
-                    WFIFOSET (fd, 150);
-                }
-                RFIFOSKIP (fd, 6);
-                break;
-
-            case 0x7955:       // Request to reload GM file (no answer)
-                login_log
-                    ("'ladmin': Request to re-load GM configuration file (ip: %s).\n",
-                     ip);
-                read_gm_account ();
-                // send GM accounts to all char-servers
-                send_GM_accounts ();
-                RFIFOSKIP (fd, 2);
-                break;
-
-            default:
-            {
-                FILE *logfp;
-                char tmpstr[24];
-                struct timeval tv;
-                logfp = fopen_ (login_log_unknown_packets_filename, "a");
-                if (logfp)
-                {
-                    gettimeofday (&tv, NULL);
-                    strftime (tmpstr, 23, date_format, gmtime (&(tv.tv_sec)));
-                    fprintf (logfp,
-                             "%s.%03d: receiving of an unknown packet -> disconnection\n",
-                             tmpstr, (int) tv.tv_usec / 1000);
-                    fprintf (logfp,
-                             "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
-                             fd, ip, RFIFOW (fd, 0), RFIFOREST (fd));
-                    fprintf (logfp, "Detail (in hex):\n");
-                    fprintf (logfp,
-                             "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-                    memset (tmpstr, '\0', sizeof (tmpstr));
-                    for (i = 0; i < RFIFOREST (fd); i++)
-                    {
-                        if ((i & 15) == 0)
-                            fprintf (logfp, "%04X ", i);
-                        fprintf (logfp, "%02x ", RFIFOB (fd, i));
-                        if (RFIFOB (fd, i) > 0x1f)
-                            tmpstr[i % 16] = RFIFOB (fd, i);
-                        else
-                            tmpstr[i % 16] = '.';
-                        if ((i - 7) % 16 == 0)  // -8 + 1
-                            fprintf (logfp, " ");
-                        else if ((i + 1) % 16 == 0)
-                        {
-                            fprintf (logfp, " %s\n", tmpstr);
-                            memset (tmpstr, '\0', sizeof (tmpstr));
-                        }
-                    }
-                    if (i % 16 != 0)
-                    {
-                        for (j = i; j % 16 != 0; j++)
-                        {
-                            fprintf (logfp, "   ");
-                            if ((j - 7) % 16 == 0)  // -8 + 1
-                                fprintf (logfp, " ");
-                        }
-                        fprintf (logfp, " %s\n", tmpstr);
-                    }
-                    fprintf (logfp, "\n");
-                    fclose_ (logfp);
-                }
-            }
-                login_log
-                    ("'ladmin': End of connection, unknown packet (ip: %s)\n",
-                     ip);
-                session[fd]->eof = 1;
-                printf
-                    ("Remote administration has been disconnected (unknown packet).\n");
-                return;
-        }
-        //WFIFOW(fd,0) = 0x791f;
-        //WFIFOSET(fd,2);
-    }
-    return;
-}
-
-//--------------------------------------------
-// Test to know if an IP come from LAN or WAN.
-//--------------------------------------------
-int lan_ip_check (unsigned char *p)
-{
-    int  i;
-    int  lancheck = 1;
-
-//  printf("lan_ip_check: to compare: %d.%d.%d.%d, network: %d.%d.%d.%d/%d.%d.%d.%d\n",
-//         p[0], p[1], p[2], p[3],
-//         subneti[0], subneti[1], subneti[2], subneti[3],
-//         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
-    for (i = 0; i < 4; i++)
-    {
-        if ((subneti[i] & subnetmaski[i]) != (p[i] & subnetmaski[i]))
-        {
-            lancheck = 0;
-            break;
-        }
-    }
-    printf ("LAN test (result): %s source\033[0m.\n",
-            (lancheck) ? "\033[1;36mLAN" : "\033[1;32mWAN");
-    return lancheck;
-}
-
-//----------------------------------------------------------------------------------------
-// Default packet parsing (normal players or administation/char-server connexion requests)
-//----------------------------------------------------------------------------------------
-void parse_login (int fd)
-{
-    struct mmo_account account;
-    int  result, i, j;
-    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
-    char ip[16];
-    int  host_len;
-
-    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-
-    if (session[fd]->eof)
-    {
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    while (RFIFOREST (fd) >= 2)
-    {
-        if (display_parse_login == 1)
-        {
-            if (RFIFOW (fd, 0) == 0x64 || RFIFOW (fd, 0) == 0x01dd)
-            {
-                if (RFIFOREST (fd) >= ((RFIFOW (fd, 0) == 0x64) ? 55 : 47))
-                    printf
-                        ("parse_login: connection #%d, packet: 0x%x (with being read: %d), account: %s.\n",
-                         fd, RFIFOW (fd, 0), RFIFOREST (fd), RFIFOP (fd, 6));
-            }
-            else if (RFIFOW (fd, 0) == 0x2710)
-            {
-                if (RFIFOREST (fd) >= 86)
-                    printf
-                        ("parse_login: connection #%d, packet: 0x%x (with being read: %d), server: %s.\n",
-                         fd, RFIFOW (fd, 0), RFIFOREST (fd), RFIFOP (fd, 60));
-            }
-            else
-                printf
-                    ("parse_login: connection #%d, packet: 0x%x (with being read: %d).\n",
-                     fd, RFIFOW (fd, 0), RFIFOREST (fd));
-        }
-
-        switch (RFIFOW (fd, 0))
-        {
-            case 0x200:        // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
-                if (RFIFOREST (fd) < 26)
-                    return;
-                RFIFOSKIP (fd, 26);
-                break;
-
-            case 0x204:        // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
-                if (RFIFOREST (fd) < 18)
-                    return;
-                RFIFOSKIP (fd, 18);
-                break;
-
-            case 0x64:         // Ask connection of a client
-            case 0x01dd:       // Ask connection of a client (encryption mode)
-                if (RFIFOREST (fd) < ((RFIFOW (fd, 0) == 0x64) ? 55 : 47))
-                    return;
-
-                account.userid = RFIFOP (fd, 6);
-                account.userid[23] = '\0';
-                remove_control_chars (account.userid);
-                account.passwd = RFIFOP (fd, 30);
-                if (RFIFOW (fd, 0) == 0x64)
-                {
-                    account.passwd[23] = '\0';
-                    remove_control_chars (account.passwd);
-                }
-#ifdef PASSWORDENC
-                account.passwdenc =
-                    (RFIFOW (fd, 0) == 0x64) ? 0 : PASSWORDENC;
-#else
-                account.passwdenc = 0;
-#endif
-
-                if (RFIFOW (fd, 0) == 0x64)
-                {
-                    login_log
-                        ("Request for connection (non encryption mode) of %s (ip: %s).\n",
-                         account.userid, ip);
-                }
-                else
-                {
-                    login_log
-                        ("Request for connection (encryption mode) of %s (ip: %s).\n",
-                         account.userid, ip);
-                }
-
-                if (!check_ip (session[fd]->client_addr.sin_addr.s_addr))
-                {
-                    login_log
-                        ("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n",
-                         ip);
-                    WFIFOW (fd, 0) = 0x6a;
-                    WFIFOB (fd, 2) = 0x03;
-                    WFIFOSET (fd, 3);
-                    RFIFOSKIP (fd, (RFIFOW (fd, 0) == 0x64) ? 55 : 47);
-                    break;
-                }
-
-                result = mmo_auth (&account, fd);
-                if (result == -1)
-                {
-                    int  gm_level = isGM (account.account_id);
-                    if (min_level_to_connect > gm_level)
-                    {
-                        login_log
-                            ("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n",
-                             min_level_to_connect, account.userid,
-                             gm_level, ip);
-                        WFIFOW (fd, 0) = 0x81;
-                        WFIFOL (fd, 2) = 1; // 01 = Server closed
-                        WFIFOSET (fd, 3);
-                    }
-                    else
-                    {
-                        int  version_2 = RFIFOB (fd, 54);   // version 2
-
-                        if (gm_level)
-                            printf
-                                ("Connection of the GM (level:%d) account '%s' accepted.\n",
-                                 gm_level, account.userid);
-                        else
-                            printf
-                                ("Connection of the account '%s' accepted.\n",
-                                 account.userid);
-
-                        /*
-                         * Add a 0x0063 packet, which contains the name of the update host.  The packet will only
-                         * be sent if login_athena.conf contains a non-null entry for "update_host:"
-                         *
-                         * Because older clients cannot handle the 0x63 packet, we check the "version 2" value
-                         * from the incoming 0x64 packet (the byte at offset 54).  If bit 0 of this is set,
-                         * then the client can safely accept the 0x63 packet.  The "version 2" value is not
-                         * otherwise used by eAthena.
-                         */
-                        if ((RFIFOW (fd, 0) == 0x64)
-                            && (version_2 & VERSION_2_UPDATEHOST))
-                        {
-                            host_len = (int) strlen (update_host);
-                            if (host_len > 0)
-                            {
-                                WFIFOW (fd, 0) = 0x63;
-                                WFIFOW (fd, 2) = 4 + host_len;
-                                memcpy (WFIFOP (fd, 4), update_host,
-                                        host_len);
-                                WFIFOSET (fd, 4 + host_len);
-                            }
-                        }
-
-                        // Load list of char servers into outbound packet
-                        server_num = 0;
-                        if (version_2 && VERSION_2_SERVERORDER)
-                            for (i = 0; i < MAX_SERVERS; i++)
-                            {
-                                if (server_fd[i] >= 0)
-                                {
-                                    if (lan_ip_check (p))
-                                        WFIFOL (fd, 47 + server_num * 32) =
-                                            inet_addr (lan_char_ip);
-                                    else
-                                        WFIFOL (fd, 47 + server_num * 32) =
-                                            server[i].ip;
-                                    WFIFOW (fd, 47 + server_num * 32 + 4) =
-                                        server[i].port;
-                                    memcpy (WFIFOP
-                                            (fd, 47 + server_num * 32 + 6),
-                                            server[i].name, 20);
-                                    WFIFOW (fd, 47 + server_num * 32 + 26) =
-                                        server[i].users;
-                                    WFIFOW (fd, 47 + server_num * 32 + 28) =
-                                        server[i].maintenance;
-                                    WFIFOW (fd, 47 + server_num * 32 + 30) =
-                                        server[i].is_new;
-                                    server_num++;
-                                }
-                            }
-                        else    // Send them in reverse, as the client defaults to the second (!) one
-                            for (i = MAX_SERVERS - 1; i >= 0; i--)
-                            {
-                                if (server_fd[i] >= 0)
-                                {
-                                    if (lan_ip_check (p))
-                                        WFIFOL (fd, 47 + server_num * 32) =
-                                            inet_addr (lan_char_ip);
-                                    else
-                                        WFIFOL (fd, 47 + server_num * 32) =
-                                            server[i].ip;
-                                    WFIFOW (fd, 47 + server_num * 32 + 4) =
-                                        server[i].port;
-                                    memcpy (WFIFOP
-                                            (fd, 47 + server_num * 32 + 6),
-                                            server[i].name, 20);
-                                    WFIFOW (fd, 47 + server_num * 32 + 26) =
-                                        server[i].users;
-                                    WFIFOW (fd, 47 + server_num * 32 + 28) =
-                                        server[i].maintenance;
-                                    WFIFOW (fd, 47 + server_num * 32 + 30) =
-                                        server[i].is_new;
-                                    server_num++;
-                                }
-                            }
-                        // if at least 1 char-server
-                        if (server_num > 0)
-                        {
-                            WFIFOW (fd, 0) = 0x69;
-                            WFIFOW (fd, 2) = 47 + 32 * server_num;
-                            WFIFOL (fd, 4) = account.login_id1;
-                            WFIFOL (fd, 8) = account.account_id;
-                            WFIFOL (fd, 12) = account.login_id2;
-                            WFIFOL (fd, 16) = 0;    // in old version, that was for ip (not more used)
-                            memcpy (WFIFOP (fd, 20), account.lastlogin, 24);    // in old version, that was for name (not more used)
-                            WFIFOB (fd, 46) = account.sex;
-                            WFIFOSET (fd, 47 + 32 * server_num);
-                            if (auth_fifo_pos >= AUTH_FIFO_SIZE)
-                                auth_fifo_pos = 0;
-                            auth_fifo[auth_fifo_pos].account_id =
-                                account.account_id;
-                            auth_fifo[auth_fifo_pos].login_id1 =
-                                account.login_id1;
-                            auth_fifo[auth_fifo_pos].login_id2 =
-                                account.login_id2;
-                            auth_fifo[auth_fifo_pos].sex = account.sex;
-                            auth_fifo[auth_fifo_pos].delflag = 0;
-                            auth_fifo[auth_fifo_pos].ip =
-                                session[fd]->client_addr.sin_addr.s_addr;
-                            auth_fifo_pos++;
-                            // if no char-server, don't send void list of servers, just disconnect the player with proper message
-                        }
-                        else
-                        {
-                            login_log
-                                ("Connection refused: there is no char-server online (account: %s, ip: %s).\n",
-                                 account.userid, ip);
-                            WFIFOW (fd, 0) = 0x81;
-                            WFIFOL (fd, 2) = 1; // 01 = Server closed
-                            WFIFOSET (fd, 3);
-                        }
-                    }
-                }
-                else
-                {
-                    memset (WFIFOP (fd, 0), '\0', 23);
-                    WFIFOW (fd, 0) = 0x6a;
-                    WFIFOB (fd, 2) = result;
-                    if (result == 6)
-                    {           // 6 = Your are Prohibited to log in until %s
-                        i = search_account_index (account.userid);
-                        if (i != -1)
-                        {
-                            if (auth_dat[i].ban_until_time != 0)
-                            {   // if account is banned, we send ban timestamp
-                                char tmpstr[256];
-                                strftime (tmpstr, 20, date_format,
-                                          gmtime (&auth_dat
-                                                  [i].ban_until_time));
-                                tmpstr[19] = '\0';
-                                memcpy (WFIFOP (fd, 3), tmpstr, 20);
-                            }
-                            else
-                            {   // we send error message
-                                memcpy (WFIFOP (fd, 3),
-                                        auth_dat[i].error_message, 20);
-                            }
-                        }
-                    }
-                    WFIFOSET (fd, 23);
-                }
-                RFIFOSKIP (fd, (RFIFOW (fd, 0) == 0x64) ? 55 : 47);
-                break;
-
-            case 0x01db:       // Sending request of the coding key
-            case 0x791a:       // Sending request of the coding key (administration packet)
-            {
-                struct login_session_data *ld;
-                if (session[fd]->session_data)
-                {
-                    printf
-                        ("login: abnormal request of MD5 key (already opened session).\n");
-                    session[fd]->eof = 1;
-                    return;
-                }
-                CREATE (ld, struct login_session_data, 1);
-                session[fd]->session_data = ld;
-                if (!ld)
-                {
-                    printf
-                        ("login: Request for md5 key: memory allocation failure (malloc)!\n");
-                    session[fd]->eof = 1;
-                    return;
-                }
-                if (RFIFOW (fd, 0) == 0x01db)
-                {
-                    login_log ("Sending request of the coding key (ip: %s)\n",
-                               ip);
-                }
-                else
-                {
-                    login_log
-                        ("'ladmin': Sending request of the coding key (ip: %s)\n",
-                         ip);
-                }
-                // Creation of the coding key
-                memset (ld->md5key, '\0', sizeof (ld->md5key));
-                ld->md5keylen = rand () % 4 + 12;
-                for (i = 0; i < ld->md5keylen; i++)
-                    ld->md5key[i] = rand () % 255 + 1;
-
-                RFIFOSKIP (fd, 2);
-                WFIFOW (fd, 0) = 0x01dc;
-                WFIFOW (fd, 2) = 4 + ld->md5keylen;
-                memcpy (WFIFOP (fd, 4), ld->md5key, ld->md5keylen);
-                WFIFOSET (fd, WFIFOW (fd, 2));
-            }
-                break;
-
-            case 0x2710:       // Connection request of a char-server
-                if (RFIFOREST (fd) < 86)
-                    return;
-                {
-                    int  GM_value, len;
-                    unsigned char *server_name;
-                    account.userid = RFIFOP (fd, 2);
-                    account.userid[23] = '\0';
-                    remove_control_chars (account.userid);
-                    account.passwd = RFIFOP (fd, 26);
-                    account.passwd[23] = '\0';
-                    remove_control_chars (account.passwd);
-                    account.passwdenc = 0;
-                    server_name = RFIFOP (fd, 60);
-                    server_name[19] = '\0';
-                    remove_control_chars (server_name);
-                    login_log
-                        ("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n",
-                         server_name, RFIFOB (fd, 54), RFIFOB (fd, 55),
-                         RFIFOB (fd, 56), RFIFOB (fd, 57), RFIFOW (fd, 58),
-                         ip);
-                    result = mmo_auth (&account, fd);
-
-                    if (result == -1 && account.sex == 2)
-                    {
-                        // If this is the main server, and we don't already have a main server
-                        if (server_fd[0] <= 0
-                            && strcasecmp (server_name, main_server) == 0)
-                        {
-                            account.account_id = 0;
-                        }
-                        else
-                        {
-                            int  i;
-                            for (i = 1; i < MAX_SERVERS; i++)
-                            {
-                                if (server_fd[i] <= 0)
-                                {
-                                    account.account_id = i;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-
-                    if (result == -1 && account.sex == 2
-                        && account.account_id < MAX_SERVERS
-                        && server_fd[account.account_id] == -1)
-                    {
-                        login_log
-                            ("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)\n",
-                             server_name, account.userid,
-                             account.passwd, ip);
-                        printf
-                            ("Connection of the char-server '%s' accepted.\n",
-                             server_name);
-                        memset (&server[account.account_id], 0,
-                                sizeof (struct mmo_char_server));
-                        server[account.account_id].ip = RFIFOL (fd, 54);
-                        server[account.account_id].port = RFIFOW (fd, 58);
-                        memcpy (server[account.account_id].name, server_name,
-                                20);
-                        server[account.account_id].users = 0;
-                        server[account.account_id].maintenance =
-                            RFIFOW (fd, 82);
-                        server[account.account_id].is_new = RFIFOW (fd, 84);
-                        server_fd[account.account_id] = fd;
-                        if (anti_freeze_enable)
-                            server_freezeflag[account.account_id] = 5;  // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
-                        WFIFOW (fd, 0) = 0x2711;
-                        WFIFOB (fd, 2) = 0;
-                        WFIFOSET (fd, 3);
-                        session[fd]->func_parse = parse_fromchar;
-                        realloc_fifo (fd, FIFOSIZE_SERVERLINK,
-                                      FIFOSIZE_SERVERLINK);
-                        // send GM account to char-server
-                        len = 4;
-                        WFIFOW (fd, 0) = 0x2732;
-                        for (i = 0; i < auth_num; i++)
-                            // send only existing accounts. We can not create a GM account when server is online.
-                            if ((GM_value =
-                                 isGM (auth_dat[i].account_id)) > 0)
-                            {
-                                WFIFOL (fd, len) = auth_dat[i].account_id;
-                                WFIFOB (fd, len + 4) =
-                                    (unsigned char) GM_value;
-                                len += 5;
-                            }
-                        WFIFOW (fd, 2) = len;
-                        WFIFOSET (fd, len);
-                    }
-                    else
-                    {
-                        login_log
-                            ("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)\n",
-                             server_name, account.userid,
-                             account.passwd, ip);
-                        WFIFOW (fd, 0) = 0x2711;
-                        WFIFOB (fd, 2) = 3;
-                        WFIFOSET (fd, 3);
-                    }
-                }
-                RFIFOSKIP (fd, 86);
-                return;
-
-            case 0x7530:       // Request of the server version
-                login_log ("Sending of the server version (ip: %s)\n",
-                           ip);
-                WFIFOW (fd, 0) = 0x7531;
-                WFIFOB (fd, 2) = -1;
-                WFIFOB (fd, 3) = 'T';
-                WFIFOB (fd, 4) = 'M';
-                WFIFOB (fd, 5) = 'W';
-                WFIFOL (fd, 6) = new_account_flag ? 1 : 0;
-                WFIFOSET (fd, 10);
-                RFIFOSKIP (fd, 2);
-                break;
-
-            case 0x7532:       // Request to end connection
-                login_log ("End of connection (ip: %s)\n", ip);
-                session[fd]->eof = 1;
-                return;
-
-            case 0x7918:       // Request for administation login
-                if (RFIFOREST (fd) < 4
-                    || RFIFOREST (fd) < ((RFIFOW (fd, 2) == 0) ? 28 : 20))
-                    return;
-                WFIFOW (fd, 0) = 0x7919;
-                WFIFOB (fd, 2) = 1;
-                if (!check_ladminip
-                    (session[fd]->client_addr.sin_addr.s_addr))
-                {
-                    login_log
-                        ("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n",
-                         ip);
-                }
-                else
-                {
-                    struct login_session_data *ld = (struct login_session_data *)session[fd]->session_data;
-                    if (RFIFOW (fd, 2) == 0)
-                    {           // non encrypted password
-                        unsigned char *password;
-                        password = RFIFOP (fd, 4);
-                        password[23] = '\0';
-                        remove_control_chars (password);
-                        // If remote administration is enabled and password sent by client matches password read from login server configuration file
-                        if ((admin_state == 1)
-                            && (strcmp (password, admin_pass) == 0))
-                        {
-                            login_log
-                                ("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n",
-                                 password, ip);
-                            printf
-                                ("Connection of a remote administration accepted (non encrypted password).\n");
-                            WFIFOB (fd, 2) = 0;
-                            session[fd]->func_parse = parse_admin;
-                        }
-                        else if (admin_state != 1)
-                            login_log
-                                ("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n",
-                                 password, ip);
-                        else
-                            login_log
-                                ("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n",
-                                 password, ip);
-                    }
-                    else
-                    {           // encrypted password
-                        if (!ld)
-                            printf
-                                ("'ladmin'-login: error! MD5 key not created/requested for an administration login.\n");
-                        else
-                        {
-                            char md5str[64] = "", md5bin[32];
-                            if (RFIFOW (fd, 2) == 1)
-                            {
-                                strncpy (md5str, ld->md5key, sizeof (ld->md5key));  // 20
-                                strcat (md5str, admin_pass);    // 24
-                            }
-                            else if (RFIFOW (fd, 2) == 2)
-                            {
-                                strncpy (md5str, admin_pass, sizeof (admin_pass));  // 24
-                                strcat (md5str, ld->md5key);    // 20
-                            }
-                            MD5_to_bin(MD5_from_cstring(md5str), md5bin);
-                            // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file
-                            if ((admin_state == 1)
-                                && (memcmp (md5bin, RFIFOP (fd, 4), 16) == 0))
-                            {
-                                login_log
-                                    ("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n",
-                                     ip);
-                                printf
-                                    ("Connection of a remote administration accepted (encrypted password).\n");
-                                WFIFOB (fd, 2) = 0;
-                                session[fd]->func_parse = parse_admin;
-                            }
-                            else if (admin_state != 1)
-                                login_log
-                                    ("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)\n",
-                                     ip);
-                            else
-                                login_log
-                                    ("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)\n",
-                                     ip);
-                        }
-                    }
-                }
-                WFIFOSET (fd, 3);
-                RFIFOSKIP (fd, (RFIFOW (fd, 2) == 0) ? 28 : 20);
-                break;
-
-            default:
-                if (save_unknown_packets)
-                {
-                    FILE *logfp;
-                    char tmpstr[24];
-                    struct timeval tv;
-                    logfp = fopen_ (login_log_unknown_packets_filename, "a");
-                    if (logfp)
-                    {
-                        gettimeofday (&tv, NULL);
-                        strftime (tmpstr, 23, date_format,
-                                  gmtime (&(tv.tv_sec)));
-                        fprintf (logfp,
-                                 "%s.%03d: receiving of an unknown packet -> disconnection\n",
-                                 tmpstr, (int) tv.tv_usec / 1000);
-                        fprintf (logfp,
-                                 "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
-                                 fd, ip, RFIFOW (fd, 0),
-                                 RFIFOREST (fd));
-                        fprintf (logfp, "Detail (in hex):\n");
-                        fprintf (logfp,
-                                 "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
-                        memset (tmpstr, '\0', sizeof (tmpstr));
-                        for (i = 0; i < RFIFOREST (fd); i++)
-                        {
-                            if ((i & 15) == 0)
-                                fprintf (logfp, "%04X ", i);
-                            fprintf (logfp, "%02x ", RFIFOB (fd, i));
-                            if (RFIFOB (fd, i) > 0x1f)
-                                tmpstr[i % 16] = RFIFOB (fd, i);
-                            else
-                                tmpstr[i % 16] = '.';
-                            if ((i - 7) % 16 == 0)  // -8 + 1
-                                fprintf (logfp, " ");
-                            else if ((i + 1) % 16 == 0)
-                            {
-                                fprintf (logfp, " %s\n", tmpstr);
-                                memset (tmpstr, '\0', sizeof (tmpstr));
-                            }
-                        }
-                        if (i % 16 != 0)
-                        {
-                            for (j = i; j % 16 != 0; j++)
-                            {
-                                fprintf (logfp, "   ");
-                                if ((j - 7) % 16 == 0)  // -8 + 1
-                                    fprintf (logfp, " ");
-                            }
-                            fprintf (logfp, " %s\n", tmpstr);
-                        }
-                        fprintf (logfp, "\n");
-                        fclose_ (logfp);
-                    }
-                }
-                login_log ("End of connection, unknown packet (ip: %s)\n", ip);
-                session[fd]->eof = 1;
-                return;
-        }
-    }
-    return;
-}
-
-//-------------------------------------------------
-// Return numerical value of a switch configuration
-// on/off, english, français, deutsch, español
-//-------------------------------------------------
-int config_switch (const char *str)
-{
-    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
-        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
-        || strcasecmp (str, "si") == 0)
-        return 1;
-    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
-        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
-        return 0;
-
-    return atoi (str);
-}
-
-//----------------------------------
-// Reading Lan Support configuration
-//----------------------------------
-int login_lan_config_read (const char *lancfgName)
-{
-    int  j;
-    struct hostent *h = NULL;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    // set default configuration
-    strncpy (lan_char_ip, "127.0.0.1", sizeof (lan_char_ip));
-    subneti[0] = 127;
-    subneti[1] = 0;
-    subneti[2] = 0;
-    subneti[3] = 1;
-    for (j = 0; j < 4; j++)
-        subnetmaski[j] = 255;
-
-    fp = fopen_ (lancfgName, "r");
-
-    if (fp == NULL)
-    {
-        printf
-            ("***WARNING: LAN Support configuration file is not found: %s\n",
-             lancfgName);
-        return 1;
-    }
-
-    printf ("---Start reading Lan Support configuration file\n");
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        line[sizeof (line) - 1] = '\0';
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
-            continue;
-
-        remove_control_chars (w1);
-        remove_control_chars (w2);
-        if (strcasecmp (w1, "lan_char_ip") == 0)
-        {                       // Read Char-Server Lan IP Address
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                sprintf (lan_char_ip, "%d.%d.%d.%d",
-                         (unsigned char) h->h_addr[0],
-                         (unsigned char) h->h_addr[1],
-                         (unsigned char) h->h_addr[2],
-                         (unsigned char) h->h_addr[3]);
-            }
-            else
-            {
-                strncpy (lan_char_ip, w2, sizeof (lan_char_ip));
-                lan_char_ip[sizeof (lan_char_ip) - 1] = '\0';
-            }
-            printf ("LAN IP of char-server: %s.\n", lan_char_ip);
-        }
-        else if (strcasecmp (w1, "subnet") == 0)
-        {                       // Read Subnetwork
-            for (j = 0; j < 4; j++)
-                subneti[j] = 0;
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                for (j = 0; j < 4; j++)
-                    subneti[j] = (unsigned char) h->h_addr[j];
-            }
-            else
-            {
-                sscanf (w2, "%d.%d.%d.%d", &subneti[0], &subneti[1],
-                        &subneti[2], &subneti[3]);
-            }
-            printf ("Sub-network of the char-server: %d.%d.%d.%d.\n",
-                    subneti[0], subneti[1], subneti[2], subneti[3]);
-        }
-        else if (strcasecmp (w1, "subnetmask") == 0)
-        {                       // Read Subnetwork Mask
-            for (j = 0; j < 4; j++)
-                subnetmaski[j] = 255;
-            h = gethostbyname (w2);
-            if (h != NULL)
-            {
-                for (j = 0; j < 4; j++)
-                    subnetmaski[j] = (unsigned char) h->h_addr[j];
-            }
-            else
-            {
-                sscanf (w2, "%d.%d.%d.%d", &subnetmaski[0], &subnetmaski[1],
-                        &subnetmaski[2], &subnetmaski[3]);
-            }
-            printf ("Sub-network mask of the char-server: %d.%d.%d.%d.\n",
-                    subnetmaski[0], subnetmaski[1], subnetmaski[2],
-                    subnetmaski[3]);
-        }
-    }
-    fclose_ (fp);
-
-    // log the LAN configuration
-    login_log ("The LAN configuration of the server is set:\n");
-    login_log ("- with LAN IP of char-server: %s.\n", lan_char_ip);
-    login_log
-        ("- with the sub-network of the char-server: %d.%d.%d.%d/%d.%d.%d.%d.\n",
-         subneti[0], subneti[1], subneti[2], subneti[3],
-         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
-
-    // sub-network check of the char-server
-    {
-        unsigned int a0, a1, a2, a3;
-        unsigned char p[4];
-        sscanf (lan_char_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
-        p[0] = a0;
-        p[1] = a1;
-        p[2] = a2;
-        p[3] = a3;
-        printf ("LAN test of LAN IP of the char-server: ");
-        if (lan_ip_check (p) == 0)
-        {
-            printf
-                ("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
-            login_log
-                ("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network.\n");
-        }
-    }
-
-    printf ("---End reading of Lan Support configuration file\n");
-
-    return 0;
-}
-
-//-----------------------------------
-// Reading general configuration file
-//-----------------------------------
-int login_config_read (const char *cfgName)
-{
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        printf ("Configuration file (%s) not found.\n", cfgName);
-        return 1;
-    }
-
-    printf ("---Start reading of Login Server configuration file (%s)\n",
-            cfgName);
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        line[sizeof (line) - 1] = '\0';
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
-        {
-            remove_control_chars (w1);
-            remove_control_chars (w2);
-
-            if (strcasecmp (w1, "admin_state") == 0)
-            {
-                admin_state = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "admin_pass") == 0)
-            {
-                strncpy (admin_pass, w2, sizeof (admin_pass));
-                admin_pass[sizeof (admin_pass) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "ladminallowip") == 0)
-            {
-                if (strcasecmp (w2, "clear") == 0)
-                {
-                    if (access_ladmin_allow)
-                        free (access_ladmin_allow);
-                    access_ladmin_allow = NULL;
-                    access_ladmin_allownum = 0;
-                }
-                else
-                {
-                    if (strcasecmp (w2, "all") == 0)
-                    {
-                        // reset all previous values
-                        if (access_ladmin_allow)
-                            free (access_ladmin_allow);
-                        // set to all
-                        CREATE (access_ladmin_allow, char, ACO_STRSIZE);
-                        access_ladmin_allownum = 1;
-                    }
-                    else if (w2[0]
-                             && !(access_ladmin_allownum == 1
-                                  && access_ladmin_allow[0] == '\0'))
-                    {           // don't add IP if already 'all'
-                        if (access_ladmin_allow)
-                            RECREATE (access_ladmin_allow, char, (access_ladmin_allownum + 1) * ACO_STRSIZE);
-                        else
-                            CREATE (access_ladmin_allow, char, ACO_STRSIZE);
-                        strncpy (access_ladmin_allow +
-                                 (access_ladmin_allownum++) * ACO_STRSIZE, w2,
-                                 ACO_STRSIZE);
-                        access_ladmin_allow[access_ladmin_allownum *
-                                            ACO_STRSIZE - 1] = '\0';
-                    }
-                }
-            }
-            else if (strcasecmp (w1, "gm_pass") == 0)
-            {
-                strncpy (gm_pass, w2, sizeof (gm_pass));
-                gm_pass[sizeof (gm_pass) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "level_new_gm") == 0)
-            {
-                level_new_gm = atoi (w2);
-            }
-            else if (strcasecmp (w1, "new_account") == 0)
-            {
-                new_account_flag = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "login_port") == 0)
-            {
-                login_port = atoi (w2);
-            }
-            else if (strcasecmp (w1, "account_filename") == 0)
-            {
-                strncpy (account_filename, w2, sizeof (account_filename));
-                account_filename[sizeof (account_filename) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "gm_account_filename") == 0)
-            {
-                strncpy (GM_account_filename, w2,
-                         sizeof (GM_account_filename));
-                GM_account_filename[sizeof (GM_account_filename) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "gm_account_filename_check_timer") == 0)
-            {
-                gm_account_filename_check_timer = atoi (w2);
-            }
-            else if (strcasecmp (w1, "login_log_filename") == 0)
-            {
-                strncpy (login_log_filename, w2, sizeof (login_log_filename));
-                login_log_filename[sizeof (login_log_filename) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "login_log_unknown_packets_filename") == 0)
-            {
-                strncpy (login_log_unknown_packets_filename, w2,
-                         sizeof (login_log_unknown_packets_filename));
-                login_log_unknown_packets_filename[sizeof
-                                                   (login_log_unknown_packets_filename)
-                                                   - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "save_unknown_packets") == 0)
-            {
-                save_unknown_packets = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "display_parse_login") == 0)
-            {
-                display_parse_login = config_switch (w2);   // 0: no, 1: yes
-            }
-            else if (strcasecmp (w1, "display_parse_admin") == 0)
-            {
-                display_parse_admin = config_switch (w2);   // 0: no, 1: yes
-            }
-            else if (strcasecmp (w1, "display_parse_fromchar") == 0)
-            {
-                display_parse_fromchar = config_switch (w2);    // 0: no, 1: yes (without packet 0x2714), 2: all packets
-            }
-            else if (strcasecmp (w1, "date_format") == 0)
-            {                   // note: never have more than 19 char for the date!
-                switch (atoi (w2))
-                {
-                    case 0:
-                        strcpy (date_format, "%d-%m-%Y %H:%M:%S");  // 31-12-2004 23:59:59
-                        break;
-                    case 1:
-                        strcpy (date_format, "%m-%d-%Y %H:%M:%S");  // 12-31-2004 23:59:59
-                        break;
-                    case 2:
-                        strcpy (date_format, "%Y-%d-%m %H:%M:%S");  // 2004-31-12 23:59:59
-                        break;
-                    case 3:
-                        strcpy (date_format, "%Y-%m-%d %H:%M:%S");  // 2004-12-31 23:59:59
-                        break;
-                }
-            }
-            else if (strcasecmp (w1, "min_level_to_connect") == 0)
-            {
-                min_level_to_connect = atoi (w2);
-            }
-            else if (strcasecmp (w1, "add_to_unlimited_account") == 0)
-            {
-                add_to_unlimited_account = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "start_limited_time") == 0)
-            {
-                start_limited_time = atoi (w2);
-            }
-            else if (strcasecmp (w1, "check_ip_flag") == 0)
-            {
-                check_ip_flag = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "order") == 0)
-            {
-                access_order = atoi (w2);
-                if (strcasecmp (w2, "deny,allow") == 0 ||
-                    strcasecmp (w2, "deny, allow") == 0)
-                    access_order = ACO_DENY_ALLOW;
-                if (strcasecmp (w2, "allow,deny") == 0 ||
-                    strcasecmp (w2, "allow, deny") == 0)
-                    access_order = ACO_ALLOW_DENY;
-                if (strcasecmp (w2, "mutual-failture") == 0 ||
-                    strcasecmp (w2, "mutual-failure") == 0)
-                    access_order = ACO_MUTUAL_FAILTURE;
-            }
-            else if (strcasecmp (w1, "allow") == 0)
-            {
-                if (strcasecmp (w2, "clear") == 0)
-                {
-                    if (access_allow)
-                        free (access_allow);
-                    access_allow = NULL;
-                    access_allownum = 0;
-                }
-                else
-                {
-                    if (strcasecmp (w2, "all") == 0)
-                    {
-                        // reset all previous values
-                        if (access_allow)
-                            free (access_allow);
-                        // set to all
-                        CREATE (access_allow, char, ACO_STRSIZE);
-                        access_allownum = 1;
-                    }
-                    else if (w2[0]
-                             && !(access_allownum == 1
-                                  && access_allow[0] == '\0'))
-                    {           // don't add IP if already 'all'
-                        if (access_allow)
-                            RECREATE (access_allow, char, (access_allownum + 1) * ACO_STRSIZE);
-                        else
-                            CREATE (access_allow, char, ACO_STRSIZE);
-                        strncpy (access_allow +
-                                 (access_allownum++) * ACO_STRSIZE, w2,
-                                 ACO_STRSIZE);
-                        access_allow[access_allownum * ACO_STRSIZE - 1] =
-                            '\0';
-                    }
-                }
-            }
-            else if (strcasecmp (w1, "deny") == 0)
-            {
-                if (strcasecmp (w2, "clear") == 0)
-                {
-                    if (access_deny)
-                        free (access_deny);
-                    access_deny = NULL;
-                    access_denynum = 0;
-                }
-                else
-                {
-                    if (strcasecmp (w2, "all") == 0)
-                    {
-                        // reset all previous values
-                        if (access_deny)
-                            free (access_deny);
-                        // set to all
-                        CREATE (access_deny, char, ACO_STRSIZE);
-                        access_denynum = 1;
-                    }
-                    else if (w2[0]
-                             && !(access_denynum == 1
-                                  && access_deny[0] == '\0'))
-                    {           // don't add IP if already 'all'
-                        if (access_deny)
-                            RECREATE (access_deny, char, (access_denynum + 1) * ACO_STRSIZE);
-                        else
-                            CREATE (access_deny, char, ACO_STRSIZE);
-                        strncpy (access_deny +
-                                 (access_denynum++) * ACO_STRSIZE, w2,
-                                 ACO_STRSIZE);
-                        access_deny[access_denynum * ACO_STRSIZE - 1] = '\0';
-                    }
-                }
-            }
-            else if (strcasecmp (w1, "anti_freeze_enable") == 0)
-            {
-                anti_freeze_enable = config_switch (w2);
-            }
-            else if (strcasecmp (w1, "anti_freeze_interval") == 0)
-            {
-                ANTI_FREEZE_INTERVAL = atoi (w2);
-                if (ANTI_FREEZE_INTERVAL < 5)
-                    ANTI_FREEZE_INTERVAL = 5;   // minimum 5 seconds
-            }
-            else if (strcasecmp (w1, "import") == 0)
-            {
-                login_config_read (w2);
-            }
-            else if (strcasecmp (w1, "update_host") == 0)
-            {
-                strncpy (update_host, w2, sizeof (update_host));
-                update_host[sizeof (update_host) - 1] = '\0';
-            }
-            else if (strcasecmp (w1, "main_server") == 0)
-            {
-                strncpy (main_server, w2, sizeof (main_server));
-                main_server[sizeof (main_server) - 1] = '\0';
-            }
-        }
-    }
-    fclose_ (fp);
-
-    printf ("---End reading of Login Server configuration file.\n");
-
-    return 0;
-}
-
-//-------------------------------------
-// Displaying of configuration warnings
-//-------------------------------------
-void display_conf_warnings (void)
-{
-    if (admin_state != 0 && admin_state != 1)
-    {
-        printf
-            ("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n");
-        admin_state = 0;
-    }
-
-    if (admin_state == 1)
-    {
-        if (admin_pass[0] == '\0')
-        {
-            printf
-                ("***WARNING: Administrator password is void (admin_pass).\n");
-        }
-        else if (strcmp (admin_pass, "admin") == 0)
-        {
-            printf
-                ("***WARNING: You are using the default administrator password (admin_pass).\n");
-            printf ("            We highly recommend that you change it.\n");
-        }
-    }
-
-    if (gm_pass[0] == '\0')
-    {
-        printf ("***WARNING: 'To GM become' password is void (gm_pass).\n");
-        printf
-            ("            We highly recommend that you set one password.\n");
-    }
-    else if (strcmp (gm_pass, "gm") == 0)
-    {
-        printf
-            ("***WARNING: You are using the default GM password (gm_pass).\n");
-        printf ("            We highly recommend that you change it.\n");
-    }
-
-    if (level_new_gm < 0 || level_new_gm > 99)
-    {
-        printf
-            ("***WARNING: Invalid value for level_new_gm parameter -> set to 60 (default).\n");
-        level_new_gm = 60;
-    }
-
-    if (new_account_flag != 0 && new_account_flag != 1)
-    {
-        printf
-            ("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n");
-        new_account_flag = 0;
-    }
-
-    if (login_port < 1024 || login_port > 65535)
-    {
-        printf
-            ("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n");
-        login_port = 6900;
-    }
-
-    if (gm_account_filename_check_timer < 0)
-    {
-        printf
-            ("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
-        printf ("            -> set to 15 sec (default).\n");
-        gm_account_filename_check_timer = 15;
-    }
-    else if (gm_account_filename_check_timer == 1)
-    {
-        printf
-            ("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
-        printf ("            -> set to 2 sec (minimum value).\n");
-        gm_account_filename_check_timer = 2;
-    }
-
-    if (save_unknown_packets != 0 && save_unknown_packets != 1)
-    {
-        printf
-            ("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n");
-        save_unknown_packets = 0;
-    }
-
-    if (display_parse_login != 0 && display_parse_login != 1)
-    {                           // 0: no, 1: yes
-        printf
-            ("***WARNING: Invalid value for display_parse_login parameter\n");
-        printf ("            -> set to 0 (no display).\n");
-        display_parse_login = 0;
-    }
-
-    if (display_parse_admin != 0 && display_parse_admin != 1)
-    {                           // 0: no, 1: yes
-        printf
-            ("***WARNING: Invalid value for display_parse_admin parameter\n");
-        printf ("            -> set to 0 (no display).\n");
-        display_parse_admin = 0;
-    }
-
-    if (display_parse_fromchar < 0 || display_parse_fromchar > 2)
-    {                           // 0: no, 1: yes (without packet 0x2714), 2: all packets
-        printf
-            ("***WARNING: Invalid value for display_parse_fromchar parameter\n");
-        printf ("            -> set to 0 (no display).\n");
-        display_parse_fromchar = 0;
-    }
-
-    if (min_level_to_connect < 0)
-    {                           // 0: all players, 1-99 at least gm level x
-        printf
-            ("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n",
-             min_level_to_connect);
-        printf ("            -> set to 0 (any player).\n");
-        min_level_to_connect = 0;
-    }
-    else if (min_level_to_connect > 99)
-    {                           // 0: all players, 1-99 at least gm level x
-        printf
-            ("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n",
-             min_level_to_connect);
-        printf ("            -> set to 99 (only GM level 99).\n");
-        min_level_to_connect = 99;
-    }
-
-    if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1)
-    {                           // 0: no, 1: yes
-        printf
-            ("***WARNING: Invalid value for add_to_unlimited_account parameter\n");
-        printf
-            ("            -> set to 0 (impossible to add a time to an unlimited account).\n");
-        add_to_unlimited_account = 0;
-    }
-
-    if (start_limited_time < -1)
-    {                           // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
-        printf
-            ("***WARNING: Invalid value for start_limited_time parameter\n");
-        printf
-            ("            -> set to -1 (new accounts are created with unlimited time).\n");
-        start_limited_time = -1;
-    }
-
-    if (check_ip_flag != 0 && check_ip_flag != 1)
-    {                           // 0: no, 1: yes
-        printf ("***WARNING: Invalid value for check_ip_flag parameter\n");
-        printf
-            ("            -> set to 1 (check players ip between login-server & char-server).\n");
-        check_ip_flag = 1;
-    }
-
-    if (access_order == ACO_DENY_ALLOW)
-    {
-        if (access_denynum == 1 && access_deny[0] == '\0')
-        {
-            printf
-                ("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n");
-            printf ("            And you refuse ALL IP.\n");
-        }
-    }
-    else if (access_order == ACO_ALLOW_DENY)
-    {
-        if (access_allownum == 0)
-        {
-            printf
-                ("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n");
-            printf ("            But, NO IP IS AUTHORISED!\n");
-        }
-    }
-    else
-    {                           // ACO_MUTUAL_FAILTURE
-        if (access_allownum == 0)
-        {
-            printf
-                ("***WARNING: The IP security order is 'mutual-failture'\n");
-            printf
-                ("            (allow if in the allow list and not in the deny list).\n");
-            printf ("            But, NO IP IS AUTHORISED!\n");
-        }
-        else if (access_denynum == 1 && access_deny[0] == '\0')
-        {
-            printf ("***WARNING: The IP security order is mutual-failture\n");
-            printf
-                ("            (allow if in the allow list and not in the deny list).\n");
-            printf ("            But, you refuse ALL IP!\n");
-        }
-    }
-
-    return;
-}
-
-//-------------------------------
-// Save configuration in log file
-//-------------------------------
-void save_config_in_log (void)
-{
-    int  i;
-
-    // a newline in the log...
-    login_log ("");
-    login_log ("The login-server starting...\n");
-
-    // save configuration in log file
-    login_log ("The configuration of the server is set:\n");
-
-    if (admin_state != 1)
-        login_log ("- with no remote administration.\n");
-    else if (admin_pass[0] == '\0')
-        login_log ("- with a remote administration with a VOID password.\n");
-    else if (strcmp (admin_pass, "admin") == 0)
-        login_log ("- with a remote administration with the DEFAULT password.\n");
-    else
-        login_log
-            ("- with a remote administration with the password of %d character(s).\n",
-             strlen (admin_pass));
-    if (access_ladmin_allownum == 0
-        || (access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0'))
-    {
-        login_log ("- to accept any IP for remote administration\n");
-    }
-    else
-    {
-        login_log ("- to accept following IP for remote administration:\n");
-        for (i = 0; i < access_ladmin_allownum; i++)
-            login_log ("  %s\n",
-                       (char *) (access_ladmin_allow + i * ACO_STRSIZE));
-    }
-
-    if (gm_pass[0] == '\0')
-        login_log ("- with a VOID 'To GM become' password (gm_pass).\n");
-    else if (strcmp (gm_pass, "gm") == 0)
-        login_log ("- with the DEFAULT 'To GM become' password (gm_pass).\n");
-    else
-        login_log
-            ("- with a 'To GM become' password (gm_pass) of %d character(s).\n",
-             strlen (gm_pass));
-    if (level_new_gm == 0)
-        login_log ("- to refuse any creation of GM with @gm.\n");
-    else
-        login_log ("- to create GM with level '%d' when @gm is used.\n",
-                   level_new_gm);
-
-    if (new_account_flag == 1)
-        login_log ("- to ALLOW new users (with _F/_M).\n");
-    else
-        login_log ("- to NOT ALLOW new users (with _F/_M).\n");
-    login_log ("- with port: %d.\n", login_port);
-    login_log ("- with the accounts file name: '%s'.\n",
-               account_filename);
-    login_log ("- with the GM accounts file name: '%s'.\n",
-               GM_account_filename);
-    if (gm_account_filename_check_timer == 0)
-        login_log ("- to NOT check GM accounts file modifications.\n");
-    else
-        login_log
-            ("- to check GM accounts file modifications every %d seconds.\n",
-             gm_account_filename_check_timer);
-
-    // not necessary to log the 'login_log_filename', we are inside :)
-
-    login_log ("- with the unknown packets file name: '%s'.\n",
-               login_log_unknown_packets_filename);
-    if (save_unknown_packets)
-        login_log ("- to SAVE all unkown packets.\n");
-    else
-        login_log
-            ("- to SAVE only unkown packets sending by a char-server or a remote administration.\n");
-    if (display_parse_login)
-        login_log ("- to display normal parse packets on console.\n");
-    else
-        login_log ("- to NOT display normal parse packets on console.\n");
-    if (display_parse_admin)
-        login_log ("- to display administration parse packets on console.\n");
-    else
-        login_log ("- to NOT display administration parse packets on console.\n");
-    if (display_parse_fromchar)
-        login_log ("- to display char-server parse packets on console.\n");
-    else
-        login_log ("- to NOT display char-server parse packets on console.\n");
-
-    if (min_level_to_connect == 0)  // 0: all players, 1-99 at least gm level x
-        login_log ("- with no minimum level for connection.\n");
-    else if (min_level_to_connect == 99)
-        login_log ("- to accept only GM with level 99.\n");
-    else
-        login_log ("- to accept only GM with level %d or more.\n",
-                   min_level_to_connect);
-
-    if (add_to_unlimited_account)
-        login_log
-            ("- to authorize adjustment (with timeadd ladmin) on an unlimited account.\n");
-    else
-        login_log
-            ("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n");
-
-    if (start_limited_time < 0)
-        login_log ("- to create new accounts with an unlimited time.\n");
-    else if (start_limited_time == 0)
-        login_log
-            ("- to create new accounts with a limited time: time of creation.\n");
-    else
-        login_log
-            ("- to create new accounts with a limited time: time of creation + %d second(s).\n",
-             start_limited_time);
-
-    if (check_ip_flag)
-        login_log
-            ("- with control of players IP between login-server and char-server.\n");
-    else
-        login_log
-            ("- to not check players IP between login-server and char-server.\n");
-
-    if (access_order == ACO_DENY_ALLOW)
-    {
-        if (access_denynum == 0)
-        {
-            login_log
-                ("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP.\n");
-        }
-        else if (access_denynum == 1 && access_deny[0] == '\0')
-        {
-            login_log
-                ("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP.\n");
-        }
-        else
-        {
-            login_log
-                ("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n");
-            for (i = 0; i < access_denynum; i++)
-                login_log ("  %s\n",
-                           (char *) (access_deny + i * ACO_STRSIZE));
-        }
-    }
-    else if (access_order == ACO_ALLOW_DENY)
-    {
-        if (access_allownum == 0)
-        {
-            login_log
-                ("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!\n");
-        }
-        else if (access_allownum == 1 && access_allow[0] == '\0')
-        {
-            login_log
-                ("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP.\n");
-        }
-        else
-        {
-            login_log
-                ("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n");
-            for (i = 0; i < access_allownum; i++)
-                login_log ("  %s\n",
-                           (char *) (access_allow + i * ACO_STRSIZE));
-        }
-    }
-    else
-    {                           // ACO_MUTUAL_FAILTURE
-        login_log
-            ("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list).\n");
-        if (access_allownum == 0)
-        {
-            login_log ("  But, NO IP IS AUTHORISED!\n");
-        }
-        else if (access_denynum == 1 && access_deny[0] == '\0')
-        {
-            login_log ("  But, you refuse ALL IP!\n");
-        }
-        else
-        {
-            if (access_allownum == 1 && access_allow[0] == '\0')
-            {
-                login_log ("  You authorise ALL IP.\n");
-            }
-            else
-            {
-                login_log ("  Authorised IP are:\n");
-                for (i = 0; i < access_allownum; i++)
-                    login_log ("    %s\n",
-                               (char *) (access_allow + i * ACO_STRSIZE));
-            }
-            login_log ("  Refused IP are:\n");
-            for (i = 0; i < access_denynum; i++)
-                login_log ("    %s\n",
-                           (char *) (access_deny + i * ACO_STRSIZE));
-        }
-    }
-}
-
-//--------------------------------------
-// Function called at exit of the server
-//--------------------------------------
-void term_func (void)
-{
-    int  i, fd;
-
-    mmo_auth_sync ();
-
-    free (auth_dat);
-    free (gm_account_db);
-    for (i = 0; i < MAX_SERVERS; i++)
-    {
-        if ((fd = server_fd[i]) >= 0)
-            delete_session (fd);
-    }
-    delete_session (login_fd);
-
-    login_log
-        ("----End of login-server (normal end with closing of all files).\n");
-}
-
-//------------------------------
-// Main function of login-server
-//------------------------------
-int do_init (int argc, char **argv)
-{
-    int  i, j;
-
-    // read login-server configuration
-    login_config_read ((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
-    display_conf_warnings ();   // not in login_config_read, because we can use 'import' option, and display same message twice or more
-    save_config_in_log ();      // not before, because log file name can be changed
-    login_lan_config_read ((argc > 1) ? argv[1] : LAN_CONF_NAME);
-
-    for (i = 0; i < AUTH_FIFO_SIZE; i++)
-        auth_fifo[i].delflag = 1;
-    for (i = 0; i < MAX_SERVERS; i++)
-        server_fd[i] = -1;
-
-    gm_account_db = numdb_init ();
-
-    read_gm_account ();
-    mmo_auth_init ();
-//     set_termfunc (mmo_auth_sync);
-    set_defaultparse (parse_login);
-    login_fd = make_listen_port (login_port);
-
-//    add_timer_func_list (check_auth_sync, "check_auth_sync");
-
-    // Trigger auth sync every 5 minutes
-    i = add_timer_interval (gettick () + 300000, check_auth_sync, 0, 0, 300000);
-
-    if (anti_freeze_enable > 0)
-    {
-//        add_timer_func_list (char_anti_freeze_system, "char_anti_freeze_system");
-        i = add_timer_interval (gettick () + 1000, char_anti_freeze_system, 0,
-                                0, ANTI_FREEZE_INTERVAL * 1000);
-    }
-
-    // add timer to check GM accounts file modification
-    j = gm_account_filename_check_timer;
-    if (j == 0)                 // if we would not to check, we check every 60 sec, just to have timer (if we change timer, is was not necessary to check if timer already exists)
-        j = 60;
-//    add_timer_func_list (check_GM_file, "check_GM_file");
-    i = add_timer_interval (gettick () + j * 1000, check_GM_file, 0, 0, j * 1000);  // every x sec we check if gm file has been changed
-
-    login_log
-        ("The login-server is ready (Server is listening on the port %d).\n",
-         login_port);
-
-    printf
-        ("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
-         login_port);
-
-    return 0;
-}
diff --git a/src/login/login.cpp b/src/login/login.cpp
new file mode 100644
index 0000000..543f32f
--- /dev/null
+++ b/src/login/login.cpp
@@ -0,0 +1,5038 @@
+// $Id: login.c,v 1.1.1.1 2004/09/10 17:26:53 MagicalTux Exp $
+// new version of the login-server by [Yor]
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>           // for stat/lstat/fstat
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/wait.h>
+
+#include "../common/core.hpp"
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "login.hpp"
+#include "../common/mmo.hpp"
+#include "../common/version.hpp"
+#include "../common/db.hpp"
+#include "../common/lock.hpp"
+#include "../common/mt_rand.hpp"
+
+#include "../common/md5calc.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+int  account_id_count = START_ACCOUNT_NUM;
+int  server_num;
+int  new_account_flag = 0;
+int  login_port = 6900;
+char lan_char_ip[16];
+int  subneti[4];
+int  subnetmaski[4];
+char update_host[128] = "";
+char main_server[20] = "";
+
+char account_filename[1024] = "save/account.txt";
+char GM_account_filename[1024] = "conf/GM_account.txt";
+char login_log_filename[1024] = "log/login.log";
+char login_log_unknown_packets_filename[1024] =
+    "log/login_unknown_packets.log";
+char date_format[32] = "%Y-%m-%d %H:%M:%S";
+int  save_unknown_packets = 0;
+long creation_time_GM_account_file;
+int  gm_account_filename_check_timer = 15;  // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15)
+
+int  display_parse_login = 0;   // 0: no, 1: yes
+int  display_parse_admin = 0;   // 0: no, 1: yes
+int  display_parse_fromchar = 0;    // 0: no, 1: yes (without packet 0x2714), 2: all packets
+
+struct mmo_char_server server[MAX_SERVERS];
+int  server_fd[MAX_SERVERS];
+int  server_freezeflag[MAX_SERVERS];    // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+int  anti_freeze_enable = 0;
+int  ANTI_FREEZE_INTERVAL = 15;
+
+int  login_fd;
+
+enum
+{
+    ACO_DENY_ALLOW = 0,
+    ACO_ALLOW_DENY,
+    ACO_MUTUAL_FAILTURE,
+    ACO_STRSIZE = 128,
+};
+
+int  access_order = ACO_DENY_ALLOW;
+int  access_allownum = 0;
+int  access_denynum = 0;
+char *access_allow = NULL;
+char *access_deny = NULL;
+
+int  access_ladmin_allownum = 0;
+char *access_ladmin_allow = NULL;
+
+int  min_level_to_connect = 0;  // minimum level of player/GM (0: player, 1-99: gm) to connect on the server
+int  add_to_unlimited_account = 0;  // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account.
+int  start_limited_time = -1;   // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now)
+int  check_ip_flag = 1;         // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
+
+struct login_session_data
+{
+    int  md5keylen;
+    char md5key[20];
+};
+
+#define AUTH_FIFO_SIZE 256
+struct
+{
+    int  account_id, login_id1, login_id2;
+    int  ip, sex, delflag;
+} auth_fifo[AUTH_FIFO_SIZE];
+int  auth_fifo_pos = 0;
+
+struct auth_dat
+{
+    int  account_id, sex;
+    char userid[24], pass[40], lastlogin[24];
+    int  logincount;
+    int  state;                 // packet 0x006a value + 1 (0: compte OK)
+    char email[40];             // e-mail (by default: a@a.com)
+    char error_message[20];     // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
+    time_t ban_until_time;      // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
+    time_t connect_until_time;  // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+    char last_ip[16];           // save of last IP of connection
+    char memo[255];             // a memo field
+    int  account_reg2_num;
+    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+}   *auth_dat;
+
+int  auth_num = 0, auth_max = 0;
+
+int  admin_state = 0;
+char admin_pass[24] = "";
+char gm_pass[64] = "";
+int  level_new_gm = 60;
+
+static struct dbt *gm_account_db;
+
+pid_t pid = 0; // For forked DB writes
+
+
+#define VERSION_2_UPDATEHOST 0x01   // client supports updatehost
+#define VERSION_2_SERVERORDER 0x02  // send servers in forward order
+//------------------------------
+// Writing function of logs file
+//------------------------------
+int login_log (char *fmt, ...)
+{
+    FILE *logfp;
+    va_list ap;
+    struct timeval tv;
+    char tmpstr[2048];
+
+    va_start (ap, fmt);
+
+    logfp = fopen_ (login_log_filename, "a");
+    if (logfp)
+    {
+        if (fmt[0] == '\0')     // jump a line if no message
+            fprintf (logfp, "\n");
+        else
+        {
+            gettimeofday (&tv, NULL);
+            strftime (tmpstr, 24, date_format, gmtime (&(tv.tv_sec)));
+            sprintf (tmpstr + strlen (tmpstr), ".%03d: %s",
+                     (int) tv.tv_usec / 1000, fmt);
+            vfprintf (logfp, tmpstr, ap);
+        }
+        fclose_ (logfp);
+    }
+
+    va_end (ap);
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// Determine if an account (id) is a GM account
+// and returns its level (or 0 if it isn't a GM account or if not found)
+//----------------------------------------------------------------------
+int isGM (int account_id)
+{
+    struct gm_account *p = (struct gm_account*) numdb_search (gm_account_db, account_id);
+    if (p == NULL)
+        return 0;
+    return p->level;
+}
+
+//-------------------------------------------------------
+// Reading function of GM accounts file (and their level)
+//-------------------------------------------------------
+int read_gm_account (void)
+{
+    char line[512];
+    struct gm_account *p;
+    FILE *fp;
+    int  c = 0;
+    int  GM_level;
+    struct stat file_stat;
+
+    free (gm_account_db);
+    gm_account_db = numdb_init ();
+
+    // get last modify time/date
+    if (stat (GM_account_filename, &file_stat))
+        creation_time_GM_account_file = 0;  // error
+    else
+        creation_time_GM_account_file = file_stat.st_mtime;
+
+    if ((fp = fopen_ (GM_account_filename, "r")) == NULL)
+    {
+        printf ("read_gm_account: GM accounts file [%s] not found.\n",
+                GM_account_filename);
+        printf
+            ("                 Actually, there is no GM accounts on the server.\n");
+        login_log ("read_gm_account: GM accounts file [%s] not found.\n",
+                   GM_account_filename);
+        login_log
+            ("                 Actually, there is no GM accounts on the server.\n");
+        return 1;
+    }
+    // limited to 4000, because we send information to char-servers (more than 4000 GM accounts???)
+    // int (id) + int (level) = 8 bytes * 4000 = 32k (limit of packets in windows)
+    while (fgets (line, sizeof (line) - 1, fp) && c < 4000)
+    {
+        if ((line[0] == '/' && line[1] == '/') || line[0] == '\0'
+            || line[0] == '\n' || line[0] == '\r')
+            continue;
+        CREATE (p, struct gm_account, 1);
+        if (sscanf (line, "%d %d", &p->account_id, &p->level) != 2
+            && sscanf (line, "%d: %d", &p->account_id, &p->level) != 2)
+            printf
+                ("read_gm_account: file [%s], invalid 'id_acount level' format.\n",
+                 GM_account_filename);
+        else if (p->level <= 0)
+            printf
+                ("read_gm_account: file [%s] %dth account (invalid level [0 or negative]: %d).\n",
+                 GM_account_filename, c + 1, p->level);
+        else
+        {
+            if (p->level > 99)
+            {
+                printf
+                    ("read_gm_account: file [%s] %dth account (invalid level, but corrected: %d->99).\n",
+                     GM_account_filename, c + 1, p->level);
+                p->level = 99;
+            }
+            if ((GM_level = isGM (p->account_id)) > 0)
+            {                   // if it's not a new account
+                if (GM_level == p->level)
+                    printf
+                        ("read_gm_account: GM account %d defined twice (same level: %d).\n",
+                         p->account_id, p->level);
+                else
+                    printf
+                        ("read_gm_account: GM account %d defined twice (levels: %d and %d).\n",
+                         p->account_id, GM_level, p->level);
+            }
+            if (GM_level != p->level)
+            {                   // if new account or new level
+                numdb_insert (gm_account_db, p->account_id, p);
+                //printf("GM account:%d, level: %d->%d\n", p->account_id, GM_level, p->level);
+                if (GM_level == 0)
+                {               // if new account
+                    c++;
+                    if (c >= 4000)
+                    {
+                        printf
+                            ("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
+                        login_log
+                            ("***WARNING: 4000 GM accounts found. Next GM accounts are not readed.\n");
+                    }
+                }
+            }
+        }
+    }
+    fclose_ (fp);
+
+    printf ("read_gm_account: file '%s' readed (%d GM accounts found).\n",
+            GM_account_filename, c);
+    login_log ("read_gm_account: file '%s' readed (%d GM accounts found).\n",
+               GM_account_filename, c);
+
+    return 0;
+}
+
+//--------------------------------------------------------------
+// Test of the IP mask
+// (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
+//--------------------------------------------------------------
+int check_ipmask (unsigned int ip, const unsigned char *str)
+{
+    unsigned int mask = 0, i = 0, m, ip2, a0, a1, a2, a3;
+    unsigned char *p = (unsigned char *) &ip2, *p2 = (unsigned char *) &mask;
+
+    if (sscanf (str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0)
+        return 0;
+    p[0] = a0;
+    p[1] = a1;
+    p[2] = a2;
+    p[3] = a3;
+
+    if (sscanf (str + i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4)
+    {
+        p2[0] = a0;
+        p2[1] = a1;
+        p2[2] = a2;
+        p2[3] = a3;
+        mask = ntohl (mask);
+    }
+    else if (sscanf (str + i, "%d", &m) == 1 && m >= 0 && m <= 32)
+    {
+        for (i = 0; i < m && i < 32; i++)
+            mask = (mask >> 1) | 0x80000000;
+    }
+    else
+    {
+        printf ("check_ipmask: invalid mask [%s].\n", str);
+        return 0;
+    }
+
+//  printf("Tested IP: %08x, network: %08x, network mask: %08x\n",
+//         (unsigned int)ntohl(ip), (unsigned int)ntohl(ip2), (unsigned int)mask);
+    return ((ntohl (ip) & mask) == (ntohl (ip2) & mask));
+}
+
+//---------------------
+// Access control by IP
+//---------------------
+int check_ip (unsigned int ip)
+{
+    int  i;
+    unsigned char *p = (unsigned char *) &ip;
+    char buf[32];
+    enum
+    { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
+
+    if (access_allownum == 0 && access_denynum == 0)
+        return 1;               // When there is no restriction, all IP are authorised.
+
+//  +   012.345.: front match form, or
+//      all: all IP are matched, or
+//      012.345.678.901/24: network form (mask with # of bits), or
+//      012.345.678.901/255.255.255.0: network form (mask with ip mask)
+//  +   Note about the DNS resolution (like www.ne.jp, etc.):
+//      There is no guarantee to have an answer.
+//      If we have an answer, there is no guarantee to have a 100% correct value.
+//      And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
+//      So, DNS notation isn't authorised for ip checking.
+    sprintf (buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
+
+    for (i = 0; i < access_allownum; i++)
+    {
+        const char *p = access_allow + i * ACO_STRSIZE;
+        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
+        {
+            flag = ACF_ALLOW;
+            if (access_order == ACO_ALLOW_DENY)
+                return 1;       // With 'allow, deny' (deny if not allow), allow has priority
+            break;
+        }
+    }
+
+    for (i = 0; i < access_denynum; i++)
+    {
+        const char *p = access_deny + i * ACO_STRSIZE;
+        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
+        {
+            flag = ACF_DENY;
+            return 0;           // At this point, if it's 'deny', we refuse connection.
+            break;
+        }
+    }
+
+    return (flag == ACF_ALLOW || access_order == ACO_DENY_ALLOW) ? 1 : 0;
+    // With 'mutual-failture', only 'allow' and non 'deny' IP are authorised.
+    //   A non 'allow' (even non 'deny') IP is not authorised. It's like: if allowed and not denied, it's authorised.
+    //   So, it's disapproval if you have no description at the time of 'mutual-failture'.
+    // With 'deny,allow' (allow if not deny), because here it's not deny, we authorise.
+}
+
+//--------------------------------
+// Access control by IP for ladmin
+//--------------------------------
+int check_ladminip (unsigned int ip)
+{
+    int  i;
+    unsigned char *p = (unsigned char *) &ip;
+    char buf[32];
+
+    if (access_ladmin_allownum == 0)
+        return 1;               // When there is no restriction, all IP are authorised.
+
+//  +   012.345.: front match form, or
+//      all: all IP are matched, or
+//      012.345.678.901/24: network form (mask with # of bits), or
+//      012.345.678.901/255.255.255.0: network form (mask with ip mask)
+//  +   Note about the DNS resolution (like www.ne.jp, etc.):
+//      There is no guarantee to have an answer.
+//      If we have an answer, there is no guarantee to have a 100% correct value.
+//      And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
+//      So, DNS notation isn't authorised for ip checking.
+    sprintf (buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
+
+    for (i = 0; i < access_ladmin_allownum; i++)
+    {
+        const char *p = access_ladmin_allow + i * ACO_STRSIZE;
+        if (memcmp (p, buf, strlen (p)) == 0 || check_ipmask (ip, p))
+        {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+//-----------------------------------------------------
+// Function to suppress control characters in a string.
+//-----------------------------------------------------
+int remove_control_chars (unsigned char *str)
+{
+    int  i;
+    int  change = 0;
+
+    for (i = 0; str[i]; i++)
+    {
+        if (str[i] < 32)
+        {
+            str[i] = '_';
+            change = 1;
+        }
+    }
+
+    return change;
+}
+
+//---------------------------------------------------
+// E-mail check: return 0 (not correct) or 1 (valid).
+//---------------------------------------------------
+int e_mail_check (unsigned char *email)
+{
+    char ch;
+    unsigned char *last_arobas;
+
+    // athena limits
+    if (strlen (email) < 3 || strlen (email) > 39)
+        return 0;
+
+    // part of RFC limits (official reference of e-mail description)
+    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
+        return 0;
+
+    if (email[strlen (email) - 1] == '.')
+        return 0;
+
+    last_arobas = strrchr (email, '@');
+
+    if (strstr (last_arobas, "@.") != NULL ||
+        strstr (last_arobas, "..") != NULL)
+        return 0;
+
+    for (ch = 1; ch < 32; ch++)
+    {
+        if (strchr (last_arobas, ch) != NULL)
+        {
+            return 0;
+            break;
+        }
+    }
+
+    if (strchr (last_arobas, ' ') != NULL ||
+        strchr (last_arobas, ';') != NULL)
+        return 0;
+
+    // all correct
+    return 1;
+}
+
+//-----------------------------------------------
+// Search an account id
+//   (return account index or -1 (if not found))
+//   If exact account name is not found,
+//   the function checks without case sensitive
+//   and returns index if only 1 account is found
+//   and similar to the searched name.
+//-----------------------------------------------
+int search_account_index (char *account_name)
+{
+    int  i, quantity, index;
+
+    quantity = 0;
+    index = -1;
+    for (i = 0; i < auth_num; i++)
+    {
+        // Without case sensitive check (increase the number of similar account names found)
+        if (strcasecmp (auth_dat[i].userid, account_name) == 0)
+        {
+            // Strict comparison (if found, we finish the function immediatly with correct value)
+            if (strcmp (auth_dat[i].userid, account_name) == 0)
+                return i;
+            quantity++;
+            index = i;
+        }
+    }
+    // Here, the exact account name is not found
+    // We return the found index of a similar account ONLY if there is 1 similar account
+    if (quantity == 1)
+        return index;
+
+    // Exact account name is not found and 0 or more than 1 similar accounts have been found ==> we say not found
+    return -1;
+}
+
+//--------------------------------------------------------
+// Create a string to save the account in the account file
+//--------------------------------------------------------
+int mmo_auth_tostr (char *str, struct auth_dat *p)
+{
+    int  i;
+    char *str_p = str;
+
+    str_p += sprintf (str_p, "%d\t%s\t%s\t%s\t%c\t%d\t%d\t"
+                      "%s\t%s\t%ld\t%s\t%s\t%ld\t",
+                      p->account_id, p->userid, p->pass, p->lastlogin,
+                      (p->sex == 2) ? 'S' : (p->sex ? 'M' : 'F'),
+                      p->logincount, p->state,
+                      p->email, p->error_message,
+                      p->connect_until_time, p->last_ip, p->memo,
+                      p->ban_until_time);
+
+    for (i = 0; i < p->account_reg2_num; i++)
+        if (p->account_reg2[i].str[0])
+            str_p +=
+                sprintf (str_p, "%s,%d ", p->account_reg2[i].str,
+                         p->account_reg2[i].value);
+
+    return 0;
+}
+
+//---------------------------------
+// Reading of the accounts database
+//---------------------------------
+int mmo_auth_init (void)
+{
+    FILE *fp;
+    int  account_id, logincount, state, n, i, j, v;
+    char line[2048], *p, userid[2048], pass[2048], lastlogin[2048], sex,
+        email[2048], error_message[2048], last_ip[2048], memo[2048];
+    time_t ban_until_time;
+    time_t connect_until_time;
+    char str[2048];
+    int  GM_count = 0;
+    int  server_count = 0;
+
+    CREATE (auth_dat, struct auth_dat, 256);
+    auth_max = 256;
+
+    fp = fopen_ (account_filename, "r");
+    if (fp == NULL)
+    {
+        // no account file -> no account -> no login, including char-server (ERROR)
+        printf
+            ("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n",
+             account_filename);
+        return 0;
+    }
+
+    while (fgets (line, sizeof (line) - 1, fp) != NULL)
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        line[sizeof (line) - 1] = '\0';
+        p = line;
+
+        // database version reading (v2)
+        if (((i = sscanf (line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
+                          "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n",
+                          &account_id, userid, pass, lastlogin, &sex,
+                          &logincount, &state, email, error_message,
+                          &connect_until_time, last_ip, memo, &ban_until_time,
+                          &n)) == 13 && line[n] == '\t')
+            ||
+            ((i =
+              sscanf (line,
+                      "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
+                      "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]%n", &account_id,
+                      userid, pass, lastlogin, &sex, &logincount, &state,
+                      email, error_message, &connect_until_time, last_ip,
+                      memo, &n)) == 12 && line[n] == '\t'))
+        {
+            n = n + 1;
+
+            // Some checks
+            if (account_id > END_ACCOUNT_NUM)
+            {
+                printf
+                    ("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n",
+                     END_ACCOUNT_NUM);
+                printf
+                    ("               account id #%d -> account not read (saved in log file).\033[0m\n",
+                     account_id);
+                login_log
+                    ("mmmo_auth_init: ******Error: an account has an id higher than %d.\n",
+                     END_ACCOUNT_NUM);
+                login_log
+                    ("               account id #%d -> account not read (saved in next line):\n",
+                     account_id);
+                login_log ("%s", line);
+                continue;
+            }
+            userid[23] = '\0';
+            remove_control_chars (userid);
+            for (j = 0; j < auth_num; j++)
+            {
+                if (auth_dat[j].account_id == account_id)
+                {
+                    printf
+                        ("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    printf
+                        ("               account id #%d -> new account not read (saved in log file).\033[0m\n",
+                         account_id);
+                    login_log
+                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    login_log
+                        ("               account id #%d -> new account not read (saved in next line):\n",
+                         account_id);
+                    login_log ("%s", line);
+                    break;
+                }
+                else if (strcmp (auth_dat[j].userid, userid) == 0)
+                {
+                    printf
+                        ("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
+                    printf ("               account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
+                    printf
+                        ("               Account saved in log file.\033[0m\n");
+                    login_log
+                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    login_log
+                        ("               account id #%d -> new account not read (saved in next line):\n",
+                         account_id);
+                    login_log ("%s", line);
+                    break;
+                }
+            }
+            if (j != auth_num)
+                continue;
+
+            if (auth_num >= auth_max)
+            {
+                auth_max += 256;
+                RECREATE (auth_dat, struct auth_dat, auth_max);
+            }
+
+            memset (&auth_dat[auth_num], '\0', sizeof (struct auth_dat));
+
+            auth_dat[auth_num].account_id = account_id;
+
+            strncpy (auth_dat[auth_num].userid, userid, 24);
+
+            memo[254] = '\0';
+            remove_control_chars (memo);
+            strncpy (auth_dat[auth_num].memo, memo, 255);
+
+            pass[39] = '\0';
+            remove_control_chars (pass);
+            // If a password is not encrypted, we encrypt it now.
+	    // A password beginning with ! and - in the memo field is our magic
+	    if (pass[0] != '!' && memo[0] == '-') {
+		strcpy(auth_dat[auth_num].pass, MD5_saltcrypt(pass, make_salt()));
+		auth_dat[auth_num].memo[0] = '!';
+		printf("encrypting pass: %s %s\n", pass, auth_dat[auth_num].pass);
+	    }
+	    else
+		strcpy(auth_dat[auth_num].pass, pass);
+
+            lastlogin[23] = '\0';
+            remove_control_chars (lastlogin);
+            strncpy (auth_dat[auth_num].lastlogin, lastlogin, 24);
+
+            auth_dat[auth_num].sex = (sex == 'S'
+                                      || sex == 's') ? 2 : (sex == 'M'
+                                                            || sex == 'm');
+
+            if (logincount >= 0)
+                auth_dat[auth_num].logincount = logincount;
+            else
+                auth_dat[auth_num].logincount = 0;
+
+            if (state > 255)
+                auth_dat[auth_num].state = 100;
+            else if (state < 0)
+                auth_dat[auth_num].state = 0;
+            else
+                auth_dat[auth_num].state = state;
+
+            if (e_mail_check (email) == 0)
+            {
+                printf
+                    ("Account %s (%d): invalid e-mail (replaced par a@a.com).\n",
+                     auth_dat[auth_num].userid,
+                     auth_dat[auth_num].account_id);
+                strncpy (auth_dat[auth_num].email, "a@a.com", 40);
+            }
+            else
+            {
+                remove_control_chars (email);
+                strncpy (auth_dat[auth_num].email, email, 40);
+            }
+
+            error_message[19] = '\0';
+            remove_control_chars (error_message);
+            if (error_message[0] == '\0' || state != 7)
+            {                   // 7, because state is packet 0x006a value + 1
+                strncpy (auth_dat[auth_num].error_message, "-", 20);
+            }
+            else
+            {
+                strncpy (auth_dat[auth_num].error_message, error_message, 20);
+            }
+
+            if (i == 13)
+                auth_dat[auth_num].ban_until_time = ban_until_time;
+            else
+                auth_dat[auth_num].ban_until_time = 0;
+
+            auth_dat[auth_num].connect_until_time = connect_until_time;
+
+            last_ip[15] = '\0';
+            remove_control_chars (last_ip);
+            strncpy (auth_dat[auth_num].last_ip, last_ip, 16);
+
+            for (j = 0; j < ACCOUNT_REG2_NUM; j++)
+            {
+                p += n;
+                if (sscanf (p, "%[^\t,],%d %n", str, &v, &n) != 2)
+                {
+                    // We must check if a str is void. If it's, we can continue to read other REG2.
+                    // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
+                    if (p[0] == ',' && sscanf (p, ",%d %n", &v, &n) == 1)
+                    {
+                        j--;
+                        continue;
+                    }
+                    else
+                        break;
+                }
+                str[31] = '\0';
+                remove_control_chars (str);
+                strncpy (auth_dat[auth_num].account_reg2[j].str, str, 32);
+                auth_dat[auth_num].account_reg2[j].value = v;
+            }
+            auth_dat[auth_num].account_reg2_num = j;
+
+            if (isGM (account_id) > 0)
+                GM_count++;
+            if (auth_dat[auth_num].sex == 2)
+                server_count++;
+
+            auth_num++;
+            if (account_id >= account_id_count)
+                account_id_count = account_id + 1;
+
+            // Old athena database version reading (v1)
+        }
+        else if ((i =
+                  sscanf (line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
+                          &account_id, userid, pass, lastlogin, &sex,
+                          &logincount, &state, &n)) >= 5)
+        {
+            if (account_id > END_ACCOUNT_NUM)
+            {
+                printf
+                    ("\033[1;31mmmo_auth_init: ******Error: an account has an id higher than %d\n",
+                     END_ACCOUNT_NUM);
+                printf
+                    ("               account id #%d -> account not read (saved in log file).\033[0m\n",
+                     account_id);
+                login_log
+                    ("mmmo_auth_init: ******Error: an account has an id higher than %d.\n",
+                     END_ACCOUNT_NUM);
+                login_log
+                    ("               account id #%d -> account not read (saved in next line):\n",
+                     account_id);
+                login_log ("%s", line);
+                continue;
+            }
+            userid[23] = '\0';
+            remove_control_chars (userid);
+            for (j = 0; j < auth_num; j++)
+            {
+                if (auth_dat[j].account_id == account_id)
+                {
+                    printf
+                        ("\033[1;31mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    printf
+                        ("               account id #%d -> new account not read (saved in log file).\033[0m\n",
+                         account_id);
+                    login_log
+                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    login_log
+                        ("               account id #%d -> new account not read (saved in next line):\n",
+                         account_id);
+                    login_log ("%s", line);
+                    break;
+                }
+                else if (strcmp (auth_dat[j].userid, userid) == 0)
+                {
+                    printf
+                        ("\033[1;31mmmo_auth_init: ******Error: account name already exists.\n");
+                    printf ("               account name '%s' -> new account not read.\n", userid); // 2 lines, account name can be long.
+                    printf
+                        ("               Account saved in log file.\033[0m\n");
+                    login_log
+                        ("mmmo_auth_init: ******Error: an account has an identical id to another.\n");
+                    login_log
+                        ("               account id #%d -> new account not read (saved in next line):\n",
+                         account_id);
+                    login_log ("%s", line);
+                    break;
+                }
+            }
+            if (j != auth_num)
+                continue;
+
+            if (auth_num >= auth_max)
+            {
+                auth_max += 256;
+                RECREATE (auth_dat, struct auth_dat, auth_max);
+            }
+
+            memset (&auth_dat[auth_num], '\0', sizeof (struct auth_dat));
+
+            auth_dat[auth_num].account_id = account_id;
+
+            strncpy (auth_dat[auth_num].userid, userid, 24);
+
+            lastlogin[23] = '\0';
+            remove_control_chars (lastlogin);
+            strncpy (auth_dat[auth_num].lastlogin, lastlogin, 24);
+
+            auth_dat[auth_num].sex = (sex == 'S'
+                                      || sex == 's') ? 2 : (sex == 'M'
+                                                            || sex == 'm');
+
+            if (i >= 6)
+            {
+                if (logincount >= 0)
+                    auth_dat[auth_num].logincount = logincount;
+                else
+                    auth_dat[auth_num].logincount = 0;
+            }
+            else
+                auth_dat[auth_num].logincount = 0;
+
+            if (i >= 7)
+            {
+                if (state > 255)
+                    auth_dat[auth_num].state = 100;
+                else if (state < 0)
+                    auth_dat[auth_num].state = 0;
+                else
+                    auth_dat[auth_num].state = state;
+            }
+            else
+                auth_dat[auth_num].state = 0;
+
+            // Initialization of new data
+            strncpy (auth_dat[auth_num].email, "a@a.com", 40);
+            strncpy (auth_dat[auth_num].error_message, "-", 20);
+            auth_dat[auth_num].ban_until_time = 0;
+            auth_dat[auth_num].connect_until_time = 0;
+            strncpy (auth_dat[auth_num].last_ip, "-", 16);
+            strncpy (auth_dat[auth_num].memo, "!", 255);
+
+            for (j = 0; j < ACCOUNT_REG2_NUM; j++)
+            {
+                p += n;
+                if (sscanf (p, "%[^\t,],%d %n", str, &v, &n) != 2)
+                {
+                    // We must check if a str is void. If it's, we can continue to read other REG2.
+                    // Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
+                    if (p[0] == ',' && sscanf (p, ",%d %n", &v, &n) == 1)
+                    {
+                        j--;
+                        continue;
+                    }
+                    else
+                        break;
+                }
+                str[31] = '\0';
+                remove_control_chars (str);
+                strncpy (auth_dat[auth_num].account_reg2[j].str, str, 32);
+                auth_dat[auth_num].account_reg2[j].value = v;
+            }
+            auth_dat[auth_num].account_reg2_num = j;
+
+            if (isGM (account_id) > 0)
+                GM_count++;
+            if (auth_dat[auth_num].sex == 2)
+                server_count++;
+
+            auth_num++;
+            if (account_id >= account_id_count)
+                account_id_count = account_id + 1;
+
+        }
+        else
+        {
+            i = 0;
+            if (sscanf (line, "%d\t%%newid%%\n%n", &account_id, &i) == 1 &&
+                i > 0 && account_id > account_id_count)
+                account_id_count = account_id;
+        }
+    }
+    fclose_ (fp);
+
+    if (auth_num == 0)
+    {
+        printf ("mmo_auth_init: No account found in %s.\n", account_filename);
+        sprintf (line, "No account found in %s.", account_filename);
+    }
+    else
+    {
+        if (auth_num == 1)
+        {
+            printf ("mmo_auth_init: 1 account read in %s,\n",
+                    account_filename);
+            sprintf (line, "1 account read in %s,", account_filename);
+        }
+        else
+        {
+            printf ("mmo_auth_init: %d accounts read in %s,\n", auth_num,
+                    account_filename);
+            sprintf (line, "%d accounts read in %s,", auth_num,
+                     account_filename);
+        }
+        if (GM_count == 0)
+        {
+            printf ("               of which is no GM account, and ");
+            sprintf (str, "%s of which is no GM account and", line);
+        }
+        else if (GM_count == 1)
+        {
+            printf ("               of which is 1 GM account, and ");
+            sprintf (str, "%s of which is 1 GM account and", line);
+        }
+        else
+        {
+            printf ("               of which is %d GM accounts, and ",
+                    GM_count);
+            sprintf (str, "%s of which is %d GM accounts and", line,
+                     GM_count);
+        }
+        if (server_count == 0)
+        {
+            printf ("no server account ('S').\n");
+            sprintf (line, "%s no server account ('S').", str);
+        }
+        else if (server_count == 1)
+        {
+            printf ("1 server account ('S').\n");
+            sprintf (line, "%s 1 server account ('S').", str);
+        }
+        else
+        {
+            printf ("%d server accounts ('S').\n", server_count);
+            sprintf (line, "%s %d server accounts ('S').", str, server_count);
+        }
+    }
+    login_log ("%s\n", line);
+
+    return 0;
+}
+
+//------------------------------------------
+// Writing of the accounts database file
+//   (accounts are sorted by id before save)
+//------------------------------------------
+void mmo_auth_sync (void)
+{
+    FILE *fp;
+    int  i, j, k, lock;
+    int  id[auth_num];
+    char line[65536];
+
+    // Sorting before save
+    for (i = 0; i < auth_num; i++)
+    {
+        id[i] = i;
+        for (j = 0; j < i; j++)
+        {
+            if (auth_dat[i].account_id < auth_dat[id[j]].account_id)
+            {
+                for (k = i; k > j; k--)
+                    id[k] = id[k - 1];
+                id[j] = i;      // id[i]
+                break;
+            }
+        }
+    }
+
+    // Data save
+    fp = lock_fopen (account_filename, &lock);
+    if (fp == NULL)
+        return;
+    fprintf (fp,
+             "// Accounts file: here are saved all information about the accounts.\n");
+    fprintf (fp,
+             "// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)\n");
+    fprintf (fp, "// Some explanations:\n");
+    fprintf (fp,
+             "//   account name    : between 4 to 23 char for a normal account (standard client can't send less than 4 char).\n");
+    fprintf (fp, "//   account password: between 4 to 23 char\n");
+    fprintf (fp,
+             "//   sex             : M or F for normal accounts, S for server accounts\n");
+    fprintf (fp,
+             "//   state           : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n");
+    fprintf (fp,
+             "//   email           : between 3 to 39 char (a@a.com is like no email)\n");
+    fprintf (fp,
+             "//   error message   : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char\n");
+    fprintf (fp,
+             "//   valitidy time   : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
+    fprintf (fp, "//   memo field      : max 254 char\n");
+    fprintf (fp,
+             "//   ban time        : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)\n");
+    for (i = 0; i < auth_num; i++)
+    {
+        k = id[i];              // use of sorted index
+        if (auth_dat[k].account_id < 0)
+            continue;
+
+        mmo_auth_tostr (line, &auth_dat[k]);
+        fprintf (fp, "%s\n", line);
+    }
+    fprintf (fp, "%d\t%%newid%%\n", account_id_count);
+
+    lock_fclose (fp, account_filename, &lock);
+
+    return;
+}
+
+// We want to sync the DB to disk as little as possible as it's fairly
+// resource intensive. therefore most player-triggerable events that
+// update the account DB will not immideately trigger a save. Instead
+// we save periodicly on a timer.
+//-----------------------------------------------------
+void check_auth_sync (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    if (pid != 0)
+    {
+        int status;
+        pid_t temp = waitpid (pid, &status, WNOHANG);
+
+        // Need to check status too?
+        if (temp == 0)
+        {
+            return;
+        }
+    }
+
+    // This can take a lot of time. Fork a child to handle the work and return at once
+    // If we're unable to fork just continue running the function normally
+    if ((pid = fork ()) > 0)
+        return;
+
+    mmo_auth_sync ();
+
+    // If we're a child we should suicide now.
+    if (pid == 0)
+        _exit (0);
+
+    return;
+}
+
+//--------------------------------------------------------------------
+// Packet send to all char-servers, except one (wos: without our self)
+//--------------------------------------------------------------------
+int charif_sendallwos (int sfd, unsigned char *buf, unsigned int len)
+{
+    int  i, c;
+
+    for (i = 0, c = 0; i < MAX_SERVERS; i++)
+    {
+        int  fd;
+        if ((fd = server_fd[i]) >= 0 && fd != sfd)
+        {
+            memcpy (WFIFOP (fd, 0), buf, len);
+            WFIFOSET (fd, len);
+            c++;
+        }
+    }
+    return c;
+}
+
+//-----------------------------------------------------
+// Send GM accounts to all char-server
+//-----------------------------------------------------
+void send_GM_accounts (void)
+{
+    int  i;
+    char buf[32000];
+    int  GM_value;
+    int  len;
+
+    len = 4;
+    WBUFW (buf, 0) = 0x2732;
+    for (i = 0; i < auth_num; i++)
+        // send only existing accounts. We can not create a GM account when server is online.
+        if ((GM_value = isGM (auth_dat[i].account_id)) > 0)
+        {
+            WBUFL (buf, len) = auth_dat[i].account_id;
+            WBUFB (buf, len + 4) = (unsigned char) GM_value;
+            len += 5;
+        }
+    WBUFW (buf, 2) = len;
+    charif_sendallwos (-1, buf, len);
+
+    return;
+}
+
+//-----------------------------------------------------
+// Check if GM file account have been changed
+//-----------------------------------------------------
+void check_GM_file (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct stat file_stat;
+    long new_time;
+
+    // if we would not check
+    if (gm_account_filename_check_timer < 1)
+        return;
+
+    // get last modify time/date
+    if (stat (GM_account_filename, &file_stat))
+        new_time = 0;           // error
+    else
+        new_time = file_stat.st_mtime;
+
+    if (new_time != creation_time_GM_account_file)
+    {
+        read_gm_account ();
+        send_GM_accounts ();
+    }
+}
+
+//-------------------------------------
+// Account creation (with e-mail check)
+//-------------------------------------
+int mmo_auth_new (struct mmo_account *account, char sex, char *email)
+{
+    time_t timestamp, timestamp_temp;
+    struct tm *tmtime;
+    int  i = auth_num;
+
+    if (auth_num >= auth_max)
+    {
+        auth_max += 256;
+        RECREATE (auth_dat, struct auth_dat, auth_max);
+    }
+
+    memset (&auth_dat[i], '\0', sizeof (struct auth_dat));
+
+    while (isGM (account_id_count) > 0)
+        account_id_count++;
+
+    auth_dat[i].account_id = account_id_count++;
+
+    strncpy (auth_dat[i].userid, account->userid, 24);
+    auth_dat[i].userid[23] = '\0';
+
+    strcpy(auth_dat[i].pass, MD5_saltcrypt(account->passwd, make_salt()));
+    auth_dat[i].pass[39] = '\0';
+
+    memcpy (auth_dat[i].lastlogin, "-", 2);
+
+    auth_dat[i].sex = (sex == 'M');
+
+    auth_dat[i].logincount = 0;
+
+    auth_dat[i].state = 0;
+
+    if (e_mail_check (email) == 0)
+        strncpy (auth_dat[i].email, "a@a.com", 40);
+    else
+        strncpy (auth_dat[i].email, email, 40);
+
+    strncpy (auth_dat[i].error_message, "-", 20);
+
+    auth_dat[i].ban_until_time = 0;
+
+    if (start_limited_time < 0)
+        auth_dat[i].connect_until_time = 0; // unlimited
+    else
+    {                           // limited time
+        timestamp = time (NULL) + start_limited_time;
+        // double conversion to be sure that it is possible
+        tmtime = gmtime (&timestamp);
+        timestamp_temp = mktime (tmtime);
+        if (timestamp_temp != -1 && (timestamp_temp + 3600) >= timestamp)   // check possible value and overflow (and avoid summer/winter hour)
+            auth_dat[i].connect_until_time = timestamp_temp;
+        else
+            auth_dat[i].connect_until_time = 0; // unlimited
+    }
+
+    strncpy (auth_dat[i].last_ip, "-", 16);
+
+    strncpy (auth_dat[i].memo, "!", 255);
+
+    auth_dat[i].account_reg2_num = 0;
+
+    auth_num++;
+
+    return (account_id_count - 1);
+}
+
+//---------------------------------------
+// Check/authentification of a connection
+//---------------------------------------
+int mmo_auth (struct mmo_account *account, int fd)
+{
+    int  i;
+    struct timeval tv;
+    char tmpstr[256];
+    int  len, newaccount = 0;
+#ifdef PASSWDENC
+    char md5str[64], md5bin[32];
+#endif
+    char ip[16];
+    unsigned char *sin_addr =
+        (unsigned char *) &session[fd]->client_addr.sin_addr;
+
+    sprintf (ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2],
+             sin_addr[3]);
+
+    len = strlen (account->userid) - 2;
+    // Account creation with _M/_F
+    if (account->passwdenc == 0 && account->userid[len] == '_' &&
+        (account->userid[len + 1] == 'F' || account->userid[len + 1] == 'M')
+        && new_account_flag == 1 && account_id_count <= END_ACCOUNT_NUM
+        && len >= 4 && strlen (account->passwd) >= 4)
+    {
+        if (new_account_flag == 1)
+            newaccount = 1;
+        account->userid[len] = '\0';
+    }
+
+    // Strict account search
+    for (i = 0; i < auth_num; i++)
+    {
+        if (strcmp (account->userid, auth_dat[i].userid) == 0)
+            break;
+    }
+    // if there is no creation request and strict account search fails, we do a no sensitive case research for index
+    if (newaccount == 0 && i == auth_num)
+    {
+        i = search_account_index (account->userid);
+        if (i == -1)
+            i = auth_num;
+        else
+            memcpy (account->userid, auth_dat[i].userid, 24);   // for the possible tests/checks afterwards (copy correcte sensitive case).
+    }
+
+    if (i != auth_num)
+    {
+        int  encpasswdok = 0;
+        struct login_session_data *ld;
+        if (newaccount)
+        {
+            login_log
+                ("Attempt of creation of an already existant account (account: %s_%c, ip: %s)\n",
+                 account->userid, account->userid[len + 1], ip);
+            return 9;           // 9 = Account already exists
+        }
+        ld = (struct login_session_data*) session[fd]->session_data;
+#ifdef PASSWORDENC
+        if (account->passwdenc > 0)
+        {
+            int  j = account->passwdenc;
+            if (!ld)
+            {
+                login_log ("Md5 key not created (account: %s, ip: %s)\n",
+                           account->userid, ip);
+                return 1;       // 1 = Incorrect Password
+            }
+            if (j > 2)
+                j = 1;
+            do
+            {
+                if (j == 1)
+                {
+                    strncpy (md5str, ld->md5key, sizeof (ld->md5key));  // 20
+                    strcat (md5str, auth_dat[i].pass);  // 24
+                }
+                else if (j == 2)
+                {
+                    strncpy (md5str, auth_dat[i].pass, sizeof (auth_dat[i].pass));  // 24
+                    strcat (md5str, ld->md5key);    // 20
+                }
+                else
+                    md5str[0] = '\0';
+                md5str[sizeof (md5str) - 1] = '\0'; // 64
+                MD5_String2binary (md5str, md5bin);
+                encpasswdok = (memcmp (account->passwd, md5bin, 16) == 0);
+            }
+            while (j < 2 && !encpasswdok && (j++) != account->passwdenc);
+//          printf("key[%s] md5 [%s] ", md5key, md5);
+//          printf("client [%s] accountpass [%s]\n", account->passwd, auth_dat[i].pass);
+        }
+#endif
+        if ((!pass_ok (account->passwd, auth_dat[i].pass)) && !encpasswdok)
+        {
+            if (account->passwdenc == 0)
+                login_log
+                    ("Invalid password (account: %s, ip: %s)\n",
+                     account->userid, ip);
+
+#ifdef PASSWORDENC
+            else
+            {
+                char logbuf[512], *p = logbuf;
+                int  j;
+                p += sprintf (p,
+                              "Invalid password (account: %s, received md5[",
+                              account->userid);
+                for (j = 0; j < 16; j++)
+                    p += sprintf (p, "%02x",
+                                  ((unsigned char *) account->passwd)[j]);
+                p += sprintf (p, "] calculated md5[");
+                for (j = 0; j < 16; j++)
+                    p += sprintf (p, "%02x", ((unsigned char *) md5bin)[j]);
+                p += sprintf (p, "] md5 key[");
+                for (j = 0; j < ld->md5keylen; j++)
+                    p += sprintf (p, "%02x",
+                                  ((unsigned char *) ld->md5key)[j]);
+                p += sprintf (p, "], ip: %s)\n", ip);
+                login_log (logbuf);
+            }
+#endif
+            return 1;           // 1 = Incorrect Password
+        }
+
+        if (auth_dat[i].state)
+        {
+            login_log
+                ("Connection refused (account: %s, state: %d, ip: %s)\n",
+                 account->userid, auth_dat[i].state,
+                 ip);
+            switch (auth_dat[i].state)
+            {                   // packet 0x006a value + 1
+                case 1:        // 0 = Unregistered ID
+                case 2:        // 1 = Incorrect Password
+                case 3:        // 2 = This ID is expired
+                case 4:        // 3 = Rejected from Server
+                case 5:        // 4 = You have been blocked by the GM Team
+                case 6:        // 5 = Your Game's EXE file is not the latest version
+                case 7:        // 6 = Your are Prohibited to log in until %s
+                case 8:        // 7 = Server is jammed due to over populated
+                case 9:        // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
+                case 100:      // 99 = This ID has been totally erased
+                    return auth_dat[i].state - 1;
+                    break;
+                default:
+                    return 99;  // 99 = ID has been totally erased
+                    break;
+            }
+        }
+
+        if (auth_dat[i].ban_until_time != 0)
+        {                       // if account is banned
+            strftime (tmpstr, 20, date_format,
+                      gmtime (&auth_dat[i].ban_until_time));
+            tmpstr[19] = '\0';
+            if (auth_dat[i].ban_until_time > time (NULL))
+            {                   // always banned
+                login_log
+                    ("Connection refused (account: %s, banned until %s, ip: %s)\n",
+                     account->userid, tmpstr, ip);
+                return 6;       // 6 = Your are Prohibited to log in until %s
+            }
+            else
+            {                   // ban is finished
+                login_log
+                    ("End of ban (account: %s, previously banned until %s -> not more banned, ip: %s)\n",
+                     account->userid, tmpstr, ip);
+                auth_dat[i].ban_until_time = 0; // reset the ban time
+            }
+        }
+
+        if (auth_dat[i].connect_until_time != 0
+            && auth_dat[i].connect_until_time < time (NULL))
+        {
+            login_log
+                ("Connection refused (account: %s, expired ID, ip: %s)\n",
+                 account->userid, ip);
+            return 2;           // 2 = This ID is expired
+        }
+
+        login_log ("Authentification accepted (account: %s (id: %d), ip: %s)\n",
+                   account->userid, auth_dat[i].account_id, ip);
+    }
+    else
+    {
+        if (newaccount == 0)
+        {
+            login_log
+                ("Unknown account (account: %s, ip: %s)\n",
+                 account->userid, ip);
+            return 0;           // 0 = Unregistered ID
+        }
+        else
+        {
+            int  new_id =
+                mmo_auth_new (account, account->userid[len + 1], "a@a.com");
+            login_log
+                ("Account creation and authentification accepted (account %s (id: %d), sex: %c, connection with _F/_M, ip: %s)\n",
+                 account->userid, new_id,
+                 account->userid[len + 1], ip);
+        }
+    }
+
+    gettimeofday (&tv, NULL);
+    strftime (tmpstr, 24, date_format, gmtime (&(tv.tv_sec)));
+    sprintf (tmpstr + strlen (tmpstr), ".%03d", (int) tv.tv_usec / 1000);
+
+    account->account_id = auth_dat[i].account_id;
+    account->login_id1 = mt_random ();
+    account->login_id2 = mt_random ();
+    memcpy (account->lastlogin, auth_dat[i].lastlogin, 24);
+    memcpy (auth_dat[i].lastlogin, tmpstr, 24);
+    account->sex = auth_dat[i].sex;
+    strncpy (auth_dat[i].last_ip, ip, 16);
+    auth_dat[i].logincount++;
+
+    return -1;                  // account OK
+}
+
+//-------------------------------
+// Char-server anti-freeze system
+//-------------------------------
+void char_anti_freeze_system (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  i;
+
+    //printf("Entering in char_anti_freeze_system function to check freeze of servers.\n");
+    for (i = 0; i < MAX_SERVERS; i++)
+    {
+        if (server_fd[i] >= 0)
+        {                       // if char-server is online
+            //printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
+            if (server_freezeflag[i]-- < 1)
+            {                   // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+                printf
+                    ("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n",
+                     i, server[i].name);
+                login_log
+                    ("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n",
+                     i, server[i].name);
+                session[server_fd[i]]->eof = 1;
+            }
+        }
+    }
+}
+
+//--------------------------------
+// Packet parsing for char-servers
+//--------------------------------
+void parse_fromchar (int fd)
+{
+    int  i, j, id;
+    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+    char ip[16];
+
+    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+    for (id = 0; id < MAX_SERVERS; id++)
+        if (server_fd[id] == fd)
+            break;
+    if (id == MAX_SERVERS || session[fd]->eof)
+    {
+        if (id < MAX_SERVERS)
+        {
+            printf ("Char-server '%s' has disconnected.\n", server[id].name);
+            login_log ("Char-server '%s' has disconnected (ip: %s).\n",
+                       server[id].name, ip);
+            server_fd[id] = -1;
+            memset (&server[id], 0, sizeof (struct mmo_char_server));
+        }
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    while (RFIFOREST (fd) >= 2)
+    {
+        if (display_parse_fromchar == 2 || (display_parse_fromchar == 1 && RFIFOW (fd, 0) != 0x2714))   // 0x2714 is done very often (number of players)
+            printf
+                ("parse_fromchar: connection #%d, packet: 0x%x (with being read: %d bytes).\n",
+                 fd, RFIFOW (fd, 0), RFIFOREST (fd));
+
+        switch (RFIFOW (fd, 0))
+        {
+                // request from map-server via char-server to reload GM accounts (by Yor).
+            case 0x2709:
+                login_log
+                    ("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n",
+                     server[id].name, ip);
+                read_gm_account ();
+                // send GM accounts to all char-servers
+                send_GM_accounts ();
+                RFIFOSKIP (fd, 2);
+                break;
+
+            case 0x2712:       // request from char-server to authentify an account
+                if (RFIFOREST (fd) < 19)
+                    return;
+                {
+                    int  acc;
+                    acc = RFIFOL (fd, 2);   // speed up
+                    for (i = 0; i < AUTH_FIFO_SIZE; i++)
+                    {
+                        if (auth_fifo[i].account_id == acc &&
+                            auth_fifo[i].login_id1 == RFIFOL (fd, 6) &&
+#if CMP_AUTHFIFO_LOGIN2 != 0
+                            auth_fifo[i].login_id2 == RFIFOL (fd, 10) &&    // relate to the versions higher than 18
+#endif
+                            auth_fifo[i].sex == RFIFOB (fd, 14) &&
+                            (!check_ip_flag
+                             || auth_fifo[i].ip == RFIFOL (fd, 15))
+                            && !auth_fifo[i].delflag)
+                        {
+                            int  p, k;
+                            auth_fifo[i].delflag = 1;
+                            login_log
+                                ("Char-server '%s': authentification of the account %d accepted (ip: %s).\n",
+                                 server[id].name, acc, ip);
+//                  printf("%d\n", i);
+                            for (k = 0; k < auth_num; k++)
+                            {
+                                if (auth_dat[k].account_id == acc)
+                                {
+                                    WFIFOW (fd, 0) = 0x2729;    // Sending of the account_reg2
+                                    WFIFOL (fd, 4) = acc;
+                                    for (p = 8, j = 0;
+                                         j < auth_dat[k].account_reg2_num;
+                                         p += 36, j++)
+                                    {
+                                        memcpy (WFIFOP (fd, p),
+                                                auth_dat[k].
+                                                account_reg2[j].str, 32);
+                                        WFIFOL (fd, p + 32) =
+                                            auth_dat[k].account_reg2[j].value;
+                                    }
+                                    WFIFOW (fd, 2) = p;
+                                    WFIFOSET (fd, p);
+//                          printf("parse_fromchar: Sending of account_reg2: login->char (auth fifo)\n");
+                                    WFIFOW (fd, 0) = 0x2713;
+                                    WFIFOL (fd, 2) = acc;
+                                    WFIFOB (fd, 6) = 0;
+                                    memcpy (WFIFOP (fd, 7), auth_dat[k].email,
+                                            40);
+                                    WFIFOL (fd, 47) =
+                                        (unsigned long)
+                                        auth_dat[k].connect_until_time;
+                                    WFIFOSET (fd, 51);
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                    // authentification not found
+                    if (i == AUTH_FIFO_SIZE)
+                    {
+                        login_log
+                            ("Char-server '%s': authentification of the account %d REFUSED (ip: %s).\n",
+                             server[id].name, acc, ip);
+                        WFIFOW (fd, 0) = 0x2713;
+                        WFIFOL (fd, 2) = acc;
+                        WFIFOB (fd, 6) = 1;
+                        // It is unnecessary to send email
+                        // It is unnecessary to send validity date of the account
+                        WFIFOSET (fd, 51);
+                    }
+                }
+                RFIFOSKIP (fd, 19);
+                break;
+
+            case 0x2714:
+                if (RFIFOREST (fd) < 6)
+                    return;
+                //printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2));
+                server[id].users = RFIFOL (fd, 2);
+                if (anti_freeze_enable)
+                    server_freezeflag[id] = 5;  // Char anti-freeze system. Counter. 5 ok, 4...0 freezed
+                RFIFOSKIP (fd, 6);
+                break;
+
+                // we receive a e-mail creation of an account with a default e-mail (no answer)
+            case 0x2715:
+            {
+                int  acc;
+                char email[40];
+                if (RFIFOREST (fd) < 46)
+                    return;
+                acc = RFIFOL (fd, 2);   // speed up
+                memcpy (email, RFIFOP (fd, 6), 40);
+                email[39] = '\0';
+                remove_control_chars (email);
+                //printf("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6));
+                if (e_mail_check (email) == 0)
+                    login_log
+                        ("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n",
+                         server[id].name, acc, ip);
+                else
+                {
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc
+                            && (strcmp (auth_dat[i].email, "a@a.com") == 0
+                                || auth_dat[i].email[0] == '\0'))
+                        {
+                            memcpy (auth_dat[i].email, email, 40);
+                            login_log
+                                ("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n",
+                                 server[id].name, acc, email, ip);
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                        login_log
+                            ("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n",
+                             server[id].name, acc, ip);
+                }
+                RFIFOSKIP (fd, 46);
+                break;
+
+                // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
+            }
+            case 0x2716:
+                if (RFIFOREST (fd) < 6)
+                    return;
+                //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
+                for (i = 0; i < auth_num; i++)
+                {
+                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
+                    {
+                        login_log
+                            ("Char-server '%s': e-mail of the account %d found (ip: %s).\n",
+                             server[id].name, RFIFOL (fd, 2), ip);
+                        WFIFOW (fd, 0) = 0x2717;
+                        WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].email, 40);
+                        WFIFOL (fd, 46) =
+                            (unsigned long) auth_dat[i].connect_until_time;
+                        WFIFOSET (fd, 50);
+                        break;
+                    }
+                }
+                if (i == auth_num)
+                {
+                    login_log
+                        ("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n",
+                         server[id].name, RFIFOL (fd, 2), ip);
+                }
+                RFIFOSKIP (fd, 6);
+                break;
+
+            case 0x2720:       // To become GM request
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    int  acc;
+                    unsigned char buf[10];
+                    FILE *fp;
+                    acc = RFIFOL (fd, 4);
+                    //printf("parse_fromchar: Request to become a GM acount from %d account.\n", acc);
+                    WBUFW (buf, 0) = 0x2721;
+                    WBUFL (buf, 2) = acc;
+                    WBUFL (buf, 6) = 0;
+                    if (strcmp (RFIFOP (fd, 8), gm_pass) == 0)
+                    {
+                        // only non-GM can become GM
+                        if (isGM (acc) == 0)
+                        {
+                            // if we autorise creation
+                            if (level_new_gm > 0)
+                            {
+                                // if we can open the file to add the new GM
+                                if ((fp =
+                                     fopen_ (GM_account_filename,
+                                             "a")) != NULL)
+                                {
+                                    char tmpstr[24];
+                                    struct timeval tv;
+                                    gettimeofday (&tv, NULL);
+                                    strftime (tmpstr, 23, date_format,
+                                              gmtime (&(tv.tv_sec)));
+                                    fprintf (fp,
+                                             "\n// %s: @GM command on account %d\n%d %d\n",
+                                             tmpstr,
+                                             acc, acc, level_new_gm);
+                                    fclose_ (fp);
+                                    WBUFL (buf, 6) = level_new_gm;
+                                    read_gm_account ();
+                                    send_GM_accounts ();
+                                    printf
+                                        ("GM Change of the account %d: level 0 -> %d.\n",
+                                         acc, level_new_gm);
+                                    login_log
+                                        ("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n",
+                                         server[id].name, acc,
+                                         level_new_gm, ip);
+                                }
+                                else
+                                {
+                                    printf
+                                        ("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n",
+                                         acc);
+                                    login_log
+                                        ("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n",
+                                         server[id].name, acc, ip);
+                                }
+                            }
+                            else
+                            {
+                                printf
+                                    ("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n",
+                                     acc);
+                                login_log
+                                    ("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n",
+                                     server[id].name, acc, ip);
+                            }
+                        }
+                        else
+                        {
+                            printf
+                                ("Error of GM change (suggested account: %d (already GM), correct password).\n",
+                                 acc);
+                            login_log
+                                ("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n",
+                                 server[id].name, acc, ip);
+                        }
+                    }
+                    else
+                    {
+                        printf
+                            ("Error of GM change (suggested account: %d, invalid password).\n",
+                             acc);
+                        login_log
+                            ("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n",
+                             server[id].name, acc, ip);
+                    }
+                    charif_sendallwos (-1, buf, 10);
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                return;
+
+                // Map server send information to change an email of an account via char-server
+            case 0x2722:       // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
+                if (RFIFOREST (fd) < 86)
+                    return;
+                {
+                    int  acc;
+                    char actual_email[40], new_email[40];
+                    acc = RFIFOL (fd, 2);
+                    memcpy (actual_email, RFIFOP (fd, 6), 40);
+                    actual_email[39] = '\0';
+                    remove_control_chars (actual_email);
+                    memcpy (new_email, RFIFOP (fd, 46), 40);
+                    new_email[39] = '\0';
+                    remove_control_chars (new_email);
+                    if (e_mail_check (actual_email) == 0)
+                        login_log
+                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n",
+                             server[id].name, acc, ip);
+                    else if (e_mail_check (new_email) == 0)
+                        login_log
+                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n",
+                             server[id].name, acc, ip);
+                    else if (strcasecmp (new_email, "a@a.com") == 0)
+                        login_log
+                            ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n",
+                             server[id].name, acc, ip);
+                    else
+                    {
+                        for (i = 0; i < auth_num; i++)
+                        {
+                            if (auth_dat[i].account_id == acc)
+                            {
+                                if (strcasecmp (auth_dat[i].email, actual_email)
+                                    == 0)
+                                {
+                                    memcpy (auth_dat[i].email, new_email, 40);
+                                    login_log
+                                        ("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n",
+                                         server[id].name, acc,
+                                         auth_dat[i].userid, new_email, ip);
+                                }
+                                else
+                                    login_log
+                                        ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n",
+                                         server[id].name, acc,
+                                         auth_dat[i].userid,
+                                         auth_dat[i].email, actual_email, ip);
+                                break;
+                            }
+                        }
+                        if (i == auth_num)
+                            login_log
+                                ("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n",
+                                 server[id].name, acc, ip);
+                    }
+                }
+                RFIFOSKIP (fd, 86);
+                break;
+
+                // Receiving of map-server via char-server a status change resquest (by Yor)
+            case 0x2724:
+                if (RFIFOREST (fd) < 10)
+                    return;
+                {
+                    int  acc, statut;
+                    acc = RFIFOL (fd, 2);
+                    statut = RFIFOL (fd, 6);
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            if (auth_dat[i].state != statut)
+                            {
+                                login_log
+                                    ("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n",
+                                     server[id].name, acc, statut,
+                                     ip);
+                                if (statut != 0)
+                                {
+                                    unsigned char buf[16];
+                                    WBUFW (buf, 0) = 0x2731;
+                                    WBUFL (buf, 2) = acc;
+                                    WBUFB (buf, 6) = 0; // 0: change of statut, 1: ban
+                                    WBUFL (buf, 7) = statut;    // status or final date of a banishment
+                                    charif_sendallwos (-1, buf, 11);
+                                    for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                        if (auth_fifo[j].account_id == acc)
+                                            auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                                }
+                                auth_dat[i].state = statut;
+                            }
+                            else
+                                login_log
+                                    ("Char-server '%s':  Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n",
+                                     server[id].name, acc, statut,
+                                     ip);
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                    {
+                        login_log
+                            ("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n",
+                             server[id].name, acc, statut, ip);
+                    }
+                    RFIFOSKIP (fd, 10);
+                }
+                return;
+
+            case 0x2725:       // Receiving of map-server via char-server a ban resquest (by Yor)
+                if (RFIFOREST (fd) < 18)
+                    return;
+                {
+                    int  acc;
+                    acc = RFIFOL (fd, 2);
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            time_t timestamp;
+                            struct tm *tmtime;
+                            if (auth_dat[i].ban_until_time == 0
+                                || auth_dat[i].ban_until_time < time (NULL))
+                                timestamp = time (NULL);
+                            else
+                                timestamp = auth_dat[i].ban_until_time;
+                            tmtime = gmtime (&timestamp);
+                            tmtime->tm_year =
+                                tmtime->tm_year + (short) RFIFOW (fd, 6);
+                            tmtime->tm_mon =
+                                tmtime->tm_mon + (short) RFIFOW (fd, 8);
+                            tmtime->tm_mday =
+                                tmtime->tm_mday + (short) RFIFOW (fd, 10);
+                            tmtime->tm_hour =
+                                tmtime->tm_hour + (short) RFIFOW (fd, 12);
+                            tmtime->tm_min =
+                                tmtime->tm_min + (short) RFIFOW (fd, 14);
+                            tmtime->tm_sec =
+                                tmtime->tm_sec + (short) RFIFOW (fd, 16);
+                            timestamp = timegm (tmtime);
+                            if (timestamp != -1)
+                            {
+                                if (timestamp <= time (NULL))
+                                    timestamp = 0;
+                                if (auth_dat[i].ban_until_time != timestamp)
+                                {
+                                    if (timestamp != 0)
+                                    {
+                                        unsigned char buf[16];
+                                        char tmpstr[2048];
+                                        strftime (tmpstr, 24, date_format,
+                                                  gmtime (&timestamp));
+                                        login_log
+                                            ("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n",
+                                             server[id].name, acc,
+                                             timestamp,
+                                             (timestamp ==
+                                              0 ? "no banishment" : tmpstr),
+                                             ip);
+                                        WBUFW (buf, 0) = 0x2731;
+                                        WBUFL (buf, 2) =
+                                            auth_dat[i].account_id;
+                                        WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
+                                        WBUFL (buf, 7) = timestamp; // status or final date of a banishment
+                                        charif_sendallwos (-1, buf, 11);
+                                        for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                            if (auth_fifo[j].account_id ==
+                                                acc)
+                                                auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                                    }
+                                    else
+                                    {
+                                        login_log
+                                            ("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n",
+                                             server[id].name, acc,
+                                             ip);
+                                    }
+                                    auth_dat[i].ban_until_time = timestamp;
+                                }
+                                else
+                                {
+                                    login_log
+                                        ("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s).\n",
+                                         server[id].name, acc, ip);
+                                }
+                            }
+                            else
+                            {
+                                login_log
+                                    ("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n",
+                                     server[id].name, acc, ip);
+                            }
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                    {
+                        login_log
+                            ("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n",
+                             server[id].name, acc, ip);
+                    }
+                    RFIFOSKIP (fd, 18);
+                }
+                return;
+
+            case 0x2727:       // Change of sex (sex is reversed)
+                if (RFIFOREST (fd) < 6)
+                    return;
+                {
+                    int  acc, sex;
+                    acc = RFIFOL (fd, 2);
+                    for (i = 0; i < auth_num; i++)
+                    {
+//                  printf("%d,", auth_dat[i].account_id);
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            if (auth_dat[i].sex == 2)
+                                login_log
+                                    ("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n",
+                                     server[id].name, acc,
+                                     auth_dat[i].sex, ip);
+                            else
+                            {
+                                unsigned char buf[16];
+                                if (auth_dat[i].sex == 0)
+                                    sex = 1;
+                                else
+                                    sex = 0;
+                                login_log
+                                    ("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n",
+                                     server[id].name, acc,
+                                     (sex == 2) ? 'S' : (sex ? 'M' : 'F'),
+                                     ip);
+                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                    if (auth_fifo[j].account_id == acc)
+                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                                auth_dat[i].sex = sex;
+                                WBUFW (buf, 0) = 0x2723;
+                                WBUFL (buf, 2) = acc;
+                                WBUFB (buf, 6) = sex;
+                                charif_sendallwos (-1, buf, 7);
+                            }
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                    {
+                        login_log
+                            ("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n",
+                             server[id].name, acc, ip);
+                    }
+                    RFIFOSKIP (fd, 6);
+                }
+                return;
+
+            case 0x2728:       // We receive account_reg2 from a char-server, and we send them to other char-servers.
+                if (RFIFOREST (fd) < 4 || RFIFOREST (fd) < RFIFOW (fd, 2))
+                    return;
+                {
+                    int  acc, p;
+                    acc = RFIFOL (fd, 4);
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            unsigned char buf[RFIFOW (fd, 2) + 1];
+                            login_log
+                                ("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n",
+                                 server[id].name, acc, ip);
+                            for (p = 8, j = 0;
+                                 p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
+                                 p += 36, j++)
+                            {
+                                memcpy (auth_dat[i].account_reg2[j].str,
+                                        RFIFOP (fd, p), 32);
+                                auth_dat[i].account_reg2[j].str[31] = '\0';
+                                remove_control_chars (auth_dat[i].account_reg2
+                                                      [j].str);
+                                auth_dat[i].account_reg2[j].value =
+                                    RFIFOL (fd, p + 32);
+                            }
+                            auth_dat[i].account_reg2_num = j;
+                            // Sending information towards the other char-servers.
+                            memcpy (WBUFP (buf, 0), RFIFOP (fd, 0),
+                                    RFIFOW (fd, 2));
+                            WBUFW (buf, 0) = 0x2729;
+                            charif_sendallwos (fd, buf, WBUFW (buf, 2));
+//                      printf("parse_fromchar: receiving (from the char-server) of account_reg2 (account id: %d).\n", acc);
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                    {
+//                  printf("parse_fromchar: receiving (from the char-server) of account_reg2 (unknwon account id: %d).\n", acc);
+                        login_log
+                            ("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n",
+                             server[id].name, acc, ip);
+                    }
+                }
+                RFIFOSKIP (fd, RFIFOW (fd, 2));
+                break;
+
+            case 0x272a:       // Receiving of map-server via char-server a unban resquest (by Yor)
+                if (RFIFOREST (fd) < 6)
+                    return;
+                {
+                    int  acc;
+                    acc = RFIFOL (fd, 2);
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            if (auth_dat[i].ban_until_time != 0)
+                            {
+                                auth_dat[i].ban_until_time = 0;
+                                login_log
+                                    ("Char-server '%s': UnBan request (account: %d, ip: %s).\n",
+                                     server[id].name, acc, ip);
+                            }
+                            else
+                            {
+                                login_log
+                                    ("Char-server '%s': Error of UnBan request (account: %d, no change for unban date, ip: %s).\n",
+                                     server[id].name, acc, ip);
+                            }
+                            break;
+                        }
+                    }
+                    if (i == auth_num)
+                    {
+                        login_log
+                            ("Char-server '%s': Error of UnBan request (account: %d not found, ip: %s).\n",
+                             server[id].name, acc, ip);
+                    }
+                    RFIFOSKIP (fd, 6);
+                }
+                return;
+
+                // request from char-server to change account password
+            case 0x2740:       // 0x2740 <account_id>.L <actual_password>.24B <new_password>.24B
+                if (RFIFOREST (fd) < 54)
+                    return;
+                {
+                    int  acc;
+                    char actual_pass[24], new_pass[24];
+                    acc = RFIFOL (fd, 2);
+                    memcpy (actual_pass, RFIFOP (fd, 6), 24);
+                    actual_pass[23] = '\0';
+                    remove_control_chars (actual_pass);
+                    memcpy (new_pass, RFIFOP (fd, 30), 24);
+                    new_pass[23] = '\0';
+                    remove_control_chars (new_pass);
+
+                    int  status = 0;
+
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        if (auth_dat[i].account_id == acc)
+                        {
+                            if (pass_ok (actual_pass, auth_dat[i].pass))
+                            {
+                                if (strlen (new_pass) < 4)
+                                    status = 3;
+                                else
+                                {
+                                    status = 1;
+                                    strcpy (auth_dat[i].pass, MD5_saltcrypt(new_pass, make_salt()));
+                                    login_log
+                                        ("Char-server '%s': Change pass success (account: %d (%s), ip: %s.\n",
+                                         server[id].name, acc,
+                                         auth_dat[i].userid, ip);
+                                }
+                            }
+                            else
+                            {
+                                status = 2;
+                                login_log
+                                    ("Char-server '%s': Attempt to modify a pass failed, wrong password. (account: %d (%s), ip: %s).\n",
+                                     server[id].name, acc,
+                                     auth_dat[i].userid, ip);
+                            }
+                            break;
+                        }
+                    }
+                    WFIFOW (fd, 0) = 0x2741;
+                    WFIFOL (fd, 2) = acc;
+                    WFIFOB (fd, 6) = status;    // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short
+                    WFIFOSET (fd, 7);
+                }
+
+                RFIFOSKIP (fd, 54);
+                break;
+
+            default:
+            {
+                FILE *logfp;
+                char tmpstr[24];
+                struct timeval tv;
+                logfp = fopen_ (login_log_unknown_packets_filename, "a");
+                if (logfp)
+                {
+                    gettimeofday (&tv, NULL);
+                    strftime (tmpstr, 23, date_format, gmtime (&(tv.tv_sec)));
+                    fprintf (logfp,
+                             "%s.%03d: receiving of an unknown packet -> disconnection\n",
+                             tmpstr, (int) tv.tv_usec / 1000);
+                    fprintf (logfp,
+                             "parse_fromchar: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
+                             fd, ip, RFIFOW (fd, 0), RFIFOREST (fd));
+                    fprintf (logfp, "Detail (in hex):\n");
+                    fprintf (logfp,
+                             "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
+                    memset (tmpstr, '\0', sizeof (tmpstr));
+                    for (i = 0; i < RFIFOREST (fd); i++)
+                    {
+                        if ((i & 15) == 0)
+                            fprintf (logfp, "%04X ", i);
+                        fprintf (logfp, "%02x ", RFIFOB (fd, i));
+                        if (RFIFOB (fd, i) > 0x1f)
+                            tmpstr[i % 16] = RFIFOB (fd, i);
+                        else
+                            tmpstr[i % 16] = '.';
+                        if ((i - 7) % 16 == 0)  // -8 + 1
+                            fprintf (logfp, " ");
+                        else if ((i + 1) % 16 == 0)
+                        {
+                            fprintf (logfp, " %s\n", tmpstr);
+                            memset (tmpstr, '\0', sizeof (tmpstr));
+                        }
+                    }
+                    if (i % 16 != 0)
+                    {
+                        for (j = i; j % 16 != 0; j++)
+                        {
+                            fprintf (logfp, "   ");
+                            if ((j - 7) % 16 == 0)  // -8 + 1
+                                fprintf (logfp, " ");
+                        }
+                        fprintf (logfp, " %s\n", tmpstr);
+                    }
+                    fprintf (logfp, "\n");
+                    fclose_ (logfp);
+                }
+            }
+                printf
+                    ("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n",
+                     RFIFOW (fd, 0));
+                session[fd]->eof = 1;
+                printf
+                    ("Char-server has been disconnected (unknown packet).\n");
+                return;
+        }
+    }
+    return;
+}
+
+//---------------------------------------
+// Packet parsing for administation login
+//---------------------------------------
+void parse_admin (int fd)
+{
+    int  i, j;
+    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+    char *account_name;
+    char ip[16];
+
+    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+    if (session[fd]->eof)
+    {
+        close (fd);
+        delete_session (fd);
+        printf ("Remote administration has disconnected (session #%d).\n",
+                fd);
+        return;
+    }
+
+    while (RFIFOREST (fd) >= 2)
+    {
+        if (display_parse_admin == 1)
+            printf
+                ("parse_admin: connection #%d, packet: 0x%x (with being read: %d).\n",
+                 fd, RFIFOW (fd, 0), RFIFOREST (fd));
+
+        switch (RFIFOW (fd, 0))
+        {
+            case 0x7530:       // Request of the server version
+                login_log ("'ladmin': Sending of the server version (ip: %s)\n",
+                           ip);
+                WFIFOW (fd, 0) = 0x7531;
+                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
+                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
+                WFIFOB (fd, 4) = ATHENA_REVISION;
+                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
+                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
+                WFIFOB (fd, 7) = ATHENA_SERVER_LOGIN;
+                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
+                WFIFOSET (fd, 10);
+                RFIFOSKIP (fd, 2);
+                break;
+
+            case 0x7532:       // Request of end of connection
+                login_log ("'ladmin': End of connection (ip: %s)\n",
+                           ip);
+                RFIFOSKIP (fd, 2);
+                session[fd]->eof = 1;
+                break;
+
+            case 0x7920:       // Request of an accounts list
+                if (RFIFOREST (fd) < 10)
+                    return;
+                {
+                    int  st, ed, len;
+                    int  id[auth_num];
+                    st = RFIFOL (fd, 2);
+                    ed = RFIFOL (fd, 6);
+                    RFIFOSKIP (fd, 10);
+                    WFIFOW (fd, 0) = 0x7921;
+                    if (st < 0)
+                        st = 0;
+                    if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
+                        ed = END_ACCOUNT_NUM;
+                    login_log
+                        ("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n",
+                         st, ed, ip);
+                    // Sort before send
+                    for (i = 0; i < auth_num; i++)
+                    {
+                        int  k;
+                        id[i] = i;
+                        for (j = 0; j < i; j++)
+                        {
+                            if (auth_dat[id[i]].account_id <
+                                auth_dat[id[j]].account_id)
+                            {
+                                for (k = i; k > j; k--)
+                                {
+                                    id[k] = id[k - 1];
+                                }
+                                id[j] = i;  // id[i]
+                                break;
+                            }
+                        }
+                    }
+                    // Sending accounts information
+                    len = 4;
+                    for (i = 0; i < auth_num && len < 30000; i++)
+                    {
+                        int  account_id = auth_dat[id[i]].account_id;   // use sorted index
+                        if (account_id >= st && account_id <= ed)
+                        {
+                            j = id[i];
+                            WFIFOL (fd, len) = account_id;
+                            WFIFOB (fd, len + 4) =
+                                (unsigned char) isGM (account_id);
+                            memcpy (WFIFOP (fd, len + 5), auth_dat[j].userid,
+                                    24);
+                            WFIFOB (fd, len + 29) = auth_dat[j].sex;
+                            WFIFOL (fd, len + 30) = auth_dat[j].logincount;
+                            if (auth_dat[j].state == 0 && auth_dat[j].ban_until_time != 0)  // if no state and banished
+                                WFIFOL (fd, len + 34) = 7;  // 6 = Your are Prohibited to log in until %s
+                            else
+                                WFIFOL (fd, len + 34) = auth_dat[j].state;
+                            len += 38;
+                        }
+                    }
+                    WFIFOW (fd, 2) = len;
+                    WFIFOSET (fd, len);
+                }
+                break;
+
+            case 0x7924:
+            {                   // [Fate] Itemfrob package: change item IDs
+                if (RFIFOREST (fd) < 10)
+                    return;
+                charif_sendallwos (-1, RFIFOP (fd, 0), 10); // forward package to char servers
+                RFIFOSKIP (fd, 10);
+                WFIFOW (fd, 0) = 0x7925;
+                WFIFOSET (fd, 2);
+                break;
+            }
+
+            case 0x7930:       // Request for an account creation
+                if (RFIFOREST (fd) < 91)
+                    return;
+                {
+                    struct mmo_account ma;
+                    ma.userid = RFIFOP (fd, 2);
+                    ma.passwd = RFIFOP (fd, 26);
+                    memcpy (ma.lastlogin, "-", 2);
+                    ma.sex = RFIFOB (fd, 50);
+                    WFIFOW (fd, 0) = 0x7931;
+                    WFIFOL (fd, 2) = -1;
+                    memcpy (WFIFOP (fd, 6), RFIFOP (fd, 2), 24);
+                    if (strlen (ma.userid) > 23 || strlen (ma.passwd) > 23)
+                    {
+                        login_log
+                            ("'ladmin': Attempt to create an invalid account (account or pass is too long, ip: %s)\n",
+                             ip);
+                    }
+                    else if (strlen (ma.userid) < 4 || strlen (ma.passwd) < 4)
+                    {
+                        login_log
+                            ("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n",
+                             ip);
+                    }
+                    else if (ma.sex != 'F' && ma.sex != 'M')
+                    {
+                        login_log
+                            ("'ladmin': Attempt to create an invalid account (account: %s, invalid sex, ip: %s)\n",
+                             ma.userid, ip);
+                    }
+                    else if (account_id_count > END_ACCOUNT_NUM)
+                    {
+                        login_log
+                            ("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, sex: %c, ip: %s)\n",
+                             ma.userid, ma.sex, ip);
+                    }
+                    else
+                    {
+                        remove_control_chars (ma.userid);
+                        remove_control_chars (ma.passwd);
+                        for (i = 0; i < auth_num; i++)
+                        {
+                            if (strncmp (auth_dat[i].userid, ma.userid, 24) ==
+                                0)
+                            {
+                                login_log
+                                    ("'ladmin': Attempt to create an already existing account (account: %s ip: %s)\n",
+                                     auth_dat[i].userid, ip);
+                                break;
+                            }
+                        }
+                        if (i == auth_num)
+                        {
+                            int  new_id;
+                            char email[40];
+                            memcpy (email, RFIFOP (fd, 51), 40);
+                            email[39] = '\0';
+                            remove_control_chars (email);
+                            new_id = mmo_auth_new (&ma, ma.sex, email);
+                            login_log
+                                ("'ladmin': Account creation (account: %s (id: %d), sex: %c, email: %s, ip: %s)\n",
+                                 ma.userid, new_id,
+                                 ma.sex, auth_dat[i].email, ip);
+                            WFIFOL (fd, 2) = new_id;
+                        }
+                    }
+                    WFIFOSET (fd, 30);
+                    RFIFOSKIP (fd, 91);
+                }
+                break;
+
+            case 0x7932:       // Request for an account deletion
+                if (RFIFOREST (fd) < 26)
+                    return;
+                WFIFOW (fd, 0) = 0x7933;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    // Char-server is notified of deletion (for characters deletion).
+                    unsigned char buf[65535];
+                    WBUFW (buf, 0) = 0x2730;
+                    WBUFL (buf, 2) = auth_dat[i].account_id;
+                    charif_sendallwos (-1, buf, 6);
+                    // send answer
+                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                    WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    // save deleted account in log file
+                    login_log
+                        ("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n",
+                         auth_dat[i].userid, auth_dat[i].account_id,
+                         ip);
+                    mmo_auth_tostr (buf, &auth_dat[i]);
+                    login_log ("%s\n", buf);
+                    // delete account
+                    memset (auth_dat[i].userid, '\0',
+                            sizeof (auth_dat[i].userid));
+                    auth_dat[i].account_id = -1;
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 6), account_name, 24);
+                    login_log
+                        ("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 26);
+                break;
+
+            case 0x7934:       // Request to change a password
+                if (RFIFOREST (fd) < 50)
+                    return;
+                WFIFOW (fd, 0) = 0x7935;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                    strcpy (auth_dat[i].pass, MD5_saltcrypt(RFIFOP (fd, 26), make_salt()));
+                    auth_dat[i].pass[39] = '\0';
+                    WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    login_log
+                        ("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n",
+                         auth_dat[i].userid, auth_dat[i].pass, ip);
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 6), account_name, 24);
+                    login_log
+                        ("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 50);
+                break;
+
+            case 0x7936:       // Request to modify a state
+                if (RFIFOREST (fd) < 50)
+                    return;
+                {
+                    char error_message[20];
+                    int  statut;
+                    WFIFOW (fd, 0) = 0x7937;
+                    WFIFOL (fd, 2) = -1;
+                    account_name = RFIFOP (fd, 2);
+                    account_name[23] = '\0';
+                    remove_control_chars (account_name);
+                    statut = RFIFOL (fd, 26);
+                    memcpy (error_message, RFIFOP (fd, 30), 20);
+                    error_message[19] = '\0';
+                    remove_control_chars (error_message);
+                    if (statut != 7 || error_message[0] == '\0')
+                    {           // 7: // 6 = Your are Prohibited to log in until %s
+                        strcpy (error_message, "-");
+                    }
+                    i = search_account_index (account_name);
+                    if (i != -1)
+                    {
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                        if (auth_dat[i].state == statut
+                            && strcmp (auth_dat[i].error_message,
+                                       error_message) == 0)
+                            login_log
+                                ("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n",
+                                 account_name, statut, ip);
+                        else
+                        {
+                            if (statut == 7)
+                                login_log
+                                    ("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n",
+                                     auth_dat[i].userid, statut,
+                                     error_message, ip);
+                            else
+                                login_log
+                                    ("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n",
+                                     auth_dat[i].userid, statut, ip);
+                            if (auth_dat[i].state == 0)
+                            {
+                                unsigned char buf[16];
+                                WBUFW (buf, 0) = 0x2731;
+                                WBUFL (buf, 2) = auth_dat[i].account_id;
+                                WBUFB (buf, 6) = 0; // 0: change of statut, 1: ban
+                                WBUFL (buf, 7) = statut;    // status or final date of a banishment
+                                charif_sendallwos (-1, buf, 11);
+                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                    if (auth_fifo[j].account_id ==
+                                        auth_dat[i].account_id)
+                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                            }
+                            auth_dat[i].state = statut;
+                            memcpy (auth_dat[i].error_message, error_message,
+                                    20);
+                        }
+                    }
+                    else
+                    {
+                        memcpy (WFIFOP (fd, 6), account_name, 24);
+                        login_log
+                            ("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n",
+                             account_name, statut, ip);
+                    }
+                    WFIFOL (fd, 30) = statut;
+                }
+                WFIFOSET (fd, 34);
+                RFIFOSKIP (fd, 50);
+                break;
+
+            case 0x7938:       // Request for servers list and # of online players
+                login_log ("'ladmin': Sending of servers list (ip: %s)\n", ip);
+                server_num = 0;
+                for (i = 0; i < MAX_SERVERS; i++)
+                {
+                    if (server_fd[i] >= 0)
+                    {
+                        WFIFOL (fd, 4 + server_num * 32) = server[i].ip;
+                        WFIFOW (fd, 4 + server_num * 32 + 4) = server[i].port;
+                        memcpy (WFIFOP (fd, 4 + server_num * 32 + 6),
+                                server[i].name, 20);
+                        WFIFOW (fd, 4 + server_num * 32 + 26) =
+                            server[i].users;
+                        WFIFOW (fd, 4 + server_num * 32 + 28) =
+                            server[i].maintenance;
+                        WFIFOW (fd, 4 + server_num * 32 + 30) = server[i].is_new;
+                        server_num++;
+                    }
+                }
+                WFIFOW (fd, 0) = 0x7939;
+                WFIFOW (fd, 2) = 4 + 32 * server_num;
+                WFIFOSET (fd, 4 + 32 * server_num);
+                RFIFOSKIP (fd, 2);
+                break;
+
+            case 0x793a:       // Request to password check
+                if (RFIFOREST (fd) < 50)
+                    return;
+                WFIFOW (fd, 0) = 0x793b;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+		    if ( pass_ok(RFIFOP (fd, 26), auth_dat[i].pass) )
+                    {
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                        login_log
+                            ("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n",
+                             auth_dat[i].userid, auth_dat[i].pass,
+                             ip);
+                    }
+                    else
+                    {
+                        char pass[24];
+                        memcpy (pass, RFIFOP (fd, 26), 24);
+                        pass[23] = '\0';
+                        remove_control_chars (pass);
+                        login_log
+                            ("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n",
+                             auth_dat[i].userid, pass, ip);
+                    }
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 6), account_name, 24);
+                    login_log
+                        ("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 50);
+                break;
+
+            case 0x793c:       // Request to modify sex
+                if (RFIFOREST (fd) < 27)
+                    return;
+                WFIFOW (fd, 0) = 0x793d;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                memcpy (WFIFOP (fd, 6), account_name, 24);
+                {
+                    char sex;
+                    sex = RFIFOB (fd, 26);
+                    if (sex != 'F' && sex != 'M')
+                    {
+                        if (sex > 31)
+                            login_log
+                                ("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n",
+                                 account_name, sex, ip);
+                        else
+                            login_log
+                                ("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n",
+                                 account_name, ip);
+                    }
+                    else
+                    {
+                        i = search_account_index (account_name);
+                        if (i != -1)
+                        {
+                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                            if (auth_dat[i].sex !=
+                                ((sex == 'S' || sex == 's') ? 2 : (sex == 'M'
+                                                                   || sex ==
+                                                                   'm')))
+                            {
+                                unsigned char buf[16];
+                                WFIFOL (fd, 2) = auth_dat[i].account_id;
+                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                    if (auth_fifo[j].account_id ==
+                                        auth_dat[i].account_id)
+                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                                auth_dat[i].sex = (sex == 'S'
+                                                   || sex ==
+                                                   's') ? 2 : (sex == 'M'
+                                                               || sex == 'm');
+                                login_log
+                                    ("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n",
+                                     auth_dat[i].userid, sex, ip);
+                                // send to all char-server the change
+                                WBUFW (buf, 0) = 0x2723;
+                                WBUFL (buf, 2) = auth_dat[i].account_id;
+                                WBUFB (buf, 6) = auth_dat[i].sex;
+                                charif_sendallwos (-1, buf, 7);
+                            }
+                            else
+                            {
+                                login_log
+                                    ("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n",
+                                     auth_dat[i].userid, sex, ip);
+                            }
+                        }
+                        else
+                        {
+                            login_log
+                                ("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n",
+                                 account_name, sex, ip);
+                        }
+                    }
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 27);
+                break;
+
+            case 0x793e:       // Request to modify GM level
+                if (RFIFOREST (fd) < 27)
+                    return;
+                WFIFOW (fd, 0) = 0x793f;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                memcpy (WFIFOP (fd, 6), account_name, 24);
+                {
+                    char new_gm_level;
+                    new_gm_level = RFIFOB (fd, 26);
+                    if (new_gm_level < 0 || new_gm_level > 99)
+                    {
+                        login_log
+                            ("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n",
+                             account_name, (int) new_gm_level, ip);
+                    }
+                    else
+                    {
+                        i = search_account_index (account_name);
+                        if (i != -1)
+                        {
+                            int  acc = auth_dat[i].account_id;
+                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                            if (isGM (acc) != new_gm_level)
+                            {
+                                // modification of the file
+                                FILE *fp, *fp2;
+                                int  lock;
+                                char line[512];
+                                int  GM_account, GM_level;
+                                int  modify_flag;
+                                char tmpstr[24];
+                                struct timeval tv;
+                                if ((fp2 =
+                                     lock_fopen (GM_account_filename,
+                                                 &lock)) != NULL)
+                                {
+                                    if ((fp =
+                                         fopen_ (GM_account_filename,
+                                                 "r")) != NULL)
+                                    {
+                                        gettimeofday (&tv, NULL);
+                                        strftime (tmpstr, 23, date_format,
+                                                  gmtime (&(tv.tv_sec)));
+                                        modify_flag = 0;
+                                        // read/write GM file
+                                        while (fgets
+                                               (line, sizeof (line) - 1, fp))
+                                        {
+                                            while (line[0] != '\0'
+                                                   && (line[strlen (line) - 1]
+                                                       == '\n'
+                                                       || line[strlen (line) -
+                                                               1] == '\r'))
+                                                line[strlen (line) - 1] =
+                                                    '\0';
+                                            if ((line[0] == '/'
+                                                 && line[1] == '/')
+                                                || line[0] == '\0')
+                                                fprintf (fp2, "%s\n",
+                                                         line);
+                                            else
+                                            {
+                                                if (sscanf
+                                                    (line, "%d %d",
+                                                     &GM_account,
+                                                     &GM_level) != 2
+                                                    && sscanf (line, "%d: %d",
+                                                               &GM_account,
+                                                               &GM_level) !=
+                                                    2)
+                                                    fprintf (fp2,
+                                                             "%s\n",
+                                                             line);
+                                                else if (GM_account != acc)
+                                                    fprintf (fp2,
+                                                             "%s\n",
+                                                             line);
+                                                else if (new_gm_level < 1)
+                                                {
+                                                    fprintf (fp2,
+                                                             "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n",
+                                                             tmpstr,
+                                                             acc,
+                                                             auth_dat
+                                                             [i].userid,
+                                                             GM_level, acc,
+                                                             new_gm_level);
+                                                    modify_flag = 1;
+                                                }
+                                                else
+                                                {
+                                                    fprintf (fp2,
+                                                             "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n",
+                                                             tmpstr,
+                                                             acc,
+                                                             auth_dat
+                                                             [i].userid,
+                                                             GM_level, acc,
+                                                             new_gm_level);
+                                                    modify_flag = 1;
+                                                }
+                                            }
+                                        }
+                                        if (modify_flag == 0)
+                                            fprintf (fp2,
+                                                     "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n",
+                                                     tmpstr, acc,
+                                                     auth_dat[i].userid, acc,
+                                                     new_gm_level);
+                                        fclose_ (fp);
+                                    }
+                                    else
+                                    {
+                                        login_log
+                                            ("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n",
+                                             auth_dat[i].userid, acc,
+                                             (int) new_gm_level, ip);
+                                    }
+                                    lock_fclose(fp2, GM_account_filename, &lock);
+                                    WFIFOL (fd, 2) = acc;
+                                    login_log
+                                        ("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n",
+                                         auth_dat[i].userid, acc,
+                                            (int) new_gm_level, ip);
+                                    // read and send new GM informations
+                                    read_gm_account ();
+                                    send_GM_accounts ();
+                                }
+                                else
+                                {
+                                    login_log
+                                        ("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n",
+                                         auth_dat[i].userid, acc,
+                                         (int) new_gm_level, ip);
+                                }
+                            }
+                            else
+                            {
+                                login_log
+                                    ("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n",
+                                     auth_dat[i].userid, acc,
+                                     (int) new_gm_level, ip);
+                            }
+                        }
+                        else
+                        {
+                            login_log
+                                ("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n",
+                                 account_name, (int) new_gm_level,
+                                 ip);
+                        }
+                    }
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 27);
+                break;
+
+            case 0x7940:       // Request to modify e-mail
+                if (RFIFOREST (fd) < 66)
+                    return;
+                WFIFOW (fd, 0) = 0x7941;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                memcpy (WFIFOP (fd, 6), account_name, 24);
+                {
+                    char email[40];
+                    memcpy (email, RFIFOP (fd, 26), 40);
+                    if (e_mail_check (email) == 0)
+                    {
+                        login_log
+                            ("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n",
+                             account_name, ip);
+                    }
+                    else
+                    {
+                        remove_control_chars (email);
+                        i = search_account_index (account_name);
+                        if (i != -1)
+                        {
+                            memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                            memcpy (auth_dat[i].email, email, 40);
+                            WFIFOL (fd, 2) = auth_dat[i].account_id;
+                            login_log
+                                ("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n",
+                                 auth_dat[i].userid, email, ip);
+                        }
+                        else
+                        {
+                            login_log
+                                ("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n",
+                                 account_name, email, ip);
+                        }
+                    }
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 66);
+                break;
+
+            case 0x7942:       // Request to modify memo field
+                if (RFIFOREST (fd) < 28
+                    || RFIFOREST (fd) < (28 + RFIFOW (fd, 26)))
+                    return;
+                WFIFOW (fd, 0) = 0x7943;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    int  size_of_memo = sizeof (auth_dat[i].memo);
+                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                    memset (auth_dat[i].memo, '\0', size_of_memo);
+                    if (RFIFOW (fd, 26) == 0)
+                    {
+                        strncpy (auth_dat[i].memo, "!", size_of_memo);
+                    }
+                    else if (RFIFOW (fd, 26) > size_of_memo - 1)
+                    {
+                        memcpy (auth_dat[i].memo, RFIFOP (fd, 28),
+                                size_of_memo - 1);
+                    }
+                    else
+                    {
+                        memcpy (auth_dat[i].memo, RFIFOP (fd, 28),
+                                RFIFOW (fd, 26));
+                    }
+                    auth_dat[i].memo[size_of_memo - 1] = '\0';
+                    remove_control_chars (auth_dat[i].memo);
+                    WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    login_log
+                        ("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n",
+                         auth_dat[i].userid, auth_dat[i].memo, ip);
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 6), account_name, 24);
+                    login_log
+                        ("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 28 + RFIFOW (fd, 26));
+                break;
+
+            case 0x7944:       // Request to found an account id
+                if (RFIFOREST (fd) < 26)
+                    return;
+                WFIFOW (fd, 0) = 0x7945;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                    WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    login_log
+                        ("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n",
+                         auth_dat[i].userid, auth_dat[i].account_id,
+                         ip);
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 6), account_name, 24);
+                    login_log
+                        ("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 26);
+                break;
+
+            case 0x7946:       // Request to found an account name
+                if (RFIFOREST (fd) < 6)
+                    return;
+                WFIFOW (fd, 0) = 0x7947;
+                WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                memset (WFIFOP (fd, 6), '\0', 24);
+                for (i = 0; i < auth_num; i++)
+                {
+                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
+                    {
+                        strncpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        login_log
+                            ("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n",
+                             auth_dat[i].userid, RFIFOL (fd, 2), ip);
+                        break;
+                    }
+                }
+                if (i == auth_num)
+                {
+                    login_log
+                        ("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n",
+                         RFIFOL (fd, 2), ip);
+                    strncpy (WFIFOP (fd, 6), "", 24);
+                }
+                WFIFOSET (fd, 30);
+                RFIFOSKIP (fd, 6);
+                break;
+
+            case 0x7948:       // Request to change the validity limit (timestamp) (absolute value)
+                if (RFIFOREST (fd) < 30)
+                    return;
+                {
+                    time_t timestamp;
+                    char tmpstr[2048];
+                    WFIFOW (fd, 0) = 0x7949;
+                    WFIFOL (fd, 2) = -1;
+                    account_name = RFIFOP (fd, 2);
+                    account_name[23] = '\0';
+                    remove_control_chars (account_name);
+                    timestamp = (time_t) RFIFOL (fd, 26);
+                    strftime (tmpstr, 24, date_format, gmtime (&timestamp));
+                    i = search_account_index (account_name);
+                    if (i != -1)
+                    {
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        login_log
+                            ("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n",
+                             auth_dat[i].userid, timestamp,
+                             (timestamp == 0 ? "unlimited" : tmpstr), ip);
+                        auth_dat[i].connect_until_time = timestamp;
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    }
+                    else
+                    {
+                        memcpy (WFIFOP (fd, 6), account_name, 24);
+                        login_log
+                            ("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", account_name, timestamp,
+                             (timestamp == 0 ? "unlimited" : tmpstr), ip);
+                    }
+                    WFIFOL (fd, 30) = timestamp;
+                }
+                WFIFOSET (fd, 34);
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x794a:       // Request to change the final date of a banishment (timestamp) (absolute value)
+                if (RFIFOREST (fd) < 30)
+                    return;
+                {
+                    time_t timestamp;
+                    char tmpstr[2048];
+                    WFIFOW (fd, 0) = 0x794b;
+                    WFIFOL (fd, 2) = -1;
+                    account_name = RFIFOP (fd, 2);
+                    account_name[23] = '\0';
+                    remove_control_chars (account_name);
+                    timestamp = (time_t) RFIFOL (fd, 26);
+                    if (timestamp <= time (NULL))
+                        timestamp = 0;
+                    strftime (tmpstr, 24, date_format, gmtime (&timestamp));
+                    i = search_account_index (account_name);
+                    if (i != -1)
+                    {
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                        login_log
+                            ("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n",
+                             auth_dat[i].userid, timestamp,
+                             (timestamp == 0 ? "no banishment" : tmpstr), ip);
+                        if (auth_dat[i].ban_until_time != timestamp)
+                        {
+                            if (timestamp != 0)
+                            {
+                                unsigned char buf[16];
+                                WBUFW (buf, 0) = 0x2731;
+                                WBUFL (buf, 2) = auth_dat[i].account_id;
+                                WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
+                                WBUFL (buf, 7) = timestamp; // status or final date of a banishment
+                                charif_sendallwos (-1, buf, 11);
+                                for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                    if (auth_fifo[j].account_id ==
+                                        auth_dat[i].account_id)
+                                        auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                            }
+                            auth_dat[i].ban_until_time = timestamp;
+                        }
+                    }
+                    else
+                    {
+                        memcpy (WFIFOP (fd, 6), account_name, 24);
+                        login_log
+                            ("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n",
+                             account_name, timestamp,
+                             (timestamp == 0 ? "no banishment" : tmpstr), ip);
+                    }
+                    WFIFOL (fd, 30) = timestamp;
+                }
+                WFIFOSET (fd, 34);
+                RFIFOSKIP (fd, 30);
+                break;
+
+            case 0x794c:       // Request to change the final date of a banishment (timestamp) (relative change)
+                if (RFIFOREST (fd) < 38)
+                    return;
+                {
+                    time_t timestamp;
+                    struct tm *tmtime;
+                    char tmpstr[2048];
+                    WFIFOW (fd, 0) = 0x794d;
+                    WFIFOL (fd, 2) = -1;
+                    account_name = RFIFOP (fd, 2);
+                    account_name[23] = '\0';
+                    remove_control_chars (account_name);
+                    i = search_account_index (account_name);
+                    if (i != -1)
+                    {
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        if (auth_dat[i].ban_until_time == 0
+                            || auth_dat[i].ban_until_time < time (NULL))
+                            timestamp = time (NULL);
+                        else
+                            timestamp = auth_dat[i].ban_until_time;
+                        tmtime = gmtime (&timestamp);
+                        tmtime->tm_year =
+                            tmtime->tm_year + (short) RFIFOW (fd, 26);
+                        tmtime->tm_mon =
+                            tmtime->tm_mon + (short) RFIFOW (fd, 28);
+                        tmtime->tm_mday =
+                            tmtime->tm_mday + (short) RFIFOW (fd, 30);
+                        tmtime->tm_hour =
+                            tmtime->tm_hour + (short) RFIFOW (fd, 32);
+                        tmtime->tm_min =
+                            tmtime->tm_min + (short) RFIFOW (fd, 34);
+                        tmtime->tm_sec =
+                            tmtime->tm_sec + (short) RFIFOW (fd, 36);
+                        timestamp = mktime (tmtime);
+                        if (timestamp != -1)
+                        {
+                            if (timestamp <= time (NULL))
+                                timestamp = 0;
+                            strftime (tmpstr, 24, date_format,
+                                      gmtime (&timestamp));
+                            login_log
+                                ("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n",
+                                 auth_dat[i].userid,
+                                 (short) RFIFOW (fd, 26), (short) RFIFOW (fd,
+                                                                          28),
+                                 (short) RFIFOW (fd, 30), (short) RFIFOW (fd,
+                                                                          32),
+                                 (short) RFIFOW (fd, 34), (short) RFIFOW (fd,
+                                                                          36),
+                                 timestamp,
+                                 (timestamp == 0 ? "no banishment" : tmpstr),
+                                 ip);
+                            if (auth_dat[i].ban_until_time != timestamp)
+                            {
+                                if (timestamp != 0)
+                                {
+                                    unsigned char buf[16];
+                                    WBUFW (buf, 0) = 0x2731;
+                                    WBUFL (buf, 2) = auth_dat[i].account_id;
+                                    WBUFB (buf, 6) = 1; // 0: change of statut, 1: ban
+                                    WBUFL (buf, 7) = timestamp; // status or final date of a banishment
+                                    charif_sendallwos (-1, buf, 11);
+                                    for (j = 0; j < AUTH_FIFO_SIZE; j++)
+                                        if (auth_fifo[j].account_id ==
+                                            auth_dat[i].account_id)
+                                            auth_fifo[j].login_id1++;   // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
+                                }
+                                auth_dat[i].ban_until_time = timestamp;
+                            }
+                        }
+                        else
+                        {
+                            strftime (tmpstr, 24, date_format,
+                                      gmtime (&auth_dat[i].ban_until_time));
+                            login_log
+                                ("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
+                                 auth_dat[i].userid,
+                                 auth_dat[i].ban_until_time,
+                                 (auth_dat[i].ban_until_time ==
+                                  0 ? "no banishment" : tmpstr),
+                                 (short) RFIFOW (fd, 26), (short) RFIFOW (fd,
+                                                                          28),
+                                 (short) RFIFOW (fd, 30), (short) RFIFOW (fd,
+                                                                          32),
+                                 (short) RFIFOW (fd, 34), (short) RFIFOW (fd,
+                                                                          36),
+                                 ip);
+                        }
+                        WFIFOL (fd, 30) =
+                            (unsigned long) auth_dat[i].ban_until_time;
+                    }
+                    else
+                    {
+                        memcpy (WFIFOP (fd, 6), account_name, 24);
+                        login_log
+                            ("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n",
+                             account_name, ip);
+                        WFIFOL (fd, 30) = 0;
+                    }
+                }
+                WFIFOSET (fd, 34);
+                RFIFOSKIP (fd, 38);
+                break;
+
+            case 0x794e:       // Request to send a broadcast message
+                if (RFIFOREST (fd) < 8
+                    || RFIFOREST (fd) < (8 + RFIFOL (fd, 4)))
+                    return;
+                WFIFOW (fd, 0) = 0x794f;
+                WFIFOW (fd, 2) = -1;
+                if (RFIFOL (fd, 4) < 1)
+                {
+                    login_log
+                        ("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n",
+                         ip);
+                }
+                else
+                {
+                    // at least 1 char-server
+                    for (i = 0; i < MAX_SERVERS; i++)
+                        if (server_fd[i] >= 0)
+                            break;
+                    if (i == MAX_SERVERS)
+                    {
+                        login_log
+                            ("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n",
+                             ip);
+                    }
+                    else
+                    {
+                        char buf[32000];
+                        char message[32000];
+                        WFIFOW (fd, 2) = 0;
+                        memset (message, '\0', sizeof (message));
+                        memcpy (message, RFIFOP (fd, 8), RFIFOL (fd, 4));
+                        message[sizeof (message) - 1] = '\0';
+                        remove_control_chars (message);
+                        if (RFIFOW (fd, 2) == 0)
+                            login_log
+                                ("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n",
+                                 message, ip);
+                        else
+                            login_log
+                                ("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n",
+                                 message, ip);
+                        // send same message to all char-servers (no answer)
+                        memcpy (WBUFP (buf, 0), RFIFOP (fd, 0),
+                                8 + RFIFOL (fd, 4));
+                        WBUFW (buf, 0) = 0x2726;
+                        charif_sendallwos (-1, buf, 8 + RFIFOL (fd, 4));
+                    }
+                }
+                WFIFOSET (fd, 4);
+                RFIFOSKIP (fd, 8 + RFIFOL (fd, 4));
+                break;
+
+            case 0x7950:       // Request to change the validity limite (timestamp) (relative change)
+                if (RFIFOREST (fd) < 38)
+                    return;
+                {
+                    time_t timestamp;
+                    struct tm *tmtime;
+                    char tmpstr[2048];
+                    char tmpstr2[2048];
+                    WFIFOW (fd, 0) = 0x7951;
+                    WFIFOL (fd, 2) = -1;
+                    account_name = RFIFOP (fd, 2);
+                    account_name[23] = '\0';
+                    remove_control_chars (account_name);
+                    i = search_account_index (account_name);
+                    if (i != -1)
+                    {
+                        WFIFOL (fd, 2) = auth_dat[i].account_id;
+                        memcpy (WFIFOP (fd, 6), auth_dat[i].userid, 24);
+                        timestamp = auth_dat[i].connect_until_time;
+                        if (add_to_unlimited_account == 0 && timestamp == 0)
+                        {
+                            login_log
+                                ("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n",
+                                 auth_dat[i].userid, ip);
+                            WFIFOL (fd, 30) = 0;
+                        }
+                        else
+                        {
+                            if (timestamp == 0 || timestamp < time (NULL))
+                                timestamp = time (NULL);
+                            tmtime = gmtime (&timestamp);
+                            tmtime->tm_year =
+                                tmtime->tm_year + (short) RFIFOW (fd, 26);
+                            tmtime->tm_mon =
+                                tmtime->tm_mon + (short) RFIFOW (fd, 28);
+                            tmtime->tm_mday =
+                                tmtime->tm_mday + (short) RFIFOW (fd, 30);
+                            tmtime->tm_hour =
+                                tmtime->tm_hour + (short) RFIFOW (fd, 32);
+                            tmtime->tm_min =
+                                tmtime->tm_min + (short) RFIFOW (fd, 34);
+                            tmtime->tm_sec =
+                                tmtime->tm_sec + (short) RFIFOW (fd, 36);
+                            timestamp = mktime (tmtime);
+                            if (timestamp != -1)
+                            {
+                                strftime (tmpstr, 24, date_format,
+                                          gmtime (&auth_dat
+                                                  [i].connect_until_time));
+                                strftime (tmpstr2, 24, date_format,
+                                          gmtime (&timestamp));
+                                login_log
+                                    ("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n",
+                                     auth_dat[i].userid,
+                                     auth_dat[i].connect_until_time,
+                                     (auth_dat[i].connect_until_time ==
+                                      0 ? "unlimited" : tmpstr),
+                                     (short) RFIFOW (fd, 26),
+                                     (short) RFIFOW (fd, 28),
+                                     (short) RFIFOW (fd, 30),
+                                     (short) RFIFOW (fd, 32),
+                                     (short) RFIFOW (fd, 34),
+                                     (short) RFIFOW (fd, 36), timestamp,
+                                     (timestamp == 0 ? "unlimited" : tmpstr2),
+                                     ip);
+                                auth_dat[i].connect_until_time = timestamp;
+                                WFIFOL (fd, 30) =
+                                    (unsigned long)
+                                    auth_dat[i].connect_until_time;
+                            }
+                            else
+                            {
+                                strftime (tmpstr, 24, date_format,
+                                          gmtime (&auth_dat
+                                                  [i].connect_until_time));
+                                login_log
+                                    ("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n",
+                                     auth_dat[i].userid,
+                                     auth_dat[i].connect_until_time,
+                                     (auth_dat[i].connect_until_time ==
+                                      0 ? "unlimited" : tmpstr),
+                                     (short) RFIFOW (fd, 26),
+                                     (short) RFIFOW (fd, 28),
+                                     (short) RFIFOW (fd, 30),
+                                     (short) RFIFOW (fd, 32),
+                                     (short) RFIFOW (fd, 34),
+                                     (short) RFIFOW (fd, 36), ip);
+                                WFIFOL (fd, 30) = 0;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        memcpy (WFIFOP (fd, 6), account_name, 24);
+                        login_log
+                            ("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n",
+                             account_name, ip);
+                        WFIFOL (fd, 30) = 0;
+                    }
+                }
+                WFIFOSET (fd, 34);
+                RFIFOSKIP (fd, 38);
+                break;
+
+            case 0x7952:       // Request about informations of an account (by account name)
+                if (RFIFOREST (fd) < 26)
+                    return;
+                WFIFOW (fd, 0) = 0x7953;
+                WFIFOL (fd, 2) = -1;
+                account_name = RFIFOP (fd, 2);
+                account_name[23] = '\0';
+                remove_control_chars (account_name);
+                i = search_account_index (account_name);
+                if (i != -1)
+                {
+                    WFIFOL (fd, 2) = auth_dat[i].account_id;
+                    WFIFOB (fd, 6) =
+                        (unsigned char) isGM (auth_dat[i].account_id);
+                    memcpy (WFIFOP (fd, 7), auth_dat[i].userid, 24);
+                    WFIFOB (fd, 31) = auth_dat[i].sex;
+                    WFIFOL (fd, 32) = auth_dat[i].logincount;
+                    WFIFOL (fd, 36) = auth_dat[i].state;
+                    memcpy (WFIFOP (fd, 40), auth_dat[i].error_message, 20);
+                    memcpy (WFIFOP (fd, 60), auth_dat[i].lastlogin, 24);
+                    memcpy (WFIFOP (fd, 84), auth_dat[i].last_ip, 16);
+                    memcpy (WFIFOP (fd, 100), auth_dat[i].email, 40);
+                    WFIFOL (fd, 140) =
+                        (unsigned long) auth_dat[i].connect_until_time;
+                    WFIFOL (fd, 144) =
+                        (unsigned long) auth_dat[i].ban_until_time;
+                    WFIFOW (fd, 148) = strlen (auth_dat[i].memo);
+                    if (auth_dat[i].memo[0])
+                    {
+                        memcpy (WFIFOP (fd, 150), auth_dat[i].memo,
+                                strlen (auth_dat[i].memo));
+                    }
+                    login_log
+                        ("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n",
+                         auth_dat[i].userid, auth_dat[i].account_id,
+                         ip);
+                    WFIFOSET (fd, 150 + strlen (auth_dat[i].memo));
+                }
+                else
+                {
+                    memcpy (WFIFOP (fd, 7), account_name, 24);
+                    WFIFOW (fd, 148) = 0;
+                    login_log
+                        ("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n",
+                         account_name, ip);
+                    WFIFOSET (fd, 150);
+                }
+                RFIFOSKIP (fd, 26);
+                break;
+
+            case 0x7954:       // Request about information of an account (by account id)
+                if (RFIFOREST (fd) < 6)
+                    return;
+                WFIFOW (fd, 0) = 0x7953;
+                WFIFOL (fd, 2) = RFIFOL (fd, 2);
+                memset (WFIFOP (fd, 7), '\0', 24);
+                for (i = 0; i < auth_num; i++)
+                {
+                    if (auth_dat[i].account_id == RFIFOL (fd, 2))
+                    {
+                        login_log
+                            ("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n",
+                             auth_dat[i].userid, RFIFOL (fd, 2), ip);
+                        WFIFOB (fd, 6) =
+                            (unsigned char) isGM (auth_dat[i].account_id);
+                        memcpy (WFIFOP (fd, 7), auth_dat[i].userid, 24);
+                        WFIFOB (fd, 31) = auth_dat[i].sex;
+                        WFIFOL (fd, 32) = auth_dat[i].logincount;
+                        WFIFOL (fd, 36) = auth_dat[i].state;
+                        memcpy (WFIFOP (fd, 40), auth_dat[i].error_message,
+                                20);
+                        memcpy (WFIFOP (fd, 60), auth_dat[i].lastlogin, 24);
+                        memcpy (WFIFOP (fd, 84), auth_dat[i].last_ip, 16);
+                        memcpy (WFIFOP (fd, 100), auth_dat[i].email, 40);
+                        WFIFOL (fd, 140) =
+                            (unsigned long) auth_dat[i].connect_until_time;
+                        WFIFOL (fd, 144) =
+                            (unsigned long) auth_dat[i].ban_until_time;
+                        WFIFOW (fd, 148) = strlen (auth_dat[i].memo);
+                        if (auth_dat[i].memo[0])
+                        {
+                            memcpy (WFIFOP (fd, 150), auth_dat[i].memo,
+                                    strlen (auth_dat[i].memo));
+                        }
+                        WFIFOSET (fd, 150 + strlen (auth_dat[i].memo));
+                        break;
+                    }
+                }
+                if (i == auth_num)
+                {
+                    login_log
+                        ("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n",
+                         RFIFOL (fd, 2), ip);
+                    strncpy (WFIFOP (fd, 7), "", 24);
+                    WFIFOW (fd, 148) = 0;
+                    WFIFOSET (fd, 150);
+                }
+                RFIFOSKIP (fd, 6);
+                break;
+
+            case 0x7955:       // Request to reload GM file (no answer)
+                login_log
+                    ("'ladmin': Request to re-load GM configuration file (ip: %s).\n",
+                     ip);
+                read_gm_account ();
+                // send GM accounts to all char-servers
+                send_GM_accounts ();
+                RFIFOSKIP (fd, 2);
+                break;
+
+            default:
+            {
+                FILE *logfp;
+                char tmpstr[24];
+                struct timeval tv;
+                logfp = fopen_ (login_log_unknown_packets_filename, "a");
+                if (logfp)
+                {
+                    gettimeofday (&tv, NULL);
+                    strftime (tmpstr, 23, date_format, gmtime (&(tv.tv_sec)));
+                    fprintf (logfp,
+                             "%s.%03d: receiving of an unknown packet -> disconnection\n",
+                             tmpstr, (int) tv.tv_usec / 1000);
+                    fprintf (logfp,
+                             "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
+                             fd, ip, RFIFOW (fd, 0), RFIFOREST (fd));
+                    fprintf (logfp, "Detail (in hex):\n");
+                    fprintf (logfp,
+                             "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
+                    memset (tmpstr, '\0', sizeof (tmpstr));
+                    for (i = 0; i < RFIFOREST (fd); i++)
+                    {
+                        if ((i & 15) == 0)
+                            fprintf (logfp, "%04X ", i);
+                        fprintf (logfp, "%02x ", RFIFOB (fd, i));
+                        if (RFIFOB (fd, i) > 0x1f)
+                            tmpstr[i % 16] = RFIFOB (fd, i);
+                        else
+                            tmpstr[i % 16] = '.';
+                        if ((i - 7) % 16 == 0)  // -8 + 1
+                            fprintf (logfp, " ");
+                        else if ((i + 1) % 16 == 0)
+                        {
+                            fprintf (logfp, " %s\n", tmpstr);
+                            memset (tmpstr, '\0', sizeof (tmpstr));
+                        }
+                    }
+                    if (i % 16 != 0)
+                    {
+                        for (j = i; j % 16 != 0; j++)
+                        {
+                            fprintf (logfp, "   ");
+                            if ((j - 7) % 16 == 0)  // -8 + 1
+                                fprintf (logfp, " ");
+                        }
+                        fprintf (logfp, " %s\n", tmpstr);
+                    }
+                    fprintf (logfp, "\n");
+                    fclose_ (logfp);
+                }
+            }
+                login_log
+                    ("'ladmin': End of connection, unknown packet (ip: %s)\n",
+                     ip);
+                session[fd]->eof = 1;
+                printf
+                    ("Remote administration has been disconnected (unknown packet).\n");
+                return;
+        }
+        //WFIFOW(fd,0) = 0x791f;
+        //WFIFOSET(fd,2);
+    }
+    return;
+}
+
+//--------------------------------------------
+// Test to know if an IP come from LAN or WAN.
+//--------------------------------------------
+int lan_ip_check (unsigned char *p)
+{
+    int  i;
+    int  lancheck = 1;
+
+//  printf("lan_ip_check: to compare: %d.%d.%d.%d, network: %d.%d.%d.%d/%d.%d.%d.%d\n",
+//         p[0], p[1], p[2], p[3],
+//         subneti[0], subneti[1], subneti[2], subneti[3],
+//         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
+    for (i = 0; i < 4; i++)
+    {
+        if ((subneti[i] & subnetmaski[i]) != (p[i] & subnetmaski[i]))
+        {
+            lancheck = 0;
+            break;
+        }
+    }
+    printf ("LAN test (result): %s source\033[0m.\n",
+            (lancheck) ? "\033[1;36mLAN" : "\033[1;32mWAN");
+    return lancheck;
+}
+
+//----------------------------------------------------------------------------------------
+// Default packet parsing (normal players or administation/char-server connexion requests)
+//----------------------------------------------------------------------------------------
+void parse_login (int fd)
+{
+    struct mmo_account account;
+    int  result, i, j;
+    unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+    char ip[16];
+    int  host_len;
+
+    sprintf (ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+    if (session[fd]->eof)
+    {
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    while (RFIFOREST (fd) >= 2)
+    {
+        if (display_parse_login == 1)
+        {
+            if (RFIFOW (fd, 0) == 0x64 || RFIFOW (fd, 0) == 0x01dd)
+            {
+                if (RFIFOREST (fd) >= ((RFIFOW (fd, 0) == 0x64) ? 55 : 47))
+                    printf
+                        ("parse_login: connection #%d, packet: 0x%x (with being read: %d), account: %s.\n",
+                         fd, RFIFOW (fd, 0), RFIFOREST (fd), RFIFOP (fd, 6));
+            }
+            else if (RFIFOW (fd, 0) == 0x2710)
+            {
+                if (RFIFOREST (fd) >= 86)
+                    printf
+                        ("parse_login: connection #%d, packet: 0x%x (with being read: %d), server: %s.\n",
+                         fd, RFIFOW (fd, 0), RFIFOREST (fd), RFIFOP (fd, 60));
+            }
+            else
+                printf
+                    ("parse_login: connection #%d, packet: 0x%x (with being read: %d).\n",
+                     fd, RFIFOW (fd, 0), RFIFOREST (fd));
+        }
+
+        switch (RFIFOW (fd, 0))
+        {
+            case 0x200:        // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
+                if (RFIFOREST (fd) < 26)
+                    return;
+                RFIFOSKIP (fd, 26);
+                break;
+
+            case 0x204:        // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
+                if (RFIFOREST (fd) < 18)
+                    return;
+                RFIFOSKIP (fd, 18);
+                break;
+
+            case 0x64:         // Ask connection of a client
+            case 0x01dd:       // Ask connection of a client (encryption mode)
+                if (RFIFOREST (fd) < ((RFIFOW (fd, 0) == 0x64) ? 55 : 47))
+                    return;
+
+                account.userid = RFIFOP (fd, 6);
+                account.userid[23] = '\0';
+                remove_control_chars (account.userid);
+                account.passwd = RFIFOP (fd, 30);
+                if (RFIFOW (fd, 0) == 0x64)
+                {
+                    account.passwd[23] = '\0';
+                    remove_control_chars (account.passwd);
+                }
+#ifdef PASSWORDENC
+                account.passwdenc =
+                    (RFIFOW (fd, 0) == 0x64) ? 0 : PASSWORDENC;
+#else
+                account.passwdenc = 0;
+#endif
+
+                if (RFIFOW (fd, 0) == 0x64)
+                {
+                    login_log
+                        ("Request for connection (non encryption mode) of %s (ip: %s).\n",
+                         account.userid, ip);
+                }
+                else
+                {
+                    login_log
+                        ("Request for connection (encryption mode) of %s (ip: %s).\n",
+                         account.userid, ip);
+                }
+
+                if (!check_ip (session[fd]->client_addr.sin_addr.s_addr))
+                {
+                    login_log
+                        ("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n",
+                         ip);
+                    WFIFOW (fd, 0) = 0x6a;
+                    WFIFOB (fd, 2) = 0x03;
+                    WFIFOSET (fd, 3);
+                    RFIFOSKIP (fd, (RFIFOW (fd, 0) == 0x64) ? 55 : 47);
+                    break;
+                }
+
+                result = mmo_auth (&account, fd);
+                if (result == -1)
+                {
+                    int  gm_level = isGM (account.account_id);
+                    if (min_level_to_connect > gm_level)
+                    {
+                        login_log
+                            ("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n",
+                             min_level_to_connect, account.userid,
+                             gm_level, ip);
+                        WFIFOW (fd, 0) = 0x81;
+                        WFIFOL (fd, 2) = 1; // 01 = Server closed
+                        WFIFOSET (fd, 3);
+                    }
+                    else
+                    {
+                        int  version_2 = RFIFOB (fd, 54);   // version 2
+
+                        if (gm_level)
+                            printf
+                                ("Connection of the GM (level:%d) account '%s' accepted.\n",
+                                 gm_level, account.userid);
+                        else
+                            printf
+                                ("Connection of the account '%s' accepted.\n",
+                                 account.userid);
+
+                        /*
+                         * Add a 0x0063 packet, which contains the name of the update host.  The packet will only
+                         * be sent if login_athena.conf contains a non-null entry for "update_host:"
+                         *
+                         * Because older clients cannot handle the 0x63 packet, we check the "version 2" value
+                         * from the incoming 0x64 packet (the byte at offset 54).  If bit 0 of this is set,
+                         * then the client can safely accept the 0x63 packet.  The "version 2" value is not
+                         * otherwise used by eAthena.
+                         */
+                        if ((RFIFOW (fd, 0) == 0x64)
+                            && (version_2 & VERSION_2_UPDATEHOST))
+                        {
+                            host_len = (int) strlen (update_host);
+                            if (host_len > 0)
+                            {
+                                WFIFOW (fd, 0) = 0x63;
+                                WFIFOW (fd, 2) = 4 + host_len;
+                                memcpy (WFIFOP (fd, 4), update_host,
+                                        host_len);
+                                WFIFOSET (fd, 4 + host_len);
+                            }
+                        }
+
+                        // Load list of char servers into outbound packet
+                        server_num = 0;
+                        if (version_2 && VERSION_2_SERVERORDER)
+                            for (i = 0; i < MAX_SERVERS; i++)
+                            {
+                                if (server_fd[i] >= 0)
+                                {
+                                    if (lan_ip_check (p))
+                                        WFIFOL (fd, 47 + server_num * 32) =
+                                            inet_addr (lan_char_ip);
+                                    else
+                                        WFIFOL (fd, 47 + server_num * 32) =
+                                            server[i].ip;
+                                    WFIFOW (fd, 47 + server_num * 32 + 4) =
+                                        server[i].port;
+                                    memcpy (WFIFOP
+                                            (fd, 47 + server_num * 32 + 6),
+                                            server[i].name, 20);
+                                    WFIFOW (fd, 47 + server_num * 32 + 26) =
+                                        server[i].users;
+                                    WFIFOW (fd, 47 + server_num * 32 + 28) =
+                                        server[i].maintenance;
+                                    WFIFOW (fd, 47 + server_num * 32 + 30) =
+                                        server[i].is_new;
+                                    server_num++;
+                                }
+                            }
+                        else    // Send them in reverse, as the client defaults to the second (!) one
+                            for (i = MAX_SERVERS - 1; i >= 0; i--)
+                            {
+                                if (server_fd[i] >= 0)
+                                {
+                                    if (lan_ip_check (p))
+                                        WFIFOL (fd, 47 + server_num * 32) =
+                                            inet_addr (lan_char_ip);
+                                    else
+                                        WFIFOL (fd, 47 + server_num * 32) =
+                                            server[i].ip;
+                                    WFIFOW (fd, 47 + server_num * 32 + 4) =
+                                        server[i].port;
+                                    memcpy (WFIFOP
+                                            (fd, 47 + server_num * 32 + 6),
+                                            server[i].name, 20);
+                                    WFIFOW (fd, 47 + server_num * 32 + 26) =
+                                        server[i].users;
+                                    WFIFOW (fd, 47 + server_num * 32 + 28) =
+                                        server[i].maintenance;
+                                    WFIFOW (fd, 47 + server_num * 32 + 30) =
+                                        server[i].is_new;
+                                    server_num++;
+                                }
+                            }
+                        // if at least 1 char-server
+                        if (server_num > 0)
+                        {
+                            WFIFOW (fd, 0) = 0x69;
+                            WFIFOW (fd, 2) = 47 + 32 * server_num;
+                            WFIFOL (fd, 4) = account.login_id1;
+                            WFIFOL (fd, 8) = account.account_id;
+                            WFIFOL (fd, 12) = account.login_id2;
+                            WFIFOL (fd, 16) = 0;    // in old version, that was for ip (not more used)
+                            memcpy (WFIFOP (fd, 20), account.lastlogin, 24);    // in old version, that was for name (not more used)
+                            WFIFOB (fd, 46) = account.sex;
+                            WFIFOSET (fd, 47 + 32 * server_num);
+                            if (auth_fifo_pos >= AUTH_FIFO_SIZE)
+                                auth_fifo_pos = 0;
+                            auth_fifo[auth_fifo_pos].account_id =
+                                account.account_id;
+                            auth_fifo[auth_fifo_pos].login_id1 =
+                                account.login_id1;
+                            auth_fifo[auth_fifo_pos].login_id2 =
+                                account.login_id2;
+                            auth_fifo[auth_fifo_pos].sex = account.sex;
+                            auth_fifo[auth_fifo_pos].delflag = 0;
+                            auth_fifo[auth_fifo_pos].ip =
+                                session[fd]->client_addr.sin_addr.s_addr;
+                            auth_fifo_pos++;
+                            // if no char-server, don't send void list of servers, just disconnect the player with proper message
+                        }
+                        else
+                        {
+                            login_log
+                                ("Connection refused: there is no char-server online (account: %s, ip: %s).\n",
+                                 account.userid, ip);
+                            WFIFOW (fd, 0) = 0x81;
+                            WFIFOL (fd, 2) = 1; // 01 = Server closed
+                            WFIFOSET (fd, 3);
+                        }
+                    }
+                }
+                else
+                {
+                    memset (WFIFOP (fd, 0), '\0', 23);
+                    WFIFOW (fd, 0) = 0x6a;
+                    WFIFOB (fd, 2) = result;
+                    if (result == 6)
+                    {           // 6 = Your are Prohibited to log in until %s
+                        i = search_account_index (account.userid);
+                        if (i != -1)
+                        {
+                            if (auth_dat[i].ban_until_time != 0)
+                            {   // if account is banned, we send ban timestamp
+                                char tmpstr[256];
+                                strftime (tmpstr, 20, date_format,
+                                          gmtime (&auth_dat
+                                                  [i].ban_until_time));
+                                tmpstr[19] = '\0';
+                                memcpy (WFIFOP (fd, 3), tmpstr, 20);
+                            }
+                            else
+                            {   // we send error message
+                                memcpy (WFIFOP (fd, 3),
+                                        auth_dat[i].error_message, 20);
+                            }
+                        }
+                    }
+                    WFIFOSET (fd, 23);
+                }
+                RFIFOSKIP (fd, (RFIFOW (fd, 0) == 0x64) ? 55 : 47);
+                break;
+
+            case 0x01db:       // Sending request of the coding key
+            case 0x791a:       // Sending request of the coding key (administration packet)
+            {
+                struct login_session_data *ld;
+                if (session[fd]->session_data)
+                {
+                    printf
+                        ("login: abnormal request of MD5 key (already opened session).\n");
+                    session[fd]->eof = 1;
+                    return;
+                }
+                CREATE (ld, struct login_session_data, 1);
+                session[fd]->session_data = ld;
+                if (!ld)
+                {
+                    printf
+                        ("login: Request for md5 key: memory allocation failure (malloc)!\n");
+                    session[fd]->eof = 1;
+                    return;
+                }
+                if (RFIFOW (fd, 0) == 0x01db)
+                {
+                    login_log ("Sending request of the coding key (ip: %s)\n",
+                               ip);
+                }
+                else
+                {
+                    login_log
+                        ("'ladmin': Sending request of the coding key (ip: %s)\n",
+                         ip);
+                }
+                // Creation of the coding key
+                memset (ld->md5key, '\0', sizeof (ld->md5key));
+                ld->md5keylen = rand () % 4 + 12;
+                for (i = 0; i < ld->md5keylen; i++)
+                    ld->md5key[i] = rand () % 255 + 1;
+
+                RFIFOSKIP (fd, 2);
+                WFIFOW (fd, 0) = 0x01dc;
+                WFIFOW (fd, 2) = 4 + ld->md5keylen;
+                memcpy (WFIFOP (fd, 4), ld->md5key, ld->md5keylen);
+                WFIFOSET (fd, WFIFOW (fd, 2));
+            }
+                break;
+
+            case 0x2710:       // Connection request of a char-server
+                if (RFIFOREST (fd) < 86)
+                    return;
+                {
+                    int  GM_value, len;
+                    unsigned char *server_name;
+                    account.userid = RFIFOP (fd, 2);
+                    account.userid[23] = '\0';
+                    remove_control_chars (account.userid);
+                    account.passwd = RFIFOP (fd, 26);
+                    account.passwd[23] = '\0';
+                    remove_control_chars (account.passwd);
+                    account.passwdenc = 0;
+                    server_name = RFIFOP (fd, 60);
+                    server_name[19] = '\0';
+                    remove_control_chars (server_name);
+                    login_log
+                        ("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n",
+                         server_name, RFIFOB (fd, 54), RFIFOB (fd, 55),
+                         RFIFOB (fd, 56), RFIFOB (fd, 57), RFIFOW (fd, 58),
+                         ip);
+                    result = mmo_auth (&account, fd);
+
+                    if (result == -1 && account.sex == 2)
+                    {
+                        // If this is the main server, and we don't already have a main server
+                        if (server_fd[0] <= 0
+                            && strcasecmp (server_name, main_server) == 0)
+                        {
+                            account.account_id = 0;
+                        }
+                        else
+                        {
+                            int  i;
+                            for (i = 1; i < MAX_SERVERS; i++)
+                            {
+                                if (server_fd[i] <= 0)
+                                {
+                                    account.account_id = i;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    if (result == -1 && account.sex == 2
+                        && account.account_id < MAX_SERVERS
+                        && server_fd[account.account_id] == -1)
+                    {
+                        login_log
+                            ("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)\n",
+                             server_name, account.userid,
+                             account.passwd, ip);
+                        printf
+                            ("Connection of the char-server '%s' accepted.\n",
+                             server_name);
+                        memset (&server[account.account_id], 0,
+                                sizeof (struct mmo_char_server));
+                        server[account.account_id].ip = RFIFOL (fd, 54);
+                        server[account.account_id].port = RFIFOW (fd, 58);
+                        memcpy (server[account.account_id].name, server_name,
+                                20);
+                        server[account.account_id].users = 0;
+                        server[account.account_id].maintenance =
+                            RFIFOW (fd, 82);
+                        server[account.account_id].is_new = RFIFOW (fd, 84);
+                        server_fd[account.account_id] = fd;
+                        if (anti_freeze_enable)
+                            server_freezeflag[account.account_id] = 5;  // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+                        WFIFOW (fd, 0) = 0x2711;
+                        WFIFOB (fd, 2) = 0;
+                        WFIFOSET (fd, 3);
+                        session[fd]->func_parse = parse_fromchar;
+                        realloc_fifo (fd, FIFOSIZE_SERVERLINK,
+                                      FIFOSIZE_SERVERLINK);
+                        // send GM account to char-server
+                        len = 4;
+                        WFIFOW (fd, 0) = 0x2732;
+                        for (i = 0; i < auth_num; i++)
+                            // send only existing accounts. We can not create a GM account when server is online.
+                            if ((GM_value =
+                                 isGM (auth_dat[i].account_id)) > 0)
+                            {
+                                WFIFOL (fd, len) = auth_dat[i].account_id;
+                                WFIFOB (fd, len + 4) =
+                                    (unsigned char) GM_value;
+                                len += 5;
+                            }
+                        WFIFOW (fd, 2) = len;
+                        WFIFOSET (fd, len);
+                    }
+                    else
+                    {
+                        login_log
+                            ("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)\n",
+                             server_name, account.userid,
+                             account.passwd, ip);
+                        WFIFOW (fd, 0) = 0x2711;
+                        WFIFOB (fd, 2) = 3;
+                        WFIFOSET (fd, 3);
+                    }
+                }
+                RFIFOSKIP (fd, 86);
+                return;
+
+            case 0x7530:       // Request of the server version
+                login_log ("Sending of the server version (ip: %s)\n",
+                           ip);
+                WFIFOW (fd, 0) = 0x7531;
+                WFIFOB (fd, 2) = -1;
+                WFIFOB (fd, 3) = 'T';
+                WFIFOB (fd, 4) = 'M';
+                WFIFOB (fd, 5) = 'W';
+                WFIFOL (fd, 6) = new_account_flag ? 1 : 0;
+                WFIFOSET (fd, 10);
+                RFIFOSKIP (fd, 2);
+                break;
+
+            case 0x7532:       // Request to end connection
+                login_log ("End of connection (ip: %s)\n", ip);
+                session[fd]->eof = 1;
+                return;
+
+            case 0x7918:       // Request for administation login
+                if (RFIFOREST (fd) < 4
+                    || RFIFOREST (fd) < ((RFIFOW (fd, 2) == 0) ? 28 : 20))
+                    return;
+                WFIFOW (fd, 0) = 0x7919;
+                WFIFOB (fd, 2) = 1;
+                if (!check_ladminip
+                    (session[fd]->client_addr.sin_addr.s_addr))
+                {
+                    login_log
+                        ("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n",
+                         ip);
+                }
+                else
+                {
+                    struct login_session_data *ld = (struct login_session_data *)session[fd]->session_data;
+                    if (RFIFOW (fd, 2) == 0)
+                    {           // non encrypted password
+                        unsigned char *password;
+                        password = RFIFOP (fd, 4);
+                        password[23] = '\0';
+                        remove_control_chars (password);
+                        // If remote administration is enabled and password sent by client matches password read from login server configuration file
+                        if ((admin_state == 1)
+                            && (strcmp (password, admin_pass) == 0))
+                        {
+                            login_log
+                                ("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n",
+                                 password, ip);
+                            printf
+                                ("Connection of a remote administration accepted (non encrypted password).\n");
+                            WFIFOB (fd, 2) = 0;
+                            session[fd]->func_parse = parse_admin;
+                        }
+                        else if (admin_state != 1)
+                            login_log
+                                ("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n",
+                                 password, ip);
+                        else
+                            login_log
+                                ("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n",
+                                 password, ip);
+                    }
+                    else
+                    {           // encrypted password
+                        if (!ld)
+                            printf
+                                ("'ladmin'-login: error! MD5 key not created/requested for an administration login.\n");
+                        else
+                        {
+                            char md5str[64] = "", md5bin[32];
+                            if (RFIFOW (fd, 2) == 1)
+                            {
+                                strncpy (md5str, ld->md5key, sizeof (ld->md5key));  // 20
+                                strcat (md5str, admin_pass);    // 24
+                            }
+                            else if (RFIFOW (fd, 2) == 2)
+                            {
+                                strncpy (md5str, admin_pass, sizeof (admin_pass));  // 24
+                                strcat (md5str, ld->md5key);    // 20
+                            }
+                            MD5_to_bin(MD5_from_cstring(md5str), md5bin);
+                            // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file
+                            if ((admin_state == 1)
+                                && (memcmp (md5bin, RFIFOP (fd, 4), 16) == 0))
+                            {
+                                login_log
+                                    ("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n",
+                                     ip);
+                                printf
+                                    ("Connection of a remote administration accepted (encrypted password).\n");
+                                WFIFOB (fd, 2) = 0;
+                                session[fd]->func_parse = parse_admin;
+                            }
+                            else if (admin_state != 1)
+                                login_log
+                                    ("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)\n",
+                                     ip);
+                            else
+                                login_log
+                                    ("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)\n",
+                                     ip);
+                        }
+                    }
+                }
+                WFIFOSET (fd, 3);
+                RFIFOSKIP (fd, (RFIFOW (fd, 2) == 0) ? 28 : 20);
+                break;
+
+            default:
+                if (save_unknown_packets)
+                {
+                    FILE *logfp;
+                    char tmpstr[24];
+                    struct timeval tv;
+                    logfp = fopen_ (login_log_unknown_packets_filename, "a");
+                    if (logfp)
+                    {
+                        gettimeofday (&tv, NULL);
+                        strftime (tmpstr, 23, date_format,
+                                  gmtime (&(tv.tv_sec)));
+                        fprintf (logfp,
+                                 "%s.%03d: receiving of an unknown packet -> disconnection\n",
+                                 tmpstr, (int) tv.tv_usec / 1000);
+                        fprintf (logfp,
+                                 "parse_login: connection #%d (ip: %s), packet: 0x%x (with being read: %d).\n",
+                                 fd, ip, RFIFOW (fd, 0),
+                                 RFIFOREST (fd));
+                        fprintf (logfp, "Detail (in hex):\n");
+                        fprintf (logfp,
+                                 "---- 00-01-02-03-04-05-06-07  08-09-0A-0B-0C-0D-0E-0F\n");
+                        memset (tmpstr, '\0', sizeof (tmpstr));
+                        for (i = 0; i < RFIFOREST (fd); i++)
+                        {
+                            if ((i & 15) == 0)
+                                fprintf (logfp, "%04X ", i);
+                            fprintf (logfp, "%02x ", RFIFOB (fd, i));
+                            if (RFIFOB (fd, i) > 0x1f)
+                                tmpstr[i % 16] = RFIFOB (fd, i);
+                            else
+                                tmpstr[i % 16] = '.';
+                            if ((i - 7) % 16 == 0)  // -8 + 1
+                                fprintf (logfp, " ");
+                            else if ((i + 1) % 16 == 0)
+                            {
+                                fprintf (logfp, " %s\n", tmpstr);
+                                memset (tmpstr, '\0', sizeof (tmpstr));
+                            }
+                        }
+                        if (i % 16 != 0)
+                        {
+                            for (j = i; j % 16 != 0; j++)
+                            {
+                                fprintf (logfp, "   ");
+                                if ((j - 7) % 16 == 0)  // -8 + 1
+                                    fprintf (logfp, " ");
+                            }
+                            fprintf (logfp, " %s\n", tmpstr);
+                        }
+                        fprintf (logfp, "\n");
+                        fclose_ (logfp);
+                    }
+                }
+                login_log ("End of connection, unknown packet (ip: %s)\n", ip);
+                session[fd]->eof = 1;
+                return;
+        }
+    }
+    return;
+}
+
+//-------------------------------------------------
+// Return numerical value of a switch configuration
+// on/off, english, français, deutsch, español
+//-------------------------------------------------
+int config_switch (const char *str)
+{
+    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
+        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
+        || strcasecmp (str, "si") == 0)
+        return 1;
+    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
+        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
+        return 0;
+
+    return atoi (str);
+}
+
+//----------------------------------
+// Reading Lan Support configuration
+//----------------------------------
+int login_lan_config_read (const char *lancfgName)
+{
+    int  j;
+    struct hostent *h = NULL;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    // set default configuration
+    strncpy (lan_char_ip, "127.0.0.1", sizeof (lan_char_ip));
+    subneti[0] = 127;
+    subneti[1] = 0;
+    subneti[2] = 0;
+    subneti[3] = 1;
+    for (j = 0; j < 4; j++)
+        subnetmaski[j] = 255;
+
+    fp = fopen_ (lancfgName, "r");
+
+    if (fp == NULL)
+    {
+        printf
+            ("***WARNING: LAN Support configuration file is not found: %s\n",
+             lancfgName);
+        return 1;
+    }
+
+    printf ("---Start reading Lan Support configuration file\n");
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        line[sizeof (line) - 1] = '\0';
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) != 2)
+            continue;
+
+        remove_control_chars (w1);
+        remove_control_chars (w2);
+        if (strcasecmp (w1, "lan_char_ip") == 0)
+        {                       // Read Char-Server Lan IP Address
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                sprintf (lan_char_ip, "%d.%d.%d.%d",
+                         (unsigned char) h->h_addr[0],
+                         (unsigned char) h->h_addr[1],
+                         (unsigned char) h->h_addr[2],
+                         (unsigned char) h->h_addr[3]);
+            }
+            else
+            {
+                strncpy (lan_char_ip, w2, sizeof (lan_char_ip));
+                lan_char_ip[sizeof (lan_char_ip) - 1] = '\0';
+            }
+            printf ("LAN IP of char-server: %s.\n", lan_char_ip);
+        }
+        else if (strcasecmp (w1, "subnet") == 0)
+        {                       // Read Subnetwork
+            for (j = 0; j < 4; j++)
+                subneti[j] = 0;
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                for (j = 0; j < 4; j++)
+                    subneti[j] = (unsigned char) h->h_addr[j];
+            }
+            else
+            {
+                sscanf (w2, "%d.%d.%d.%d", &subneti[0], &subneti[1],
+                        &subneti[2], &subneti[3]);
+            }
+            printf ("Sub-network of the char-server: %d.%d.%d.%d.\n",
+                    subneti[0], subneti[1], subneti[2], subneti[3]);
+        }
+        else if (strcasecmp (w1, "subnetmask") == 0)
+        {                       // Read Subnetwork Mask
+            for (j = 0; j < 4; j++)
+                subnetmaski[j] = 255;
+            h = gethostbyname (w2);
+            if (h != NULL)
+            {
+                for (j = 0; j < 4; j++)
+                    subnetmaski[j] = (unsigned char) h->h_addr[j];
+            }
+            else
+            {
+                sscanf (w2, "%d.%d.%d.%d", &subnetmaski[0], &subnetmaski[1],
+                        &subnetmaski[2], &subnetmaski[3]);
+            }
+            printf ("Sub-network mask of the char-server: %d.%d.%d.%d.\n",
+                    subnetmaski[0], subnetmaski[1], subnetmaski[2],
+                    subnetmaski[3]);
+        }
+    }
+    fclose_ (fp);
+
+    // log the LAN configuration
+    login_log ("The LAN configuration of the server is set:\n");
+    login_log ("- with LAN IP of char-server: %s.\n", lan_char_ip);
+    login_log
+        ("- with the sub-network of the char-server: %d.%d.%d.%d/%d.%d.%d.%d.\n",
+         subneti[0], subneti[1], subneti[2], subneti[3],
+         subnetmaski[0], subnetmaski[1], subnetmaski[2], subnetmaski[3]);
+
+    // sub-network check of the char-server
+    {
+        unsigned int a0, a1, a2, a3;
+        unsigned char p[4];
+        sscanf (lan_char_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
+        p[0] = a0;
+        p[1] = a1;
+        p[2] = a2;
+        p[3] = a3;
+        printf ("LAN test of LAN IP of the char-server: ");
+        if (lan_ip_check (p) == 0)
+        {
+            printf
+                ("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
+            login_log
+                ("***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network.\n");
+        }
+    }
+
+    printf ("---End reading of Lan Support configuration file\n");
+
+    return 0;
+}
+
+//-----------------------------------
+// Reading general configuration file
+//-----------------------------------
+int login_config_read (const char *cfgName)
+{
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        printf ("Configuration file (%s) not found.\n", cfgName);
+        return 1;
+    }
+
+    printf ("---Start reading of Login Server configuration file (%s)\n",
+            cfgName);
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        line[sizeof (line) - 1] = '\0';
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
+        {
+            remove_control_chars (w1);
+            remove_control_chars (w2);
+
+            if (strcasecmp (w1, "admin_state") == 0)
+            {
+                admin_state = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "admin_pass") == 0)
+            {
+                strncpy (admin_pass, w2, sizeof (admin_pass));
+                admin_pass[sizeof (admin_pass) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "ladminallowip") == 0)
+            {
+                if (strcasecmp (w2, "clear") == 0)
+                {
+                    if (access_ladmin_allow)
+                        free (access_ladmin_allow);
+                    access_ladmin_allow = NULL;
+                    access_ladmin_allownum = 0;
+                }
+                else
+                {
+                    if (strcasecmp (w2, "all") == 0)
+                    {
+                        // reset all previous values
+                        if (access_ladmin_allow)
+                            free (access_ladmin_allow);
+                        // set to all
+                        CREATE (access_ladmin_allow, char, ACO_STRSIZE);
+                        access_ladmin_allownum = 1;
+                    }
+                    else if (w2[0]
+                             && !(access_ladmin_allownum == 1
+                                  && access_ladmin_allow[0] == '\0'))
+                    {           // don't add IP if already 'all'
+                        if (access_ladmin_allow)
+                            RECREATE (access_ladmin_allow, char, (access_ladmin_allownum + 1) * ACO_STRSIZE);
+                        else
+                            CREATE (access_ladmin_allow, char, ACO_STRSIZE);
+                        strncpy (access_ladmin_allow +
+                                 (access_ladmin_allownum++) * ACO_STRSIZE, w2,
+                                 ACO_STRSIZE);
+                        access_ladmin_allow[access_ladmin_allownum *
+                                            ACO_STRSIZE - 1] = '\0';
+                    }
+                }
+            }
+            else if (strcasecmp (w1, "gm_pass") == 0)
+            {
+                strncpy (gm_pass, w2, sizeof (gm_pass));
+                gm_pass[sizeof (gm_pass) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "level_new_gm") == 0)
+            {
+                level_new_gm = atoi (w2);
+            }
+            else if (strcasecmp (w1, "new_account") == 0)
+            {
+                new_account_flag = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "login_port") == 0)
+            {
+                login_port = atoi (w2);
+            }
+            else if (strcasecmp (w1, "account_filename") == 0)
+            {
+                strncpy (account_filename, w2, sizeof (account_filename));
+                account_filename[sizeof (account_filename) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "gm_account_filename") == 0)
+            {
+                strncpy (GM_account_filename, w2,
+                         sizeof (GM_account_filename));
+                GM_account_filename[sizeof (GM_account_filename) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "gm_account_filename_check_timer") == 0)
+            {
+                gm_account_filename_check_timer = atoi (w2);
+            }
+            else if (strcasecmp (w1, "login_log_filename") == 0)
+            {
+                strncpy (login_log_filename, w2, sizeof (login_log_filename));
+                login_log_filename[sizeof (login_log_filename) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "login_log_unknown_packets_filename") == 0)
+            {
+                strncpy (login_log_unknown_packets_filename, w2,
+                         sizeof (login_log_unknown_packets_filename));
+                login_log_unknown_packets_filename[sizeof
+                                                   (login_log_unknown_packets_filename)
+                                                   - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "save_unknown_packets") == 0)
+            {
+                save_unknown_packets = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "display_parse_login") == 0)
+            {
+                display_parse_login = config_switch (w2);   // 0: no, 1: yes
+            }
+            else if (strcasecmp (w1, "display_parse_admin") == 0)
+            {
+                display_parse_admin = config_switch (w2);   // 0: no, 1: yes
+            }
+            else if (strcasecmp (w1, "display_parse_fromchar") == 0)
+            {
+                display_parse_fromchar = config_switch (w2);    // 0: no, 1: yes (without packet 0x2714), 2: all packets
+            }
+            else if (strcasecmp (w1, "date_format") == 0)
+            {                   // note: never have more than 19 char for the date!
+                switch (atoi (w2))
+                {
+                    case 0:
+                        strcpy (date_format, "%d-%m-%Y %H:%M:%S");  // 31-12-2004 23:59:59
+                        break;
+                    case 1:
+                        strcpy (date_format, "%m-%d-%Y %H:%M:%S");  // 12-31-2004 23:59:59
+                        break;
+                    case 2:
+                        strcpy (date_format, "%Y-%d-%m %H:%M:%S");  // 2004-31-12 23:59:59
+                        break;
+                    case 3:
+                        strcpy (date_format, "%Y-%m-%d %H:%M:%S");  // 2004-12-31 23:59:59
+                        break;
+                }
+            }
+            else if (strcasecmp (w1, "min_level_to_connect") == 0)
+            {
+                min_level_to_connect = atoi (w2);
+            }
+            else if (strcasecmp (w1, "add_to_unlimited_account") == 0)
+            {
+                add_to_unlimited_account = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "start_limited_time") == 0)
+            {
+                start_limited_time = atoi (w2);
+            }
+            else if (strcasecmp (w1, "check_ip_flag") == 0)
+            {
+                check_ip_flag = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "order") == 0)
+            {
+                access_order = atoi (w2);
+                if (strcasecmp (w2, "deny,allow") == 0 ||
+                    strcasecmp (w2, "deny, allow") == 0)
+                    access_order = ACO_DENY_ALLOW;
+                if (strcasecmp (w2, "allow,deny") == 0 ||
+                    strcasecmp (w2, "allow, deny") == 0)
+                    access_order = ACO_ALLOW_DENY;
+                if (strcasecmp (w2, "mutual-failture") == 0 ||
+                    strcasecmp (w2, "mutual-failure") == 0)
+                    access_order = ACO_MUTUAL_FAILTURE;
+            }
+            else if (strcasecmp (w1, "allow") == 0)
+            {
+                if (strcasecmp (w2, "clear") == 0)
+                {
+                    if (access_allow)
+                        free (access_allow);
+                    access_allow = NULL;
+                    access_allownum = 0;
+                }
+                else
+                {
+                    if (strcasecmp (w2, "all") == 0)
+                    {
+                        // reset all previous values
+                        if (access_allow)
+                            free (access_allow);
+                        // set to all
+                        CREATE (access_allow, char, ACO_STRSIZE);
+                        access_allownum = 1;
+                    }
+                    else if (w2[0]
+                             && !(access_allownum == 1
+                                  && access_allow[0] == '\0'))
+                    {           // don't add IP if already 'all'
+                        if (access_allow)
+                            RECREATE (access_allow, char, (access_allownum + 1) * ACO_STRSIZE);
+                        else
+                            CREATE (access_allow, char, ACO_STRSIZE);
+                        strncpy (access_allow +
+                                 (access_allownum++) * ACO_STRSIZE, w2,
+                                 ACO_STRSIZE);
+                        access_allow[access_allownum * ACO_STRSIZE - 1] =
+                            '\0';
+                    }
+                }
+            }
+            else if (strcasecmp (w1, "deny") == 0)
+            {
+                if (strcasecmp (w2, "clear") == 0)
+                {
+                    if (access_deny)
+                        free (access_deny);
+                    access_deny = NULL;
+                    access_denynum = 0;
+                }
+                else
+                {
+                    if (strcasecmp (w2, "all") == 0)
+                    {
+                        // reset all previous values
+                        if (access_deny)
+                            free (access_deny);
+                        // set to all
+                        CREATE (access_deny, char, ACO_STRSIZE);
+                        access_denynum = 1;
+                    }
+                    else if (w2[0]
+                             && !(access_denynum == 1
+                                  && access_deny[0] == '\0'))
+                    {           // don't add IP if already 'all'
+                        if (access_deny)
+                            RECREATE (access_deny, char, (access_denynum + 1) * ACO_STRSIZE);
+                        else
+                            CREATE (access_deny, char, ACO_STRSIZE);
+                        strncpy (access_deny +
+                                 (access_denynum++) * ACO_STRSIZE, w2,
+                                 ACO_STRSIZE);
+                        access_deny[access_denynum * ACO_STRSIZE - 1] = '\0';
+                    }
+                }
+            }
+            else if (strcasecmp (w1, "anti_freeze_enable") == 0)
+            {
+                anti_freeze_enable = config_switch (w2);
+            }
+            else if (strcasecmp (w1, "anti_freeze_interval") == 0)
+            {
+                ANTI_FREEZE_INTERVAL = atoi (w2);
+                if (ANTI_FREEZE_INTERVAL < 5)
+                    ANTI_FREEZE_INTERVAL = 5;   // minimum 5 seconds
+            }
+            else if (strcasecmp (w1, "import") == 0)
+            {
+                login_config_read (w2);
+            }
+            else if (strcasecmp (w1, "update_host") == 0)
+            {
+                strncpy (update_host, w2, sizeof (update_host));
+                update_host[sizeof (update_host) - 1] = '\0';
+            }
+            else if (strcasecmp (w1, "main_server") == 0)
+            {
+                strncpy (main_server, w2, sizeof (main_server));
+                main_server[sizeof (main_server) - 1] = '\0';
+            }
+        }
+    }
+    fclose_ (fp);
+
+    printf ("---End reading of Login Server configuration file.\n");
+
+    return 0;
+}
+
+//-------------------------------------
+// Displaying of configuration warnings
+//-------------------------------------
+void display_conf_warnings (void)
+{
+    if (admin_state != 0 && admin_state != 1)
+    {
+        printf
+            ("***WARNING: Invalid value for admin_state parameter -> set to 0 (no remote admin).\n");
+        admin_state = 0;
+    }
+
+    if (admin_state == 1)
+    {
+        if (admin_pass[0] == '\0')
+        {
+            printf
+                ("***WARNING: Administrator password is void (admin_pass).\n");
+        }
+        else if (strcmp (admin_pass, "admin") == 0)
+        {
+            printf
+                ("***WARNING: You are using the default administrator password (admin_pass).\n");
+            printf ("            We highly recommend that you change it.\n");
+        }
+    }
+
+    if (gm_pass[0] == '\0')
+    {
+        printf ("***WARNING: 'To GM become' password is void (gm_pass).\n");
+        printf
+            ("            We highly recommend that you set one password.\n");
+    }
+    else if (strcmp (gm_pass, "gm") == 0)
+    {
+        printf
+            ("***WARNING: You are using the default GM password (gm_pass).\n");
+        printf ("            We highly recommend that you change it.\n");
+    }
+
+    if (level_new_gm < 0 || level_new_gm > 99)
+    {
+        printf
+            ("***WARNING: Invalid value for level_new_gm parameter -> set to 60 (default).\n");
+        level_new_gm = 60;
+    }
+
+    if (new_account_flag != 0 && new_account_flag != 1)
+    {
+        printf
+            ("***WARNING: Invalid value for new_account parameter -> set to 0 (no new account).\n");
+        new_account_flag = 0;
+    }
+
+    if (login_port < 1024 || login_port > 65535)
+    {
+        printf
+            ("***WARNING: Invalid value for login_port parameter -> set to 6900 (default).\n");
+        login_port = 6900;
+    }
+
+    if (gm_account_filename_check_timer < 0)
+    {
+        printf
+            ("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
+        printf ("            -> set to 15 sec (default).\n");
+        gm_account_filename_check_timer = 15;
+    }
+    else if (gm_account_filename_check_timer == 1)
+    {
+        printf
+            ("***WARNING: Invalid value for gm_account_filename_check_timer parameter.\n");
+        printf ("            -> set to 2 sec (minimum value).\n");
+        gm_account_filename_check_timer = 2;
+    }
+
+    if (save_unknown_packets != 0 && save_unknown_packets != 1)
+    {
+        printf
+            ("WARNING: Invalid value for save_unknown_packets parameter -> set to 0-no save.\n");
+        save_unknown_packets = 0;
+    }
+
+    if (display_parse_login != 0 && display_parse_login != 1)
+    {                           // 0: no, 1: yes
+        printf
+            ("***WARNING: Invalid value for display_parse_login parameter\n");
+        printf ("            -> set to 0 (no display).\n");
+        display_parse_login = 0;
+    }
+
+    if (display_parse_admin != 0 && display_parse_admin != 1)
+    {                           // 0: no, 1: yes
+        printf
+            ("***WARNING: Invalid value for display_parse_admin parameter\n");
+        printf ("            -> set to 0 (no display).\n");
+        display_parse_admin = 0;
+    }
+
+    if (display_parse_fromchar < 0 || display_parse_fromchar > 2)
+    {                           // 0: no, 1: yes (without packet 0x2714), 2: all packets
+        printf
+            ("***WARNING: Invalid value for display_parse_fromchar parameter\n");
+        printf ("            -> set to 0 (no display).\n");
+        display_parse_fromchar = 0;
+    }
+
+    if (min_level_to_connect < 0)
+    {                           // 0: all players, 1-99 at least gm level x
+        printf
+            ("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n",
+             min_level_to_connect);
+        printf ("            -> set to 0 (any player).\n");
+        min_level_to_connect = 0;
+    }
+    else if (min_level_to_connect > 99)
+    {                           // 0: all players, 1-99 at least gm level x
+        printf
+            ("***WARNING: Invalid value for min_level_to_connect (%d) parameter\n",
+             min_level_to_connect);
+        printf ("            -> set to 99 (only GM level 99).\n");
+        min_level_to_connect = 99;
+    }
+
+    if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1)
+    {                           // 0: no, 1: yes
+        printf
+            ("***WARNING: Invalid value for add_to_unlimited_account parameter\n");
+        printf
+            ("            -> set to 0 (impossible to add a time to an unlimited account).\n");
+        add_to_unlimited_account = 0;
+    }
+
+    if (start_limited_time < -1)
+    {                           // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time
+        printf
+            ("***WARNING: Invalid value for start_limited_time parameter\n");
+        printf
+            ("            -> set to -1 (new accounts are created with unlimited time).\n");
+        start_limited_time = -1;
+    }
+
+    if (check_ip_flag != 0 && check_ip_flag != 1)
+    {                           // 0: no, 1: yes
+        printf ("***WARNING: Invalid value for check_ip_flag parameter\n");
+        printf
+            ("            -> set to 1 (check players ip between login-server & char-server).\n");
+        check_ip_flag = 1;
+    }
+
+    if (access_order == ACO_DENY_ALLOW)
+    {
+        if (access_denynum == 1 && access_deny[0] == '\0')
+        {
+            printf
+                ("***WARNING: The IP security order is 'deny,allow' (allow if not deny).\n");
+            printf ("            And you refuse ALL IP.\n");
+        }
+    }
+    else if (access_order == ACO_ALLOW_DENY)
+    {
+        if (access_allownum == 0)
+        {
+            printf
+                ("***WARNING: The IP security order is 'allow,deny' (deny if not allow).\n");
+            printf ("            But, NO IP IS AUTHORISED!\n");
+        }
+    }
+    else
+    {                           // ACO_MUTUAL_FAILTURE
+        if (access_allownum == 0)
+        {
+            printf
+                ("***WARNING: The IP security order is 'mutual-failture'\n");
+            printf
+                ("            (allow if in the allow list and not in the deny list).\n");
+            printf ("            But, NO IP IS AUTHORISED!\n");
+        }
+        else if (access_denynum == 1 && access_deny[0] == '\0')
+        {
+            printf ("***WARNING: The IP security order is mutual-failture\n");
+            printf
+                ("            (allow if in the allow list and not in the deny list).\n");
+            printf ("            But, you refuse ALL IP!\n");
+        }
+    }
+
+    return;
+}
+
+//-------------------------------
+// Save configuration in log file
+//-------------------------------
+void save_config_in_log (void)
+{
+    int  i;
+
+    // a newline in the log...
+    login_log ("");
+    login_log ("The login-server starting...\n");
+
+    // save configuration in log file
+    login_log ("The configuration of the server is set:\n");
+
+    if (admin_state != 1)
+        login_log ("- with no remote administration.\n");
+    else if (admin_pass[0] == '\0')
+        login_log ("- with a remote administration with a VOID password.\n");
+    else if (strcmp (admin_pass, "admin") == 0)
+        login_log ("- with a remote administration with the DEFAULT password.\n");
+    else
+        login_log
+            ("- with a remote administration with the password of %d character(s).\n",
+             strlen (admin_pass));
+    if (access_ladmin_allownum == 0
+        || (access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0'))
+    {
+        login_log ("- to accept any IP for remote administration\n");
+    }
+    else
+    {
+        login_log ("- to accept following IP for remote administration:\n");
+        for (i = 0; i < access_ladmin_allownum; i++)
+            login_log ("  %s\n",
+                       (char *) (access_ladmin_allow + i * ACO_STRSIZE));
+    }
+
+    if (gm_pass[0] == '\0')
+        login_log ("- with a VOID 'To GM become' password (gm_pass).\n");
+    else if (strcmp (gm_pass, "gm") == 0)
+        login_log ("- with the DEFAULT 'To GM become' password (gm_pass).\n");
+    else
+        login_log
+            ("- with a 'To GM become' password (gm_pass) of %d character(s).\n",
+             strlen (gm_pass));
+    if (level_new_gm == 0)
+        login_log ("- to refuse any creation of GM with @gm.\n");
+    else
+        login_log ("- to create GM with level '%d' when @gm is used.\n",
+                   level_new_gm);
+
+    if (new_account_flag == 1)
+        login_log ("- to ALLOW new users (with _F/_M).\n");
+    else
+        login_log ("- to NOT ALLOW new users (with _F/_M).\n");
+    login_log ("- with port: %d.\n", login_port);
+    login_log ("- with the accounts file name: '%s'.\n",
+               account_filename);
+    login_log ("- with the GM accounts file name: '%s'.\n",
+               GM_account_filename);
+    if (gm_account_filename_check_timer == 0)
+        login_log ("- to NOT check GM accounts file modifications.\n");
+    else
+        login_log
+            ("- to check GM accounts file modifications every %d seconds.\n",
+             gm_account_filename_check_timer);
+
+    // not necessary to log the 'login_log_filename', we are inside :)
+
+    login_log ("- with the unknown packets file name: '%s'.\n",
+               login_log_unknown_packets_filename);
+    if (save_unknown_packets)
+        login_log ("- to SAVE all unkown packets.\n");
+    else
+        login_log
+            ("- to SAVE only unkown packets sending by a char-server or a remote administration.\n");
+    if (display_parse_login)
+        login_log ("- to display normal parse packets on console.\n");
+    else
+        login_log ("- to NOT display normal parse packets on console.\n");
+    if (display_parse_admin)
+        login_log ("- to display administration parse packets on console.\n");
+    else
+        login_log ("- to NOT display administration parse packets on console.\n");
+    if (display_parse_fromchar)
+        login_log ("- to display char-server parse packets on console.\n");
+    else
+        login_log ("- to NOT display char-server parse packets on console.\n");
+
+    if (min_level_to_connect == 0)  // 0: all players, 1-99 at least gm level x
+        login_log ("- with no minimum level for connection.\n");
+    else if (min_level_to_connect == 99)
+        login_log ("- to accept only GM with level 99.\n");
+    else
+        login_log ("- to accept only GM with level %d or more.\n",
+                   min_level_to_connect);
+
+    if (add_to_unlimited_account)
+        login_log
+            ("- to authorize adjustment (with timeadd ladmin) on an unlimited account.\n");
+    else
+        login_log
+            ("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n");
+
+    if (start_limited_time < 0)
+        login_log ("- to create new accounts with an unlimited time.\n");
+    else if (start_limited_time == 0)
+        login_log
+            ("- to create new accounts with a limited time: time of creation.\n");
+    else
+        login_log
+            ("- to create new accounts with a limited time: time of creation + %d second(s).\n",
+             start_limited_time);
+
+    if (check_ip_flag)
+        login_log
+            ("- with control of players IP between login-server and char-server.\n");
+    else
+        login_log
+            ("- to not check players IP between login-server and char-server.\n");
+
+    if (access_order == ACO_DENY_ALLOW)
+    {
+        if (access_denynum == 0)
+        {
+            login_log
+                ("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP.\n");
+        }
+        else if (access_denynum == 1 && access_deny[0] == '\0')
+        {
+            login_log
+                ("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP.\n");
+        }
+        else
+        {
+            login_log
+                ("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n");
+            for (i = 0; i < access_denynum; i++)
+                login_log ("  %s\n",
+                           (char *) (access_deny + i * ACO_STRSIZE));
+        }
+    }
+    else if (access_order == ACO_ALLOW_DENY)
+    {
+        if (access_allownum == 0)
+        {
+            login_log
+                ("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!\n");
+        }
+        else if (access_allownum == 1 && access_allow[0] == '\0')
+        {
+            login_log
+                ("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP.\n");
+        }
+        else
+        {
+            login_log
+                ("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n");
+            for (i = 0; i < access_allownum; i++)
+                login_log ("  %s\n",
+                           (char *) (access_allow + i * ACO_STRSIZE));
+        }
+    }
+    else
+    {                           // ACO_MUTUAL_FAILTURE
+        login_log
+            ("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list).\n");
+        if (access_allownum == 0)
+        {
+            login_log ("  But, NO IP IS AUTHORISED!\n");
+        }
+        else if (access_denynum == 1 && access_deny[0] == '\0')
+        {
+            login_log ("  But, you refuse ALL IP!\n");
+        }
+        else
+        {
+            if (access_allownum == 1 && access_allow[0] == '\0')
+            {
+                login_log ("  You authorise ALL IP.\n");
+            }
+            else
+            {
+                login_log ("  Authorised IP are:\n");
+                for (i = 0; i < access_allownum; i++)
+                    login_log ("    %s\n",
+                               (char *) (access_allow + i * ACO_STRSIZE));
+            }
+            login_log ("  Refused IP are:\n");
+            for (i = 0; i < access_denynum; i++)
+                login_log ("    %s\n",
+                           (char *) (access_deny + i * ACO_STRSIZE));
+        }
+    }
+}
+
+//--------------------------------------
+// Function called at exit of the server
+//--------------------------------------
+void term_func (void)
+{
+    int  i, fd;
+
+    mmo_auth_sync ();
+
+    free (auth_dat);
+    free (gm_account_db);
+    for (i = 0; i < MAX_SERVERS; i++)
+    {
+        if ((fd = server_fd[i]) >= 0)
+            delete_session (fd);
+    }
+    delete_session (login_fd);
+
+    login_log
+        ("----End of login-server (normal end with closing of all files).\n");
+}
+
+//------------------------------
+// Main function of login-server
+//------------------------------
+int do_init (int argc, char **argv)
+{
+    int  i, j;
+
+    // read login-server configuration
+    login_config_read ((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
+    display_conf_warnings ();   // not in login_config_read, because we can use 'import' option, and display same message twice or more
+    save_config_in_log ();      // not before, because log file name can be changed
+    login_lan_config_read ((argc > 1) ? argv[1] : LAN_CONF_NAME);
+
+    for (i = 0; i < AUTH_FIFO_SIZE; i++)
+        auth_fifo[i].delflag = 1;
+    for (i = 0; i < MAX_SERVERS; i++)
+        server_fd[i] = -1;
+
+    gm_account_db = numdb_init ();
+
+    read_gm_account ();
+    mmo_auth_init ();
+//     set_termfunc (mmo_auth_sync);
+    set_defaultparse (parse_login);
+    login_fd = make_listen_port (login_port);
+
+//    add_timer_func_list (check_auth_sync, "check_auth_sync");
+
+    // Trigger auth sync every 5 minutes
+    i = add_timer_interval (gettick () + 300000, check_auth_sync, 0, 0, 300000);
+
+    if (anti_freeze_enable > 0)
+    {
+//        add_timer_func_list (char_anti_freeze_system, "char_anti_freeze_system");
+        i = add_timer_interval (gettick () + 1000, char_anti_freeze_system, 0,
+                                0, ANTI_FREEZE_INTERVAL * 1000);
+    }
+
+    // add timer to check GM accounts file modification
+    j = gm_account_filename_check_timer;
+    if (j == 0)                 // if we would not to check, we check every 60 sec, just to have timer (if we change timer, is was not necessary to check if timer already exists)
+        j = 60;
+//    add_timer_func_list (check_GM_file, "check_GM_file");
+    i = add_timer_interval (gettick () + j * 1000, check_GM_file, 0, 0, j * 1000);  // every x sec we check if gm file has been changed
+
+    login_log
+        ("The login-server is ready (Server is listening on the port %d).\n",
+         login_port);
+
+    printf
+        ("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
+         login_port);
+
+    return 0;
+}
diff --git a/src/login/login.h b/src/login/login.h
deleted file mode 100644
index a1f8fef..0000000
--- a/src/login/login.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// $Id: login.h,v 1.1.1.1 2004/09/10 17:26:53 MagicalTux Exp $
-#ifndef _LOGIN_H_
-#define _LOGIN_H_
-
-#define MAX_SERVERS 30
-
-#define LOGIN_CONF_NAME "conf/login_athena.conf"
-#define LAN_CONF_NAME "conf/lan_support.conf"
-// It seems we don't need to emulate RO's "password encryption" - MC/TMW
-//#define PASSWORDENC 3           // A definition is given when making an encryption password correspond.
-                        // It is 1 at the time of passwordencrypt.
-                        // It is made into 2 at the time of passwordencrypt2.
-                        // When it is made 3, it corresponds to both.
-#define START_ACCOUNT_NUM 2000000
-#define END_ACCOUNT_NUM 100000000
-
-struct mmo_account
-{
-    char *userid;
-    char *passwd;
-    int  passwdenc;
-
-    long account_id;
-    long login_id1;
-    long login_id2;
-    long char_id;
-    char lastlogin[24];
-    int  sex;
-};
-
-struct mmo_char_server
-{
-    char name[20];
-    long ip;
-    short port;
-    int  users;
-    int  maintenance;
-    int  is_new;
-};
-
-#endif
diff --git a/src/login/login.hpp b/src/login/login.hpp
new file mode 100644
index 0000000..49d1c12
--- /dev/null
+++ b/src/login/login.hpp
@@ -0,0 +1,41 @@
+// $Id: login.h,v 1.1.1.1 2004/09/10 17:26:53 MagicalTux Exp $
+#ifndef LOGIN_HPP
+#define LOGIN_HPP
+
+#define MAX_SERVERS 30
+
+#define LOGIN_CONF_NAME "conf/login_athena.conf"
+#define LAN_CONF_NAME "conf/lan_support.conf"
+// It seems we don't need to emulate RO's "password encryption" - MC/TMW
+//#define PASSWORDENC 3           // A definition is given when making an encryption password correspond.
+                        // It is 1 at the time of passwordencrypt.
+                        // It is made into 2 at the time of passwordencrypt2.
+                        // When it is made 3, it corresponds to both.
+#define START_ACCOUNT_NUM 2000000
+#define END_ACCOUNT_NUM 100000000
+
+struct mmo_account
+{
+    char *userid;
+    char *passwd;
+    int  passwdenc;
+
+    long account_id;
+    long login_id1;
+    long login_id2;
+    long char_id;
+    char lastlogin[24];
+    int  sex;
+};
+
+struct mmo_char_server
+{
+    char name[20];
+    long ip;
+    short port;
+    int  users;
+    int  maintenance;
+    int  is_new;
+};
+
+#endif
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
deleted file mode 100644
index 88e756d..0000000
--- a/src/map/atcommand.c
+++ /dev/null
@@ -1,8728 +0,0 @@
-// $Id: atcommand.c 148 2004-09-30 14:05:37Z MouseJstr $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mt_rand.h"
-
-#include "atcommand.h"
-#include "battle.h"
-#include "clif.h"
-#include "chrif.h"
-#include "guild.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "pc.h"
-#include "party.h"
-#include "script.h"
-#include "skill.h"
-#include "trade.h"
-
-#include "../common/core.h"
-#include "tmw.h"
-
-#define STATE_BLIND 0x10
-
-static char command_symbol = '@';   // first char of the commands (by [Yor])
-
-static char msg_table[1000][1024];  // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
-
-#define ATCOMMAND_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
-ATCOMMAND_FUNC (setup);
-ATCOMMAND_FUNC (broadcast);
-ATCOMMAND_FUNC (localbroadcast);
-ATCOMMAND_FUNC (charwarp);
-ATCOMMAND_FUNC (warp);
-ATCOMMAND_FUNC (where);
-ATCOMMAND_FUNC (goto);
-ATCOMMAND_FUNC (jump);
-ATCOMMAND_FUNC (who);
-ATCOMMAND_FUNC (whogroup);
-ATCOMMAND_FUNC (whomap);
-ATCOMMAND_FUNC (whomapgroup);
-ATCOMMAND_FUNC (whogm);         // by Yor
-ATCOMMAND_FUNC (save);
-ATCOMMAND_FUNC (load);
-ATCOMMAND_FUNC (speed);
-ATCOMMAND_FUNC (storage);
-ATCOMMAND_FUNC (guildstorage);
-ATCOMMAND_FUNC (option);
-ATCOMMAND_FUNC (hide);
-ATCOMMAND_FUNC (die);
-ATCOMMAND_FUNC (kill);
-ATCOMMAND_FUNC (alive);
-ATCOMMAND_FUNC (kami);
-ATCOMMAND_FUNC (heal);
-ATCOMMAND_FUNC (item);
-ATCOMMAND_FUNC (itemreset);
-ATCOMMAND_FUNC (itemcheck);
-ATCOMMAND_FUNC (baselevelup);
-ATCOMMAND_FUNC (joblevelup);
-ATCOMMAND_FUNC (help);
-ATCOMMAND_FUNC (gm);
-ATCOMMAND_FUNC (pvpoff);
-ATCOMMAND_FUNC (pvpon);
-ATCOMMAND_FUNC (gvgoff);
-ATCOMMAND_FUNC (gvgon);
-ATCOMMAND_FUNC (model);
-ATCOMMAND_FUNC (go);
-ATCOMMAND_FUNC (spawn);
-ATCOMMAND_FUNC (killmonster);
-ATCOMMAND_FUNC (killmonster2);
-ATCOMMAND_FUNC (refine);
-ATCOMMAND_FUNC (produce);
-ATCOMMAND_FUNC (memo);
-ATCOMMAND_FUNC (gat);
-ATCOMMAND_FUNC (packet);
-ATCOMMAND_FUNC (statuspoint);
-ATCOMMAND_FUNC (skillpoint);
-ATCOMMAND_FUNC (zeny);
-ATCOMMAND_FUNC (param);
-ATCOMMAND_FUNC (guildlevelup);
-ATCOMMAND_FUNC (recall);
-ATCOMMAND_FUNC (recallall);
-ATCOMMAND_FUNC (revive);
-ATCOMMAND_FUNC (character_stats);
-ATCOMMAND_FUNC (character_stats_all);
-ATCOMMAND_FUNC (character_option);
-ATCOMMAND_FUNC (character_save);
-ATCOMMAND_FUNC (night);
-ATCOMMAND_FUNC (day);
-ATCOMMAND_FUNC (doom);
-ATCOMMAND_FUNC (doommap);
-ATCOMMAND_FUNC (raise);
-ATCOMMAND_FUNC (raisemap);
-ATCOMMAND_FUNC (character_baselevel);
-ATCOMMAND_FUNC (character_joblevel);
-ATCOMMAND_FUNC (kick);
-ATCOMMAND_FUNC (kickall);
-ATCOMMAND_FUNC (allskills);
-ATCOMMAND_FUNC (questskill);
-ATCOMMAND_FUNC (charquestskill);
-ATCOMMAND_FUNC (lostskill);
-ATCOMMAND_FUNC (charlostskill);
-ATCOMMAND_FUNC (party);
-ATCOMMAND_FUNC (guild);
-ATCOMMAND_FUNC (charskreset);
-ATCOMMAND_FUNC (charstreset);
-ATCOMMAND_FUNC (charreset);
-ATCOMMAND_FUNC (charstpoint);
-ATCOMMAND_FUNC (charmodel);
-ATCOMMAND_FUNC (charskpoint);
-ATCOMMAND_FUNC (charzeny);
-ATCOMMAND_FUNC (agitstart);
-ATCOMMAND_FUNC (agitend);
-ATCOMMAND_FUNC (reloaditemdb);
-ATCOMMAND_FUNC (reloadmobdb);
-ATCOMMAND_FUNC (reloadskilldb);
-ATCOMMAND_FUNC (reloadscript);
-ATCOMMAND_FUNC (reloadgmdb);    // by Yor
-ATCOMMAND_FUNC (mapexit);
-ATCOMMAND_FUNC (idsearch);
-ATCOMMAND_FUNC (mapinfo);
-ATCOMMAND_FUNC (dye);           //** by fritz
-ATCOMMAND_FUNC (hair_style);    //** by fritz
-ATCOMMAND_FUNC (hair_color);    //** by fritz
-ATCOMMAND_FUNC (all_stats);     //** by fritz
-ATCOMMAND_FUNC (char_change_sex);   // by Yor
-ATCOMMAND_FUNC (char_block);    // by Yor
-ATCOMMAND_FUNC (char_ban);      // by Yor
-ATCOMMAND_FUNC (char_unblock);  // by Yor
-ATCOMMAND_FUNC (char_unban);    // by Yor
-ATCOMMAND_FUNC (mount_peco);    // by Valaris
-ATCOMMAND_FUNC (char_mount_peco);   // by Yor
-ATCOMMAND_FUNC (guildspy);      // [Syrus22]
-ATCOMMAND_FUNC (partyspy);      // [Syrus22]
-ATCOMMAND_FUNC (guildrecall);   // by Yor
-ATCOMMAND_FUNC (partyrecall);   // by Yor
-ATCOMMAND_FUNC (enablenpc);
-ATCOMMAND_FUNC (disablenpc);
-ATCOMMAND_FUNC (servertime);    // by Yor
-ATCOMMAND_FUNC (chardelitem);   // by Yor
-ATCOMMAND_FUNC (jail);          // by Yor
-ATCOMMAND_FUNC (unjail);        // by Yor
-ATCOMMAND_FUNC (disguise);      // [Valaris]
-ATCOMMAND_FUNC (undisguise);    // by Yor
-ATCOMMAND_FUNC (ignorelist);    // by Yor
-ATCOMMAND_FUNC (charignorelist);    // by Yor
-ATCOMMAND_FUNC (inall);         // by Yor
-ATCOMMAND_FUNC (exall);         // by Yor
-ATCOMMAND_FUNC (chardisguise);  // Kalaspuff
-ATCOMMAND_FUNC (charundisguise);    // Kalaspuff
-ATCOMMAND_FUNC (email);         // by Yor
-ATCOMMAND_FUNC (effect);        //by Apple
-ATCOMMAND_FUNC (character_item_list);   // by Yor
-ATCOMMAND_FUNC (character_storage_list);    // by Yor
-ATCOMMAND_FUNC (character_cart_list);   // by Yor
-ATCOMMAND_FUNC (addwarp);       // by MouseJstr
-ATCOMMAND_FUNC (follow);        // by MouseJstr
-ATCOMMAND_FUNC (skillon);       // by MouseJstr
-ATCOMMAND_FUNC (skilloff);      // by MouseJstr
-ATCOMMAND_FUNC (killer);        // by MouseJstr
-ATCOMMAND_FUNC (npcmove);       // by MouseJstr
-ATCOMMAND_FUNC (killable);      // by MouseJstr
-ATCOMMAND_FUNC (charkillable);  // by MouseJstr
-ATCOMMAND_FUNC (chareffect);    // by MouseJstr
-ATCOMMAND_FUNC (chardye);       // by MouseJstr
-ATCOMMAND_FUNC (charhairstyle); // by MouseJstr
-ATCOMMAND_FUNC (charhaircolor); // by MouseJstr
-ATCOMMAND_FUNC (dropall);       // by MouseJstr
-ATCOMMAND_FUNC (chardropall);   // by MouseJstr
-ATCOMMAND_FUNC (storeall);      // by MouseJstr
-ATCOMMAND_FUNC (charstoreall);  // by MouseJstr
-ATCOMMAND_FUNC (skillid);       // by MouseJstr
-ATCOMMAND_FUNC (useskill);      // by MouseJstr
-ATCOMMAND_FUNC (summon);
-ATCOMMAND_FUNC (rain);
-ATCOMMAND_FUNC (snow);
-ATCOMMAND_FUNC (sakura);
-ATCOMMAND_FUNC (fog);
-ATCOMMAND_FUNC (leaves);
-ATCOMMAND_FUNC (adjgmlvl);      // by MouseJstr
-ATCOMMAND_FUNC (adjcmdlvl);     // by MouseJstr
-ATCOMMAND_FUNC (trade);         // by MouseJstr
-ATCOMMAND_FUNC (unmute);        // [Valaris]
-ATCOMMAND_FUNC (char_wipe);     // [Fate]
-ATCOMMAND_FUNC (set_magic);     // [Fate]
-ATCOMMAND_FUNC (magic_info);    // [Fate]
-ATCOMMAND_FUNC (log);           // [Fate]
-ATCOMMAND_FUNC (tee);           // [Fate]
-ATCOMMAND_FUNC (invisible);     // [Fate]
-ATCOMMAND_FUNC (visible);       // [Fate]
-ATCOMMAND_FUNC (list_nearby);   // [Fate]
-ATCOMMAND_FUNC (iterate_forward_over_players);  // [Fate]
-ATCOMMAND_FUNC (iterate_backwards_over_players);    // [Fate]
-ATCOMMAND_FUNC (skillpool_info);    // [Fate]
-ATCOMMAND_FUNC (skillpool_focus);   // [Fate]
-ATCOMMAND_FUNC (skillpool_unfocus); // [Fate]
-ATCOMMAND_FUNC (skill_learn);   // [Fate]
-ATCOMMAND_FUNC (wgm);
-ATCOMMAND_FUNC (ipcheck);
-ATCOMMAND_FUNC (doomspot);
-
-/*==========================================
- *AtCommandInfo atcommand_info[]構造体の定義
- *------------------------------------------
- */
-
-// First char of commands is configured in atcommand_athena.conf. Leave @ in this list for default value.
-// to set default level, read atcommand_athena.conf first please.
-static AtCommandInfo atcommand_info[] = {
-    {AtCommand_Setup, "@setup", 40, atcommand_setup},
-    {AtCommand_CharWarp, "@charwarp", 60, atcommand_charwarp},
-    {AtCommand_Warp, "@warp", 40, atcommand_warp},
-    {AtCommand_Where, "@where", 1, atcommand_where},
-    {AtCommand_Goto, "@goto", 20, atcommand_goto},
-    {AtCommand_Jump, "@jump", 40, atcommand_jump},
-    {AtCommand_Who, "@who", 20, atcommand_who},
-    {AtCommand_WhoGroup, "@whogroup", 20, atcommand_whogroup},
-    {AtCommand_WhoMap, "@whomap", 20, atcommand_whomap},
-    {AtCommand_WhoMapGroup, "@whomapgroup", 20, atcommand_whomapgroup},
-    {AtCommand_WhoGM, "@whogm", 20, atcommand_whogm},   // by Yor
-    {AtCommand_Save, "@save", 40, atcommand_save},
-    {AtCommand_Load, "@return", 40, atcommand_load},
-    {AtCommand_Load, "@load", 40, atcommand_load},
-    {AtCommand_Speed, "@speed", 40, atcommand_speed},
-    {AtCommand_Storage, "@storage", 1, atcommand_storage},
-    {AtCommand_GuildStorage, "@gstorage", 50, atcommand_guildstorage},
-    {AtCommand_Option, "@option", 40, atcommand_option},
-    {AtCommand_Hide, "@hide", 40, atcommand_hide},  // + /hide
-    {AtCommand_Die, "@die", 1, atcommand_die},
-    {AtCommand_Kill, "@kill", 60, atcommand_kill},
-    {AtCommand_Alive, "@alive", 60, atcommand_alive},
-    {AtCommand_Kami, "@kami", 40, atcommand_kami},
-    {AtCommand_Heal, "@heal", 40, atcommand_heal},
-    {AtCommand_Item, "@item", 60, atcommand_item},
-    {AtCommand_ItemReset, "@itemreset", 40, atcommand_itemreset},
-    {AtCommand_ItemCheck, "@itemcheck", 60, atcommand_itemcheck},
-    {AtCommand_BaseLevelUp, "@blvl", 60, atcommand_baselevelup},
-    {AtCommand_JobLevelUp, "@jlvl", 60, atcommand_joblevelup},
-    {AtCommand_Help, "@help", 20, atcommand_help},
-    {AtCommand_GM, "@gm", 100, atcommand_gm},
-    {AtCommand_PvPOff, "@pvpoff", 40, atcommand_pvpoff},
-    {AtCommand_PvPOn, "@pvpon", 40, atcommand_pvpon},
-    {AtCommand_GvGOff, "@gvgoff", 40, atcommand_gvgoff},
-    {AtCommand_GvGOff, "@gpvpoff", 40, atcommand_gvgoff},
-    {AtCommand_GvGOn, "@gvgon", 40, atcommand_gvgon},
-    {AtCommand_GvGOn, "@gpvpon", 40, atcommand_gvgon},
-    {AtCommand_Model, "@model", 20, atcommand_model},
-    {AtCommand_Go, "@go", 10, atcommand_go},
-    {AtCommand_Spawn, "@spawn", 50, atcommand_spawn},
-    {AtCommand_KillMonster, "@killmonster", 60, atcommand_killmonster},
-    {AtCommand_KillMonster2, "@killmonster2", 40, atcommand_killmonster2},
-    {AtCommand_Produce, "@produce", 60, atcommand_produce},
-    {AtCommand_Memo, "@memo", 40, atcommand_memo},
-    {AtCommand_GAT, "@gat", 99, atcommand_gat}, // debug function
-    {AtCommand_Packet, "@packet", 99, atcommand_packet},    // debug function
-    {AtCommand_StatusPoint, "@stpoint", 60, atcommand_statuspoint},
-    {AtCommand_SkillPoint, "@skpoint", 60, atcommand_skillpoint},
-    {AtCommand_Zeny, "@zeny", 60, atcommand_zeny},
-    {AtCommand_Strength, "@str", 60, atcommand_param},
-    {AtCommand_Agility, "@agi", 60, atcommand_param},
-    {AtCommand_Vitality, "@vit", 60, atcommand_param},
-    {AtCommand_Intelligence, "@int", 60, atcommand_param},
-    {AtCommand_Dexterity, "@dex", 60, atcommand_param},
-    {AtCommand_Luck, "@luk", 60, atcommand_param},
-    {AtCommand_GuildLevelUp, "@guildlvl", 60, atcommand_guildlevelup},
-    {AtCommand_Recall, "@recall", 60, atcommand_recall},    // + /recall
-    {AtCommand_Revive, "@revive", 60, atcommand_revive},
-    {AtCommand_CharacterStats, "@charstats", 40, atcommand_character_stats},
-    {AtCommand_CharacterStatsAll, "@charstatsall", 40,
-     atcommand_character_stats_all},
-    {AtCommand_CharacterOption, "@charoption", 60,
-     atcommand_character_option},
-    {AtCommand_CharacterSave, "@charsave", 60, atcommand_character_save},
-    {AtCommand_Night, "@night", 80, atcommand_night},
-    {AtCommand_Day, "@day", 80, atcommand_day},
-    {AtCommand_Doom, "@doom", 80, atcommand_doom},
-    {AtCommand_DoomMap, "@doommap", 80, atcommand_doommap},
-    {AtCommand_Raise, "@raise", 80, atcommand_raise},
-    {AtCommand_RaiseMap, "@raisemap", 80, atcommand_raisemap},
-    {AtCommand_CharacterBaseLevel, "@charbaselvl", 60,
-     atcommand_character_baselevel},
-    {AtCommand_CharacterJobLevel, "@charjlvl", 60,
-     atcommand_character_joblevel},
-    {AtCommand_Kick, "@kick", 20, atcommand_kick},  // + right click menu for GM "(name) force to quit"
-    {AtCommand_KickAll, "@kickall", 99, atcommand_kickall},
-    {AtCommand_AllSkills, "@allskills", 60, atcommand_allskills},
-    {AtCommand_QuestSkill, "@questskill", 40, atcommand_questskill},
-    {AtCommand_CharQuestSkill, "@charquestskill", 60,
-     atcommand_charquestskill},
-    {AtCommand_LostSkill, "@lostskill", 40, atcommand_lostskill},
-    {AtCommand_CharLostSkill, "@charlostskill", 60, atcommand_charlostskill},
-    {AtCommand_Party, "@party", 1, atcommand_party},
-    {AtCommand_Guild, "@guild", 50, atcommand_guild},
-    {AtCommand_AgitStart, "@agitstart", 60, atcommand_agitstart},
-    {AtCommand_AgitEnd, "@agitend", 60, atcommand_agitend},
-    {AtCommand_MapExit, "@mapexit", 99, atcommand_mapexit},
-    {AtCommand_IDSearch, "@idsearch", 60, atcommand_idsearch},
-    {AtCommand_MapMove, "@mapmove", 40, atcommand_warp},    // /mm command
-    {AtCommand_Broadcast, "@broadcast", 40, atcommand_broadcast},   // /b and /nb command
-    {AtCommand_LocalBroadcast, "@localbroadcast", 40, atcommand_localbroadcast},    // /lb and /nlb command
-    {AtCommand_RecallAll, "@recallall", 80, atcommand_recallall},
-    {AtCommand_CharSkReset, "@charskreset", 60, atcommand_charskreset},
-    {AtCommand_CharStReset, "@charstreset", 60, atcommand_charstreset},
-    {AtCommand_ReloadItemDB, "@reloaditemdb", 99, atcommand_reloaditemdb},  // admin command
-    {AtCommand_ReloadMobDB, "@reloadmobdb", 99, atcommand_reloadmobdb}, // admin command
-    {AtCommand_ReloadSkillDB, "@reloadskilldb", 99, atcommand_reloadskilldb},   // admin command
-    {AtCommand_ReloadScript, "@reloadscript", 99, atcommand_reloadscript},  // admin command
-    {AtCommand_ReloadGMDB, "@reloadgmdb", 99, atcommand_reloadgmdb},    // admin command
-    {AtCommand_CharReset, "@charreset", 60, atcommand_charreset},
-    {AtCommand_CharModel, "@charmodel", 50, atcommand_charmodel},
-    {AtCommand_CharSKPoint, "@charskpoint", 60, atcommand_charskpoint},
-    {AtCommand_CharSTPoint, "@charstpoint", 60, atcommand_charstpoint},
-    {AtCommand_CharZeny, "@charzeny", 60, atcommand_charzeny},
-    {AtCommand_MapInfo, "@mapinfo", 99, atcommand_mapinfo},
-    {AtCommand_Dye, "@dye", 40, atcommand_dye}, // by fritz
-    {AtCommand_Dye, "@ccolor", 40, atcommand_dye},  // by fritz
-    {AtCommand_HairStyle, "@hairstyle", 40, atcommand_hair_style},  // by fritz
-    {AtCommand_HairColor, "@haircolor", 40, atcommand_hair_color},  // by fritz
-    {AtCommand_AllStats, "@allstats", 60, atcommand_all_stats}, // by fritz
-    {AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex}, // by Yor
-    {AtCommand_CharBlock, "@block", 60, atcommand_char_block},  // by Yor
-    {AtCommand_CharUnBlock, "@unblock", 60, atcommand_char_unblock},    // by Yor
-    {AtCommand_CharBan, "@ban", 60, atcommand_char_ban},    // by Yor
-    {AtCommand_CharUnBan, "@unban", 60, atcommand_char_unban},  // by Yor
-    {AtCommand_MountPeco, "@mountpeco", 20, atcommand_mount_peco},  // by Valaris
-    {AtCommand_CharMountPeco, "@charmountpeco", 50, atcommand_char_mount_peco}, // by Yor
-    {AtCommand_GuildSpy, "@guildspy", 60, atcommand_guildspy},  // [Syrus22]
-    {AtCommand_PartySpy, "@partyspy", 60, atcommand_partyspy},  // [Syrus22]
-    {AtCommand_GuildRecall, "@guildrecall", 60, atcommand_guildrecall}, // by Yor
-    {AtCommand_PartyRecall, "@partyrecall", 60, atcommand_partyrecall}, // by Yor
-    {AtCommand_Enablenpc, "@enablenpc", 80, atcommand_enablenpc},   // []
-    {AtCommand_Disablenpc, "@disablenpc", 80, atcommand_disablenpc},    // []
-    {AtCommand_ServerTime, "@servertime", 0, atcommand_servertime}, // by Yor
-    {AtCommand_CharDelItem, "@chardelitem", 60, atcommand_chardelitem}, // by Yor
-    {AtCommand_ListNearby, "@listnearby", 40, atcommand_list_nearby},   // by Yor
-    {AtCommand_Jail, "@jail", 60, atcommand_jail},  // by Yor
-    {AtCommand_UnJail, "@unjail", 60, atcommand_unjail},    // by Yor
-    {AtCommand_Disguise, "@disguise", 20, atcommand_disguise},  // [Valaris]
-    {AtCommand_UnDisguise, "@undisguise", 20, atcommand_undisguise},    // by Yor
-    {AtCommand_IgnoreList, "@ignorelist", 0, atcommand_ignorelist}, // by Yor
-    {AtCommand_CharIgnoreList, "@charignorelist", 20, atcommand_charignorelist},    // by Yor
-    {AtCommand_IgnoreList, "@inall", 20, atcommand_inall},  // by Yor
-    {AtCommand_ExAll, "@exall", 20, atcommand_exall},   // by Yor
-    {AtCommand_CharDisguise, "@chardisguise", 60, atcommand_chardisguise},  // Kalaspuff
-    {AtCommand_CharUnDisguise, "@charundisguise", 60, atcommand_charundisguise},    // Kalaspuff
-    {AtCommand_EMail, "@email", 0, atcommand_email},    // by Yor
-    {AtCommand_Effect, "@effect", 40, atcommand_effect},    // by Apple
-    {AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list}, // by Yor
-    {AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list},    // by Yor
-    {AtCommand_Char_Cart_List, "@charcartlist", 40, atcommand_character_cart_list}, // by Yor
-    {AtCommand_Follow, "@follow", 10, atcommand_follow},    // by MouseJstr
-    {AtCommand_AddWarp, "@addwarp", 20, atcommand_addwarp}, // by MouseJstr
-    {AtCommand_SkillOn, "@skillon", 20, atcommand_skillon}, // by MouseJstr
-    {AtCommand_SkillOff, "@skilloff", 20, atcommand_skilloff},  // by MouseJstr
-    {AtCommand_Killer, "@killer", 60, atcommand_killer},    // by MouseJstr
-    {AtCommand_NpcMove, "@npcmove", 20, atcommand_npcmove}, // by MouseJstr
-    {AtCommand_Killable, "@killable", 40, atcommand_killable},  // by MouseJstr
-    {AtCommand_CharKillable, "@charkillable", 40, atcommand_charkillable},  // by MouseJstr
-    {AtCommand_Chareffect, "@chareffect", 40, atcommand_chareffect},    // MouseJstr
-    //{ AtCommand_Chardye,  "@chardye",  40, atcommand_chardye }, // MouseJstr
-    //{ AtCommand_Charhairstyle,  "@charhairstyle",  40, atcommand_charhairstyle }, // MouseJstr
-    //{ AtCommand_Charhaircolor,  "@charhaircolor",  40, atcommand_charhaircolor }, // MouseJstr
-    {AtCommand_Dropall, "@dropall", 40, atcommand_dropall}, // MouseJstr
-    {AtCommand_Chardropall, "@chardropall", 40, atcommand_chardropall}, // MouseJstr
-    {AtCommand_Storeall, "@storeall", 40, atcommand_storeall},  // MouseJstr
-    {AtCommand_Charstoreall, "@charstoreall", 40, atcommand_charstoreall},  // MouseJstr
-    {AtCommand_Skillid, "@skillid", 40, atcommand_skillid}, // MouseJstr
-    {AtCommand_Useskill, "@useskill", 40, atcommand_useskill},  // MouseJstr
-    {AtCommand_Rain, "@rain", 99, atcommand_rain},
-    {AtCommand_Snow, "@snow", 99, atcommand_snow},
-    {AtCommand_Sakura, "@sakura", 99, atcommand_sakura},
-    {AtCommand_Fog, "@fog", 99, atcommand_fog},
-    {AtCommand_Leaves, "@leaves", 99, atcommand_leaves},
-    //{ AtCommand_Shuffle,         "@shuffle",  99, atcommand_shuffle },
-    //{ AtCommand_Maintenance, "@maintenance", 99, atcommand_maintenance },
-    //{ AtCommand_Misceffect,    "@misceffect", 60, atcommand_misceffect },
-    {AtCommand_Summon, "@summon", 60, atcommand_summon},
-    {AtCommand_AdjGmLvl, "@adjgmlvl", 99, atcommand_adjgmlvl},
-    {AtCommand_AdjCmdLvl, "@adjcmdlvl", 99, atcommand_adjcmdlvl},
-    {AtCommand_Trade, "@trade", 60, atcommand_trade},
-    {AtCommand_UnMute, "@unmute", 60, atcommand_unmute},    // [Valaris]
-    {AtCommand_UnMute, "@charwipe", 60, atcommand_char_wipe},   // [Fate]
-    {AtCommand_SetMagic, "@setmagic", 99, atcommand_set_magic}, // [Fate]
-    {AtCommand_MagicInfo, "@magicinfo", 60, atcommand_magic_info},  // [Fate]
-    {AtCommand_Log, "@log", 60, atcommand_log}, // [Fate]
-    {AtCommand_Log, "@l", 60, atcommand_log},   // [Fate]
-    {AtCommand_Tee, "@tee", 60, atcommand_tee}, // [Fate]
-    {AtCommand_Tee, "@t", 60, atcommand_tee},   // [Fate]
-    {AtCommand_Invisible, "@invisible", 60, atcommand_invisible},   // [Fate]
-    {AtCommand_Visible, "@visible", 60, atcommand_visible}, // [Fate]
-    {AtCommand_IterateForward, "@hugo", 60, atcommand_iterate_forward_over_players},    // [Fate]
-    {AtCommand_IterateBackward, "@linus", 60, atcommand_iterate_backwards_over_players},    // [Fate]
-    {AtCommand_IterateBackward, "@sp-info", 40, atcommand_skillpool_info},  // [Fate]
-    {AtCommand_IterateBackward, "@sp-focus", 80, atcommand_skillpool_focus},    // [Fate]
-    {AtCommand_IterateBackward, "@sp-unfocus", 80, atcommand_skillpool_unfocus},    // [Fate]
-    {AtCommand_IterateBackward, "@skill-learn", 80, atcommand_skill_learn}, // [Fate]
-    {AtCommand_Wgm, "@wgm", 0, atcommand_wgm},
-    {AtCommand_IpCheck, "@ipcheck", 60, atcommand_ipcheck},
-    {AtCommand_DoomSpot, "@doomspot", 60, atcommand_doomspot},
-
-// add new commands before this line
-    {AtCommand_Unknown, NULL, 1, NULL}
-};
-
-/*====================================================
- * This function return the name of the job (by [Yor])
- *----------------------------------------------------
- */
-const char *job_name (int pc_class)
-{
-    switch (pc_class)
-    {
-        case 0:
-            return "Novice";
-        case 1:
-            return "Swordsman";
-        case 2:
-            return "Mage";
-        case 3:
-            return "Archer";
-        case 4:
-            return "Acolyte";
-        case 5:
-            return "Merchant";
-        case 6:
-            return "Thief";
-        case 7:
-            return "Knight";
-        case 8:
-            return "Priest";
-        case 9:
-            return "Wizard";
-        case 10:
-            return "Blacksmith";
-        case 11:
-            return "Hunter";
-        case 12:
-            return "Assassin";
-        case 13:
-            return "Knight 2";
-        case 14:
-            return "Crusader";
-        case 15:
-            return "Monk";
-        case 16:
-            return "Sage";
-        case 17:
-            return "Rogue";
-        case 18:
-            return "Alchemist";
-        case 19:
-            return "Bard";
-        case 20:
-            return "Dancer";
-        case 21:
-            return "Crusader 2";
-        case 22:
-            return "Wedding";
-        case 23:
-            return "Super Novice";
-        case 4001:
-            return "Novice High";
-        case 4002:
-            return "Swordsman High";
-        case 4003:
-            return "Mage High";
-        case 4004:
-            return "Archer High";
-        case 4005:
-            return "Acolyte High";
-        case 4006:
-            return "Merchant High";
-        case 4007:
-            return "Thief High";
-        case 4008:
-            return "Lord Knight";
-        case 4009:
-            return "High Priest";
-        case 4010:
-            return "High Wizard";
-        case 4011:
-            return "Whitesmith";
-        case 4012:
-            return "Sniper";
-        case 4013:
-            return "Assassin Cross";
-        case 4014:
-            return "Peko Knight";
-        case 4015:
-            return "Paladin";
-        case 4016:
-            return "Champion";
-        case 4017:
-            return "Professor";
-        case 4018:
-            return "Stalker";
-        case 4019:
-            return "Creator";
-        case 4020:
-            return "Clown";
-        case 4021:
-            return "Gypsy";
-        case 4022:
-            return "Peko Paladin";
-        case 4023:
-            return "Baby Novice";
-        case 4024:
-            return "Baby Swordsman";
-        case 4025:
-            return "Baby Mage";
-        case 4026:
-            return "Baby Archer";
-        case 4027:
-            return "Baby Acolyte";
-        case 4028:
-            return "Baby Merchant";
-        case 4029:
-            return "Baby Thief";
-        case 4030:
-            return "Baby Knight";
-        case 4031:
-            return "Baby Priest";
-        case 4032:
-            return "Baby Wizard";
-        case 4033:
-            return "Baby Blacksmith";
-        case 4034:
-            return "Baby Hunter";
-        case 4035:
-            return "Baby Assassin";
-        case 4036:
-            return "Baby Peco Knight";
-        case 4037:
-            return "Baby Crusader";
-        case 4038:
-            return "Baby Monk";
-        case 4039:
-            return "Baby Sage";
-        case 4040:
-            return "Baby Rogue";
-        case 4041:
-            return "Baby Alchemist";
-        case 4042:
-            return "Baby Bard";
-        case 4043:
-            return "Baby Dancer";
-        case 4044:
-            return "Baby Peco Crusader";
-        case 4045:
-            return "Super Baby";
-    }
-    return "Unknown Job";
-}
-
-//-----------------------------------------------------------
-// Return the message string of the specified number by [Yor]
-//-----------------------------------------------------------
-char *msg_txt (int msg_number)
-{
-    if (msg_number >= 0
-        && msg_number < (int) (sizeof (msg_table) / sizeof (msg_table[0]))
-        && msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0')
-        return msg_table[msg_number];
-
-    return "??";
-}
-
-//------------------------------------------------------------
-// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
-//------------------------------------------------------------
-int e_mail_check (unsigned char *email)
-{
-    char ch;
-    unsigned char *last_arobas;
-
-    // athena limits
-    if (strlen (email) < 3 || strlen (email) > 39)
-        return 0;
-
-    // part of RFC limits (official reference of e-mail description)
-    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
-        return 0;
-
-    if (email[strlen (email) - 1] == '.')
-        return 0;
-
-    last_arobas = strrchr (email, '@');
-
-    if (strstr (last_arobas, "@.") != NULL ||
-        strstr (last_arobas, "..") != NULL)
-        return 0;
-
-    for (ch = 1; ch < 32; ch++)
-    {
-        if (strchr (last_arobas, ch) != NULL)
-        {
-            return 0;
-            break;
-        }
-    }
-
-    if (strchr (last_arobas, ' ') != NULL ||
-        strchr (last_arobas, ';') != NULL)
-        return 0;
-
-    // all correct
-    return 1;
-}
-
-/*==========================================
- * get_atcommand_level @コマンドの必要レベルを取得
- *------------------------------------------
- */
-int get_atcommand_level (const AtCommandType type)
-{
-    int  i;
-
-    for (i = 0; atcommand_info[i].type != AtCommand_None; i++)
-        if (atcommand_info[i].type == type)
-            return atcommand_info[i].level;
-
-    return 100;                 // 100: command can not be used
-}
-
-/*========================================
- * At-command logging
- */
-void log_atcommand (struct map_session_data *sd, const char *fmt, ...)
-{
-    char message[512];
-    va_list ap;
-
-    va_start (ap, fmt);
-    vsnprintf (message, 511, fmt, ap);
-    va_end (ap);
-
-    gm_log ("%s(%d,%d) %s(%d) : %s", map[sd->bl.m].name, sd->bl.x,
-                sd->bl.y, sd->status.name, sd->status.account_id, message);
-}
-
-char *gm_logfile_name = NULL;
-/*==========================================
- * Log a timestamped line to GM log file
- *------------------------------------------
- */
-void gm_log (const char *fmt, ...)
-{
-    static int last_logfile_nr = 0;
-    static FILE *gm_logfile = NULL;
-    time_t time_v;
-    struct tm ctime;
-    int  month, year, logfile_nr;
-    char message[512];
-    va_list ap;
-
-    if (!gm_logfile_name)
-        return;
-
-    va_start (ap, fmt);
-    vsnprintf (message, 511, fmt, ap);
-    va_end (ap);
-
-    time (&time_v);
-    gmtime_r (&time_v, &ctime);
-
-    year = ctime.tm_year + 1900;
-    month = ctime.tm_mon + 1;
-    logfile_nr = (year * 12) + month;
-
-    if (logfile_nr != last_logfile_nr)
-    {
-        char *fullname = (char *)malloc (strlen (gm_logfile_name) + 10);
-        sprintf (fullname, "%s.%04d-%02d", gm_logfile_name, year, month);
-
-        if (gm_logfile)
-            fclose_ (gm_logfile);
-
-        gm_logfile = fopen_ (fullname, "a");
-        free (fullname);
-
-        if (!gm_logfile)
-        {
-            perror ("GM log file");
-            gm_logfile_name = NULL;
-        }
-        last_logfile_nr = logfile_nr;
-    }
-
-    fprintf (gm_logfile, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
-             year, month, ctime.tm_mday, ctime.tm_hour,
-             ctime.tm_min, ctime.tm_sec, message);
-
-    fflush (gm_logfile);
-}
-
-/*==========================================
- *is_atcommand @コマンドに存在するかどうか確認する
- *------------------------------------------
- */
-AtCommandType
-is_atcommand (const int fd, struct map_session_data *sd, const char *message,
-              int gmlvl)
-{
-    AtCommandInfo info;
-    AtCommandType type;
-
-    nullpo_retr (AtCommand_None, sd);
-
-    if (!message || !*message)
-        return AtCommand_None;
-
-    memset (&info, 0, sizeof (info));
-
-    type = atcommand (gmlvl > 0 ? gmlvl : pc_isGM (sd), message, &info);
-    if (type != AtCommand_None)
-    {
-        char command[100];
-        char output[200];
-        const char *str = message;
-        const char *p = message;
-        memset (command, '\0', sizeof (command));
-        memset (output, '\0', sizeof (output));
-        while (*p && !isspace (*p))
-            p++;
-        if (p - str >= sizeof (command))    // too long
-            return AtCommand_Unknown;
-        strncpy (command, str, p - str);
-        while (isspace (*p))
-            p++;
-
-        if (type == AtCommand_Unknown || info.proc == NULL)
-        {
-            sprintf (output, msg_table[153], command);  // %s is Unknown Command.
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            if (info.proc (fd, sd, command, p) != 0)
-            {
-                // Command can not be executed
-                sprintf (output, msg_table[154], command);  // %s failed.
-                clif_displaymessage (fd, output);
-            }
-            else
-            {
-                if (get_atcommand_level (type) != 0)    // Don't log level 0 commands
-                    log_atcommand (sd, "%s %s", command, p);
-            }
-        }
-
-        return info.type;
-    }
-
-    return AtCommand_None;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-AtCommandType atcommand (const int level, const char *message,
-                         struct AtCommandInfo * info)
-{
-    char *p = (char *) message; // it's 'char' and not 'const char' to have possibility to modify the first character if necessary
-
-    if (!info)
-        return AtCommand_None;
-    if (battle_config.atc_gmonly != 0 && !level)    // level = pc_isGM(sd)
-        return AtCommand_None;
-    if (!p || !*p)
-    {
-        fprintf (stderr, "at command message is empty\n");
-        return AtCommand_None;
-    }
-
-    if (*p == command_symbol)
-    {                           // check first char.
-        char command[101];
-        int  i = 0;
-        memset (info, 0, sizeof (AtCommandInfo));
-        sscanf (p, "%100s", command);
-        command[sizeof (command) - 1] = '\0';
-
-        while (atcommand_info[i].type != AtCommand_Unknown)
-        {
-            if (strcasecmp (command + 1, atcommand_info[i].command + 1) == 0
-                && level >= atcommand_info[i].level)
-            {
-                p[0] = atcommand_info[i].command[0];    // set correct first symbol for after.
-                break;
-            }
-            i++;
-        }
-
-        if (atcommand_info[i].type == AtCommand_Unknown)
-        {
-            // doesn't return Unknown if player is normal player (display the text, not display: unknown command)
-            if (level == 0)
-                return AtCommand_None;
-            else
-                return AtCommand_Unknown;
-        }
-        memcpy (info, &atcommand_info[i], sizeof atcommand_info[i]);
-    }
-    else
-    {
-        return AtCommand_None;
-    }
-
-    return info->type;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int atkillmonster_sub (struct block_list *bl, va_list ap)
-{
-    int  flag = va_arg (ap, int);
-
-    nullpo_retr (0, bl);
-
-    if (flag)
-        mob_damage (NULL, (struct mob_data *) bl,
-                    ((struct mob_data *) bl)->hp, 2);
-    else
-        mob_delete ((struct mob_data *) bl);
-
-    return 0;
-}
-
-/*==========================================
- * Read Message Data
- *------------------------------------------
- */
-int msg_config_read (const char *cfgName)
-{
-    int  msg_number;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    if ((fp = fopen_ (cfgName, "r")) == NULL)
-    {
-        printf ("Messages file not found: %s\n", cfgName);
-        return 1;
-    }
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
-        {
-            if (strcasecmp (w1, "import") == 0)
-            {
-                msg_config_read (w2);
-            }
-            else
-            {
-                msg_number = atoi (w1);
-                if (msg_number >= 0
-                    && msg_number <
-                    (int) (sizeof (msg_table) / sizeof (msg_table[0])))
-                    strcpy (msg_table[msg_number], w2);
-                //  printf("message #%d: '%s'.\n", msg_number, msg_table[msg_number]);
-            }
-        }
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static AtCommandInfo *get_atcommandinfo_byname (const char *name)
-{
-    int  i;
-
-    for (i = 0; atcommand_info[i].type != AtCommand_Unknown; i++)
-        if (strcasecmp (atcommand_info[i].command + 1, name) == 0)
-            return &atcommand_info[i];
-
-    return NULL;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_config_read (const char *cfgName)
-{
-    char line[1024], w1[1024], w2[1024];
-    AtCommandInfo *p;
-    FILE *fp;
-
-    if ((fp = fopen_ (cfgName, "r")) == NULL)
-    {
-        printf ("At commands configuration file not found: %s\n", cfgName);
-        return 1;
-    }
-
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-
-        if (sscanf (line, "%1023[^:]:%1023s", w1, w2) != 2)
-            continue;
-        p = get_atcommandinfo_byname (w1);
-        if (p != NULL)
-        {
-            p->level = atoi (w2);
-            if (p->level > 100)
-                p->level = 100;
-            else if (p->level < 0)
-                p->level = 0;
-        }
-
-        if (strcasecmp (w1, "import") == 0)
-            atcommand_config_read (w2);
-        else if (strcasecmp (w1, "command_symbol") == 0 && w2[0] > 31 && w2[0] != '/' &&   // symbol of standard ragnarok GM commands
-                 w2[0] != '%')  // symbol of party chat speaking
-            command_symbol = w2[0];
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-/*==========================================
-// @ command processing functions
- *------------------------------------------
- */
-
-/*==========================================
- * @setup - Safely set a chars levels and warp them to a special place
- * TAW Specific
- *------------------------------------------
- */
-int atcommand_setup (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char buf[256];
-    char character[100];
-    int  level = 1;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &level, character) < 2)
-    {
-        clif_displaymessage (fd, "Usage: @setup <level> <char name>");
-        return -1;
-    }
-    level--;
-
-    snprintf (buf, 255, "-255 %s", character);
-    atcommand_character_baselevel (fd, sd, "@charbaselvl", buf);
-
-    snprintf (buf, 255, "%d %s", level, character);
-    atcommand_character_baselevel (fd, sd, "@charbaselvl", buf);
-
-    // Emote skill
-    snprintf (buf, 255, "1 1 %s", character);
-    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
-
-    // Trade skill
-    snprintf (buf, 255, "2 1 %s", character);
-    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
-
-    // Party skill
-    snprintf (buf, 255, "2 2 %s", character);
-    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
-
-    snprintf (buf, 255, "018-1.gat 24 98 %s", character);
-    atcommand_charwarp (fd, sd, "@charwarp", buf);
-
-    return (0);
-
-}
-
-/*==========================================
- * @rura+
- *------------------------------------------
- */
-int atcommand_charwarp (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char map_name[100];
-    char character[100];
-    int  x = 0, y = 0;
-    struct map_session_data *pl_sd;
-    int  m;
-
-    memset (map_name, '\0', sizeof (map_name));
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d %d %99[^\n]", map_name, &x, &y,
-                   character) < 4)
-    {
-        clif_displaymessage (fd,
-                             "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>");
-        return -1;
-    }
-
-    if (x <= 0)
-        x = MRAND (399) + 1;
-    if (y <= 0)
-        y = MRAND (399) + 1;
-    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-        strcat (map_name, ".gat");
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can rura+ only lower or same GM level
-            if (x > 0 && x < 800 && y > 0 && y < 800)
-            {
-                m = map_mapname2mapid (map_name);
-                if (m >= 0 && map[m].flag.nowarpto
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                {
-                    clif_displaymessage (fd,
-                                         "You are not authorised to warp someone to this map.");
-                    return -1;
-                }
-                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                {
-                    clif_displaymessage (fd,
-                                         "You are not authorised to warp this player from its actual map.");
-                    return -1;
-                }
-                if (pc_setpos (pl_sd, map_name, x, y, 3) == 0)
-                {
-                    clif_displaymessage (pl_sd->fd, msg_table[0]);  // Warped.
-                    clif_displaymessage (fd, msg_table[15]);    // Player warped (message sends to player too).
-                }
-                else
-                {
-                    clif_displaymessage (fd, msg_table[1]); // Map not found.
-                    return -1;
-                }
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_warp (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char map_name[100];
-    int  x = 0, y = 0;
-    int  m;
-
-    memset (map_name, '\0', sizeof (map_name));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d %d", map_name, &x, &y) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a map (usage: @warp <mapname> <x> <y>).");
-        return -1;
-    }
-
-    if (x <= 0)
-        x = MRAND (399) + 1;
-    if (y <= 0)
-        y = MRAND (399) + 1;
-
-    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-        strcat (map_name, ".gat");
-
-    if (x > 0 && x < 800 && y > 0 && y < 800)
-    {
-        m = map_mapname2mapid (map_name);
-        if (m >= 0 && map[m].flag.nowarpto
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you to this map.");
-            return -1;
-        }
-        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you from your actual map.");
-            return -1;
-        }
-        if (pc_setpos (sd, map_name, x, y, 3) == 0)
-            clif_displaymessage (fd, msg_table[0]); // Warped.
-        else
-        {
-            clif_displaymessage (fd, msg_table[1]); // Map not found.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_where (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (sscanf (message, "%99[^\n]", character) < 1)
-        strcpy (character, sd->status.name);
-
-    if ((pl_sd = map_nick2sd (character)) != NULL &&
-        !((battle_config.hide_GM_session
-           || (pl_sd->status.option & OPTION_HIDE))
-          && (pc_isGM (pl_sd) > pc_isGM (sd))))
-    {                           // you can look only lower or same level
-        sprintf (output, "%s: %s (%d,%d)", pl_sd->status.name, pl_sd->mapname,
-                 pl_sd->bl.x, pl_sd->bl.y);
-        clif_displaymessage (fd, output);
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_goto (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you to the map of this player.");
-            return -1;
-        }
-        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you from your actual map.");
-            return -1;
-        }
-        pc_setpos (sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
-        sprintf (output, msg_table[4], character);  // Jump to %s
-        clif_displaymessage (fd, output);
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_jump (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char output[200];
-    int  x = 0, y = 0;
-
-    memset (output, '\0', sizeof (output));
-
-    sscanf (message, "%d %d", &x, &y);
-
-    if (x <= 0)
-        x = MRAND (399) + 1;
-    if (y <= 0)
-        y = MRAND (399) + 1;
-    if (x > 0 && x < 800 && y > 0 && y < 800)
-    {
-        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you to your actual map.");
-            return -1;
-        }
-        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-        {
-            clif_displaymessage (fd,
-                                 "You are not authorised to warp you from your actual map.");
-            return -1;
-        }
-        pc_setpos (sd, sd->mapname, x, y, 3);
-        sprintf (output, msg_table[5], x, y);   // Jump to %d %d
-        clif_displaymessage (fd, output);
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_who (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i, j, count;
-    int  pl_GM_level, GM_level;
-    char match_text[100];
-    char player_name[24];
-
-    memset (output, '\0', sizeof (output));
-    memset (match_text, '\0', sizeof (match_text));
-    memset (player_name, '\0', sizeof (player_name));
-
-    if (sscanf (message, "%99[^\n]", match_text) < 1)
-        strcpy (match_text, "");
-    for (j = 0; match_text[j]; j++)
-        match_text[j] = tolower (match_text[j]);
-
-    count = 0;
-    GM_level = pc_isGM (sd);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            pl_GM_level = pc_isGM (pl_sd);
-            if (!
-                ((battle_config.hide_GM_session
-                  || (pl_sd->status.option & OPTION_HIDE))
-                 && (pl_GM_level > GM_level)))
-            {                   // you can look only lower or same level
-                memcpy (player_name, pl_sd->status.name, 24);
-                for (j = 0; player_name[j]; j++)
-                    player_name[j] = tolower (player_name[j]);
-                if (strstr (player_name, match_text) != NULL)
-                {               // search with no case sensitive
-                    if (pl_GM_level > 0)
-                        sprintf (output,
-                                 "Name: %s (GM:%d) | Location: %s %d %d",
-                                 pl_sd->status.name, pl_GM_level,
-                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
-                    else
-                        sprintf (output, "Name: %s | Location: %s %d %d",
-                                 pl_sd->status.name, pl_sd->mapname,
-                                 pl_sd->bl.x, pl_sd->bl.y);
-                    clif_displaymessage (fd, output);
-                    count++;
-                }
-            }
-        }
-    }
-
-    if (count == 0)
-        clif_displaymessage (fd, msg_table[28]);    // No player found.
-    else if (count == 1)
-        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
-    else
-    {
-        sprintf (output, msg_table[30], count); // %d players found.
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_whogroup (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char temp0[100];
-    char temp1[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i, j, count;
-    int  pl_GM_level, GM_level;
-    char match_text[100];
-    char player_name[24];
-    struct guild *g;
-    struct party *p;
-
-    memset (temp0, '\0', sizeof (temp0));
-    memset (temp1, '\0', sizeof (temp1));
-    memset (output, '\0', sizeof (output));
-    memset (match_text, '\0', sizeof (match_text));
-    memset (player_name, '\0', sizeof (player_name));
-
-    if (sscanf (message, "%99[^\n]", match_text) < 1)
-        strcpy (match_text, "");
-    for (j = 0; match_text[j]; j++)
-        match_text[j] = tolower (match_text[j]);
-
-    count = 0;
-    GM_level = pc_isGM (sd);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            pl_GM_level = pc_isGM (pl_sd);
-            if (!
-                ((battle_config.hide_GM_session
-                  || (pl_sd->status.option & OPTION_HIDE))
-                 && (pl_GM_level > GM_level)))
-            {                   // you can look only lower or same level
-                memcpy (player_name, pl_sd->status.name, 24);
-                for (j = 0; player_name[j]; j++)
-                    player_name[j] = tolower (player_name[j]);
-                if (strstr (player_name, match_text) != NULL)
-                {               // search with no case sensitive
-                    g = guild_search (pl_sd->status.guild_id);
-                    if (g == NULL)
-                        sprintf (temp1, "None");
-                    else
-                        sprintf (temp1, "%s", g->name);
-                    p = party_search (pl_sd->status.party_id);
-                    if (p == NULL)
-                        sprintf (temp0, "None");
-                    else
-                        sprintf (temp0, "%s", p->name);
-                    if (pl_GM_level > 0)
-                        sprintf (output,
-                                 "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'",
-                                 pl_sd->status.name, pl_GM_level, temp0,
-                                 temp1);
-                    else
-                        sprintf (output,
-                                 "Name: %s | Party: '%s' | Guild: '%s'",
-                                 pl_sd->status.name, temp0, temp1);
-                    clif_displaymessage (fd, output);
-                    count++;
-                }
-            }
-        }
-    }
-
-    if (count == 0)
-        clif_displaymessage (fd, msg_table[28]);    // No player found.
-    else if (count == 1)
-        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
-    else
-    {
-        sprintf (output, msg_table[30], count); // %d players found.
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_whomap (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i, count;
-    int  pl_GM_level, GM_level;
-    int  map_id;
-    char map_name[100];
-
-    memset (output, '\0', sizeof (output));
-    memset (map_name, '\0', sizeof (map_name));
-
-    if (!message || !*message)
-        map_id = sd->bl.m;
-    else
-    {
-        sscanf (message, "%99s", map_name);
-        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-            strcat (map_name, ".gat");
-        if ((map_id = map_mapname2mapid (map_name)) < 0)
-            map_id = sd->bl.m;
-    }
-
-    count = 0;
-    GM_level = pc_isGM (sd);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            pl_GM_level = pc_isGM (pl_sd);
-            if (!
-                ((battle_config.hide_GM_session
-                  || (pl_sd->status.option & OPTION_HIDE))
-                 && (pl_GM_level > GM_level)))
-            {                   // you can look only lower or same level
-                if (pl_sd->bl.m == map_id)
-                {
-                    if (pl_GM_level > 0)
-                        sprintf (output,
-                                 "Name: %s (GM:%d) | Location: %s %d %d",
-                                 pl_sd->status.name, pl_GM_level,
-                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
-                    else
-                        sprintf (output, "Name: %s | Location: %s %d %d",
-                                 pl_sd->status.name, pl_sd->mapname,
-                                 pl_sd->bl.x, pl_sd->bl.y);
-                    clif_displaymessage (fd, output);
-                    count++;
-                }
-            }
-        }
-    }
-
-    if (count == 0)
-        sprintf (output, msg_table[54], map[map_id].name);  // No player found in map '%s'.
-    else if (count == 1)
-        sprintf (output, msg_table[55], map[map_id].name);  // 1 player found in map '%s'.
-    else
-    {
-        sprintf (output, msg_table[56], count, map[map_id].name);   // %d players found in map '%s'.
-    }
-    clif_displaymessage (fd, output);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_whomapgroup (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    char temp0[100];
-    char temp1[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i, count;
-    int  pl_GM_level, GM_level;
-    int  map_id = 0;
-    char map_name[100];
-    struct guild *g;
-    struct party *p;
-
-    memset (temp0, '\0', sizeof (temp0));
-    memset (temp1, '\0', sizeof (temp1));
-    memset (output, '\0', sizeof (output));
-    memset (map_name, '\0', sizeof (map_name));
-
-    if (!message || !*message)
-        map_id = sd->bl.m;
-    else
-    {
-        sscanf (message, "%99s", map_name);
-        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-            strcat (map_name, ".gat");
-        if ((map_id = map_mapname2mapid (map_name)) < 0)
-            map_id = sd->bl.m;
-    }
-
-    count = 0;
-    GM_level = pc_isGM (sd);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            pl_GM_level = pc_isGM (pl_sd);
-            if (!
-                ((battle_config.hide_GM_session
-                  || (pl_sd->status.option & OPTION_HIDE))
-                 && (pl_GM_level > GM_level)))
-            {                   // you can look only lower or same level
-                if (pl_sd->bl.m == map_id)
-                {
-                    g = guild_search (pl_sd->status.guild_id);
-                    if (g == NULL)
-                        sprintf (temp1, "None");
-                    else
-                        sprintf (temp1, "%s", g->name);
-                    p = party_search (pl_sd->status.party_id);
-                    if (p == NULL)
-                        sprintf (temp0, "None");
-                    else
-                        sprintf (temp0, "%s", p->name);
-                    if (pl_GM_level > 0)
-                        sprintf (output,
-                                 "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'",
-                                 pl_sd->status.name, pl_GM_level, temp0,
-                                 temp1);
-                    else
-                        sprintf (output,
-                                 "Name: %s | Party: '%s' | Guild: '%s'",
-                                 pl_sd->status.name, temp0, temp1);
-                    clif_displaymessage (fd, output);
-                    count++;
-                }
-            }
-        }
-    }
-
-    if (count == 0)
-        sprintf (output, msg_table[54], map[map_id].name);  // No player found in map '%s'.
-    else if (count == 1)
-        sprintf (output, msg_table[55], map[map_id].name);  // 1 player found in map '%s'.
-    else
-    {
-        sprintf (output, msg_table[56], count, map[map_id].name);   // %d players found in map '%s'.
-    }
-    clif_displaymessage (fd, output);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_whogm (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char temp0[100];
-    char temp1[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i, j, count;
-    int  pl_GM_level, GM_level;
-    char match_text[100];
-    char player_name[24];
-    struct guild *g;
-    struct party *p;
-
-    memset (temp0, '\0', sizeof (temp0));
-    memset (temp1, '\0', sizeof (temp1));
-    memset (output, '\0', sizeof (output));
-    memset (match_text, '\0', sizeof (match_text));
-    memset (player_name, '\0', sizeof (player_name));
-
-    if (sscanf (message, "%99[^\n]", match_text) < 1)
-        strcpy (match_text, "");
-    for (j = 0; match_text[j]; j++)
-        match_text[j] = tolower (match_text[j]);
-
-    count = 0;
-    GM_level = pc_isGM (sd);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            pl_GM_level = pc_isGM (pl_sd);
-            if (pl_GM_level > 0)
-            {
-                if (!
-                    ((battle_config.hide_GM_session
-                      || (pl_sd->status.option & OPTION_HIDE))
-                     && (pl_GM_level > GM_level)))
-                {               // you can look only lower or same level
-                    memcpy (player_name, pl_sd->status.name, 24);
-                    for (j = 0; player_name[j]; j++)
-                        player_name[j] = tolower (player_name[j]);
-                    if (strstr (player_name, match_text) != NULL)
-                    {           // search with no case sensitive
-                        sprintf (output,
-                                 "Name: %s (GM:%d) | Location: %s %d %d",
-                                 pl_sd->status.name, pl_GM_level,
-                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
-                        clif_displaymessage (fd, output);
-                        sprintf (output,
-                                 "       BLvl: %d | Job: %s (Lvl: %d)",
-                                 pl_sd->status.base_level,
-                                 job_name (pl_sd->status.pc_class),
-                                 pl_sd->status.job_level);
-                        clif_displaymessage (fd, output);
-                        g = guild_search (pl_sd->status.guild_id);
-                        if (g == NULL)
-                            sprintf (temp1, "None");
-                        else
-                            sprintf (temp1, "%s", g->name);
-                        p = party_search (pl_sd->status.party_id);
-                        if (p == NULL)
-                            sprintf (temp0, "None");
-                        else
-                            sprintf (temp0, "%s", p->name);
-                        sprintf (output, "       Party: '%s' | Guild: '%s'",
-                                 temp0, temp1);
-                        clif_displaymessage (fd, output);
-                        count++;
-                    }
-                }
-            }
-        }
-    }
-
-    if (count == 0)
-        clif_displaymessage (fd, msg_table[150]);   // No GM found.
-    else if (count == 1)
-        clif_displaymessage (fd, msg_table[151]);   // 1 GM found.
-    else
-    {
-        sprintf (output, msg_table[152], count);    // %d GMs found.
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_save (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    nullpo_retr (-1, sd);
-
-    pc_setsavepoint (sd, sd->mapname, sd->bl.x, sd->bl.y);
-    pc_makesavestatus (sd);
-    chrif_save (sd);
-    clif_displaymessage (fd, msg_table[6]); // Character data respawn point saved.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_load (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  m;
-
-    m = map_mapname2mapid (sd->status.save_point.map);
-    if (m >= 0 && map[m].flag.nowarpto
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp you to your save map.");
-        return -1;
-    }
-    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp you from your actual map.");
-        return -1;
-    }
-
-    pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
-               sd->status.save_point.y, 0);
-    clif_displaymessage (fd, msg_table[7]); // Warping to respawn point.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_speed (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char output[200];
-    int  speed;
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message)
-    {
-        sprintf (output,
-                 "Please, enter a speed value (usage: @speed <%d-%d>).",
-                 MIN_WALK_SPEED, MAX_WALK_SPEED);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    speed = atoi (message);
-    if (speed >= MIN_WALK_SPEED && speed <= MAX_WALK_SPEED)
-    {
-        sd->speed = speed;
-        //sd->walktimer = x;
-        //この文を追加 by れ
-        clif_updatestatus (sd, SP_SPEED);
-        clif_displaymessage (fd, msg_table[8]); // Speed changed.
-    }
-    else
-    {
-        sprintf (output,
-                 "Please, enter a valid speed value (usage: @speed <%d-%d>).",
-                 MIN_WALK_SPEED, MAX_WALK_SPEED);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_storage (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct storage *stor;       //changes from Freya/Yor
-    nullpo_retr (-1, sd);
-
-    if (sd->state.storage_flag)
-    {
-        clif_displaymessage (fd, msg_table[250]);
-        return -1;
-    }
-
-    if ((stor = account2storage2 (sd->status.account_id)) != NULL
-        && stor->storage_status == 1)
-    {
-        clif_displaymessage (fd, msg_table[250]);
-        return -1;
-    }
-
-    storage_storageopen (sd);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_guildstorage (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    struct storage *stor;       //changes from Freya/Yor
-    nullpo_retr (-1, sd);
-
-    if (sd->status.guild_id > 0)
-    {
-        if (sd->state.storage_flag)
-        {
-            clif_displaymessage (fd, msg_table[251]);
-            return -1;
-        }
-        if ((stor = account2storage2 (sd->status.account_id)) != NULL
-            && stor->storage_status == 1)
-        {
-            clif_displaymessage (fd, msg_table[251]);
-            return -1;
-        }
-        storage_guild_storageopen (sd);
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[252]);
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_option (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    int  param1 = 0, param2 = 0, param3 = 0;
-    nullpo_retr (-1, sd);
-
-    if (!message || !*message
-        || sscanf (message, "%d %d %d", &param1, &param2, &param3) < 1
-        || param1 < 0 || param2 < 0 || param3 < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>).");
-        return -1;
-    }
-
-    sd->opt1 = param1;
-    sd->opt2 = param2;
-    if (!(sd->status.option & CART_MASK) && param3 & CART_MASK)
-    {
-        clif_cart_itemlist (sd);
-        clif_cart_equiplist (sd);
-        clif_updatestatus (sd, SP_CARTINFO);
-    }
-    sd->status.option = param3;
-    // fix pecopeco display
-    if (sd->status.pc_class == 13 || sd->status.pc_class == 21
-        || sd->status.pc_class == 4014 || sd->status.pc_class == 4022)
-    {
-        if (!pc_isriding (sd))
-        {                       // sd have the new value...
-            if (sd->status.pc_class == 13)
-                sd->status.pc_class = sd->view_class = 7;
-            else if (sd->status.pc_class == 21)
-                sd->status.pc_class = sd->view_class = 14;
-            else if (sd->status.pc_class == 4014)
-                sd->status.pc_class = sd->view_class = 4008;
-            else if (sd->status.pc_class == 4022)
-                sd->status.pc_class = sd->view_class = 4015;
-        }
-    }
-    else
-    {
-        if (pc_isriding (sd))
-        {                       // sd have the new value...
-            if (sd->disguise > 0)
-            {                   // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
-                sd->status.option &= ~0x0020;
-            }
-            else
-            {
-                if (sd->status.pc_class == 7)
-                    sd->status.pc_class = sd->view_class = 13;
-                else if (sd->status.pc_class == 14)
-                    sd->status.pc_class = sd->view_class = 21;
-                else if (sd->status.pc_class == 4008)
-                    sd->status.pc_class = sd->view_class = 4014;
-                else if (sd->status.pc_class == 4015)
-                    sd->status.pc_class = sd->view_class = 4022;
-                else
-                    sd->status.option &= ~0x0020;
-            }
-        }
-    }
-
-    clif_changeoption (&sd->bl);
-    pc_calcstatus (sd, 0);
-    clif_displaymessage (fd, msg_table[9]); // Options changed.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_hide (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    if (sd->status.option & OPTION_HIDE)
-    {
-        sd->status.option &= ~OPTION_HIDE;
-        clif_displaymessage (fd, msg_table[10]);    // Invisible: Off
-    }
-    else
-    {
-        sd->status.option |= OPTION_HIDE;
-        clif_displaymessage (fd, msg_table[11]);    // Invisible: On
-    }
-    clif_changeoption (&sd->bl);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_die (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    pc_damage (NULL, sd, sd->status.hp + 1);
-    clif_displaymessage (fd, msg_table[13]);    // A pity! You've died.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_kill (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @kill <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can kill only lower or same level
-            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
-            clif_displaymessage (fd, msg_table[14]);    // Character killed.
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_alive (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    sd->status.hp = sd->status.max_hp;
-    sd->status.sp = sd->status.max_sp;
-    pc_setstand (sd);
-    if (battle_config.pc_invincible_time > 0)
-        pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
-    clif_updatestatus (sd, SP_HP);
-    clif_updatestatus (sd, SP_SP);
-    clif_resurrection (&sd->bl, 1);
-    clif_displaymessage (fd, msg_table[16]);    // You've been revived! It's a miracle!
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_kami (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a message (usage: @kami <message>).");
-        return -1;
-    }
-
-    sscanf (message, "%199[^\n]", output);
-    intif_GMmessage (output, strlen (output) + 1, 0);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_heal (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  hp = 0, sp = 0;        // [Valaris] thanks to fov
-
-    sscanf (message, "%d %d", &hp, &sp);
-
-    if (hp == 0 && sp == 0)
-    {
-        hp = sd->status.max_hp - sd->status.hp;
-        sp = sd->status.max_sp - sd->status.sp;
-    }
-    else
-    {
-        if (hp > 0 && (hp > sd->status.max_hp || hp > (sd->status.max_hp - sd->status.hp))) // fix positiv overflow
-            hp = sd->status.max_hp - sd->status.hp;
-        else if (hp < 0 && (hp < -sd->status.max_hp || hp < (1 - sd->status.hp)))   // fix negativ overflow
-            hp = 1 - sd->status.hp;
-        if (sp > 0 && (sp > sd->status.max_sp || sp > (sd->status.max_sp - sd->status.sp))) // fix positiv overflow
-            sp = sd->status.max_sp - sd->status.sp;
-        else if (sp < 0 && (sp < -sd->status.max_sp || sp < (1 - sd->status.sp)))   // fix negativ overflow
-            sp = 1 - sd->status.sp;
-    }
-
-    if (hp > 0)                 // display like heal
-        clif_heal (fd, SP_HP, hp);
-    else if (hp < 0)            // display like damage
-        clif_damage (&sd->bl, &sd->bl, gettick (), 0, 0, -hp, 0, 4, 0);
-    if (sp > 0)                 // no display when we lost SP
-        clif_heal (fd, SP_SP, sp);
-
-    if (hp != 0 || sp != 0)
-    {
-        pc_heal (sd, hp, sp);
-        if (hp >= 0 && sp >= 0)
-            clif_displaymessage (fd, msg_table[17]);    // HP, SP recovered.
-        else
-            clif_displaymessage (fd, msg_table[156]);   // HP or/and SP modified.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[157]);   // HP and SP are already with the good value.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @item command (usage: @item <name/id_of_item> <quantity>)
- *------------------------------------------
- */
-int atcommand_item (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char item_name[100];
-    int  number = 0, item_id, flag;
-    struct item item_tmp;
-    struct item_data *item_data;
-    int  get_count, i;
-
-    memset (item_name, '\0', sizeof (item_name));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d", item_name, &number) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter an item name/id (usage: @item <item name or ID> [quantity]).");
-        return -1;
-    }
-
-    if (number <= 0)
-        number = 1;
-
-    item_id = 0;
-    if ((item_data = itemdb_searchname (item_name)) != NULL ||
-        (item_data = itemdb_exists (atoi (item_name))) != NULL)
-        item_id = item_data->nameid;
-
-    if (item_id >= 500)
-    {
-        get_count = number;
-        if (item_data->type == 4 || item_data->type == 5 ||
-            item_data->type == 7 || item_data->type == 8)
-        {
-            get_count = 1;
-        }
-        for (i = 0; i < number; i += get_count)
-        {
-            memset (&item_tmp, 0, sizeof (item_tmp));
-            item_tmp.nameid = item_id;
-            item_tmp.identify = 1;
-            if ((flag =
-                 pc_additem ((struct map_session_data *) sd, &item_tmp,
-                             get_count)))
-                clif_additem ((struct map_session_data *) sd, 0, 0, flag);
-        }
-        clif_displaymessage (fd, msg_table[18]);    // Item created.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[19]);    // Invalid item ID or name.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_itemreset (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    int  i;
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].amount
-            && sd->status.inventory[i].equip == 0)
-            pc_delitem (sd, i, sd->status.inventory[i].amount, 0);
-    }
-    clif_displaymessage (fd, msg_table[20]);    // All of your items have been removed.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_itemcheck (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    pc_checkitem (sd);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_baselevelup (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    int  level, i;
-
-    if (!message || !*message || (level = atoi (message)) == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a level adjustement (usage: @blvl <number of levels>).");
-        return -1;
-    }
-
-    if (level > 0)
-    {
-        if (sd->status.base_level == battle_config.maximum_level)
-        {                       // check for max level by Valaris
-            clif_displaymessage (fd, msg_table[47]);    // Base level can't go any higher.
-            return -1;
-        }                       // End Addition
-        if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level))   // fix positiv overflow
-            level = battle_config.maximum_level - sd->status.base_level;
-        for (i = 1; i <= level; i++)
-            sd->status.status_point += (sd->status.base_level + i + 14) / 4;
-        sd->status.base_level += level;
-        clif_updatestatus (sd, SP_BASELEVEL);
-        clif_updatestatus (sd, SP_NEXTBASEEXP);
-        clif_updatestatus (sd, SP_STATUSPOINT);
-        pc_calcstatus (sd, 0);
-        pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
-        clif_misceffect (&sd->bl, 0);
-        clif_displaymessage (fd, msg_table[21]);    // Base level raised.
-    }
-    else
-    {
-        if (sd->status.base_level == 1)
-        {
-            clif_displaymessage (fd, msg_table[158]);   // Base level can't go any lower.
-            return -1;
-        }
-        if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level))    // fix negativ overflow
-            level = 1 - sd->status.base_level;
-        if (sd->status.status_point > 0)
-        {
-            for (i = 0; i > level; i--)
-                sd->status.status_point -=
-                    (sd->status.base_level + i + 14) / 4;
-            if (sd->status.status_point < 0)
-                sd->status.status_point = 0;
-            clif_updatestatus (sd, SP_STATUSPOINT);
-        }                       // to add: remove status points from stats
-        sd->status.base_level += level;
-        clif_updatestatus (sd, SP_BASELEVEL);
-        clif_updatestatus (sd, SP_NEXTBASEEXP);
-        pc_calcstatus (sd, 0);
-        clif_displaymessage (fd, msg_table[22]);    // Base level lowered.
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_joblevelup (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    int  up_level = 50, level;
-
-    if (!message || !*message || (level = atoi (message)) == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a level adjustement (usage: @jlvl <number of levels>).");
-        return -1;
-    }
-
-    if (sd->status.pc_class == 0 || sd->status.pc_class == 4001)
-        up_level -= 40;
-    else if ((sd->status.pc_class > 4007 && sd->status.pc_class < 4024)
-             || sd->status.pc_class == 23)
-        up_level += 20;
-
-    if (level > 0)
-    {
-        if (sd->status.job_level == up_level)
-        {
-            clif_displaymessage (fd, msg_table[23]);    // Job level can't go any higher.
-            return -1;
-        }
-        if (level > up_level || level > (up_level - sd->status.job_level))  // fix positiv overflow
-            level = up_level - sd->status.job_level;
-        sd->status.job_level += level;
-        clif_updatestatus (sd, SP_JOBLEVEL);
-        clif_updatestatus (sd, SP_NEXTJOBEXP);
-        sd->status.skill_point += level;
-        clif_updatestatus (sd, SP_SKILLPOINT);
-        pc_calcstatus (sd, 0);
-        clif_misceffect (&sd->bl, 1);
-        clif_displaymessage (fd, msg_table[24]);    // Job level raised.
-    }
-    else
-    {
-        if (sd->status.job_level == 1)
-        {
-            clif_displaymessage (fd, msg_table[159]);   // Job level can't go any lower.
-            return -1;
-        }
-        if (level < -up_level || level < (1 - sd->status.job_level))    // fix negativ overflow
-            level = 1 - sd->status.job_level;
-        sd->status.job_level += level;
-        clif_updatestatus (sd, SP_JOBLEVEL);
-        clif_updatestatus (sd, SP_NEXTJOBEXP);
-        if (sd->status.skill_point > 0)
-        {
-            sd->status.skill_point += level;
-            if (sd->status.skill_point < 0)
-                sd->status.skill_point = 0;
-            clif_updatestatus (sd, SP_SKILLPOINT);
-        }                       // to add: remove status points from skills
-        pc_calcstatus (sd, 0);
-        clif_displaymessage (fd, msg_table[25]);    // Job level lowered.
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_help (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char buf[2048], w1[2048], w2[2048];
-    int  i, gm_level;
-    FILE *fp;
-
-    memset (buf, '\0', sizeof (buf));
-
-    if ((fp = fopen_ (help_txt, "r")) != NULL)
-    {
-        clif_displaymessage (fd, msg_table[26]);    // Help commands:
-        gm_level = pc_isGM (sd);
-        while (fgets (buf, sizeof (buf) - 1, fp) != NULL)
-        {
-            if (buf[0] == '/' && buf[1] == '/')
-                continue;
-            for (i = 0; buf[i] != '\0'; i++)
-            {
-                if (buf[i] == '\r' || buf[i] == '\n')
-                {
-                    buf[i] = '\0';
-                    break;
-                }
-            }
-            if (sscanf (buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2)
-                clif_displaymessage (fd, buf);
-            else if (gm_level >= atoi (w1))
-                clif_displaymessage (fd, w2);
-        }
-        fclose_ (fp);
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[27]);    // File help.txt not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_gm (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-    char password[100];
-
-    memset (password, '\0', sizeof (password));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", password) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a password (usage: @gm <password>).");
-        return -1;
-    }
-
-    if (pc_isGM (sd))
-    {                           // a GM can not use this function. only a normal player (become gm is not for gm!)
-        clif_displaymessage (fd, msg_table[50]);    // You already have some GM powers.
-        return -1;
-    }
-    else
-        chrif_changegm (sd->status.account_id, password,
-                        strlen (password) + 1);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_pvpoff (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    if (battle_config.pk_mode)
-    {                           //disable command if server is in PK mode [Valaris]
-        clif_displaymessage (fd, msg_table[52]);    // This option cannot be used in PK Mode.
-        return -1;
-    }
-
-    if (map[sd->bl.m].flag.pvp)
-    {
-        map[sd->bl.m].flag.pvp = 0;
-        clif_send0199 (sd->bl.m, 0);
-        for (i = 0; i < fd_max; i++)
-        {                       //人数分ループ
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                if (sd->bl.m == pl_sd->bl.m)
-                {
-                    clif_pvpset (pl_sd, 0, 0, 2);
-                    if (pl_sd->pvp_timer != -1)
-                    {
-                        delete_timer (pl_sd->pvp_timer,
-                                      pc_calc_pvprank_timer);
-                        pl_sd->pvp_timer = -1;
-                    }
-                }
-            }
-        }
-        clif_displaymessage (fd, msg_table[31]);    // PvP: Off.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[160]);   // PvP is already Off.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_pvpon (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    if (battle_config.pk_mode)
-    {                           //disable command if server is in PK mode [Valaris]
-        clif_displaymessage (fd, msg_table[52]);    // This option cannot be used in PK Mode.
-        return -1;
-    }
-
-    if (!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.nopvp)
-    {
-        map[sd->bl.m].flag.pvp = 1;
-        clif_send0199 (sd->bl.m, 1);
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                if (sd->bl.m == pl_sd->bl.m && pl_sd->pvp_timer == -1)
-                {
-                    pl_sd->pvp_timer = add_timer (gettick () + 200,
-                                                  pc_calc_pvprank_timer,
-                                                  pl_sd->bl.id, 0);
-                    pl_sd->pvp_rank = 0;
-                    pl_sd->pvp_lastusers = 0;
-                    pl_sd->pvp_point = 5;
-                }
-            }
-        }
-        clif_displaymessage (fd, msg_table[32]);    // PvP: On.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[161]);   // PvP is already On.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_gvgoff (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    if (map[sd->bl.m].flag.gvg)
-    {
-        map[sd->bl.m].flag.gvg = 0;
-        clif_send0199 (sd->bl.m, 0);
-        clif_displaymessage (fd, msg_table[33]);    // GvG: Off.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[162]);   // GvG is already Off.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_gvgon (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    if (!map[sd->bl.m].flag.gvg)
-    {
-        map[sd->bl.m].flag.gvg = 1;
-        clif_send0199 (sd->bl.m, 3);
-        clif_displaymessage (fd, msg_table[34]);    // GvG: On.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[163]);   // GvG is already On.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_model (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    int  hair_style = 0, hair_color = 0, cloth_color = 0;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message
-        || sscanf (message, "%d %d %d", &hair_style, &hair_color,
-                   &cloth_color) < 1)
-    {
-        sprintf (output,
-                 "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).",
-                 MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR,
-                 MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
-        hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
-        cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
-    {
-        //服の色変更
-        if (cloth_color != 0 && sd->status.sex == 1
-            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
-        {
-            //服の色未実装職の判定
-            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
-            return -1;
-        }
-        else
-        {
-            pc_changelook (sd, LOOK_HAIR, hair_style);
-            pc_changelook (sd, LOOK_HAIR_COLOR, hair_color);
-            pc_changelook (sd, LOOK_CLOTHES_COLOR, cloth_color);
-            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @dye && @ccolor
- *------------------------------------------
- */
-int atcommand_dye (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    int  cloth_color = 0;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%d", &cloth_color) < 1)
-    {
-        sprintf (output,
-                 "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).",
-                 MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
-    {
-        if (cloth_color != 0 && sd->status.sex == 1
-            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
-        {
-            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
-            return -1;
-        }
-        else
-        {
-            pc_changelook (sd, LOOK_CLOTHES_COLOR, cloth_color);
-            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @chardye by [MouseJstr]
- *------------------------------------------
- */
-int
-atcommand_chardye (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    return 0;
-}
-
-/*==========================================
- * @hairstyle && @hstyle
- *------------------------------------------
- */
-int atcommand_hair_style (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    int  hair_style = 0;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%d", &hair_style) < 1)
-    {
-        sprintf (output,
-                 "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).",
-                 MIN_HAIR_STYLE, MAX_HAIR_STYLE);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE)
-    {
-        if (hair_style != 0 && sd->status.sex == 1
-            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
-        {
-            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
-            return -1;
-        }
-        else
-        {
-            pc_changelook (sd, LOOK_HAIR, hair_style);
-            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charhairstyle by [MouseJstr]
- *------------------------------------------
- */
-int
-atcommand_charhairstyle (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    return 0;
-}
-
-/*==========================================
- * @haircolor && @hcolor
- *------------------------------------------
- */
-int atcommand_hair_color (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    int  hair_color = 0;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%d", &hair_color) < 1)
-    {
-        sprintf (output,
-                 "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).",
-                 MIN_HAIR_COLOR, MAX_HAIR_COLOR);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR)
-    {
-        if (hair_color != 0 && sd->status.sex == 1
-            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
-        {
-            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
-            return -1;
-        }
-        else
-        {
-            pc_changelook (sd, LOOK_HAIR_COLOR, hair_color);
-            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charhaircolor by [MouseJstr]
- *------------------------------------------
- */
-int
-atcommand_charhaircolor (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    return 0;
-}
-
-/*==========================================
- * @go [city_number/city_name]: improved by [yor] to add city names and help
- *------------------------------------------
- */
-int atcommand_go (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-    int  i;
-    int  town;
-    char map_name[100];
-    char output[200];
-    int  m;
-
-    struct
-    {
-        char map[16];
-        int  x, y;
-    } data[] =
-    {
-        {
-        "prontera.gat", 156, 191},  //   0=Prontera
-        {
-        "morocc.gat", 156, 93}, //   1=Morroc
-        {
-        "geffen.gat", 119, 59}, //   2=Geffen
-        {
-        "payon.gat", 162, 233}, //   3=Payon
-        {
-        "alberta.gat", 192, 147},   //   4=Alberta
-        {
-        "izlude.gat", 128, 114},    //   5=Izlude
-        {
-        "aldebaran.gat", 140, 131}, //   6=Al de Baran
-        {
-        "xmas.gat", 147, 134},  //   7=Lutie
-        {
-        "comodo.gat", 209, 143},    //   8=Comodo
-        {
-        "yuno.gat", 157, 51},   //   9=Yuno
-        {
-        "amatsu.gat", 198, 84}, //  10=Amatsu
-        {
-        "gonryun.gat", 160, 120},   //  11=Gon Ryun
-        {
-        "umbala.gat", 89, 157}, //  12=Umbala
-        {
-        "niflheim.gat", 21, 153},   //  13=Niflheim
-        {
-        "louyang.gat", 217, 40},    //  14=Lou Yang
-        {
-        "new_1-1.gat", 53, 111},    //  15=Start point
-        {
-        "sec_pri.gat", 23, 61}, //  16=Prison
-    };
-
-    memset (map_name, '\0', sizeof (map_name));
-    memset (output, '\0', sizeof (output));
-
-    // get the number
-    town = atoi (message);
-
-    // if no value, display all value
-    if (!message || !*message || sscanf (message, "%99s", map_name) < 1
-        || town < -3 || town >= (int) (sizeof (data) / sizeof (data[0])))
-    {
-        clif_displaymessage (fd, msg_table[38]);    // Invalid location number or name.
-        clif_displaymessage (fd, msg_table[82]);    // Please, use one of this number/name:
-        clif_displaymessage (fd,
-                             "-3=(Memo point 2)   4=Alberta       11=Gon Ryun");
-        clif_displaymessage (fd,
-                             "-2=(Memo point 1)   5=Izlude        12=Umbala");
-        clif_displaymessage (fd,
-                             "-1=(Memo point 0)   6=Al de Baran   13=Niflheim");
-        clif_displaymessage (fd,
-                             " 0=Prontera         7=Lutie         14=Lou Yang");
-        clif_displaymessage (fd,
-                             " 1=Morroc           8=Comodo        15=Start point");
-        clif_displaymessage (fd,
-                             " 2=Geffen           9=Yuno          16=Prison");
-        clif_displaymessage (fd, " 3=Payon           10=Amatsu");
-        return -1;
-    }
-    else
-    {
-        // get possible name of the city and add .gat if not in the name
-        map_name[sizeof (map_name) - 1] = '\0';
-        for (i = 0; map_name[i]; i++)
-            map_name[i] = tolower (map_name[i]);
-        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-            strcat (map_name, ".gat");
-        // try to see if it's a name, and not a number (try a lot of possibilities, write errors and abbreviations too)
-        if (strncmp (map_name, "prontera.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 0;
-        }
-        else if (strncmp (map_name, "morocc.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 1;
-        }
-        else if (strncmp (map_name, "geffen.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 2;
-        }
-        else if (strncmp (map_name, "payon.gat", 3) == 0 || // 3 first characters
-                 strncmp (map_name, "paion.gat", 3) == 0)
-        {                       // writing error (3 first characters)
-            town = 3;
-        }
-        else if (strncmp (map_name, "alberta.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 4;
-        }
-        else if (strncmp (map_name, "izlude.gat", 3) == 0 ||    // 3 first characters
-                 strncmp (map_name, "islude.gat", 3) == 0)
-        {                       // writing error (3 first characters)
-            town = 5;
-        }
-        else if (strncmp (map_name, "aldebaran.gat", 3) == 0 || // 3 first characters
-                 strcmp (map_name, "al.gat") == 0)
-        {                       // al (de baran)
-            town = 6;
-        }
-        else if (strncmp (map_name, "lutie.gat", 3) == 0 || // name of the city, not name of the map (3 first characters)
-                 strcmp (map_name, "christmas.gat") == 0 || // name of the symbol
-                 strncmp (map_name, "xmas.gat", 3) == 0 ||  // 3 first characters
-                 strncmp (map_name, "x-mas.gat", 3) == 0)
-        {                       // writing error (3 first characters)
-            town = 7;
-        }
-        else if (strncmp (map_name, "comodo.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 8;
-        }
-        else if (strncmp (map_name, "yuno.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 9;
-        }
-        else if (strncmp (map_name, "amatsu.gat", 3) == 0 ||    // 3 first characters
-                 strncmp (map_name, "ammatsu.gat", 3) == 0)
-        {                       // writing error (3 first characters)
-            town = 10;
-        }
-        else if (strncmp (map_name, "gonryun.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 11;
-        }
-        else if (strncmp (map_name, "umbala.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 12;
-        }
-        else if (strncmp (map_name, "niflheim.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 13;
-        }
-        else if (strncmp (map_name, "louyang.gat", 3) == 0)
-        {                       // 3 first characters
-            town = 14;
-        }
-        else if (strncmp (map_name, "new_1-1.gat", 3) == 0 ||   // 3 first characters (or "newbies")
-                 strncmp (map_name, "startpoint.gat", 3) == 0 ||    // name of the position (3 first characters)
-                 strncmp (map_name, "begining.gat", 3) == 0)
-        {                       // name of the position (3 first characters)
-            town = 15;
-        }
-        else if (strncmp (map_name, "sec_pri.gat", 3) == 0 ||   // 3 first characters
-                 strncmp (map_name, "prison.gat", 3) == 0 ||    // name of the position (3 first characters)
-                 strncmp (map_name, "jails.gat", 3) == 0)
-        {                       // name of the position
-            town = 16;
-        }
-
-        if (town >= -3 && town <= -1)
-        {
-            if (sd->status.memo_point[-town - 1].map[0])
-            {
-                m = map_mapname2mapid (sd->status.memo_point[-town - 1].map);
-                if (m >= 0 && map[m].flag.nowarpto
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                {
-                    clif_displaymessage (fd,
-                                         "You are not authorised to warp you to this memo map.");
-                    return -1;
-                }
-                if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                {
-                    clif_displaymessage (fd,
-                                         "You are not authorised to warp you from your actual map.");
-                    return -1;
-                }
-                if (pc_setpos
-                    (sd, sd->status.memo_point[-town - 1].map,
-                     sd->status.memo_point[-town - 1].x,
-                     sd->status.memo_point[-town - 1].y, 3) == 0)
-                {
-                    clif_displaymessage (fd, msg_table[0]); // Warped.
-                }
-                else
-                {
-                    clif_displaymessage (fd, msg_table[1]); // Map not found.
-                    return -1;
-                }
-            }
-            else
-            {
-                sprintf (output, msg_table[164], -town - 1);    // Your memo point #%d doesn't exist.
-                clif_displaymessage (fd, output);
-                return -1;
-            }
-        }
-        else if (town >= 0 && town < (int) (sizeof (data) / sizeof (data[0])))
-        {
-            m = map_mapname2mapid (data[town].map);
-            if (m >= 0 && map[m].flag.nowarpto
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-            {
-                clif_displaymessage (fd,
-                                     "You are not authorised to warp you to this destination map.");
-                return -1;
-            }
-            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-            {
-                clif_displaymessage (fd,
-                                     "You are not authorised to warp you from your actual map.");
-                return -1;
-            }
-            if (pc_setpos (sd, data[town].map, data[town].x, data[town].y, 3)
-                == 0)
-            {
-                clif_displaymessage (fd, msg_table[0]); // Warped.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[1]); // Map not found.
-                return -1;
-            }
-        }
-        else
-        {                       // if you arrive here, you have an error in town variable when reading of names
-            clif_displaymessage (fd, msg_table[38]);    // Invalid location number or name.
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_spawn (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char monster[100];
-    char output[200];
-    int  mob_id;
-    int  number = 0;
-    int  x = 0, y = 0;
-    int  count;
-    int  i, j, k;
-    int  mx, my, range;
-
-    memset (monster, '\0', sizeof (monster));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d %d %d", monster, &number, &x, &y) < 1)
-    {
-        clif_displaymessage (fd, msg_table[143]);   // Give a monster name/id please.
-        return -1;
-    }
-
-    // If monster identifier/name argument is a name
-    if ((mob_id = mobdb_searchname (monster)) == 0) // check name first (to avoid possible name begining by a number)
-        mob_id = mobdb_checkid (atoi (monster));
-
-    if (mob_id == 0)
-    {
-        clif_displaymessage (fd, msg_table[40]);    // Invalid monster ID or name.
-        return -1;
-    }
-
-    if (mob_id == 1288)
-    {
-        clif_displaymessage (fd, msg_table[83]);    // Cannot spawn emperium.
-        return -1;
-    }
-
-    if (number <= 0)
-        number = 1;
-
-    // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
-    if (battle_config.atc_spawn_quantity_limit >= 1
-        && number > battle_config.atc_spawn_quantity_limit)
-        number = battle_config.atc_spawn_quantity_limit;
-
-    if (battle_config.etc_log)
-        printf ("%s monster='%s' id=%d count=%d (%d,%d)\n", command, monster,
-                mob_id, number, x, y);
-
-    count = 0;
-    range = sqrt (number) / 2;
-    range = range * 2 + 5;      // calculation of an odd number (+ 4 area around)
-    for (i = 0; i < number; i++)
-    {
-        j = 0;
-        k = 0;
-        while (j++ < 8 && k == 0)
-        {                       // try 8 times to spawn the monster (needed for close area)
-            if (x <= 0)
-                mx = sd->bl.x + (MRAND (range) - (range / 2));
-            else
-                mx = x;
-            if (y <= 0)
-                my = sd->bl.y + (MRAND (range) - (range / 2));
-            else
-                my = y;
-            k = mob_once_spawn ((struct map_session_data *) sd, "this", mx,
-                                my, "", mob_id, 1, "");
-        }
-        count += (k != 0) ? 1 : 0;
-    }
-
-    if (count != 0)
-        if (number == count)
-            clif_displaymessage (fd, msg_table[39]);    // All monster summoned!
-        else
-        {
-            sprintf (output, msg_table[240], count);    // %d monster(s) summoned!
-            clif_displaymessage (fd, output);
-        }
-    else
-    {
-        clif_displaymessage (fd, msg_table[40]);    // Invalid monster ID or name.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void atcommand_killmonster_sub (const int fd, struct map_session_data *sd,
-                                const char *message, const int drop)
-{
-    int  map_id;
-    char map_name[100];
-
-    memset (map_name, '\0', sizeof (map_name));
-
-    if (!message || !*message || sscanf (message, "%99s", map_name) < 1)
-        map_id = sd->bl.m;
-    else
-    {
-        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-            strcat (map_name, ".gat");
-        if ((map_id = map_mapname2mapid (map_name)) < 0)
-            map_id = sd->bl.m;
-    }
-
-    map_foreachinarea (atkillmonster_sub, map_id, 0, 0, map[map_id].xs,
-                       map[map_id].ys, BL_MOB, drop);
-
-    clif_displaymessage (fd, msg_table[165]);   // All monsters killed!
-
-    return;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_killmonster (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    atcommand_killmonster_sub (fd, sd, message, 1);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int atlist_nearby_sub (struct block_list *bl, va_list ap)
-{
-    char buf[32];
-    int  fd = va_arg (ap, int);
-    nullpo_retr (0, bl);
-
-    sprintf (buf, " - \"%s\"", ((struct map_session_data *) bl)->status.name);
-    clif_displaymessage (fd, buf);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_list_nearby (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    clif_displaymessage (fd, "Nearby players:");
-    map_foreachinarea (atlist_nearby_sub, sd->bl.m, sd->bl.x - 1,
-                       sd->bl.y - 1, sd->bl.x + 1, sd->bl.x + 1, BL_PC, fd);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_killmonster2 (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    atcommand_killmonster_sub (fd, sd, message, 0);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_produce (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    char item_name[100];
-    int  item_id, attribute = 0, star = 0;
-    int  flag = 0;
-    struct item_data *item_data;
-    struct item tmp_item;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-    memset (item_name, '\0', sizeof (item_name));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d %d", item_name, &attribute, &star) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter at least an item name/id (usage: @produce <equip name or equip ID> <element> <# of very's>).");
-        return -1;
-    }
-
-    item_id = 0;
-    if ((item_data = itemdb_searchname (item_name)) != NULL ||
-        (item_data = itemdb_exists (atoi (item_name))) != NULL)
-        item_id = item_data->nameid;
-
-    if (itemdb_exists (item_id) &&
-        (item_id <= 500 || item_id > 1099) &&
-        (item_id < 4001 || item_id > 4148) &&
-        (item_id < 7001 || item_id > 10019) && itemdb_isequip (item_id))
-    {
-        if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE)
-            attribute = ATTRIBUTE_NORMAL;
-        if (star < MIN_STAR || star > MAX_STAR)
-            star = 0;
-        memset (&tmp_item, 0, sizeof tmp_item);
-        tmp_item.nameid = item_id;
-        tmp_item.amount = 1;
-        tmp_item.identify = 1;
-        tmp_item.card[0] = 0x00ff;
-        tmp_item.card[1] = ((star * 5) << 8) + attribute;
-        *((unsigned long *) (&tmp_item.card[2])) = sd->char_id;
-        clif_produceeffect (sd, 0, item_id);    // 製造エフェクトパケット
-        clif_misceffect (&sd->bl, 3);   // 他人にも成功を通知
-        if ((flag = pc_additem (sd, &tmp_item, 1)))
-            clif_additem (sd, 0, 0, flag);
-    }
-    else
-    {
-        if (battle_config.error_log)
-            printf ("@produce NOT WEAPON [%d]\n", item_id);
-        if (item_id != 0 && itemdb_exists (item_id))
-            sprintf (output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment.
-        else
-            sprintf (output, "%s", msg_table[170]);   // This item is not an equipment.
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Sub-function to display actual memo points
- *------------------------------------------
- */
-void atcommand_memo_sub (struct map_session_data *sd)
-{
-    int  i;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    clif_displaymessage (sd->fd,
-                         "Your actual memo positions are (except respawn point):");
-    for (i = MIN_PORTAL_MEMO; i <= MAX_PORTAL_MEMO; i++)
-    {
-        if (sd->status.memo_point[i].map[0])
-            sprintf (output, "%d - %s (%d,%d)", i,
-                     sd->status.memo_point[i].map, sd->status.memo_point[i].x,
-                     sd->status.memo_point[i].y);
-        else
-            sprintf (output, msg_table[171], i);    // %d - void
-        clif_displaymessage (sd->fd, output);
-    }
-
-    return;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_memo (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  position = 0;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%d", &position) < 1)
-        atcommand_memo_sub (sd);
-    else
-    {
-        if (position >= MIN_PORTAL_MEMO && position <= MAX_PORTAL_MEMO)
-        {
-            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-            {
-                clif_displaymessage (fd,
-                                     "You are not authorised to memo this map.");
-                return -1;
-            }
-            if (sd->status.memo_point[position].map[0])
-            {
-                sprintf (output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y);  // You replace previous memo position %d - %s (%d,%d).
-                clif_displaymessage (fd, output);
-            }
-            memcpy (sd->status.memo_point[position].map, map[sd->bl.m].name,
-                    24);
-            sd->status.memo_point[position].x = sd->bl.x;
-            sd->status.memo_point[position].y = sd->bl.y;
-            clif_skill_memo (sd, 0);
-            if (pc_checkskill (sd, AL_WARP) <= (position + 1))
-                clif_displaymessage (fd, msg_table[173]);   // Note: you don't have the 'Warp' skill level to use it.
-            atcommand_memo_sub (sd);
-        }
-        else
-        {
-            sprintf (output,
-                     "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).",
-                     MIN_PORTAL_MEMO, MAX_PORTAL_MEMO);
-            clif_displaymessage (fd, output);
-            atcommand_memo_sub (sd);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_gat (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    char output[200];
-    int  y;
-
-    memset (output, '\0', sizeof (output));
-
-    for (y = 2; y >= -2; y--)
-    {
-        sprintf (output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
-                 map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
-                 map_getcell (sd->bl.m, sd->bl.x - 2, sd->bl.y + y),
-                 map_getcell (sd->bl.m, sd->bl.x - 1, sd->bl.y + y),
-                 map_getcell (sd->bl.m, sd->bl.x, sd->bl.y + y),
-                 map_getcell (sd->bl.m, sd->bl.x + 1, sd->bl.y + y),
-                 map_getcell (sd->bl.m, sd->bl.x + 2, sd->bl.y + y));
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_packet (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    int  x = 0, y = 0;
-
-    if (!message || !*message || sscanf (message, "%d %d", &x, &y) < 2)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a status type/flag (usage: @packet <status type> <flag>).");
-        return -1;
-    }
-
-    clif_status_change (&sd->bl, x, y);
-
-    return 0;
-}
-
-/*==========================================
- * @stpoint (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_statuspoint (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    int  point, new_status_point;
-
-    if (!message || !*message || (point = atoi (message)) == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a number (usage: @stpoint <number of points>).");
-        return -1;
-    }
-
-    new_status_point = (int) sd->status.status_point + point;
-    if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
-        new_status_point = 0x7FFF;
-    else if (point < 0 && (point < -0x7FFF || new_status_point < 0))    // fix negativ overflow
-        new_status_point = 0;
-
-    if (new_status_point != (int) sd->status.status_point)
-    {
-        sd->status.status_point = (short) new_status_point;
-        clif_updatestatus (sd, SP_STATUSPOINT);
-        clif_displaymessage (fd, msg_table[174]);   // Number of status points changed!
-    }
-    else
-    {
-        if (point < 0)
-            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-        else
-            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @skpoint (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_skillpoint (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    int  point, new_skill_point;
-
-    if (!message || !*message || (point = atoi (message)) == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a number (usage: @skpoint <number of points>).");
-        return -1;
-    }
-
-    new_skill_point = (int) sd->status.skill_point + point;
-    if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))  // fix positiv overflow
-        new_skill_point = 0x7FFF;
-    else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow
-        new_skill_point = 0;
-
-    if (new_skill_point != (int) sd->status.skill_point)
-    {
-        sd->status.skill_point = (short) new_skill_point;
-        clif_updatestatus (sd, SP_SKILLPOINT);
-        clif_displaymessage (fd, msg_table[175]);   // Number of skill points changed!
-    }
-    else
-    {
-        if (point < 0)
-            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-        else
-            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @zeny (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_zeny (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  zeny, new_zeny;
-
-    if (!message || !*message || (zeny = atoi (message)) == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter an amount (usage: @zeny <amount>).");
-        return -1;
-    }
-
-    new_zeny = sd->status.zeny + zeny;
-    if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))   // fix positiv overflow
-        new_zeny = MAX_ZENY;
-    else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))    // fix negativ overflow
-        new_zeny = 0;
-
-    if (new_zeny != sd->status.zeny)
-    {
-        sd->status.zeny = new_zeny;
-        clif_updatestatus (sd, SP_ZENY);
-        clif_displaymessage (fd, msg_table[176]);   // Number of zenys changed!
-    }
-    else
-    {
-        if (zeny < 0)
-            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-        else
-            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_param (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    int  i, index, value = 0, new_value;
-    const char *param[] =
-        { "@str", "@agi", "@vit", "@int", "@dex", "@luk", NULL };
-    short *status[] = {
-        &sd->status.str, &sd->status.agi, &sd->status.vit,
-        &sd->status.int_, &sd->status.dex, &sd->status.luk
-    };
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%d", &value) < 1
-        || value == 0)
-    {
-        sprintf (output,
-                 "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    index = -1;
-    for (i = 0; param[i] != NULL; i++)
-    {
-        if (strcasecmp (command, param[i]) == 0)
-        {
-            index = i;
-            break;
-        }
-    }
-    if (index < 0 || index > MAX_STATUS_TYPE)
-    {                           // normaly impossible...
-        sprintf (output,
-                 "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    new_value = (int) *status[index] + value;
-    if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))  // fix positiv overflow
-        new_value = battle_config.max_parameter;
-    else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))  // fix negativ overflow
-        new_value = 1;
-
-    if (new_value != (int) *status[index])
-    {
-        *status[index] = new_value;
-        clif_updatestatus (sd, SP_STR + index);
-        clif_updatestatus (sd, SP_USTR + index);
-        pc_calcstatus (sd, 0);
-        clif_displaymessage (fd, msg_table[42]);    // Stat changed.
-    }
-    else
-    {
-        if (value < 0)
-            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-        else
-            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-//** Stat all by fritz (rewritten by [Yor])
-int atcommand_all_stats (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    int  index, count, value = 0, new_value;
-    short *status[] = {
-        &sd->status.str, &sd->status.agi, &sd->status.vit,
-        &sd->status.int_, &sd->status.dex, &sd->status.luk
-    };
-
-    if (!message || !*message || sscanf (message, "%d", &value) < 1
-        || value == 0)
-        value = battle_config.max_parameter;
-
-    count = 0;
-    for (index = 0; index < (int) (sizeof (status) / sizeof (status[0]));
-         index++)
-    {
-
-        new_value = (int) *status[index] + value;
-        if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))  // fix positiv overflow
-            new_value = battle_config.max_parameter;
-        else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))  // fix negativ overflow
-            new_value = 1;
-
-        if (new_value != (int) *status[index])
-        {
-            *status[index] = new_value;
-            clif_updatestatus (sd, SP_STR + index);
-            clif_updatestatus (sd, SP_USTR + index);
-            pc_calcstatus (sd, 0);
-            count++;
-        }
-    }
-
-    if (count > 0)              // if at least 1 stat modified
-        clif_displaymessage (fd, msg_table[84]);    // All stats changed!
-    else
-    {
-        if (value < 0)
-            clif_displaymessage (fd, msg_table[177]);   // Impossible to decrease a stat.
-        else
-            clif_displaymessage (fd, msg_table[178]);   // Impossible to increase a stat.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_guildlevelup (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    int  level = 0;
-    short added_level;
-    struct guild *guild_info;
-
-    if (!message || !*message || sscanf (message, "%d", &level) < 1
-        || level == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a valid level (usage: @guildlvl <# of levels>).");
-        return -1;
-    }
-
-    if (sd->status.guild_id <= 0
-        || (guild_info = guild_search (sd->status.guild_id)) == NULL)
-    {
-        clif_displaymessage (fd, msg_table[43]);    // You're not in a guild.
-        return -1;
-    }
-    if (strcmp (sd->status.name, guild_info->master) != 0)
-    {
-        clif_displaymessage (fd, msg_table[44]);    // You're not the master of your guild.
-        return -1;
-    }
-
-    added_level = (short) level;
-    if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short) MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow
-        added_level = (short) MAX_GUILDLEVEL - guild_info->guild_lv;
-    else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv)))    // fix negativ overflow
-        added_level = 1 - guild_info->guild_lv;
-
-    if (added_level != 0)
-    {
-        intif_guild_change_basicinfo (guild_info->guild_id, GBI_GUILDLV,
-                                      &added_level, 2);
-        clif_displaymessage (fd, msg_table[179]);   // Guild level changed.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[45]);    // Guild level change failed.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_recall (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @recall <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can recall only lower or same level
-            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-            {
-                clif_displaymessage (fd,
-                                     "You are not authorised to warp somenone to your actual map.");
-                return -1;
-            }
-            if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-            {
-                clif_displaymessage (fd,
-                                     "You are not authorised to warp this player from its actual map.");
-                return -1;
-            }
-            pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
-            sprintf (output, msg_table[46], character); // %s recalled!
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_revive (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @revive <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        pl_sd->status.hp = pl_sd->status.max_hp;
-        pc_setstand (pl_sd);
-        if (battle_config.pc_invincible_time > 0)
-            pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
-        clif_updatestatus (pl_sd, SP_HP);
-        clif_updatestatus (pl_sd, SP_SP);
-        clif_resurrection (&pl_sd->bl, 1);
-        clif_displaymessage (fd, msg_table[51]);    // Character revived.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_character_stats (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    char character[100];
-    char job_jobname[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-    int  i;
-
-    memset (character, '\0', sizeof (character));
-    memset (job_jobname, '\0', sizeof (job_jobname));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charstats <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        struct
-        {
-            const char *format;
-            int  value;
-        } output_table[] =
-        {
-            {
-            "Base Level - %d", pl_sd->status.base_level},
-            {
-            job_jobname, pl_sd->status.job_level},
-            {
-            "Hp - %d", pl_sd->status.hp},
-            {
-            "MaxHp - %d", pl_sd->status.max_hp},
-            {
-            "Sp - %d", pl_sd->status.sp},
-            {
-            "MaxSp - %d", pl_sd->status.max_sp},
-            {
-            "Str - %3d", pl_sd->status.str},
-            {
-            "Agi - %3d", pl_sd->status.agi},
-            {
-            "Vit - %3d", pl_sd->status.vit},
-            {
-            "Int - %3d", pl_sd->status.int_},
-            {
-            "Dex - %3d", pl_sd->status.dex},
-            {
-            "Luk - %3d", pl_sd->status.luk},
-            {
-            "Zeny - %d", pl_sd->status.zeny},
-            {
-            NULL, 0}
-        };
-        sprintf (job_jobname, "Job - %s %s", job_name (pl_sd->status.pc_class),
-                 "(level %d)");
-        sprintf (output, msg_table[53], pl_sd->status.name);    // '%s' stats:
-        clif_displaymessage (fd, output);
-        for (i = 0; output_table[i].format != NULL; i++)
-        {
-            sprintf (output, output_table[i].format, output_table[i].value);
-            clif_displaymessage (fd, output);
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-//** Character Stats All by fritz
-int atcommand_character_stats_all (const int fd, struct map_session_data *sd,
-                                   const char *command, const char *message)
-{
-    char output[1024], gmlevel[1024];
-    int  i;
-    int  count;
-    struct map_session_data *pl_sd;
-
-    memset (output, '\0', sizeof (output));
-    memset (gmlevel, '\0', sizeof (gmlevel));
-
-    count = 0;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-
-            if (pc_isGM (pl_sd) > 0)
-                sprintf (gmlevel, "| GM Lvl: %d", pc_isGM (pl_sd));
-            else
-                sprintf (gmlevel, " ");
-
-            sprintf (output,
-                     "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d",
-                     pl_sd->status.name, pl_sd->status.base_level,
-                     job_name (pl_sd->status.pc_class), pl_sd->status.job_level,
-                     pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp,
-                     pl_sd->status.max_sp);
-            clif_displaymessage (fd, output);
-            sprintf (output,
-                     "STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s",
-                     pl_sd->status.str, pl_sd->status.agi, pl_sd->status.vit,
-                     pl_sd->status.int_, pl_sd->status.dex, pl_sd->status.luk,
-                     pl_sd->status.zeny, gmlevel);
-            clif_displaymessage (fd, output);
-            clif_displaymessage (fd, "--------");
-            count++;
-        }
-    }
-
-    if (count == 0)
-        clif_displaymessage (fd, msg_table[28]);    // No player found.
-    else if (count == 1)
-        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
-    else
-    {
-        sprintf (output, msg_table[30], count); // %d players found.
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_character_option (const int fd, struct map_session_data *sd,
-                                const char *command, const char *message)
-{
-    char character[100];
-    int  opt1 = 0, opt2 = 0, opt3 = 0;
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %d %d %99[^\n]", &opt1, &opt2, &opt3,
-                   character) < 4 || opt1 < 0 || opt2 < 0 || opt3 < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter valid options and a player name (usage: @charoption <param1> <param2> <param3> <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change option only to lower or same level
-            pl_sd->opt1 = opt1;
-            pl_sd->opt2 = opt2;
-            pl_sd->status.option = opt3;
-            // fix pecopeco display
-            if (pl_sd->status.pc_class == 13 || pl_sd->status.pc_class == 21
-                || pl_sd->status.pc_class == 4014 || pl_sd->status.pc_class == 4022)
-            {
-                if (!pc_isriding (pl_sd))
-                {               // pl_sd have the new value...
-                    if (pl_sd->status.pc_class == 13)
-                        pl_sd->status.pc_class = pl_sd->view_class = 7;
-                    else if (pl_sd->status.pc_class == 21)
-                        pl_sd->status.pc_class = pl_sd->view_class = 14;
-                    else if (pl_sd->status.pc_class == 4014)
-                        pl_sd->status.pc_class = pl_sd->view_class = 4008;
-                    else if (pl_sd->status.pc_class == 4022)
-                        pl_sd->status.pc_class = pl_sd->view_class = 4015;
-                }
-            }
-            else
-            {
-                if (pc_isriding (pl_sd))
-                {               // pl_sd have the new value...
-                    if (pl_sd->disguise > 0)
-                    {           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
-                        pl_sd->status.option &= ~0x0020;
-                    }
-                    else
-                    {
-                        if (pl_sd->status.pc_class == 7)
-                            pl_sd->status.pc_class = pl_sd->view_class = 13;
-                        else if (pl_sd->status.pc_class == 14)
-                            pl_sd->status.pc_class = pl_sd->view_class = 21;
-                        else if (pl_sd->status.pc_class == 4008)
-                            pl_sd->status.pc_class = pl_sd->view_class = 4014;
-                        else if (pl_sd->status.pc_class == 4015)
-                            pl_sd->status.pc_class = pl_sd->view_class = 4022;
-                        else
-                            pl_sd->status.option &= ~0x0020;
-                    }
-                }
-            }
-            clif_changeoption (&pl_sd->bl);
-            pc_calcstatus (pl_sd, 0);
-            clif_displaymessage (fd, msg_table[58]);    // Character's options changed.
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * charchangesex command (usage: charchangesex <player_name>)
- *------------------------------------------
- */
-int atcommand_char_change_sex (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    char character[100];
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charchangesex <name>).");
-        return -1;
-    }
-
-    // check player name
-    if (strlen (character) < 4)
-    {
-        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
-        return -1;
-    }
-    else if (strlen (character) > 23)
-    {
-        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
-        return -1;
-    }
-    else
-    {
-        chrif_char_ask_name (sd->status.account_id, character, 5, 0, 0, 0, 0, 0, 0);    // type: 5 - changesex
-        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
-    }
-
-    return 0;
-}
-
-/*==========================================
- * charblock command (usage: charblock <player_name>)
- * This command do a definitiv ban on a player
- *------------------------------------------
- */
-int atcommand_char_block (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    char character[100];
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @block <name>).");
-        return -1;
-    }
-
-    // check player name
-    if (strlen (character) < 4)
-    {
-        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
-        return -1;
-    }
-    else if (strlen (character) > 23)
-    {
-        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
-        return -1;
-    }
-    else
-    {
-        chrif_char_ask_name (sd->status.account_id, character, 1, 0, 0, 0, 0, 0, 0);    // type: 1 - block
-        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
-    }
-
-    return 0;
-}
-
-/*==========================================
- * charban command (usage: charban <time> <player_name>)
- * This command do a limited ban on a player
- * Time is done as follows:
- *   Adjustment value (-1, 1, +1, etc...)
- *   Modified element:
- *     a or y: year
- *     m:  month
- *     j or d: day
- *     h:  hour
- *     mn: minute
- *     s:  second
- * <example> @ban +1m-2mn1s-6y test_player
- *           this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
- *------------------------------------------
- */
-int atcommand_char_ban (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char modif[100], character[100];
-    char *modif_p;
-    int  year, month, day, hour, minute, second, value;
-
-    memset (modif, '\0', sizeof (modif));
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%s %99[^\n]", modif, character) < 2)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>).");
-        return -1;
-    }
-
-    modif[sizeof (modif) - 1] = '\0';
-    character[sizeof (character) - 1] = '\0';
-
-    modif_p = modif;
-    year = month = day = hour = minute = second = 0;
-    while (modif_p[0] != '\0')
-    {
-        value = atoi (modif_p);
-        if (value == 0)
-            modif_p++;
-        else
-        {
-            if (modif_p[0] == '-' || modif_p[0] == '+')
-                modif_p++;
-            while (modif_p[0] >= '0' && modif_p[0] <= '9')
-                modif_p++;
-            if (modif_p[0] == 's')
-            {
-                second = value;
-                modif_p++;
-            }
-            else if (modif_p[0] == 'm' && modif_p[1] == 'n')
-            {
-                minute = value;
-                modif_p = modif_p + 2;
-            }
-            else if (modif_p[0] == 'h')
-            {
-                hour = value;
-                modif_p++;
-            }
-            else if (modif_p[0] == 'd' || modif_p[0] == 'j')
-            {
-                day = value;
-                modif_p++;
-            }
-            else if (modif_p[0] == 'm')
-            {
-                month = value;
-                modif_p++;
-            }
-            else if (modif_p[0] == 'y' || modif_p[0] == 'a')
-            {
-                year = value;
-                modif_p++;
-            }
-            else if (modif_p[0] != '\0')
-            {
-                modif_p++;
-            }
-        }
-    }
-    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
-        && second == 0)
-    {
-        clif_displaymessage (fd, msg_table[85]);    // Invalid time for ban command.
-        return -1;
-    }
-
-    // check player name
-    if (strlen (character) < 4)
-    {
-        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
-        return -1;
-    }
-    else if (strlen (character) > 23)
-    {
-        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
-        return -1;
-    }
-    else
-    {
-        chrif_char_ask_name (sd->status.account_id, character, 2, year, month, day, hour, minute, second);  // type: 2 - ban
-        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
-    }
-
-    return 0;
-}
-
-/*==========================================
- * charunblock command (usage: charunblock <player_name>)
- *------------------------------------------
- */
-int atcommand_char_unblock (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    char character[100];
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charunblock <player_name>).");
-        return -1;
-    }
-
-    // check player name
-    if (strlen (character) < 4)
-    {
-        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
-        return -1;
-    }
-    else if (strlen (character) > 23)
-    {
-        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
-        return -1;
-    }
-    else
-    {
-        // send answer to login server via char-server
-        chrif_char_ask_name (sd->status.account_id, character, 3, 0, 0, 0, 0, 0, 0);    // type: 3 - unblock
-        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
-    }
-
-    return 0;
-}
-
-/*==========================================
- * charunban command (usage: charunban <player_name>)
- *------------------------------------------
- */
-int atcommand_char_unban (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    char character[100];
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charunban <player_name>).");
-        return -1;
-    }
-
-    // check player name
-    if (strlen (character) < 4)
-    {
-        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
-        return -1;
-    }
-    else if (strlen (character) > 23)
-    {
-        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
-        return -1;
-    }
-    else
-    {
-        // send answer to login server via char-server
-        chrif_char_ask_name (sd->status.account_id, character, 4, 0, 0, 0, 0, 0, 0);    // type: 4 - unban
-        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_character_save (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char map_name[100];
-    char character[100];
-    struct map_session_data *pl_sd;
-    int  x = 0, y = 0;
-    int  m;
-
-    memset (map_name, '\0', sizeof (map_name));
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %d %d %99[^\n]", map_name, &x, &y,
-                   character) < 4 || x < 0 || y < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a valid save point and a player name (usage: @charsave <map> <x> <y> <charname>).");
-        return -1;
-    }
-
-    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-        strcat (map_name, ".gat");
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change save point only to lower or same gm level
-            m = map_mapname2mapid (map_name);
-            if (m < 0)
-            {
-                clif_displaymessage (fd, msg_table[1]); // Map not found.
-                return -1;
-            }
-            else
-            {
-                if (m >= 0 && map[m].flag.nowarpto
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                {
-                    clif_displaymessage (fd,
-                                         "You are not authorised to set this map as a save map.");
-                    return -1;
-                }
-                pc_setsavepoint (pl_sd, map_name, x, y);
-                clif_displaymessage (fd, msg_table[57]);    // Character's respawn point changed.
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_night (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    if (night_flag != 1)
-    {
-        night_flag = 1;         // 0=day, 1=night [Yor]
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                pl_sd->opt2 |= STATE_BLIND;
-                clif_changeoption (&pl_sd->bl);
-                clif_displaymessage (pl_sd->fd, msg_table[59]); // Night has fallen.
-            }
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[89]);    // Sorry, it's already the night. Impossible to execute the command.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_day (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    if (night_flag != 0)
-    {
-        night_flag = 0;         // 0=day, 1=night [Yor]
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                pl_sd->opt2 &= ~STATE_BLIND;
-                clif_changeoption (&pl_sd->bl);
-                clif_displaymessage (pl_sd->fd, msg_table[60]); // Day has arrived.
-            }
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[90]);    // Sorry, it's already the day. Impossible to execute the command.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_doom (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth && i != fd
-            && pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can doom only lower or same gm level
-            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
-            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
-        }
-    }
-    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_doommap (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m
-            && pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can doom only lower or same gm level
-            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
-            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
-        }
-    }
-    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static void atcommand_raise_sub (struct map_session_data *sd)
-{
-    if (sd && sd->state.auth && pc_isdead (sd))
-    {
-        sd->status.hp = sd->status.max_hp;
-        sd->status.sp = sd->status.max_sp;
-        pc_setstand (sd);
-        clif_updatestatus (sd, SP_HP);
-        clif_updatestatus (sd, SP_SP);
-        clif_resurrection (&sd->bl, 1);
-        clif_displaymessage (sd->fd, msg_table[63]);    // Mercy has been shown.
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_raise (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i])
-            atcommand_raise_sub ((struct map_session_data *)session[i]->session_data);
-    }
-    clif_displaymessage (fd, msg_table[64]);    // Mercy has been granted.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_raisemap (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m)
-            atcommand_raise_sub (pl_sd);
-    }
-    clif_displaymessage (fd, msg_table[64]);    // Mercy has been granted.
-
-    return 0;
-}
-
-/*==========================================
- * atcommand_character_baselevel @charbaselvlで対象キャラのレベルを上げる
- *------------------------------------------
-*/
-int atcommand_character_baselevel (const int fd, struct map_session_data *sd,
-                                   const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    int  level = 0, i;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &level, character) < 2
-        || level == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a level adjustement and a player name (usage: @charblvl <#> <nickname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change base level only lower or same gm level
-
-            if (level > 0)
-            {
-                if (pl_sd->status.base_level == battle_config.maximum_level)
-                {               // check for max level by Valaris
-                    clif_displaymessage (fd, msg_table[91]);    // Character's base level can't go any higher.
-                    return 0;
-                }               // End Addition
-                if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level))    // fix positiv overflow
-                    level =
-                        battle_config.maximum_level -
-                        pl_sd->status.base_level;
-                for (i = 1; i <= level; i++)
-                    pl_sd->status.status_point +=
-                        (pl_sd->status.base_level + i + 14) / 4;
-                pl_sd->status.base_level += level;
-                clif_updatestatus (pl_sd, SP_BASELEVEL);
-                clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
-                clif_updatestatus (pl_sd, SP_STATUSPOINT);
-                pc_calcstatus (pl_sd, 0);
-                pc_heal (pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp);
-                clif_misceffect (&pl_sd->bl, 0);
-                clif_displaymessage (fd, msg_table[65]);    // Character's base level raised.
-            }
-            else
-            {
-                if (pl_sd->status.base_level == 1)
-                {
-                    clif_displaymessage (fd, msg_table[193]);   // Character's base level can't go any lower.
-                    return -1;
-                }
-                if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level)) // fix negativ overflow
-                    level = 1 - pl_sd->status.base_level;
-                if (pl_sd->status.status_point > 0)
-                {
-                    for (i = 0; i > level; i--)
-                        pl_sd->status.status_point -=
-                            (pl_sd->status.base_level + i + 14) / 4;
-                    if (pl_sd->status.status_point < 0)
-                        pl_sd->status.status_point = 0;
-                    clif_updatestatus (pl_sd, SP_STATUSPOINT);
-                }               // to add: remove status points from stats
-                pl_sd->status.base_level += level;
-                pl_sd->status.base_exp = 0;
-                clif_updatestatus (pl_sd, SP_BASELEVEL);
-                clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
-                clif_updatestatus (pl_sd, SP_BASEEXP);
-                pc_calcstatus (pl_sd, 0);
-                clif_displaymessage (fd, msg_table[66]);    // Character's base level lowered.
-            }
-	    // Reset their stat points to prevent extra points from stacking
-	    atcommand_charstreset(fd, sd,"@charstreset", character);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;                   //正常終了
-}
-
-/*==========================================
- * atcommand_character_joblevel @charjoblvlで対象キャラのJobレベルを上げる
- *------------------------------------------
- */
-int atcommand_character_joblevel (const int fd, struct map_session_data *sd,
-                                  const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    int  max_level = 50, level = 0;
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job pl_s_class;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &level, character) < 2
-        || level == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        pl_s_class = pc_calc_base_job (pl_sd->status.pc_class);
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change job level only lower or same gm level
-            if (pl_s_class.job == 0)
-                max_level -= 40;
-            if ((pl_s_class.job == 23) || (pl_s_class.upper == 1 && pl_s_class.type == 2))  //スパノビと転生職はJobレベルの最高が70
-                max_level += 20;
-
-            if (level > 0)
-            {
-                if (pl_sd->status.job_level == max_level)
-                {
-                    clif_displaymessage (fd, msg_table[67]);    // Character's job level can't go any higher.
-                    return -1;
-                }
-                if (pl_sd->status.job_level + level > max_level)
-                    level = max_level - pl_sd->status.job_level;
-                pl_sd->status.job_level += level;
-                clif_updatestatus (pl_sd, SP_JOBLEVEL);
-                clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
-                pl_sd->status.skill_point += level;
-                clif_updatestatus (pl_sd, SP_SKILLPOINT);
-                pc_calcstatus (pl_sd, 0);
-                clif_misceffect (&pl_sd->bl, 1);
-                clif_displaymessage (fd, msg_table[68]);    // character's job level raised.
-            }
-            else
-            {
-                if (pl_sd->status.job_level == 1)
-                {
-                    clif_displaymessage (fd, msg_table[194]);   // Character's job level can't go any lower.
-                    return -1;
-                }
-                if (pl_sd->status.job_level + level < 1)
-                    level = 1 - pl_sd->status.job_level;
-                pl_sd->status.job_level += level;
-                clif_updatestatus (pl_sd, SP_JOBLEVEL);
-                clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
-                if (pl_sd->status.skill_point > 0)
-                {
-                    pl_sd->status.skill_point += level;
-                    if (pl_sd->status.skill_point < 0)
-                        pl_sd->status.skill_point = 0;
-                    clif_updatestatus (pl_sd, SP_SKILLPOINT);
-                }               // to add: remove status points from skills
-                pc_calcstatus (pl_sd, 0);
-                clif_displaymessage (fd, msg_table[69]);    // Character's job level lowered.
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_kick (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @kick <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))    // you can kick only lower or same gm level
-            clif_GM_kick (sd, pl_sd, 1);
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_kickall (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth && pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can kick only lower or same gm level
-            if (sd->status.account_id != pl_sd->status.account_id)
-                clif_GM_kick (sd, pl_sd, 0);
-        }
-    }
-
-    clif_displaymessage (fd, msg_table[195]);   // All players have been kicked!
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_allskills (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    pc_allskillup (sd);         // all skills
-    sd->status.skill_point = 0; // 0 skill points
-    clif_updatestatus (sd, SP_SKILLPOINT);  // update
-    clif_displaymessage (fd, msg_table[76]);    // You have received all skills.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_questskill (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    int  skill_id;
-
-    if (!message || !*message || (skill_id = atoi (message)) < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a quest skill number (usage: @questskill <#:0+>).");
-        return -1;
-    }
-
-    if (skill_id >= 0 && skill_id < MAX_SKILL_DB)
-    {
-        if (skill_get_inf2 (skill_id) & 0x01)
-        {
-            if (pc_checkskill (sd, skill_id) == 0)
-            {
-                pc_skill (sd, skill_id, 1, 0);
-                clif_displaymessage (fd, msg_table[70]);    // You have learned the skill.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[196]);   // You already have this quest skill.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_charquestskill (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-    int  skill_id = 0;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &skill_id, character) < 2
-        || skill_id < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>).");
-        return -1;
-    }
-
-    if (skill_id >= 0 && skill_id < MAX_SKILL_DB)
-    {
-        if (skill_get_inf2 (skill_id) & 0x01)
-        {
-            if ((pl_sd = map_nick2sd (character)) != NULL)
-            {
-                if (pc_checkskill (pl_sd, skill_id) == 0)
-                {
-                    pc_skill (pl_sd, skill_id, 1, 0);
-                    clif_displaymessage (fd, msg_table[199]);   // This player has learned the skill.
-                }
-                else
-                {
-                    clif_displaymessage (fd, msg_table[200]);   // This player already has this quest skill.
-                    return -1;
-                }
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[3]); // Character not found.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_lostskill (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    int  skill_id;
-
-    if (!message || !*message || (skill_id = atoi (message)) < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a quest skill number (usage: @lostskill <#:0+>).");
-        return -1;
-    }
-
-    if (skill_id >= 0 && skill_id < MAX_SKILL)
-    {
-        if (skill_get_inf2 (skill_id) & 0x01)
-        {
-            if (pc_checkskill (sd, skill_id) > 0)
-            {
-                sd->status.skill[skill_id].lv = 0;
-                sd->status.skill[skill_id].flags = 0;
-                clif_skillinfoblock (sd);
-                clif_displaymessage (fd, msg_table[71]);    // You have forgotten the skill.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[201]);   // You don't have this quest skill.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_charlostskill (const int fd, struct map_session_data *sd,
-                             const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-    int  skill_id = 0;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &skill_id, character) < 2
-        || skill_id < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
-        return -1;
-    }
-
-    if (skill_id >= 0 && skill_id < MAX_SKILL)
-    {
-        if (skill_get_inf2 (skill_id) & 0x01)
-        {
-            if ((pl_sd = map_nick2sd (character)) != NULL)
-            {
-                if (pc_checkskill (pl_sd, skill_id) > 0)
-                {
-                    pl_sd->status.skill[skill_id].lv = 0;
-                    pl_sd->status.skill[skill_id].flags = 0;
-                    clif_skillinfoblock (pl_sd);
-                    clif_displaymessage (fd, msg_table[202]);   // This player has forgotten the skill.
-                }
-                else
-                {
-                    clif_displaymessage (fd, msg_table[203]);   // This player doesn't have this quest skill.
-                    return -1;
-                }
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[3]); // Character not found.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_party (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char party[100];
-
-    memset (party, '\0', sizeof (party));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", party) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a party name (usage: @party <party_name>).");
-        return -1;
-    }
-
-    party_create (sd, party);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_guild (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char guild[100];
-    int  prev;
-
-    memset (guild, '\0', sizeof (guild));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", guild) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a guild name (usage: @guild <guild_name>).");
-        return -1;
-    }
-
-    prev = battle_config.guild_emperium_check;
-    battle_config.guild_emperium_check = 0;
-    guild_create (sd, guild);
-    battle_config.guild_emperium_check = prev;
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_agitstart (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    if (agit_flag == 1)
-    {
-        clif_displaymessage (fd, msg_table[73]);    // Already it has started siege warfare.
-        return -1;
-    }
-
-    agit_flag = 1;
-    guild_agit_start ();
-    clif_displaymessage (fd, msg_table[72]);    // Guild siege warfare start!
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_agitend (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    if (agit_flag == 0)
-    {
-        clif_displaymessage (fd, msg_table[75]);    // Siege warfare hasn't started yet.
-        return -1;
-    }
-
-    agit_flag = 0;
-    guild_agit_end ();
-    clif_displaymessage (fd, msg_table[74]);    // Guild siege warfare end!
-
-    return 0;
-}
-
-/*==========================================
- * @mapexitでマップサーバーを終了させる
- *------------------------------------------
- */
-int atcommand_mapexit (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            if (sd->status.account_id != pl_sd->status.account_id)
-                clif_GM_kick (sd, pl_sd, 0);
-        }
-    }
-    clif_GM_kick (sd, sd, 0);
-
-    runflag = 0;
-
-    return 0;
-}
-
-/*==========================================
- * idsearch <part_of_name>: revrited by [Yor]
- *------------------------------------------
- */
-int atcommand_idsearch (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char item_name[100];
-    char output[200];
-    int  i, match;
-    struct item_data *item;
-
-    memset (item_name, '\0', sizeof (item_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99s", item_name) < 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a part of item name (usage: @idsearch <part_of_item_name>).");
-        return -1;
-    }
-
-    sprintf (output, msg_table[77], item_name); // The reference result of '%s' (name: id):
-    clif_displaymessage (fd, output);
-    match = 0;
-    for (i = 0; i < 20000; i++)
-    {
-        if ((item = itemdb_exists (i)) != NULL
-            && strstr (item->jname, item_name) != NULL)
-        {
-            match++;
-            sprintf (output, msg_table[78], item->jname, item->nameid); // %s: %d
-            clif_displaymessage (fd, output);
-        }
-    }
-    sprintf (output, msg_table[79], match); // It is %d affair above.
-    clif_displaymessage (fd, output);
-
-    return 0;
-}
-
-/*==========================================
- * Character Skill Reset
- *------------------------------------------
- */
-int atcommand_charskreset (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charskreset <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can reset skill points only lower or same gm level
-            pc_resetskill (pl_sd);
-            sprintf (output, msg_table[206], character);    // '%s' skill points reseted!
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Stat Reset
- *------------------------------------------
- */
-int atcommand_charstreset (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charstreset <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can reset stats points only lower or same gm level
-            pc_resetstate (pl_sd);
-            sprintf (output, msg_table[207], character);    // '%s' stats points reseted!
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Reset
- *------------------------------------------
- */
-int atcommand_charreset (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charreset <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can reset a character only for lower or same GM level
-            pc_resetstate (pl_sd);
-            pc_resetskill (pl_sd);
-            pc_setglobalreg (pl_sd, "MAGIC_FLAGS", 0);  // [Fate] Reset magic quest variables
-            pc_setglobalreg (pl_sd, "MAGIC_EXP", 0);    // [Fate] Reset magic experience
-            sprintf (output, msg_table[208], character);    // '%s' skill and stats points reseted!
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Wipe
- *------------------------------------------
- */
-int atcommand_char_wipe (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charwipe <charname>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can reset a character only for lower or same GM level
-            int  i;
-
-            // Reset base level
-            pl_sd->status.base_level = 1;
-            pl_sd->status.base_exp = 0;
-            clif_updatestatus (pl_sd, SP_BASELEVEL);
-            clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
-            clif_updatestatus (pl_sd, SP_BASEEXP);
-
-            // Reset job level
-            pl_sd->status.job_level = 1;
-            pl_sd->status.job_exp = 0;
-            clif_updatestatus (pl_sd, SP_JOBLEVEL);
-            clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
-            clif_updatestatus (pl_sd, SP_JOBEXP);
-
-            // Zeny to 50
-            pl_sd->status.zeny = 50;
-            clif_updatestatus (pl_sd, SP_ZENY);
-
-            // Clear inventory
-            for (i = 0; i < MAX_INVENTORY; i++)
-            {
-                if (sd->status.inventory[i].amount)
-                {
-                    if (sd->status.inventory[i].equip)
-                        pc_unequipitem (pl_sd, i, 0);
-                    pc_delitem (pl_sd, i, sd->status.inventory[i].amount, 0);
-                }
-            }
-
-            // Give knife and shirt
-            struct item item;
-            item.nameid = 1201; // knife
-            item.identify = 1;
-            item.broken = 0;
-            pc_additem (pl_sd, &item, 1);
-            item.nameid = 1202; // shirt
-            pc_additem (pl_sd, &item, 1);
-
-            // Reset stats and skills
-            pc_calcstatus (pl_sd, 0);
-            pc_resetstate (pl_sd);
-            pc_resetskill (pl_sd);
-            pc_setglobalreg (pl_sd, "MAGIC_FLAGS", 0);  // [Fate] Reset magic quest variables
-            pc_setglobalreg (pl_sd, "MAGIC_EXP", 0);    // [Fate] Reset magic experience
-
-            sprintf (output, "%s:  wiped.", character); // '%s' skill and stats points reseted!
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Model by chbrules
- *------------------------------------------
- */
-int atcommand_charmodel (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    int  hair_style = 0, hair_color = 0, cloth_color = 0;
-    struct map_session_data *pl_sd;
-    char character[100];
-    char output[200];
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message
-        || sscanf (message, "%d %d %d %99[^\n]", &hair_style, &hair_color,
-                   &cloth_color, character) < 4 || hair_style < 0
-        || hair_color < 0 || cloth_color < 0)
-    {
-        sprintf (output,
-                 "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
-                 MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR,
-                 MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
-        clif_displaymessage (fd, output);
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
-            hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
-            cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
-        {
-
-            if (cloth_color != 0 &&
-                pl_sd->status.sex == 1 &&
-                (pl_sd->status.pc_class == 12 || pl_sd->status.pc_class == 17))
-            {
-                clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
-                return -1;
-            }
-            else
-            {
-                pc_changelook (pl_sd, LOOK_HAIR, hair_style);
-                pc_changelook (pl_sd, LOOK_HAIR_COLOR, hair_color);
-                pc_changelook (pl_sd, LOOK_CLOTHES_COLOR, cloth_color);
-                clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Skill Point (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_charskpoint (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    int  new_skill_point;
-    int  point = 0;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &point, character) < 2
-        || point == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        new_skill_point = (int) pl_sd->status.skill_point + point;
-        if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))  // fix positiv overflow
-            new_skill_point = 0x7FFF;
-        else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow
-            new_skill_point = 0;
-        if (new_skill_point != (int) pl_sd->status.skill_point)
-        {
-            pl_sd->status.skill_point = new_skill_point;
-            clif_updatestatus (pl_sd, SP_SKILLPOINT);
-            clif_displaymessage (fd, msg_table[209]);   // Character's number of skill points changed!
-        }
-        else
-        {
-            if (point < 0)
-                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-            else
-                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Status Point (rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_charstpoint (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    int  new_status_point;
-    int  point = 0;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &point, character) < 2
-        || point == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        new_status_point = (int) pl_sd->status.status_point + point;
-        if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
-            new_status_point = 0x7FFF;
-        else if (point < 0 && (point < -0x7FFF || new_status_point < 0))    // fix negativ overflow
-            new_status_point = 0;
-        if (new_status_point != (int) pl_sd->status.status_point)
-        {
-            pl_sd->status.status_point = new_status_point;
-            clif_updatestatus (pl_sd, SP_STATUSPOINT);
-            clif_displaymessage (fd, msg_table[210]);   // Character's number of status points changed!
-        }
-        else
-        {
-            if (point < 0)
-                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-            else
-                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Character Zeny Point (Rewritten by [Yor])
- *------------------------------------------
- */
-int atcommand_charzeny (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    int  zeny = 0, new_zeny;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a number and a player name (usage: @charzeny <zeny> <name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        new_zeny = pl_sd->status.zeny + zeny;
-        if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))   // fix positiv overflow
-            new_zeny = MAX_ZENY;
-        else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))    // fix negativ overflow
-            new_zeny = 0;
-        if (new_zeny != pl_sd->status.zeny)
-        {
-            pl_sd->status.zeny = new_zeny;
-            clif_updatestatus (pl_sd, SP_ZENY);
-            clif_displaymessage (fd, msg_table[211]);   // Character's number of zenys changed!
-        }
-        else
-        {
-            if (zeny < 0)
-                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
-            else
-                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Recall All Characters Online To Your Location
- *------------------------------------------
- */
-int atcommand_recallall (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-    int  count;
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp somenone to your actual map.");
-        return -1;
-    }
-
-    count = 0;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth
-            && sd->status.account_id != pl_sd->status.account_id
-            && pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can recall only lower or same level
-            if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
-                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                count++;
-            else
-                pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
-        }
-    }
-
-    clif_displaymessage (fd, msg_table[92]);    // All characters recalled!
-    if (count)
-    {
-        sprintf (output,
-                 "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
-                 count);
-        clif_displaymessage (fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Recall online characters of a guild to your location
- *------------------------------------------
- */
-int atcommand_guildrecall (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-    char guild_name[100];
-    char output[200];
-    struct guild *g;
-    int  count;
-
-    memset (guild_name, '\0', sizeof (guild_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", guild_name) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a guild name/id (usage: @guildrecall <guild_name/id>).");
-        return -1;
-    }
-
-    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp somenone to your actual map.");
-        return -1;
-    }
-
-    if ((g = guild_searchname (guild_name)) != NULL ||  // name first to avoid error when name begin with a number
-        (g = guild_search (atoi (message))) != NULL)
-    {
-        count = 0;
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth
-                && sd->status.account_id != pl_sd->status.account_id
-                && pl_sd->status.guild_id == g->guild_id)
-            {
-                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                    count++;
-                else
-                    pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
-            }
-        }
-        sprintf (output, msg_table[93], g->name);   // All online characters of the %s guild are near you.
-        clif_displaymessage (fd, output);
-        if (count)
-        {
-            sprintf (output,
-                     "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
-                     count);
-            clif_displaymessage (fd, output);
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[94]);    // Incorrect name/ID, or no one from the guild is online.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Recall online characters of a party to your location
- *------------------------------------------
- */
-int atcommand_partyrecall (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    int  i;
-    struct map_session_data *pl_sd;
-    char party_name[100];
-    char output[200];
-    struct party *p;
-    int  count;
-
-    memset (party_name, '\0', sizeof (party_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", party_name) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a party name/id (usage: @partyrecall <party_name/id>).");
-        return -1;
-    }
-
-    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp somenone to your actual map.");
-        return -1;
-    }
-
-    if ((p = party_searchname (party_name)) != NULL ||  // name first to avoid error when name begin with a number
-        (p = party_search (atoi (message))) != NULL)
-    {
-        count = 0;
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth
-                && sd->status.account_id != pl_sd->status.account_id
-                && pl_sd->status.party_id == p->party_id)
-            {
-                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
-                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-                    count++;
-                else
-                    pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
-            }
-        }
-        sprintf (output, msg_table[95], p->name);   // All online characters of the %s party are near you.
-        clif_displaymessage (fd, output);
-        if (count)
-        {
-            sprintf (output,
-                     "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
-                     count);
-            clif_displaymessage (fd, output);
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[96]);    // Incorrect name or ID, or no one from the party is online.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_reloaditemdb (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    itemdb_reload ();
-    clif_displaymessage (fd, msg_table[97]);    // Item database reloaded.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_reloadmobdb (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    mob_reload ();
-    clif_displaymessage (fd, msg_table[98]);    // Monster database reloaded.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_reloadskilldb (const int fd, struct map_session_data *sd,
-                             const char *command, const char *message)
-{
-    skill_reload ();
-    clif_displaymessage (fd, msg_table[99]);    // Skill database reloaded.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_reloadscript (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    do_init_npc ();
-    do_init_script ();
-
-    npc_event_do_oninit ();
-
-    clif_displaymessage (fd, msg_table[100]);   // Scripts reloaded.
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_reloadgmdb (      // by [Yor]
-                             const int fd, struct map_session_data *sd,
-                             const char *command, const char *message)
-{
-    chrif_reloadGMdb ();
-
-    clif_displaymessage (fd, msg_table[101]);   // Login-server asked to reload GM accounts and their level.
-
-    return 0;
-}
-
-/*==========================================
- * @mapinfo <map name> [0-3] by MC_Cameri
- * => Shows information about the map [map name]
- * 0 = no additional information
- * 1 = Show users in that map and their location
- * 2 = Shows NPCs in that map
- * 3 = Shows the shops/chats in that map (not implemented)
- *------------------------------------------
- */
-int atcommand_mapinfo (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    struct npc_data *nd = NULL;
-    struct chat_data *cd = NULL;
-    char output[200], map_name[100];
-    char direction[12];
-    int  m_id, i, chat_num, list = 0;
-
-    memset (output, '\0', sizeof (output));
-    memset (map_name, '\0', sizeof (map_name));
-    memset (direction, '\0', sizeof (direction));
-
-    sscanf (message, "%d %99[^\n]", &list, map_name);
-
-    if (list < 0 || list > 3)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
-        return -1;
-    }
-
-    if (map_name[0] == '\0')
-        strcpy (map_name, sd->mapname);
-    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
-        strcat (map_name, ".gat");
-
-    if ((m_id = map_mapname2mapid (map_name)) < 0)
-    {
-        clif_displaymessage (fd, msg_table[1]); // Map not found.
-        return -1;
-    }
-
-    clif_displaymessage (fd, "------ Map Info ------");
-    sprintf (output, "Map Name: %s", map_name);
-    clif_displaymessage (fd, output);
-    sprintf (output, "Players In Map: %d", map[m_id].users);
-    clif_displaymessage (fd, output);
-    sprintf (output, "NPCs In Map: %d", map[m_id].npc_num);
-    clif_displaymessage (fd, output);
-    chat_num = 0;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth
-            && (cd = (struct chat_data *) map_id2bl (pl_sd->chatID)))
-        {
-            chat_num++;
-        }
-    }
-    sprintf (output, "Chats In Map: %d", chat_num);
-    clif_displaymessage (fd, output);
-    clif_displaymessage (fd, "------ Map Flags ------");
-    sprintf (output, "Player vs Player: %s | No Guild: %s | No Party: %s",
-             (map[m_id].flag.pvp) ? "True" : "False",
-             (map[m_id].flag.pvp_noguild) ? "True" : "False",
-             (map[m_id].flag.pvp_noparty) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "Guild vs Guild: %s | No Party: %s",
-             (map[m_id].flag.gvg) ? "True" : "False",
-             (map[m_id].flag.gvg_noparty) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Dead Branch: %s",
-             (map[m_id].flag.nobranch) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Memo: %s",
-             (map[m_id].flag.nomemo) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Penalty: %s",
-             (map[m_id].flag.nopenalty) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Return: %s",
-             (map[m_id].flag.noreturn) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Save: %s",
-             (map[m_id].flag.nosave) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Teleport: %s",
-             (map[m_id].flag.noteleport) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Monster Teleport: %s",
-             (map[m_id].flag.monster_noteleport) ? "True" : "False");
-    clif_displaymessage (fd, output);
-    sprintf (output, "No Zeny Penalty: %s",
-             (map[m_id].flag.nozenypenalty) ? "True" : "False");
-    clif_displaymessage (fd, output);
-
-    switch (list)
-    {
-        case 0:
-            // Do nothing. It's list 0, no additional display.
-            break;
-        case 1:
-            clif_displaymessage (fd, "----- Players in Map -----");
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                    && pl_sd->state.auth
-                    && strcmp (pl_sd->mapname, map_name) == 0)
-                {
-                    sprintf (output,
-                             "Player '%s' (session #%d) | Location: %d,%d",
-                             pl_sd->status.name, i, pl_sd->bl.x, pl_sd->bl.y);
-                    clif_displaymessage (fd, output);
-                }
-            }
-            break;
-        case 2:
-            clif_displaymessage (fd, "----- NPCs in Map -----");
-            for (i = 0; i < map[m_id].npc_num;)
-            {
-                nd = map[m_id].npc[i];
-                switch (nd->dir)
-                {
-                    case 0:
-                        strcpy (direction, "North");
-                        break;
-                    case 1:
-                        strcpy (direction, "North West");
-                        break;
-                    case 2:
-                        strcpy (direction, "West");
-                        break;
-                    case 3:
-                        strcpy (direction, "South West");
-                        break;
-                    case 4:
-                        strcpy (direction, "South");
-                        break;
-                    case 5:
-                        strcpy (direction, "South East");
-                        break;
-                    case 6:
-                        strcpy (direction, "East");
-                        break;
-                    case 7:
-                        strcpy (direction, "North East");
-                        break;
-                    case 9:
-                        strcpy (direction, "North");
-                        break;
-                    default:
-                        strcpy (direction, "Unknown");
-                        break;
-                }
-                sprintf (output,
-                         "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d",
-                         ++i, nd->name, direction, nd->npc_class, nd->bl.x,
-                         nd->bl.y);
-                clif_displaymessage (fd, output);
-            }
-            break;
-        case 3:
-            clif_displaymessage (fd, "----- Chats in Map -----");
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                    && pl_sd->state.auth
-                    && (cd = (struct chat_data *) map_id2bl (pl_sd->chatID))
-                    && strcmp (pl_sd->mapname, map_name) == 0
-                    && cd->usersd[0] == pl_sd)
-                {
-                    sprintf (output,
-                             "Chat %d: %s | Player: %s | Location: %d %d", i,
-                             cd->title, pl_sd->status.name, cd->bl.x,
-                             cd->bl.y);
-                    clif_displaymessage (fd, output);
-                    sprintf (output,
-                             "   Users: %d/%d | Password: %s | Public: %s",
-                             cd->users, cd->limit, cd->pass,
-                             (cd->pub) ? "Yes" : "No");
-                    clif_displaymessage (fd, output);
-                }
-            }
-            break;
-        default:               // normally impossible to arrive here
-            clif_displaymessage (fd,
-                                 "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
-            return -1;
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_mount_peco (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    if (sd->disguise > 0)
-    {                           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-        clif_displaymessage (fd, msg_table[212]);   // Cannot mount a Peco while in disguise.
-        return -1;
-    }
-
-    if (!pc_isriding (sd))
-    {                           // if actually no peco
-        if (sd->status.pc_class == 7 || sd->status.pc_class == 14
-            || sd->status.pc_class == 4008 || sd->status.pc_class == 4015)
-        {
-            if (sd->status.pc_class == 7)
-                sd->status.pc_class = sd->view_class = 13;
-            else if (sd->status.pc_class == 14)
-                sd->status.pc_class = sd->view_class = 21;
-            else if (sd->status.pc_class == 4008)
-                sd->status.pc_class = sd->view_class = 4014;
-            else if (sd->status.pc_class == 4015)
-                sd->status.pc_class = sd->view_class = 4022;
-            pc_setoption (sd, sd->status.option | 0x0020);
-            clif_displaymessage (fd, msg_table[102]);   // Mounted Peco.
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[213]);   // You can not mount a peco with your job.
-            return -1;
-        }
-    }
-    else
-    {
-        if (sd->status.pc_class == 13)
-            sd->status.pc_class = sd->view_class = 7;
-        else if (sd->status.pc_class == 21)
-            sd->status.pc_class = sd->view_class = 14;
-        else if (sd->status.pc_class == 4014)
-            sd->status.pc_class = sd->view_class = 4008;
-        else if (sd->status.pc_class == 4022)
-            sd->status.pc_class = sd->view_class = 4015;
-        pc_setoption (sd, sd->status.option & ~0x0020);
-        clif_displaymessage (fd, msg_table[214]);   // Unmounted Peco.
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_char_mount_peco (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charmountpeco <char_name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pl_sd->disguise > 0)
-        {                       // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-            clif_displaymessage (fd, msg_table[215]);   // This player cannot mount a Peco while in disguise.
-            return -1;
-        }
-
-        if (!pc_isriding (pl_sd))
-        {                       // if actually no peco
-            if (pl_sd->status.pc_class == 7 || pl_sd->status.pc_class == 14
-                || pl_sd->status.pc_class == 4008 || pl_sd->status.pc_class == 4015)
-            {
-                if (pl_sd->status.pc_class == 7)
-                    pl_sd->status.pc_class = pl_sd->view_class = 13;
-                else if (pl_sd->status.pc_class == 14)
-                    pl_sd->status.pc_class = pl_sd->view_class = 21;
-                else if (pl_sd->status.pc_class == 4008)
-                    pl_sd->status.pc_class = pl_sd->view_class = 4014;
-                else if (pl_sd->status.pc_class == 4015)
-                    pl_sd->status.pc_class = pl_sd->view_class = 4022;
-                pc_setoption (pl_sd, pl_sd->status.option | 0x0020);
-                clif_displaymessage (fd, msg_table[216]);   // Now, this player mounts a peco.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[217]);   // This player can not mount a peco with his/her job.
-                return -1;
-            }
-        }
-        else
-        {
-            if (pl_sd->status.pc_class == 13)
-                pl_sd->status.pc_class = pl_sd->view_class = 7;
-            else if (pl_sd->status.pc_class == 21)
-                pl_sd->status.pc_class = pl_sd->view_class = 14;
-            else if (pl_sd->status.pc_class == 4014)
-                pl_sd->status.pc_class = pl_sd->view_class = 4008;
-            else if (pl_sd->status.pc_class == 4022)
-                pl_sd->status.pc_class = pl_sd->view_class = 4015;
-            pc_setoption (pl_sd, pl_sd->status.option & ~0x0020);
-            clif_displaymessage (fd, msg_table[218]);   // Now, this player has not more peco.
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *Spy Commands by Syrus22
- *------------------------------------------
- */
-int atcommand_guildspy (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char guild_name[100];
-    char output[200];
-    struct guild *g;
-
-    memset (guild_name, '\0', sizeof (guild_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", guild_name) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a guild name/id (usage: @guildspy <guild_name/id>).");
-        return -1;
-    }
-
-    if ((g = guild_searchname (guild_name)) != NULL ||  // name first to avoid error when name begin with a number
-        (g = guild_search (atoi (message))) != NULL)
-    {
-        if (sd->guildspy == g->guild_id)
-        {
-            sd->guildspy = 0;
-            sprintf (output, msg_table[103], g->name);  // No longer spying on the %s guild.
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            sd->guildspy = g->guild_id;
-            sprintf (output, msg_table[104], g->name);  // Spying on the %s guild.
-            clif_displaymessage (fd, output);
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[94]);    // Incorrect name/ID, or no one from the guild is online.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_partyspy (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    char party_name[100];
-    char output[200];
-    struct party *p;
-
-    memset (party_name, '\0', sizeof (party_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", party_name) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a party name/id (usage: @partyspy <party_name/id>).");
-        return -1;
-    }
-
-    if ((p = party_searchname (party_name)) != NULL ||  // name first to avoid error when name begin with a number
-        (p = party_search (atoi (message))) != NULL)
-    {
-        if (sd->partyspy == p->party_id)
-        {
-            sd->partyspy = 0;
-            sprintf (output, msg_table[105], p->name);  // No longer spying on the %s party.
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            sd->partyspy = p->party_id;
-            sprintf (output, msg_table[106], p->name);  // Spying on the %s party.
-            clif_displaymessage (fd, output);
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[96]);    // Incorrect name or ID, or no one from the party is online.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_enablenpc (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    char NPCname[100];
-
-    memset (NPCname, '\0', sizeof (NPCname));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", NPCname) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a NPC name (usage: @npcon <NPC_name>).");
-        return -1;
-    }
-
-    if (npc_name2id (NPCname) != NULL)
-    {
-        npc_enable (NPCname, 1);
-        clif_displaymessage (fd, msg_table[110]);   // Npc Enabled.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[111]);   // This NPC doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_disablenpc (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    char NPCname[100];
-
-    memset (NPCname, '\0', sizeof (NPCname));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", NPCname) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a NPC name (usage: @npcoff <NPC_name>).");
-        return -1;
-    }
-
-    if (npc_name2id (NPCname) != NULL)
-    {
-        npc_enable (NPCname, 0);
-        clif_displaymessage (fd, msg_table[112]);   // Npc Disabled.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[111]);   // This NPC doesn't exist.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * time in txt for time command (by [Yor])
- *------------------------------------------
- */
-char *txt_time (unsigned int duration)
-{
-    int  days, hours, minutes, seconds;
-    char temp[256];
-    static char temp1[256];
-
-    memset (temp, '\0', sizeof (temp));
-    memset (temp1, '\0', sizeof (temp1));
-
-    if (duration < 0)
-        duration = 0;
-
-    days = duration / (60 * 60 * 24);
-    duration = duration - (60 * 60 * 24 * days);
-    hours = duration / (60 * 60);
-    duration = duration - (60 * 60 * hours);
-    minutes = duration / 60;
-    seconds = duration - (60 * minutes);
-
-    if (days < 2)
-        sprintf (temp, msg_table[219], days);   // %d day
-    else
-        sprintf (temp, msg_table[220], days);   // %d days
-    if (hours < 2)
-        sprintf (temp1, msg_table[221], temp, hours);   // %s %d hour
-    else
-        sprintf (temp1, msg_table[222], temp, hours);   // %s %d hours
-    if (minutes < 2)
-        sprintf (temp, msg_table[223], temp1, minutes); // %s %d minute
-    else
-        sprintf (temp, msg_table[224], temp1, minutes); // %s %d minutes
-    if (seconds < 2)
-        sprintf (temp1, msg_table[225], temp, seconds); // %s and %d second
-    else
-        sprintf (temp1, msg_table[226], temp, seconds); // %s and %d seconds
-
-    return temp1;
-}
-
-/*==========================================
- * @time/@date/@server_date/@serverdate/@server_time/@servertime: Display the date/time of the server (by [Yor]
- * Calculation management of GM modification (@day/@night GM commands) is done
- *------------------------------------------
- */
-int atcommand_servertime (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    struct TimerData *timer_data;
-    struct TimerData *timer_data2;
-    time_t time_server;         // variable for number of seconds (used with time() function)
-    struct tm *datetime;        // variable for time in structure ->tm_mday, ->tm_sec, ...
-    char temp[256];
-
-    memset (temp, '\0', sizeof (temp));
-
-    time (&time_server);        // get time in seconds since 1/1/1970
-    datetime = gmtime (&time_server);   // convert seconds in structure
-    // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52)
-    strftime (temp, sizeof (temp) - 1, msg_table[230], datetime);   // Server time (normal time): %A, %B %d %Y %X.
-    clif_displaymessage (fd, temp);
-
-    if (battle_config.night_duration == 0 && battle_config.day_duration == 0)
-    {
-        if (night_flag == 0)
-            clif_displaymessage (fd, msg_table[231]);   // Game time: The game is in permanent daylight.
-        else
-            clif_displaymessage (fd, msg_table[232]);   // Game time: The game is in permanent night.
-    }
-    else if (battle_config.night_duration == 0)
-        if (night_flag == 1)
-        {                       // we start with night
-            timer_data = get_timer (day_timer_tid);
-            sprintf (temp, msg_table[233], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in night for %s.
-            clif_displaymessage (fd, temp);
-            clif_displaymessage (fd, msg_table[234]);   // Game time: After, the game will be in permanent daylight.
-        }
-        else
-            clif_displaymessage (fd, msg_table[231]);   // Game time: The game is in permanent daylight.
-    else if (battle_config.day_duration == 0)
-        if (night_flag == 0)
-        {                       // we start with day
-            timer_data = get_timer (night_timer_tid);
-            sprintf (temp, msg_table[235], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in daylight for %s.
-            clif_displaymessage (fd, temp);
-            clif_displaymessage (fd, msg_table[236]);   // Game time: After, the game will be in permanent night.
-        }
-        else
-            clif_displaymessage (fd, msg_table[232]);   // Game time: The game is in permanent night.
-    else
-    {
-        if (night_flag == 0)
-        {
-            timer_data = get_timer (night_timer_tid);
-            timer_data2 = get_timer (day_timer_tid);
-            sprintf (temp, msg_table[235], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in daylight for %s.
-            clif_displaymessage (fd, temp);
-            if (timer_data->tick > timer_data2->tick)
-                sprintf (temp, msg_table[237], txt_time ((timer_data->interval - abs (timer_data->tick - timer_data2->tick)) / 1000));  // Game time: After, the game will be in night for %s.
-            else
-                sprintf (temp, msg_table[237], txt_time (abs (timer_data->tick - timer_data2->tick) / 1000));   // Game time: After, the game will be in night for %s.
-            clif_displaymessage (fd, temp);
-            sprintf (temp, msg_table[238], txt_time (timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
-            clif_displaymessage (fd, temp);
-        }
-        else
-        {
-            timer_data = get_timer (day_timer_tid);
-            timer_data2 = get_timer (night_timer_tid);
-            sprintf (temp, msg_table[233], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in night for %s.
-            clif_displaymessage (fd, temp);
-            if (timer_data->tick > timer_data2->tick)
-                sprintf (temp, msg_table[239], txt_time ((timer_data->interval - abs (timer_data->tick - timer_data2->tick)) / 1000));  // Game time: After, the game will be in daylight for %s.
-            else
-                sprintf (temp, msg_table[239], txt_time (abs (timer_data->tick - timer_data2->tick) / 1000));   // Game time: After, the game will be in daylight for %s.
-            clif_displaymessage (fd, temp);
-            sprintf (temp, msg_table[238], txt_time (timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
-            clif_displaymessage (fd, temp);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @chardelitem <item_name_or_ID> <quantity> <player> (by [Yor]
- * removes <quantity> item from a character
- * item can be equiped or not.
- * Inspired from a old command created by RoVeRT
- *------------------------------------------
- */
-int atcommand_chardelitem (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    char character[100];
-    char item_name[100];
-    int  i, number = 0, item_id, item_position, count;
-    char output[200];
-    struct item_data *item_data;
-
-    memset (character, '\0', sizeof (character));
-    memset (item_name, '\0', sizeof (item_name));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message
-        || sscanf (message, "%s %d %99[^\n]", item_name, &number,
-                   character) < 3 || number < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>).");
-        return -1;
-    }
-
-    item_id = 0;
-    if ((item_data = itemdb_searchname (item_name)) != NULL ||
-        (item_data = itemdb_exists (atoi (item_name))) != NULL)
-        item_id = item_data->nameid;
-
-    if (item_id > 500)
-    {
-        if ((pl_sd = map_nick2sd (character)) != NULL)
-        {
-            if (pc_isGM (sd) >= pc_isGM (pl_sd))
-            {                   // you can kill only lower or same level
-                item_position = pc_search_inventory (pl_sd, item_id);
-                if (item_position >= 0)
-                {
-                    count = 0;
-                    for (i = 0; i < number && item_position >= 0; i++)
-                    {
-                        pc_delitem (pl_sd, item_position, 1, 0);
-                        count++;
-                        item_position = pc_search_inventory (pl_sd, item_id);   // for next loop
-                    }
-                    sprintf (output, msg_table[113], count);    // %d item(s) removed by a GM.
-                    clif_displaymessage (pl_sd->fd, output);
-                    if (number == count)
-                        sprintf (output, msg_table[114], count);    // %d item(s) removed from the player.
-                    else
-                        sprintf (output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items.
-                    clif_displaymessage (fd, output);
-                }
-                else
-                {
-                    clif_displaymessage (fd, msg_table[116]);   // Character does not have the item.
-                    return -1;
-                }
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[3]); // Character not found.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[19]);    // Invalid item ID or name.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @jail <char_name> by [Yor]
- * Special warp! No check with nowarp and nowarpto flag
- *------------------------------------------
- */
-int atcommand_jail (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-    int  x, y;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @jail <char_name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can jail only lower or same GM
-            switch (MRAND (2))
-            {
-                case 0:
-                    x = 24;
-                    y = 75;
-                    break;
-                default:
-                    x = 49;
-                    y = 75;
-                    break;
-            }
-            if (pc_setpos (pl_sd, "sec_pri.gat", x, y, 3) == 0)
-            {
-                pc_setsavepoint (pl_sd, "sec_pri.gat", x, y);   // Save Char Respawn Point in the jail room [Lupus]
-                clif_displaymessage (pl_sd->fd, msg_table[117]);    // GM has send you in jails.
-                clif_displaymessage (fd, msg_table[118]);   // Player warped in jails.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[1]); // Map not found.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @unjail/@discharge <char_name> by [Yor]
- * Special warp! No check with nowarp and nowarpto flag
- *------------------------------------------
- */
-int atcommand_unjail (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @unjail/@discharge <char_name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can jail only lower or same GM
-            if (pl_sd->bl.m != map_mapname2mapid ("sec_pri.gat"))
-            {
-                clif_displaymessage (fd, msg_table[119]);   // This player is not in jails.
-                return -1;
-            }
-            else if (pc_setpos (pl_sd, "prontera.gat", 156, 191, 3) == 0)
-            {
-                pc_setsavepoint (pl_sd, "prontera.gat", 156, 191);  // Save char respawn point in Prontera
-                clif_displaymessage (pl_sd->fd, msg_table[120]);    // GM has discharge you.
-                clif_displaymessage (fd, msg_table[121]);   // Player warped to Prontera.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[1]); // Map not found.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @disguise <mob_id> by [Valaris] (simplified by [Yor])
- *------------------------------------------
- */
-int atcommand_disguise (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    int  mob_id;
-
-    if (!message || !*message)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a Monster/NPC name/id (usage: @disguise <monster_name_or_monster_ID>).");
-        return -1;
-    }
-
-    if ((mob_id = mobdb_searchname (message)) == 0) // check name first (to avoid possible name begining by a number)
-        mob_id = atoi (message);
-
-    if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) ||  // NPC
-        (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
-        (mob_id >= 813 && mob_id <= 834) || // NPC
-        (mob_id > 1000 && mob_id < 1521))
-    {                           // monsters
-        if (pc_isriding (sd))
-        {                       // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-            clif_displaymessage (fd, msg_table[227]);   // Cannot wear disguise while riding a Peco.
-            return -1;
-        }
-        sd->disguiseflag = 1;   // set to override items with disguise script [Valaris]
-        sd->disguise = mob_id;
-        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
-        clif_displaymessage (fd, msg_table[122]);   // Disguise applied.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[123]);   // Monster/NPC name/id hasn't been found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @undisguise by [Yor]
- *------------------------------------------
- */
-int atcommand_undisguise (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    if (sd->disguise)
-    {
-        clif_clearchar (&sd->bl, 9);
-        sd->disguise = 0;
-        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
-        clif_displaymessage (fd, msg_table[124]);   // Undisguise applied.
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[125]);   // You're not disguised.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @broadcast by [Valaris]
- *------------------------------------------
- */
-int atcommand_broadcast (const int fd, struct map_session_data *sd,
-                         const char *command, const char *message)
-{
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a message (usage: @broadcast <message>).");
-        return -1;
-    }
-
-    snprintf (output, 199, "%s : %s", sd->status.name, message);
-    intif_GMmessage (output, strlen (output) + 1, 0);
-
-    return 0;
-}
-
-/*==========================================
- * @localbroadcast by [Valaris]
- *------------------------------------------
- */
-int atcommand_localbroadcast (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char output[200];
-
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a message (usage: @localbroadcast <message>).");
-        return -1;
-    }
-
-    snprintf (output, 199, "%s : %s", sd->status.name, message);
-
-    clif_GMmessage (&sd->bl, output, strlen (output) + 1, 1);   // 1: ALL_SAMEMAP
-
-    return 0;
-}
-
-/*==========================================
- * @ignorelist by [Yor]
- *------------------------------------------
- */
-int atcommand_ignorelist (const int fd, struct map_session_data *sd,
-                          const char *command, const char *message)
-{
-    char output[200];
-    int  count;
-    int  i;
-
-    memset (output, '\0', sizeof (output));
-
-    count = 0;
-    for (i = 0; i < (int) (sizeof (sd->ignore) / sizeof (sd->ignore[0])); i++)
-        if (sd->ignore[i].name[0])
-            count++;
-
-    if (sd->ignoreAll == 0)
-        if (count == 0)
-            clif_displaymessage (fd, msg_table[126]);   // You accept any wisp (no wisper is refused).
-        else
-        {
-            sprintf (output, msg_table[127], count);    // You accept any wisp, except thoses from %d player(s):
-            clif_displaymessage (fd, output);
-        }
-    else if (count == 0)
-        clif_displaymessage (fd, msg_table[128]);   // You refuse all wisps (no specifical wisper is refused).
-    else
-    {
-        sprintf (output, msg_table[129], count);    // You refuse all wisps, AND refuse wisps from %d player(s):
-        clif_displaymessage (fd, output);
-    }
-
-    if (count > 0)
-        for (i = 0; i < (int) (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
-             i++)
-            if (sd->ignore[i].name[0])
-                clif_displaymessage (fd, sd->ignore[i].name);
-
-    return 0;
-}
-
-/*==========================================
- * @charignorelist <player_name> by [Yor]
- *------------------------------------------
- */
-int atcommand_charignorelist (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-    char output[200];
-    int  count;
-    int  i;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charignorelist <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        count = 0;
-        for (i = 0;
-             i < (int) (sizeof (pl_sd->ignore) / sizeof (pl_sd->ignore[0]));
-             i++)
-            if (pl_sd->ignore[i].name[0])
-                count++;
-
-        if (pl_sd->ignoreAll == 0)
-            if (count == 0)
-            {
-                sprintf (output, msg_table[130], pl_sd->status.name);   // '%s' accept any wisp (no wisper is refused).
-                clif_displaymessage (fd, output);
-            }
-            else
-            {
-                sprintf (output, msg_table[131], pl_sd->status.name, count);    // '%s' accept any wisp, except thoses from %d player(s):
-                clif_displaymessage (fd, output);
-            }
-        else if (count == 0)
-        {
-            sprintf (output, msg_table[132], pl_sd->status.name);   // '%s' refuse all wisps (no specifical wisper is refused).
-            clif_displaymessage (fd, output);
-        }
-        else
-        {
-            sprintf (output, msg_table[133], pl_sd->status.name, count);    // '%s' refuse all wisps, AND refuse wisps from %d player(s):
-            clif_displaymessage (fd, output);
-        }
-
-        if (count > 0)
-            for (i = 0;
-                 i <
-                 (int) (sizeof (pl_sd->ignore) / sizeof (pl_sd->ignore[0]));
-                 i++)
-                if (pl_sd->ignore[i].name[0])
-                    clif_displaymessage (fd, pl_sd->ignore[i].name);
-
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @inall <player_name> by [Yor]
- *------------------------------------------
- */
-int atcommand_inall (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @inall <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change wisp option only to lower or same level
-            if (pl_sd->ignoreAll == 0)
-            {
-                sprintf (output, msg_table[134], pl_sd->status.name);   // '%s' already accepts all wispers.
-                clif_displaymessage (fd, output);
-                return -1;
-            }
-            else
-            {
-                pl_sd->ignoreAll = 0;
-                sprintf (output, msg_table[135], pl_sd->status.name);   // '%s' now accepts all wispers.
-                clif_displaymessage (fd, output);
-                // message to player
-                clif_displaymessage (pl_sd->fd, msg_table[136]);    // A GM has authorised all wispers for you.
-                WFIFOW (pl_sd->fd, 0) = 0x0d2;  // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-                WFIFOB (pl_sd->fd, 2) = 1;
-                WFIFOB (pl_sd->fd, 3) = 0;  // success
-                WFIFOSET (pl_sd->fd, 4);    // packet_len_table[0x0d2]
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @exall <player_name> by [Yor]
- *------------------------------------------
- */
-int atcommand_exall (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char character[100];
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @exall <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can change wisp option only to lower or same level
-            if (pl_sd->ignoreAll == 1)
-            {
-                sprintf (output, msg_table[137], pl_sd->status.name);   // '%s' already blocks all wispers.
-                clif_displaymessage (fd, output);
-                return -1;
-            }
-            else
-            {
-                pl_sd->ignoreAll = 1;
-                sprintf (output, msg_table[138], pl_sd->status.name);   // '%s' blocks now all wispers.
-                clif_displaymessage (fd, output);
-                // message to player
-                clif_displaymessage (pl_sd->fd, msg_table[139]);    // A GM has blocked all wispers for you.
-                WFIFOW (pl_sd->fd, 0) = 0x0d2;  // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-                WFIFOB (pl_sd->fd, 2) = 0;
-                WFIFOB (pl_sd->fd, 3) = 0;  // success
-                WFIFOSET (pl_sd->fd, 4);    // packet_len_table[0x0d2]
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @chardisguise <mob_id> <character> by Kalaspuff (based off Valaris' and Yor's work)
- *------------------------------------------
- */
-int atcommand_chardisguise (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message)
-{
-    int  mob_id;
-    char character[100];
-    char mob_name[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-    memset (mob_name, '\0', sizeof (mob_name));
-
-    if (!message || !*message
-        || sscanf (message, "%s %99[^\n]", mob_name, character) < 2)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a Monster/NPC name/id and a player name (usage: @chardisguise <monster_name_or_monster_ID> <char name>).");
-        return -1;
-    }
-
-    if ((mob_id = mobdb_searchname (mob_name)) == 0)    // check name first (to avoid possible name begining by a number)
-        mob_id = atoi (mob_name);
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can disguise only lower or same level
-            if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) ||  // NPC
-                (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
-                (mob_id >= 813 && mob_id <= 834) || // NPC
-                (mob_id > 1000 && mob_id < 1521))
-            {                   // monsters
-                if (pc_isriding (pl_sd))
-                {               // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-                    clif_displaymessage (fd, msg_table[228]);   // Character cannot wear disguise while riding a Peco.
-                    return -1;
-                }
-                pl_sd->disguiseflag = 1;    // set to override items with disguise script [Valaris]
-                pl_sd->disguise = mob_id;
-                pc_setpos (pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y,
-                           3);
-                clif_displaymessage (fd, msg_table[140]);   // Character's disguise applied.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[123]);   // Monster/NPC name/id hasn't been found.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charundisguise <character> by Kalaspuff (based off Yor's work)
- *------------------------------------------
- */
-int atcommand_charundisguise (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charundisguise <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can undisguise only lower or same level
-            if (pl_sd->disguise)
-            {
-                clif_clearchar (&pl_sd->bl, 9);
-                pl_sd->disguise = 0;
-                pc_setpos (pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y,
-                           3);
-                clif_displaymessage (fd, msg_table[141]);   // Character's undisguise applied.
-            }
-            else
-            {
-                clif_displaymessage (fd, msg_table[142]);   // Character is not disguised.
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @email <actual@email> <new@email> by [Yor]
- *------------------------------------------
- */
-int atcommand_email (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char actual_email[100];
-    char new_email[100];
-
-    memset (actual_email, '\0', sizeof (actual_email));
-    memset (new_email, '\0', sizeof (new_email));
-
-    if (!message || !*message
-        || sscanf (message, "%99s %99s", actual_email, new_email) < 2)
-    {
-        clif_displaymessage (fd,
-                             "Please enter 2 emails (usage: @email <actual@email> <new@email>).");
-        return -1;
-    }
-
-    if (e_mail_check (actual_email) == 0)
-    {
-        clif_displaymessage (fd, msg_table[144]);   // Invalid actual email. If you have default e-mail, give a@a.com.
-        return -1;
-    }
-    else if (e_mail_check (new_email) == 0)
-    {
-        clif_displaymessage (fd, msg_table[145]);   // Invalid new email. Please enter a real e-mail.
-        return -1;
-    }
-    else if (strcasecmp (new_email, "a@a.com") == 0)
-    {
-        clif_displaymessage (fd, msg_table[146]);   // New email must be a real e-mail.
-        return -1;
-    }
-    else if (strcasecmp (actual_email, new_email) == 0)
-    {
-        clif_displaymessage (fd, msg_table[147]);   // New email must be different of the actual e-mail.
-        return -1;
-    }
-    else
-    {
-        chrif_changeemail (sd->status.account_id, actual_email, new_email);
-        clif_displaymessage (fd, msg_table[148]);   // Information sended to login-server via char-server.
-    }
-
-    return 0;
-}
-
-/*==========================================
- *@effect
- *------------------------------------------
- */
-int atcommand_effect (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  type = 0, flag = 0, i;
-
-    if (!message || !*message || sscanf (message, "%d %d", &type, &flag) < 2)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter at least a option (usage: @effect <type+>).");
-        return -1;
-    }
-    if (flag <= 0)
-    {
-        clif_specialeffect (&sd->bl, type, flag);
-        clif_displaymessage (fd, msg_table[229]);   // Your effect has changed.
-    }
-    else
-    {
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                clif_specialeffect (&pl_sd->bl, type, flag);
-                clif_displaymessage (pl_sd->fd, msg_table[229]);    // Your effect has changed.
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charitemlist <character>: Displays the list of a player's items.
- *------------------------------------------
- */
-int
-atcommand_character_item_list (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    struct item_data *item_data, *item_temp;
-    int  i, j, equip, count, counter, counter2;
-    char character[100], output[200], equipstr[100], outputtmp[200];
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-    memset (equipstr, '\0', sizeof (equipstr));
-    memset (outputtmp, '\0', sizeof (outputtmp));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charitemlist <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can look items only lower or same level
-            counter = 0;
-            count = 0;
-            for (i = 0; i < MAX_INVENTORY; i++)
-            {
-                if (pl_sd->status.inventory[i].nameid > 0
-                    && (item_data =
-                        itemdb_search (pl_sd->status.inventory[i].nameid)) !=
-                    NULL)
-                {
-                    counter = counter + pl_sd->status.inventory[i].amount;
-                    count++;
-                    if (count == 1)
-                    {
-                        sprintf (output, "------ Items list of '%s' ------",
-                                 pl_sd->status.name);
-                        clif_displaymessage (fd, output);
-                    }
-                    if ((equip = pl_sd->status.inventory[i].equip))
-                    {
-                        strcpy (equipstr, "| equiped: ");
-                        if (equip & 4)
-                            strcat (equipstr, "robe/gargment, ");
-                        if (equip & 8)
-                            strcat (equipstr, "left accessory, ");
-                        if (equip & 16)
-                            strcat (equipstr, "body/armor, ");
-                        if ((equip & 34) == 2)
-                            strcat (equipstr, "right hand, ");
-                        if ((equip & 34) == 32)
-                            strcat (equipstr, "left hand, ");
-                        if ((equip & 34) == 34)
-                            strcat (equipstr, "both hands, ");
-                        if (equip & 64)
-                            strcat (equipstr, "feet, ");
-                        if (equip & 128)
-                            strcat (equipstr, "right accessory, ");
-                        if ((equip & 769) == 1)
-                            strcat (equipstr, "lower head, ");
-                        if ((equip & 769) == 256)
-                            strcat (equipstr, "top head, ");
-                        if ((equip & 769) == 257)
-                            strcat (equipstr, "lower/top head, ");
-                        if ((equip & 769) == 512)
-                            strcat (equipstr, "mid head, ");
-                        if ((equip & 769) == 512)
-                            strcat (equipstr, "lower/mid head, ");
-                        if ((equip & 769) == 769)
-                            strcat (equipstr, "lower/mid/top head, ");
-                        // remove final ', '
-                        equipstr[strlen (equipstr) - 2] = '\0';
-                    }
-                    else
-                        memset (equipstr, '\0', sizeof (equipstr));
-                    if (sd->status.inventory[i].refine)
-                        sprintf (output, "%d %s %+d (%s %+d, id: %d) %s",
-                                 pl_sd->status.inventory[i].amount,
-                                 item_data->name,
-                                 pl_sd->status.inventory[i].refine,
-                                 item_data->jname,
-                                 pl_sd->status.inventory[i].refine,
-                                 pl_sd->status.inventory[i].nameid, equipstr);
-                    else
-                        sprintf (output, "%d %s (%s, id: %d) %s",
-                                 pl_sd->status.inventory[i].amount,
-                                 item_data->name, item_data->jname,
-                                 pl_sd->status.inventory[i].nameid, equipstr);
-                    clif_displaymessage (fd, output);
-                    memset (output, '\0', sizeof (output));
-                    counter2 = 0;
-                    for (j = 0; j < item_data->slot; j++)
-                    {
-                        if (pl_sd->status.inventory[i].card[j])
-                        {
-                            if ((item_temp =
-                                 itemdb_search (pl_sd->status.
-                                                inventory[i].card[j])) !=
-                                NULL)
-                            {
-                                if (output[0] == '\0')
-                                    sprintf (outputtmp,
-                                             " -> (card(s): #%d %s (%s), ",
-                                             ++counter2, item_temp->name,
-                                             item_temp->jname);
-                                else
-                                    sprintf (outputtmp, "#%d %s (%s), ",
-                                             ++counter2, item_temp->name,
-                                             item_temp->jname);
-                                strcat (output, outputtmp);
-                            }
-                        }
-                    }
-                    if (output[0] != '\0')
-                    {
-                        output[strlen (output) - 2] = ')';
-                        output[strlen (output) - 1] = '\0';
-                        clif_displaymessage (fd, output);
-                    }
-                }
-            }
-            if (count == 0)
-                clif_displaymessage (fd, "No item found on this player.");
-            else
-            {
-                sprintf (output, "%d item(s) found in %d kind(s) of items.",
-                         counter, count);
-                clif_displaymessage (fd, output);
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charstoragelist <character>: Displays the items list of a player's storage.
- *------------------------------------------
- */
-int
-atcommand_character_storage_list (const int fd, struct map_session_data *sd,
-                                  const char *command, const char *message)
-{
-    struct storage *stor;
-    struct map_session_data *pl_sd;
-    struct item_data *item_data, *item_temp;
-    int  i, j, count, counter, counter2;
-    char character[100], output[200], outputtmp[200];
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-    memset (outputtmp, '\0', sizeof (outputtmp));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charitemlist <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can look items only lower or same level
-            if ((stor = account2storage2 (pl_sd->status.account_id)) != NULL)
-            {
-                counter = 0;
-                count = 0;
-                for (i = 0; i < MAX_STORAGE; i++)
-                {
-                    if (stor->storage_[i].nameid > 0
-                        && (item_data =
-                            itemdb_search (stor->storage_[i].nameid)) != NULL)
-                    {
-                        counter = counter + stor->storage_[i].amount;
-                        count++;
-                        if (count == 1)
-                        {
-                            sprintf (output,
-                                     "------ Storage items list of '%s' ------",
-                                     pl_sd->status.name);
-                            clif_displaymessage (fd, output);
-                        }
-                        if (stor->storage_[i].refine)
-                            sprintf (output, "%d %s %+d (%s %+d, id: %d)",
-                                     stor->storage_[i].amount,
-                                     item_data->name,
-                                     stor->storage_[i].refine,
-                                     item_data->jname,
-                                     stor->storage_[i].refine,
-                                     stor->storage_[i].nameid);
-                        else
-                            sprintf (output, "%d %s (%s, id: %d)",
-                                     stor->storage_[i].amount,
-                                     item_data->name, item_data->jname,
-                                     stor->storage_[i].nameid);
-                        clif_displaymessage (fd, output);
-                        memset (output, '\0', sizeof (output));
-                        counter2 = 0;
-                        for (j = 0; j < item_data->slot; j++)
-                        {
-                            if (stor->storage_[i].card[j])
-                            {
-                                if ((item_temp =
-                                     itemdb_search (stor->
-                                                    storage_[i].card[j])) !=
-                                    NULL)
-                                {
-                                    if (output[0] == '\0')
-                                        sprintf (outputtmp,
-                                                 " -> (card(s): #%d %s (%s), ",
-                                                 ++counter2, item_temp->name,
-                                                 item_temp->jname);
-                                    else
-                                        sprintf (outputtmp, "#%d %s (%s), ",
-                                                 ++counter2, item_temp->name,
-                                                 item_temp->jname);
-                                    strcat (output, outputtmp);
-                                }
-                            }
-                        }
-                        if (output[0] != '\0')
-                        {
-                            output[strlen (output) - 2] = ')';
-                            output[strlen (output) - 1] = '\0';
-                            clif_displaymessage (fd, output);
-                        }
-                    }
-                }
-                if (count == 0)
-                    clif_displaymessage (fd,
-                                         "No item found in the storage of this player.");
-                else
-                {
-                    sprintf (output,
-                             "%d item(s) found in %d kind(s) of items.",
-                             counter, count);
-                    clif_displaymessage (fd, output);
-                }
-            }
-            else
-            {
-                clif_displaymessage (fd, "This player has no storage.");
-                return -1;
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @charcartlist <character>: Displays the items list of a player's cart.
- *------------------------------------------
- */
-int
-atcommand_character_cart_list (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    struct item_data *item_data, *item_temp;
-    int  i, j, count, counter, counter2;
-    char character[100], output[200], outputtmp[200];
-
-    memset (character, '\0', sizeof (character));
-    memset (output, '\0', sizeof (output));
-    memset (outputtmp, '\0', sizeof (outputtmp));
-
-    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Please, enter a player name (usage: @charitemlist <char name>).");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can look items only lower or same level
-            counter = 0;
-            count = 0;
-            for (i = 0; i < MAX_CART; i++)
-            {
-                if (pl_sd->status.cart[i].nameid > 0
-                    && (item_data =
-                        itemdb_search (pl_sd->status.cart[i].nameid)) != NULL)
-                {
-                    counter = counter + pl_sd->status.cart[i].amount;
-                    count++;
-                    if (count == 1)
-                    {
-                        sprintf (output,
-                                 "------ Cart items list of '%s' ------",
-                                 pl_sd->status.name);
-                        clif_displaymessage (fd, output);
-                    }
-                    if (pl_sd->status.cart[i].refine)
-                        sprintf (output, "%d %s %+d (%s %+d, id: %d)",
-                                 pl_sd->status.cart[i].amount,
-                                 item_data->name,
-                                 pl_sd->status.cart[i].refine,
-                                 item_data->jname,
-                                 pl_sd->status.cart[i].refine,
-                                 pl_sd->status.cart[i].nameid);
-                    else
-                        sprintf (output, "%d %s (%s, id: %d)",
-                                 pl_sd->status.cart[i].amount,
-                                 item_data->name, item_data->jname,
-                                 pl_sd->status.cart[i].nameid);
-                    clif_displaymessage (fd, output);
-                    memset (output, '\0', sizeof (output));
-                    counter2 = 0;
-                    for (j = 0; j < item_data->slot; j++)
-                    {
-                        if (pl_sd->status.cart[i].card[j])
-                        {
-                            if ((item_temp =
-                                 itemdb_search (pl_sd->status.
-                                                cart[i].card[j])) != NULL)
-                            {
-                                if (output[0] == '\0')
-                                    sprintf (outputtmp,
-                                             " -> (card(s): #%d %s (%s), ",
-                                             ++counter2, item_temp->name,
-                                             item_temp->jname);
-                                else
-                                    sprintf (outputtmp, "#%d %s (%s), ",
-                                             ++counter2, item_temp->name,
-                                             item_temp->jname);
-                                strcat (output, outputtmp);
-                            }
-                        }
-                    }
-                    if (output[0] != '\0')
-                    {
-                        output[strlen (output) - 2] = ')';
-                        output[strlen (output) - 1] = '\0';
-                        clif_displaymessage (fd, output);
-                    }
-                }
-            }
-            if (count == 0)
-                clif_displaymessage (fd,
-                                     "No item found in the cart of this player.");
-            else
-            {
-                sprintf (output, "%d item(s) found in %d kind(s) of items.",
-                         counter, count);
-                clif_displaymessage (fd, output);
-            }
-        }
-        else
-        {
-            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
-            return -1;
-        }
-    }
-    else
-    {
-        clif_displaymessage (fd, msg_table[3]); // Character not found.
-        return -1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * @killer by MouseJstr
- * enable killing players even when not in pvp
- *------------------------------------------
- */
-int
-atcommand_killer (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-    sd->special_state.killer = !sd->special_state.killer;
-
-    if (sd->special_state.killer)
-        clif_displaymessage (fd, msg_table[241]);
-    else
-        clif_displaymessage (fd, msg_table[242]);
-
-    return 0;
-}
-
-/*==========================================
- * @killable by MouseJstr
- * enable other people killing you
- *------------------------------------------
- */
-int
-atcommand_killable (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    sd->special_state.killable = !sd->special_state.killable;
-
-    if (sd->special_state.killable)
-        clif_displaymessage (fd, msg_table[242]);
-    else
-        clif_displaymessage (fd, msg_table[241]);
-
-    return 0;
-}
-
-/*==========================================
- * @charkillable by MouseJstr
- * enable another player to be killed
- *------------------------------------------
- */
-int
-atcommand_charkillable (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    struct map_session_data *pl_sd = NULL;
-
-    if (!message || !*message)
-        return -1;
-
-    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
-        return -1;
-
-    pl_sd->special_state.killable = !pl_sd->special_state.killable;
-
-    if (pl_sd->special_state.killable)
-        clif_displaymessage (fd, "The player is now killable");
-    else
-        clif_displaymessage (fd, "The player is no longer killable");
-
-    return 0;
-}
-
-/*==========================================
- * @skillon by MouseJstr
- * turn skills on for the map
- *------------------------------------------
- */
-int
-atcommand_skillon (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    map[sd->bl.m].flag.noskill = 0;
-    clif_displaymessage (fd, msg_table[244]);
-    return 0;
-}
-
-/*==========================================
- * @skilloff by MouseJstr
- * Turn skills off on the map
- *------------------------------------------
- */
-int
-atcommand_skilloff (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    map[sd->bl.m].flag.noskill = 1;
-    clif_displaymessage (fd, msg_table[243]);
-    return 0;
-}
-
-/*==========================================
- * @npcmove by MouseJstr
- *
- * move a npc
- *------------------------------------------
- */
-int
-atcommand_npcmove (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    char character[100];
-    int  x = 0, y = 0;
-    struct npc_data *nd = 0;
-
-    if (sd == NULL)
-        return -1;
-
-    if (!message || !*message)
-        return -1;
-
-    memset (character, '\0', sizeof character);
-
-    if (sscanf (message, "%d %d %99[^\n]", &x, &y, character) < 3)
-        return -1;
-
-    nd = npc_name2id (character);
-    if (nd == NULL)
-        return -1;
-
-    npc_enable (character, 0);
-    nd->bl.x = x;
-    nd->bl.y = y;
-    npc_enable (character, 1);
-
-    return 0;
-}
-
-/*==========================================
- * @addwarp by MouseJstr
- *
- * Create a new static warp point.
- *------------------------------------------
- */
-int
-atcommand_addwarp (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    char w1[64], w3[64], w4[64];
-    char map[30], output[200];
-    int  x, y, ret;
-
-    if (!message || !*message)
-        return -1;
-
-    if (sscanf (message, "%99s %d %d[^\n]", map, &x, &y) < 3)
-        return -1;
-
-    sprintf (w1, "%s,%d,%d", sd->mapname, sd->bl.x, sd->bl.y);
-    sprintf (w3, "%s%d%d%d%d", map, sd->bl.x, sd->bl.y, x, y);
-    sprintf (w4, "1,1,%s.gat,%d,%d", map, x, y);
-
-    ret = npc_parse_warp (w1, "warp", w3, w4);
-
-    sprintf (output, "New warp NPC => %s", w3);
-
-    clif_displaymessage (fd, output);
-
-    return ret;
-}
-
-/*==========================================
- * @follow by [MouseJstr]
- *
- * Follow a player .. staying no more then 5 spaces away
- *------------------------------------------
- */
-int
-atcommand_follow (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-#if 0
-    struct map_session_data *pl_sd = NULL;
-
-    if (!message || !*message)
-        return -1;
-    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
-        pc_follow (sd, pl_sd->bl.id);
-    else
-        return 1;
-#endif
-
-    /*
-     * Command disabled - it's incompatible with the TMW
-     * client.
-     */
-    clif_displaymessage (fd, "@follow command not available");
-
-    return 0;
-
-}
-
-/*==========================================
- * @chareffect by [MouseJstr]
- *
- * Create a effect localized on another character
- *------------------------------------------
- */
-int
-atcommand_chareffect (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    struct map_session_data *pl_sd = NULL;
-    char target[255];
-    int  type = 0;
-
-    if (!message || !*message
-        || sscanf (message, "%d %s", &type, target) != 2)
-    {
-        clif_displaymessage (fd, "usage: @chareffect <type+> <target>.");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd ((char *) target)) == NULL)
-        return -1;
-
-    clif_specialeffect (&pl_sd->bl, type, 0);
-    clif_displaymessage (fd, msg_table[229]);   // Your effect has changed.
-
-    return 0;
-}
-
-/*==========================================
- * @dropall by [MouseJstr]
- *
- * Drop all your possession on the ground
- *------------------------------------------
- */
-int
-atcommand_dropall (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    int  i;
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].amount)
-        {
-            if (sd->status.inventory[i].equip != 0)
-                pc_unequipitem (sd, i, 0);
-            pc_dropitem (sd, i, sd->status.inventory[i].amount);
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * @chardropall by [MouseJstr]
- *
- * Throw all the characters possessions on the ground.  Normally
- * done in response to them being disrespectful of a GM
- *------------------------------------------
- */
-int
-atcommand_chardropall (const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    int  i;
-    struct map_session_data *pl_sd = NULL;
-
-    if (!message || !*message)
-        return -1;
-    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
-        return -1;
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (pl_sd->status.inventory[i].amount)
-        {
-            if (pl_sd->status.inventory[i].equip != 0)
-                pc_unequipitem (pl_sd, i, 0);
-            pc_dropitem (pl_sd, i, pl_sd->status.inventory[i].amount);
-        }
-    }
-
-    clif_displaymessage (pl_sd->fd, "Ever play 52 card pickup?");
-    clif_displaymessage (fd, "It is done");
-    //clif_displaymessage(fd, "It is offical.. your a jerk");
-
-    return 0;
-}
-
-/*==========================================
- * @storeall by [MouseJstr]
- *
- * Put everything into storage to simplify your inventory to make
- * debugging easie
- *------------------------------------------
- */
-int
-atcommand_storeall (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  i;
-    nullpo_retr (-1, sd);
-
-    if (sd->state.storage_flag != 1)
-    {                           //Open storage.
-        switch (storage_storageopen (sd))
-        {
-            case 2:            //Try again
-                clif_displaymessage (fd, "run this command again..");
-                return 0;
-            case 1:            //Failure
-                clif_displaymessage (fd,
-                                     "You can't open the storage currently.");
-                return 1;
-        }
-    }
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].amount)
-        {
-            if (sd->status.inventory[i].equip != 0)
-                pc_unequipitem (sd, i, 0);
-            storage_storageadd (sd, i, sd->status.inventory[i].amount);
-        }
-    }
-    storage_storageclose (sd);
-
-    clif_displaymessage (fd, "It is done");
-    return 0;
-}
-
-/*==========================================
- * @charstoreall by [MouseJstr]
- *
- * A way to screw with players who piss you off
- *------------------------------------------
- */
-int
-atcommand_charstoreall (const int fd, struct map_session_data *sd,
-                        const char *command, const char *message)
-{
-    int  i;
-    struct map_session_data *pl_sd = NULL;
-
-    if (!message || !*message)
-        return -1;
-    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
-        return -1;
-
-    if (storage_storageopen (pl_sd) == 1)
-    {
-        clif_displaymessage (fd,
-                             "Had to open the characters storage window...");
-        clif_displaymessage (fd, "run this command again..");
-        return 0;
-    }
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (pl_sd->status.inventory[i].amount)
-        {
-            if (pl_sd->status.inventory[i].equip != 0)
-                pc_unequipitem (pl_sd, i, 0);
-            storage_storageadd (pl_sd, i, sd->status.inventory[i].amount);
-        }
-    }
-    storage_storageclose (pl_sd);
-
-    clif_displaymessage (pl_sd->fd,
-                         "Everything you own has been put away for safe keeping.");
-    clif_displaymessage (pl_sd->fd,
-                         "go to the nearest kafka to retrieve it..");
-    clif_displaymessage (pl_sd->fd, "   -- the management");
-
-    clif_displaymessage (fd, "It is done");
-
-    return 0;
-}
-
-/*==========================================
- * @skillid by [MouseJstr]
- *
- * lookup a skill by name
- *------------------------------------------
- */
-int
-atcommand_skillid (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    int  skillen = 0, idx = 0;
-    if (!message || !*message)
-        return -1;
-    skillen = strlen (message);
-    while (skill_names[idx].id != 0)
-    {
-        if ((strncasecmp (skill_names[idx].name, message, skillen) == 0) ||
-            (strncasecmp (skill_names[idx].desc, message, skillen) == 0))
-        {
-            char output[255];
-            sprintf (output, "skill %d: %s", skill_names[idx].id,
-                     skill_names[idx].desc);
-            clif_displaymessage (fd, output);
-        }
-        idx++;
-    }
-    return 0;
-}
-
-/*==========================================
- * @useskill by [MouseJstr]
- *
- * A way of using skills without having to find them in the skills menu
- *------------------------------------------
- */
-int
-atcommand_useskill (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    struct map_session_data *pl_sd = NULL;
-    int  skillnum;
-    int  skilllv;
-    int  inf;
-    char target[255];
-
-    if (!message || !*message)
-        return -1;
-    if (sscanf (message, "%d %d %s", &skillnum, &skilllv, target) != 3)
-    {
-        clif_displaymessage (fd,
-                             "Usage: @useskill <skillnum> <skillv> <target>");
-        return -1;
-    }
-    if ((pl_sd = map_nick2sd (target)) == NULL)
-    {
-        return -1;
-    }
-
-    inf = skill_get_inf (skillnum);
-
-    if ((inf == 2) || (inf == 1))
-        skill_use_pos (sd, pl_sd->bl.x, pl_sd->bl.y, skillnum, skilllv);
-    else
-        skill_use_id (sd, pl_sd->bl.id, skillnum, skilllv);
-
-    return 0;
-}
-
-/*==========================================
- * It is made to rain.
- *------------------------------------------
- */
-int
-atcommand_rain (const int fd, struct map_session_data *sd,
-                const char *command, const char *message)
-{
-    int  effno = 0;
-    effno = 161;
-    nullpo_retr (-1, sd);
-    if (effno < 0 || map[sd->bl.m].flag.rain)
-        return -1;
-
-    map[sd->bl.m].flag.rain = 1;
-    clif_specialeffect (&sd->bl, effno, 2);
-    return 0;
-}
-
-/*==========================================
- * It is made to snow.
- *------------------------------------------
- */
-int
-atcommand_snow (const int fd, struct map_session_data *sd,
-                const char *command, const char *message)
-{
-    int  effno = 0;
-    effno = 162;
-    nullpo_retr (-1, sd);
-    if (effno < 0 || map[sd->bl.m].flag.snow)
-        return -1;
-
-    map[sd->bl.m].flag.snow = 1;
-    clif_specialeffect (&sd->bl, effno, 2);
-    return 0;
-}
-
-/*==========================================
- * Cherry tree snowstorm is made to fall. (Sakura)
- *------------------------------------------
- */
-int
-atcommand_sakura (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-    int  effno = 0;
-    effno = 163;
-    nullpo_retr (-1, sd);
-    if (effno < 0 || map[sd->bl.m].flag.sakura)
-        return -1;
-
-    map[sd->bl.m].flag.sakura = 1;
-    clif_specialeffect (&sd->bl, effno, 2);
-    return 0;
-}
-
-/*==========================================
- * Fog hangs over.
- *------------------------------------------
- */
-int
-atcommand_fog (const int fd, struct map_session_data *sd,
-               const char *command, const char *message)
-{
-    int  effno = 0;
-    effno = 233;
-    nullpo_retr (-1, sd);
-    if (effno < 0 || map[sd->bl.m].flag.fog)
-        return -1;
-
-    map[sd->bl.m].flag.fog = 1;
-    clif_specialeffect (&sd->bl, effno, 2);
-
-    return 0;
-}
-
-/*==========================================
- * Fallen leaves fall.
- *------------------------------------------
- */
-int
-atcommand_leaves (const int fd, struct map_session_data *sd,
-                  const char *command, const char *message)
-{
-    int  effno = 0;
-    effno = 333;
-    nullpo_retr (-1, sd);
-    if (effno < 0 || map[sd->bl.m].flag.leaves)
-        return -1;
-
-    map[sd->bl.m].flag.leaves = 1;
-    clif_specialeffect (&sd->bl, effno, 2);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int atcommand_summon (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char name[100];
-    int  mob_id = 0;
-    int  x = 0;
-    int  y = 0;
-    int  id = 0;
-    struct mob_data *md;
-    unsigned int tick = gettick ();
-
-    nullpo_retr (-1, sd);
-
-    if (!message || !*message)
-        return -1;
-    if (sscanf (message, "%99s", name) < 1)
-        return -1;
-
-    if ((mob_id = atoi (name)) == 0)
-        mob_id = mobdb_searchname (name);
-    if (mob_id == 0)
-        return -1;
-
-    x = sd->bl.x + (MRAND (10) - 5);
-    y = sd->bl.y + (MRAND (10) - 5);
-
-    id = mob_once_spawn (sd, "this", x, y, "--ja--", mob_id, 1, "");
-    if ((md = (struct mob_data *) map_id2bl (id)))
-    {
-        md->master_id = sd->bl.id;
-        md->state.special_mob_ai = 1;
-        md->mode = mob_db[md->mob_class].mode | 0x04;
-        md->deletetimer = add_timer (tick + 60000, mob_timer_delete, id, 0);
-        clif_misceffect (&md->bl, 344);
-    }
-    clif_skill_poseffect (&sd->bl, AM_CALLHOMUN, 1, x, y, tick);
-
-    return 0;
-}
-
-/*==========================================
- * @adjcmdlvl by [MouseJstr]
- *
- * Temp adjust the GM level required to use a GM command
- *
- * Used during beta testing to allow players to use GM commands
- * for short periods of time
- *------------------------------------------
- */
-int
-atcommand_adjcmdlvl (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    int  i, newlev;
-    char cmd[100];
-
-    if (!message || !*message || sscanf (message, "%d %s", &newlev, cmd) != 2)
-    {
-        clif_displaymessage (fd, "usage: @adjcmdlvl <lvl> <command>.");
-        return -1;
-    }
-
-    for (i = 0; atcommand_info[i].type != AtCommand_None; i++)
-        if (strcasecmp (cmd, atcommand_info[i].command + 1) == 0)
-        {
-            atcommand_info[i].level = newlev;
-            clif_displaymessage (fd, "@command level changed.");
-            return 0;
-        }
-
-    clif_displaymessage (fd, "@command not found.");
-    return -1;
-}
-
-/*==========================================
- * @adjgmlvl by [MouseJstr]
- *
- * Create a temp GM
- *
- * Used during beta testing to allow players to use GM commands
- * for short periods of time
- *------------------------------------------
- */
-int
-atcommand_adjgmlvl (const int fd, struct map_session_data *sd,
-                    const char *command, const char *message)
-{
-    int  newlev;
-    char user[100];
-    struct map_session_data *pl_sd;
-
-    if (!message || !*message
-        || sscanf (message, "%d %s", &newlev, user) != 2)
-    {
-        clif_displaymessage (fd, "usage: @adjgmlvl <lvl> <user>.");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd ((char *) user)) == NULL)
-        return -1;
-
-    pc_set_gm_level (pl_sd->status.account_id, newlev);
-
-    return 0;
-}
-
-/*==========================================
- * @trade by [MouseJstr]
- *
- * Open a trade window with a remote player
- *
- * If I have to jump to a remote player one more time, I am
- * gonna scream!
- *------------------------------------------
- */
-int
-atcommand_trade (const int fd, struct map_session_data *sd,
-                 const char *command, const char *message)
-{
-    struct map_session_data *pl_sd = NULL;
-
-    if (!message || !*message)
-        return -1;
-    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
-    {
-        trade_traderequest (sd, pl_sd->bl.id);
-        return 0;
-    }
-    return -1;
-}
-
-/*===========================
- * @unmute [Valaris]
- *===========================
-*/
-int atcommand_unmute (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    struct map_session_data *pl_sd = NULL;
-    if (!message || !*message)
-        return -1;
-
-    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
-    {
-        if (pl_sd->sc_data[SC_NOCHAT].timer != -1)
-        {
-            skill_status_change_end (&pl_sd->bl, SC_NOCHAT, -1);
-            clif_displaymessage (sd->fd, "Player unmuted");
-        }
-        else
-            clif_displaymessage (sd->fd, "Player is not muted");
-    }
-
-    return 0;
-}
-
-/* Magic atcommands by Fate */
-
-static int magic_base = TMW_MAGIC;
-#define magic_skills_nr 6
-static char *magic_skill_names[magic_skills_nr] =
-    { "magic", "life", "war", "transmute", "nature", "astral" };
-
-int
-atcommand_magic_info (const int fd, struct map_session_data *sd,
-                      const char *command, const char *message)
-{
-    char character[100];
-    char buf[200];
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message || sscanf (message, "%99s", character) < 1)
-    {
-        clif_displaymessage (fd, "Usage: @magicinfo <char_name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        int  i;
-
-        sprintf (buf, "`%s' has the following magic skills:", character);
-        clif_displaymessage (fd, buf);
-
-        for (i = 0; i < magic_skills_nr; i++)
-        {
-            sprintf (buf, "%d in %s", pl_sd->status.skill[i + magic_base].lv,
-                     magic_skill_names[i]);
-            if (pl_sd->status.skill[i + magic_base].id == i + magic_base)
-                clif_displaymessage (fd, buf);
-        }
-
-        return 0;
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return -1;
-}
-
-static void set_skill (struct map_session_data *sd, int i, int level)
-{
-    sd->status.skill[i].id = level ? i : 0;
-    sd->status.skill[i].lv = level;
-}
-
-int
-atcommand_set_magic (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    char character[100];
-    char magic_type[20];
-    int  skill_index = -1;      // 0: all
-    int  value;
-    struct map_session_data *pl_sd;
-
-    memset (character, '\0', sizeof (character));
-
-    if (!message || !*message
-        || sscanf (message, "%19s %i %99s", magic_type, &value,
-                   character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'.");
-        return -1;
-    }
-
-    if (!strcasecmp ("all", magic_type))
-        skill_index = 0;
-    else
-    {
-        int  i;
-        for (i = 0; i < magic_skills_nr; i++)
-        {
-            if (!strcasecmp (magic_skill_names[i], magic_type))
-            {
-                skill_index = i + magic_base;
-                break;
-            }
-        }
-    }
-
-    if (skill_index == -1)
-    {
-        clif_displaymessage (fd,
-                             "Incorrect school of magic.  Use `magic', `nature', `life', `war', `transmute', `ether', or `all'.");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        int  i;
-        if (skill_index == 0)
-            for (i = 0; i < magic_skills_nr; i++)
-                set_skill (pl_sd, i + magic_base, value);
-        else
-            set_skill (pl_sd, skill_index, value);
-
-        clif_skillinfoblock (pl_sd);
-        return 0;
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return -1;
-}
-
-int
-atcommand_log (const int fd, struct map_session_data *sd,
-               const char *command, const char *message)
-{
-    return 0;                   // only used for (implicit) logging
-}
-
-int
-atcommand_tee (const int fd, struct map_session_data *sd,
-               const char *command, const char *message)
-{
-    char *data = (char *)malloc (strlen (message) + 28);
-    strcpy (data, sd->status.name);
-    strcat (data, " : ");
-    strcat (data, message);
-    clif_message (&sd->bl, data);
-    return 0;
-}
-
-int
-atcommand_invisible (const int fd, struct map_session_data *sd,
-                     const char *command, const char *message)
-{
-    pc_invisibility (sd, 1);
-    return 0;
-}
-
-int
-atcommand_visible (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    pc_invisibility (sd, 0);
-    return 0;
-}
-
-int atcommand_jump_iterate (const int fd, struct map_session_data *sd,
-                            const char *command, const char *message,
-                            struct map_session_data *(*get_start) (void),
-                            struct map_session_data *(*get_next) (struct
-                                                                  map_session_data
-                                                                  * current))
-{
-    char output[200];
-    struct map_session_data *pl_sd;
-
-    memset (output, '\0', sizeof (output));
-
-    pl_sd = (struct map_session_data *) map_id2bl (sd->followtarget);
-
-    if (pl_sd)
-        pl_sd = get_next (pl_sd);
-
-    if (!pl_sd)
-        pl_sd = get_start ();
-
-    if (pl_sd == sd)
-    {
-        pl_sd = get_next (pl_sd);
-        if (!pl_sd)
-            pl_sd = get_start ();
-    }
-
-    if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp you to the map of this player.");
-        return -1;
-    }
-    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
-        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
-    {
-        clif_displaymessage (fd,
-                             "You are not authorised to warp you from your actual map.");
-        return -1;
-    }
-    pc_setpos (sd, map[pl_sd->bl.m].name, pl_sd->bl.x, pl_sd->bl.y, 3);
-    sprintf (output, msg_table[4], pl_sd->status.name); // Jump to %s
-    clif_displaymessage (fd, output);
-
-    sd->followtarget = pl_sd->bl.id;
-
-    return 0;
-}
-
-int
-atcommand_iterate_forward_over_players (const int fd,
-                                        struct map_session_data *sd,
-                                        const char *command,
-                                        const char *message)
-{
-    return atcommand_jump_iterate (fd, sd, command, message,
-                                   map_get_first_session,
-                                   map_get_next_session);
-}
-
-int
-atcommand_iterate_backwards_over_players (const int fd,
-                                          struct map_session_data *sd,
-                                          const char *command,
-                                          const char *message)
-{
-    return atcommand_jump_iterate (fd, sd, command, message,
-                                   map_get_last_session,
-                                   map_get_prev_session);
-}
-
-int atcommand_wgm (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    if (tmw_CheckChatSpam(sd, message))
-        return 0;
-    tmw_GmHackMsg ("%s: %s", sd->status.name, message);
-    if (!pc_isGM (sd))
-        clif_displaymessage (fd, "Message sent.");
-
-    return 0;
-}
-
-
-int atcommand_skillpool_info (const int fd, struct map_session_data *sd,
-                              const char *command, const char *message)
-{
-    char character[100];
-    struct map_session_data *pl_sd;
-
-    if (!message || !*message || sscanf (message, "%99s", character) < 1)
-    {
-        clif_displaymessage (fd, "Usage: @sp-info <char_name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        char buf[200];
-        int  pool_skills[MAX_SKILL_POOL];
-        int  pool_skills_nr = skill_pool (pl_sd, pool_skills);
-        int  i;
-
-        sprintf (buf, "Active skills %d out of %d for %s:", pool_skills_nr,
-                 skill_pool_max (pl_sd), character);
-        clif_displaymessage (fd, buf);
-        for (i = 0; i < pool_skills_nr; ++i)
-        {
-            sprintf (buf, " - %s [%d]: power %d", skill_name (pool_skills[i]),
-                     pool_skills[i], skill_power (pl_sd, pool_skills[i]));
-            clif_displaymessage (fd, buf);
-        }
-
-        sprintf (buf, "Learned skills out of %d for %s:",
-                 skill_pool_skills_size, character);
-        clif_displaymessage (fd, buf);
-
-        for (i = 0; i < skill_pool_skills_size; ++i)
-        {
-            char *name = skill_name (skill_pool_skills[i]);
-            int  lvl = pl_sd->status.skill[skill_pool_skills[i]].lv;
-
-            if (lvl)
-            {
-                sprintf (buf, " - %s [%d]: lvl %d", name,
-                         skill_pool_skills[i], lvl);
-                clif_displaymessage (fd, buf);
-            }
-        }
-
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return 0;
-}
-
-int atcommand_skillpool_focus (const int fd, struct map_session_data *sd,
-                               const char *command, const char *message)
-{
-    char character[100];
-    int  skill;
-    struct map_session_data *pl_sd;
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &skill, character) < 1)
-    {
-        clif_displaymessage (fd, "Usage: @sp-focus <skill-nr> <char_name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (skill_pool_activate (pl_sd, skill))
-            clif_displaymessage (fd, "Activation failed.");
-        else
-            clif_displaymessage (fd, "Activation successful.");
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return 0;
-}
-
-int atcommand_skillpool_unfocus (const int fd, struct map_session_data *sd,
-                                 const char *command, const char *message)
-{
-    char character[100];
-    int  skill;
-    struct map_session_data *pl_sd;
-
-    if (!message || !*message
-        || sscanf (message, "%d %99[^\n]", &skill, character) < 1)
-    {
-        clif_displaymessage (fd, "Usage: @sp-unfocus <skill-nr> <char_name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        if (skill_pool_deactivate (pl_sd, skill))
-            clif_displaymessage (fd, "Deactivation failed.");
-        else
-            clif_displaymessage (fd, "Deactivation successful.");
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return 0;
-}
-
-int atcommand_skill_learn (const int fd, struct map_session_data *sd,
-                           const char *command, const char *message)
-{
-    char character[100];
-    int  skill, level;
-    struct map_session_data *pl_sd;
-
-    if (!message || !*message
-        || sscanf (message, "%d %d %99[^\n]", &skill, &level, character) < 1)
-    {
-        clif_displaymessage (fd,
-                             "Usage: @skill-learn <skill-nr> <level> <char_name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) != NULL)
-    {
-        set_skill (pl_sd, skill, level);
-        clif_skillinfoblock (pl_sd);
-    }
-    else
-        clif_displaymessage (fd, "Character not found.");
-
-    return 0;
-}
-
-int atcommand_ipcheck (const int fd, struct map_session_data *sd,
-                   const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    struct sockaddr_in sai;
-    char output[200];
-    char character[25];
-    int i;
-    socklen_t sa_len = sizeof (struct sockaddr);
-    unsigned long ip;
-
-    memset(character, '\0', sizeof(character));
-
-    if (sscanf (message, "%24[^\n]", character) < 1)
-    {
-        clif_displaymessage (fd, "Usage: @ipcheck <char name>");
-        return -1;
-    }
-
-    if ((pl_sd = map_nick2sd (character)) == NULL)
-    {
-        clif_displaymessage (fd, "Character not found.");
-        return -1;
-    }
-
-    if (getpeername (pl_sd->fd, (struct sockaddr *)&sai, &sa_len))
-    {
-        clif_displaymessage (fd,
-                             "Guru Meditation Error: getpeername() failed");
-        return -1;
-    }
-
-    ip = sai.sin_addr.s_addr;
-
-    // We now have the IP address of a character.
-    // Loop over all logged in sessions looking for matches.
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            if (getpeername (pl_sd->fd, (struct sockaddr *)&sai, &sa_len))
-                continue;
-
-            // Is checking GM levels really needed here?
-            if (ip == sai.sin_addr.s_addr)
-            {
-                snprintf (output, sizeof(output),
-                         "Name: %s | Location: %s %d %d",
-                         pl_sd->status.name, pl_sd->mapname,
-                         pl_sd->bl.x, pl_sd->bl.y);
-                clif_displaymessage (fd, output);
-            }
-        }
-    }
-
-    clif_displaymessage (fd, "End of list");
-    return 0;
-}
-
-int atcommand_doomspot(const int fd, struct map_session_data *sd,
-                       const char *command, const char *message)
-{
-    struct map_session_data *pl_sd;
-    int  i;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m
-            && sd->bl.x == pl_sd->bl.x && sd->bl.y == pl_sd->bl.y
-            && pc_isGM (sd) >= pc_isGM (pl_sd))
-        {                       // you can doom only lower or same gm level
-            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
-            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
-        }
-    }
-    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
-
-    return 0;
-}
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
new file mode 100644
index 0000000..8f62ca2
--- /dev/null
+++ b/src/map/atcommand.cpp
@@ -0,0 +1,8728 @@
+// $Id: atcommand.c 148 2004-09-30 14:05:37Z MouseJstr $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/mt_rand.hpp"
+
+#include "atcommand.hpp"
+#include "battle.hpp"
+#include "clif.hpp"
+#include "chrif.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "party.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "trade.hpp"
+
+#include "../common/core.hpp"
+#include "tmw.hpp"
+
+#define STATE_BLIND 0x10
+
+static char command_symbol = '@';   // first char of the commands (by [Yor])
+
+static char msg_table[1000][1024];  // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
+
+#define ATCOMMAND_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message)
+ATCOMMAND_FUNC (setup);
+ATCOMMAND_FUNC (broadcast);
+ATCOMMAND_FUNC (localbroadcast);
+ATCOMMAND_FUNC (charwarp);
+ATCOMMAND_FUNC (warp);
+ATCOMMAND_FUNC (where);
+ATCOMMAND_FUNC (goto);
+ATCOMMAND_FUNC (jump);
+ATCOMMAND_FUNC (who);
+ATCOMMAND_FUNC (whogroup);
+ATCOMMAND_FUNC (whomap);
+ATCOMMAND_FUNC (whomapgroup);
+ATCOMMAND_FUNC (whogm);         // by Yor
+ATCOMMAND_FUNC (save);
+ATCOMMAND_FUNC (load);
+ATCOMMAND_FUNC (speed);
+ATCOMMAND_FUNC (storage);
+ATCOMMAND_FUNC (guildstorage);
+ATCOMMAND_FUNC (option);
+ATCOMMAND_FUNC (hide);
+ATCOMMAND_FUNC (die);
+ATCOMMAND_FUNC (kill);
+ATCOMMAND_FUNC (alive);
+ATCOMMAND_FUNC (kami);
+ATCOMMAND_FUNC (heal);
+ATCOMMAND_FUNC (item);
+ATCOMMAND_FUNC (itemreset);
+ATCOMMAND_FUNC (itemcheck);
+ATCOMMAND_FUNC (baselevelup);
+ATCOMMAND_FUNC (joblevelup);
+ATCOMMAND_FUNC (help);
+ATCOMMAND_FUNC (gm);
+ATCOMMAND_FUNC (pvpoff);
+ATCOMMAND_FUNC (pvpon);
+ATCOMMAND_FUNC (gvgoff);
+ATCOMMAND_FUNC (gvgon);
+ATCOMMAND_FUNC (model);
+ATCOMMAND_FUNC (go);
+ATCOMMAND_FUNC (spawn);
+ATCOMMAND_FUNC (killmonster);
+ATCOMMAND_FUNC (killmonster2);
+ATCOMMAND_FUNC (refine);
+ATCOMMAND_FUNC (produce);
+ATCOMMAND_FUNC (memo);
+ATCOMMAND_FUNC (gat);
+ATCOMMAND_FUNC (packet);
+ATCOMMAND_FUNC (statuspoint);
+ATCOMMAND_FUNC (skillpoint);
+ATCOMMAND_FUNC (zeny);
+ATCOMMAND_FUNC (param);
+ATCOMMAND_FUNC (guildlevelup);
+ATCOMMAND_FUNC (recall);
+ATCOMMAND_FUNC (recallall);
+ATCOMMAND_FUNC (revive);
+ATCOMMAND_FUNC (character_stats);
+ATCOMMAND_FUNC (character_stats_all);
+ATCOMMAND_FUNC (character_option);
+ATCOMMAND_FUNC (character_save);
+ATCOMMAND_FUNC (night);
+ATCOMMAND_FUNC (day);
+ATCOMMAND_FUNC (doom);
+ATCOMMAND_FUNC (doommap);
+ATCOMMAND_FUNC (raise);
+ATCOMMAND_FUNC (raisemap);
+ATCOMMAND_FUNC (character_baselevel);
+ATCOMMAND_FUNC (character_joblevel);
+ATCOMMAND_FUNC (kick);
+ATCOMMAND_FUNC (kickall);
+ATCOMMAND_FUNC (allskills);
+ATCOMMAND_FUNC (questskill);
+ATCOMMAND_FUNC (charquestskill);
+ATCOMMAND_FUNC (lostskill);
+ATCOMMAND_FUNC (charlostskill);
+ATCOMMAND_FUNC (party);
+ATCOMMAND_FUNC (guild);
+ATCOMMAND_FUNC (charskreset);
+ATCOMMAND_FUNC (charstreset);
+ATCOMMAND_FUNC (charreset);
+ATCOMMAND_FUNC (charstpoint);
+ATCOMMAND_FUNC (charmodel);
+ATCOMMAND_FUNC (charskpoint);
+ATCOMMAND_FUNC (charzeny);
+ATCOMMAND_FUNC (agitstart);
+ATCOMMAND_FUNC (agitend);
+ATCOMMAND_FUNC (reloaditemdb);
+ATCOMMAND_FUNC (reloadmobdb);
+ATCOMMAND_FUNC (reloadskilldb);
+ATCOMMAND_FUNC (reloadscript);
+ATCOMMAND_FUNC (reloadgmdb);    // by Yor
+ATCOMMAND_FUNC (mapexit);
+ATCOMMAND_FUNC (idsearch);
+ATCOMMAND_FUNC (mapinfo);
+ATCOMMAND_FUNC (dye);           //** by fritz
+ATCOMMAND_FUNC (hair_style);    //** by fritz
+ATCOMMAND_FUNC (hair_color);    //** by fritz
+ATCOMMAND_FUNC (all_stats);     //** by fritz
+ATCOMMAND_FUNC (char_change_sex);   // by Yor
+ATCOMMAND_FUNC (char_block);    // by Yor
+ATCOMMAND_FUNC (char_ban);      // by Yor
+ATCOMMAND_FUNC (char_unblock);  // by Yor
+ATCOMMAND_FUNC (char_unban);    // by Yor
+ATCOMMAND_FUNC (mount_peco);    // by Valaris
+ATCOMMAND_FUNC (char_mount_peco);   // by Yor
+ATCOMMAND_FUNC (guildspy);      // [Syrus22]
+ATCOMMAND_FUNC (partyspy);      // [Syrus22]
+ATCOMMAND_FUNC (guildrecall);   // by Yor
+ATCOMMAND_FUNC (partyrecall);   // by Yor
+ATCOMMAND_FUNC (enablenpc);
+ATCOMMAND_FUNC (disablenpc);
+ATCOMMAND_FUNC (servertime);    // by Yor
+ATCOMMAND_FUNC (chardelitem);   // by Yor
+ATCOMMAND_FUNC (jail);          // by Yor
+ATCOMMAND_FUNC (unjail);        // by Yor
+ATCOMMAND_FUNC (disguise);      // [Valaris]
+ATCOMMAND_FUNC (undisguise);    // by Yor
+ATCOMMAND_FUNC (ignorelist);    // by Yor
+ATCOMMAND_FUNC (charignorelist);    // by Yor
+ATCOMMAND_FUNC (inall);         // by Yor
+ATCOMMAND_FUNC (exall);         // by Yor
+ATCOMMAND_FUNC (chardisguise);  // Kalaspuff
+ATCOMMAND_FUNC (charundisguise);    // Kalaspuff
+ATCOMMAND_FUNC (email);         // by Yor
+ATCOMMAND_FUNC (effect);        //by Apple
+ATCOMMAND_FUNC (character_item_list);   // by Yor
+ATCOMMAND_FUNC (character_storage_list);    // by Yor
+ATCOMMAND_FUNC (character_cart_list);   // by Yor
+ATCOMMAND_FUNC (addwarp);       // by MouseJstr
+ATCOMMAND_FUNC (follow);        // by MouseJstr
+ATCOMMAND_FUNC (skillon);       // by MouseJstr
+ATCOMMAND_FUNC (skilloff);      // by MouseJstr
+ATCOMMAND_FUNC (killer);        // by MouseJstr
+ATCOMMAND_FUNC (npcmove);       // by MouseJstr
+ATCOMMAND_FUNC (killable);      // by MouseJstr
+ATCOMMAND_FUNC (charkillable);  // by MouseJstr
+ATCOMMAND_FUNC (chareffect);    // by MouseJstr
+ATCOMMAND_FUNC (chardye);       // by MouseJstr
+ATCOMMAND_FUNC (charhairstyle); // by MouseJstr
+ATCOMMAND_FUNC (charhaircolor); // by MouseJstr
+ATCOMMAND_FUNC (dropall);       // by MouseJstr
+ATCOMMAND_FUNC (chardropall);   // by MouseJstr
+ATCOMMAND_FUNC (storeall);      // by MouseJstr
+ATCOMMAND_FUNC (charstoreall);  // by MouseJstr
+ATCOMMAND_FUNC (skillid);       // by MouseJstr
+ATCOMMAND_FUNC (useskill);      // by MouseJstr
+ATCOMMAND_FUNC (summon);
+ATCOMMAND_FUNC (rain);
+ATCOMMAND_FUNC (snow);
+ATCOMMAND_FUNC (sakura);
+ATCOMMAND_FUNC (fog);
+ATCOMMAND_FUNC (leaves);
+ATCOMMAND_FUNC (adjgmlvl);      // by MouseJstr
+ATCOMMAND_FUNC (adjcmdlvl);     // by MouseJstr
+ATCOMMAND_FUNC (trade);         // by MouseJstr
+ATCOMMAND_FUNC (unmute);        // [Valaris]
+ATCOMMAND_FUNC (char_wipe);     // [Fate]
+ATCOMMAND_FUNC (set_magic);     // [Fate]
+ATCOMMAND_FUNC (magic_info);    // [Fate]
+ATCOMMAND_FUNC (log);           // [Fate]
+ATCOMMAND_FUNC (tee);           // [Fate]
+ATCOMMAND_FUNC (invisible);     // [Fate]
+ATCOMMAND_FUNC (visible);       // [Fate]
+ATCOMMAND_FUNC (list_nearby);   // [Fate]
+ATCOMMAND_FUNC (iterate_forward_over_players);  // [Fate]
+ATCOMMAND_FUNC (iterate_backwards_over_players);    // [Fate]
+ATCOMMAND_FUNC (skillpool_info);    // [Fate]
+ATCOMMAND_FUNC (skillpool_focus);   // [Fate]
+ATCOMMAND_FUNC (skillpool_unfocus); // [Fate]
+ATCOMMAND_FUNC (skill_learn);   // [Fate]
+ATCOMMAND_FUNC (wgm);
+ATCOMMAND_FUNC (ipcheck);
+ATCOMMAND_FUNC (doomspot);
+
+/*==========================================
+ *AtCommandInfo atcommand_info[]構造体の定義
+ *------------------------------------------
+ */
+
+// First char of commands is configured in atcommand_athena.conf. Leave @ in this list for default value.
+// to set default level, read atcommand_athena.conf first please.
+static AtCommandInfo atcommand_info[] = {
+    {AtCommand_Setup, "@setup", 40, atcommand_setup},
+    {AtCommand_CharWarp, "@charwarp", 60, atcommand_charwarp},
+    {AtCommand_Warp, "@warp", 40, atcommand_warp},
+    {AtCommand_Where, "@where", 1, atcommand_where},
+    {AtCommand_Goto, "@goto", 20, atcommand_goto},
+    {AtCommand_Jump, "@jump", 40, atcommand_jump},
+    {AtCommand_Who, "@who", 20, atcommand_who},
+    {AtCommand_WhoGroup, "@whogroup", 20, atcommand_whogroup},
+    {AtCommand_WhoMap, "@whomap", 20, atcommand_whomap},
+    {AtCommand_WhoMapGroup, "@whomapgroup", 20, atcommand_whomapgroup},
+    {AtCommand_WhoGM, "@whogm", 20, atcommand_whogm},   // by Yor
+    {AtCommand_Save, "@save", 40, atcommand_save},
+    {AtCommand_Load, "@return", 40, atcommand_load},
+    {AtCommand_Load, "@load", 40, atcommand_load},
+    {AtCommand_Speed, "@speed", 40, atcommand_speed},
+    {AtCommand_Storage, "@storage", 1, atcommand_storage},
+    {AtCommand_GuildStorage, "@gstorage", 50, atcommand_guildstorage},
+    {AtCommand_Option, "@option", 40, atcommand_option},
+    {AtCommand_Hide, "@hide", 40, atcommand_hide},  // + /hide
+    {AtCommand_Die, "@die", 1, atcommand_die},
+    {AtCommand_Kill, "@kill", 60, atcommand_kill},
+    {AtCommand_Alive, "@alive", 60, atcommand_alive},
+    {AtCommand_Kami, "@kami", 40, atcommand_kami},
+    {AtCommand_Heal, "@heal", 40, atcommand_heal},
+    {AtCommand_Item, "@item", 60, atcommand_item},
+    {AtCommand_ItemReset, "@itemreset", 40, atcommand_itemreset},
+    {AtCommand_ItemCheck, "@itemcheck", 60, atcommand_itemcheck},
+    {AtCommand_BaseLevelUp, "@blvl", 60, atcommand_baselevelup},
+    {AtCommand_JobLevelUp, "@jlvl", 60, atcommand_joblevelup},
+    {AtCommand_Help, "@help", 20, atcommand_help},
+    {AtCommand_GM, "@gm", 100, atcommand_gm},
+    {AtCommand_PvPOff, "@pvpoff", 40, atcommand_pvpoff},
+    {AtCommand_PvPOn, "@pvpon", 40, atcommand_pvpon},
+    {AtCommand_GvGOff, "@gvgoff", 40, atcommand_gvgoff},
+    {AtCommand_GvGOff, "@gpvpoff", 40, atcommand_gvgoff},
+    {AtCommand_GvGOn, "@gvgon", 40, atcommand_gvgon},
+    {AtCommand_GvGOn, "@gpvpon", 40, atcommand_gvgon},
+    {AtCommand_Model, "@model", 20, atcommand_model},
+    {AtCommand_Go, "@go", 10, atcommand_go},
+    {AtCommand_Spawn, "@spawn", 50, atcommand_spawn},
+    {AtCommand_KillMonster, "@killmonster", 60, atcommand_killmonster},
+    {AtCommand_KillMonster2, "@killmonster2", 40, atcommand_killmonster2},
+    {AtCommand_Produce, "@produce", 60, atcommand_produce},
+    {AtCommand_Memo, "@memo", 40, atcommand_memo},
+    {AtCommand_GAT, "@gat", 99, atcommand_gat}, // debug function
+    {AtCommand_Packet, "@packet", 99, atcommand_packet},    // debug function
+    {AtCommand_StatusPoint, "@stpoint", 60, atcommand_statuspoint},
+    {AtCommand_SkillPoint, "@skpoint", 60, atcommand_skillpoint},
+    {AtCommand_Zeny, "@zeny", 60, atcommand_zeny},
+    {AtCommand_Strength, "@str", 60, atcommand_param},
+    {AtCommand_Agility, "@agi", 60, atcommand_param},
+    {AtCommand_Vitality, "@vit", 60, atcommand_param},
+    {AtCommand_Intelligence, "@int", 60, atcommand_param},
+    {AtCommand_Dexterity, "@dex", 60, atcommand_param},
+    {AtCommand_Luck, "@luk", 60, atcommand_param},
+    {AtCommand_GuildLevelUp, "@guildlvl", 60, atcommand_guildlevelup},
+    {AtCommand_Recall, "@recall", 60, atcommand_recall},    // + /recall
+    {AtCommand_Revive, "@revive", 60, atcommand_revive},
+    {AtCommand_CharacterStats, "@charstats", 40, atcommand_character_stats},
+    {AtCommand_CharacterStatsAll, "@charstatsall", 40,
+     atcommand_character_stats_all},
+    {AtCommand_CharacterOption, "@charoption", 60,
+     atcommand_character_option},
+    {AtCommand_CharacterSave, "@charsave", 60, atcommand_character_save},
+    {AtCommand_Night, "@night", 80, atcommand_night},
+    {AtCommand_Day, "@day", 80, atcommand_day},
+    {AtCommand_Doom, "@doom", 80, atcommand_doom},
+    {AtCommand_DoomMap, "@doommap", 80, atcommand_doommap},
+    {AtCommand_Raise, "@raise", 80, atcommand_raise},
+    {AtCommand_RaiseMap, "@raisemap", 80, atcommand_raisemap},
+    {AtCommand_CharacterBaseLevel, "@charbaselvl", 60,
+     atcommand_character_baselevel},
+    {AtCommand_CharacterJobLevel, "@charjlvl", 60,
+     atcommand_character_joblevel},
+    {AtCommand_Kick, "@kick", 20, atcommand_kick},  // + right click menu for GM "(name) force to quit"
+    {AtCommand_KickAll, "@kickall", 99, atcommand_kickall},
+    {AtCommand_AllSkills, "@allskills", 60, atcommand_allskills},
+    {AtCommand_QuestSkill, "@questskill", 40, atcommand_questskill},
+    {AtCommand_CharQuestSkill, "@charquestskill", 60,
+     atcommand_charquestskill},
+    {AtCommand_LostSkill, "@lostskill", 40, atcommand_lostskill},
+    {AtCommand_CharLostSkill, "@charlostskill", 60, atcommand_charlostskill},
+    {AtCommand_Party, "@party", 1, atcommand_party},
+    {AtCommand_Guild, "@guild", 50, atcommand_guild},
+    {AtCommand_AgitStart, "@agitstart", 60, atcommand_agitstart},
+    {AtCommand_AgitEnd, "@agitend", 60, atcommand_agitend},
+    {AtCommand_MapExit, "@mapexit", 99, atcommand_mapexit},
+    {AtCommand_IDSearch, "@idsearch", 60, atcommand_idsearch},
+    {AtCommand_MapMove, "@mapmove", 40, atcommand_warp},    // /mm command
+    {AtCommand_Broadcast, "@broadcast", 40, atcommand_broadcast},   // /b and /nb command
+    {AtCommand_LocalBroadcast, "@localbroadcast", 40, atcommand_localbroadcast},    // /lb and /nlb command
+    {AtCommand_RecallAll, "@recallall", 80, atcommand_recallall},
+    {AtCommand_CharSkReset, "@charskreset", 60, atcommand_charskreset},
+    {AtCommand_CharStReset, "@charstreset", 60, atcommand_charstreset},
+    {AtCommand_ReloadItemDB, "@reloaditemdb", 99, atcommand_reloaditemdb},  // admin command
+    {AtCommand_ReloadMobDB, "@reloadmobdb", 99, atcommand_reloadmobdb}, // admin command
+    {AtCommand_ReloadSkillDB, "@reloadskilldb", 99, atcommand_reloadskilldb},   // admin command
+    {AtCommand_ReloadScript, "@reloadscript", 99, atcommand_reloadscript},  // admin command
+    {AtCommand_ReloadGMDB, "@reloadgmdb", 99, atcommand_reloadgmdb},    // admin command
+    {AtCommand_CharReset, "@charreset", 60, atcommand_charreset},
+    {AtCommand_CharModel, "@charmodel", 50, atcommand_charmodel},
+    {AtCommand_CharSKPoint, "@charskpoint", 60, atcommand_charskpoint},
+    {AtCommand_CharSTPoint, "@charstpoint", 60, atcommand_charstpoint},
+    {AtCommand_CharZeny, "@charzeny", 60, atcommand_charzeny},
+    {AtCommand_MapInfo, "@mapinfo", 99, atcommand_mapinfo},
+    {AtCommand_Dye, "@dye", 40, atcommand_dye}, // by fritz
+    {AtCommand_Dye, "@ccolor", 40, atcommand_dye},  // by fritz
+    {AtCommand_HairStyle, "@hairstyle", 40, atcommand_hair_style},  // by fritz
+    {AtCommand_HairColor, "@haircolor", 40, atcommand_hair_color},  // by fritz
+    {AtCommand_AllStats, "@allstats", 60, atcommand_all_stats}, // by fritz
+    {AtCommand_CharChangeSex, "@charchangesex", 60, atcommand_char_change_sex}, // by Yor
+    {AtCommand_CharBlock, "@block", 60, atcommand_char_block},  // by Yor
+    {AtCommand_CharUnBlock, "@unblock", 60, atcommand_char_unblock},    // by Yor
+    {AtCommand_CharBan, "@ban", 60, atcommand_char_ban},    // by Yor
+    {AtCommand_CharUnBan, "@unban", 60, atcommand_char_unban},  // by Yor
+    {AtCommand_MountPeco, "@mountpeco", 20, atcommand_mount_peco},  // by Valaris
+    {AtCommand_CharMountPeco, "@charmountpeco", 50, atcommand_char_mount_peco}, // by Yor
+    {AtCommand_GuildSpy, "@guildspy", 60, atcommand_guildspy},  // [Syrus22]
+    {AtCommand_PartySpy, "@partyspy", 60, atcommand_partyspy},  // [Syrus22]
+    {AtCommand_GuildRecall, "@guildrecall", 60, atcommand_guildrecall}, // by Yor
+    {AtCommand_PartyRecall, "@partyrecall", 60, atcommand_partyrecall}, // by Yor
+    {AtCommand_Enablenpc, "@enablenpc", 80, atcommand_enablenpc},   // []
+    {AtCommand_Disablenpc, "@disablenpc", 80, atcommand_disablenpc},    // []
+    {AtCommand_ServerTime, "@servertime", 0, atcommand_servertime}, // by Yor
+    {AtCommand_CharDelItem, "@chardelitem", 60, atcommand_chardelitem}, // by Yor
+    {AtCommand_ListNearby, "@listnearby", 40, atcommand_list_nearby},   // by Yor
+    {AtCommand_Jail, "@jail", 60, atcommand_jail},  // by Yor
+    {AtCommand_UnJail, "@unjail", 60, atcommand_unjail},    // by Yor
+    {AtCommand_Disguise, "@disguise", 20, atcommand_disguise},  // [Valaris]
+    {AtCommand_UnDisguise, "@undisguise", 20, atcommand_undisguise},    // by Yor
+    {AtCommand_IgnoreList, "@ignorelist", 0, atcommand_ignorelist}, // by Yor
+    {AtCommand_CharIgnoreList, "@charignorelist", 20, atcommand_charignorelist},    // by Yor
+    {AtCommand_IgnoreList, "@inall", 20, atcommand_inall},  // by Yor
+    {AtCommand_ExAll, "@exall", 20, atcommand_exall},   // by Yor
+    {AtCommand_CharDisguise, "@chardisguise", 60, atcommand_chardisguise},  // Kalaspuff
+    {AtCommand_CharUnDisguise, "@charundisguise", 60, atcommand_charundisguise},    // Kalaspuff
+    {AtCommand_EMail, "@email", 0, atcommand_email},    // by Yor
+    {AtCommand_Effect, "@effect", 40, atcommand_effect},    // by Apple
+    {AtCommand_Char_Item_List, "@charitemlist", 40, atcommand_character_item_list}, // by Yor
+    {AtCommand_Char_Storage_List, "@charstoragelist", 40, atcommand_character_storage_list},    // by Yor
+    {AtCommand_Char_Cart_List, "@charcartlist", 40, atcommand_character_cart_list}, // by Yor
+    {AtCommand_Follow, "@follow", 10, atcommand_follow},    // by MouseJstr
+    {AtCommand_AddWarp, "@addwarp", 20, atcommand_addwarp}, // by MouseJstr
+    {AtCommand_SkillOn, "@skillon", 20, atcommand_skillon}, // by MouseJstr
+    {AtCommand_SkillOff, "@skilloff", 20, atcommand_skilloff},  // by MouseJstr
+    {AtCommand_Killer, "@killer", 60, atcommand_killer},    // by MouseJstr
+    {AtCommand_NpcMove, "@npcmove", 20, atcommand_npcmove}, // by MouseJstr
+    {AtCommand_Killable, "@killable", 40, atcommand_killable},  // by MouseJstr
+    {AtCommand_CharKillable, "@charkillable", 40, atcommand_charkillable},  // by MouseJstr
+    {AtCommand_Chareffect, "@chareffect", 40, atcommand_chareffect},    // MouseJstr
+    //{ AtCommand_Chardye,  "@chardye",  40, atcommand_chardye }, // MouseJstr
+    //{ AtCommand_Charhairstyle,  "@charhairstyle",  40, atcommand_charhairstyle }, // MouseJstr
+    //{ AtCommand_Charhaircolor,  "@charhaircolor",  40, atcommand_charhaircolor }, // MouseJstr
+    {AtCommand_Dropall, "@dropall", 40, atcommand_dropall}, // MouseJstr
+    {AtCommand_Chardropall, "@chardropall", 40, atcommand_chardropall}, // MouseJstr
+    {AtCommand_Storeall, "@storeall", 40, atcommand_storeall},  // MouseJstr
+    {AtCommand_Charstoreall, "@charstoreall", 40, atcommand_charstoreall},  // MouseJstr
+    {AtCommand_Skillid, "@skillid", 40, atcommand_skillid}, // MouseJstr
+    {AtCommand_Useskill, "@useskill", 40, atcommand_useskill},  // MouseJstr
+    {AtCommand_Rain, "@rain", 99, atcommand_rain},
+    {AtCommand_Snow, "@snow", 99, atcommand_snow},
+    {AtCommand_Sakura, "@sakura", 99, atcommand_sakura},
+    {AtCommand_Fog, "@fog", 99, atcommand_fog},
+    {AtCommand_Leaves, "@leaves", 99, atcommand_leaves},
+    //{ AtCommand_Shuffle,         "@shuffle",  99, atcommand_shuffle },
+    //{ AtCommand_Maintenance, "@maintenance", 99, atcommand_maintenance },
+    //{ AtCommand_Misceffect,    "@misceffect", 60, atcommand_misceffect },
+    {AtCommand_Summon, "@summon", 60, atcommand_summon},
+    {AtCommand_AdjGmLvl, "@adjgmlvl", 99, atcommand_adjgmlvl},
+    {AtCommand_AdjCmdLvl, "@adjcmdlvl", 99, atcommand_adjcmdlvl},
+    {AtCommand_Trade, "@trade", 60, atcommand_trade},
+    {AtCommand_UnMute, "@unmute", 60, atcommand_unmute},    // [Valaris]
+    {AtCommand_UnMute, "@charwipe", 60, atcommand_char_wipe},   // [Fate]
+    {AtCommand_SetMagic, "@setmagic", 99, atcommand_set_magic}, // [Fate]
+    {AtCommand_MagicInfo, "@magicinfo", 60, atcommand_magic_info},  // [Fate]
+    {AtCommand_Log, "@log", 60, atcommand_log}, // [Fate]
+    {AtCommand_Log, "@l", 60, atcommand_log},   // [Fate]
+    {AtCommand_Tee, "@tee", 60, atcommand_tee}, // [Fate]
+    {AtCommand_Tee, "@t", 60, atcommand_tee},   // [Fate]
+    {AtCommand_Invisible, "@invisible", 60, atcommand_invisible},   // [Fate]
+    {AtCommand_Visible, "@visible", 60, atcommand_visible}, // [Fate]
+    {AtCommand_IterateForward, "@hugo", 60, atcommand_iterate_forward_over_players},    // [Fate]
+    {AtCommand_IterateBackward, "@linus", 60, atcommand_iterate_backwards_over_players},    // [Fate]
+    {AtCommand_IterateBackward, "@sp-info", 40, atcommand_skillpool_info},  // [Fate]
+    {AtCommand_IterateBackward, "@sp-focus", 80, atcommand_skillpool_focus},    // [Fate]
+    {AtCommand_IterateBackward, "@sp-unfocus", 80, atcommand_skillpool_unfocus},    // [Fate]
+    {AtCommand_IterateBackward, "@skill-learn", 80, atcommand_skill_learn}, // [Fate]
+    {AtCommand_Wgm, "@wgm", 0, atcommand_wgm},
+    {AtCommand_IpCheck, "@ipcheck", 60, atcommand_ipcheck},
+    {AtCommand_DoomSpot, "@doomspot", 60, atcommand_doomspot},
+
+// add new commands before this line
+    {AtCommand_Unknown, NULL, 1, NULL}
+};
+
+/*====================================================
+ * This function return the name of the job (by [Yor])
+ *----------------------------------------------------
+ */
+const char *job_name (int pc_class)
+{
+    switch (pc_class)
+    {
+        case 0:
+            return "Novice";
+        case 1:
+            return "Swordsman";
+        case 2:
+            return "Mage";
+        case 3:
+            return "Archer";
+        case 4:
+            return "Acolyte";
+        case 5:
+            return "Merchant";
+        case 6:
+            return "Thief";
+        case 7:
+            return "Knight";
+        case 8:
+            return "Priest";
+        case 9:
+            return "Wizard";
+        case 10:
+            return "Blacksmith";
+        case 11:
+            return "Hunter";
+        case 12:
+            return "Assassin";
+        case 13:
+            return "Knight 2";
+        case 14:
+            return "Crusader";
+        case 15:
+            return "Monk";
+        case 16:
+            return "Sage";
+        case 17:
+            return "Rogue";
+        case 18:
+            return "Alchemist";
+        case 19:
+            return "Bard";
+        case 20:
+            return "Dancer";
+        case 21:
+            return "Crusader 2";
+        case 22:
+            return "Wedding";
+        case 23:
+            return "Super Novice";
+        case 4001:
+            return "Novice High";
+        case 4002:
+            return "Swordsman High";
+        case 4003:
+            return "Mage High";
+        case 4004:
+            return "Archer High";
+        case 4005:
+            return "Acolyte High";
+        case 4006:
+            return "Merchant High";
+        case 4007:
+            return "Thief High";
+        case 4008:
+            return "Lord Knight";
+        case 4009:
+            return "High Priest";
+        case 4010:
+            return "High Wizard";
+        case 4011:
+            return "Whitesmith";
+        case 4012:
+            return "Sniper";
+        case 4013:
+            return "Assassin Cross";
+        case 4014:
+            return "Peko Knight";
+        case 4015:
+            return "Paladin";
+        case 4016:
+            return "Champion";
+        case 4017:
+            return "Professor";
+        case 4018:
+            return "Stalker";
+        case 4019:
+            return "Creator";
+        case 4020:
+            return "Clown";
+        case 4021:
+            return "Gypsy";
+        case 4022:
+            return "Peko Paladin";
+        case 4023:
+            return "Baby Novice";
+        case 4024:
+            return "Baby Swordsman";
+        case 4025:
+            return "Baby Mage";
+        case 4026:
+            return "Baby Archer";
+        case 4027:
+            return "Baby Acolyte";
+        case 4028:
+            return "Baby Merchant";
+        case 4029:
+            return "Baby Thief";
+        case 4030:
+            return "Baby Knight";
+        case 4031:
+            return "Baby Priest";
+        case 4032:
+            return "Baby Wizard";
+        case 4033:
+            return "Baby Blacksmith";
+        case 4034:
+            return "Baby Hunter";
+        case 4035:
+            return "Baby Assassin";
+        case 4036:
+            return "Baby Peco Knight";
+        case 4037:
+            return "Baby Crusader";
+        case 4038:
+            return "Baby Monk";
+        case 4039:
+            return "Baby Sage";
+        case 4040:
+            return "Baby Rogue";
+        case 4041:
+            return "Baby Alchemist";
+        case 4042:
+            return "Baby Bard";
+        case 4043:
+            return "Baby Dancer";
+        case 4044:
+            return "Baby Peco Crusader";
+        case 4045:
+            return "Super Baby";
+    }
+    return "Unknown Job";
+}
+
+//-----------------------------------------------------------
+// Return the message string of the specified number by [Yor]
+//-----------------------------------------------------------
+char *msg_txt (int msg_number)
+{
+    if (msg_number >= 0
+        && msg_number < (int) (sizeof (msg_table) / sizeof (msg_table[0]))
+        && msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0')
+        return msg_table[msg_number];
+
+    return "??";
+}
+
+//------------------------------------------------------------
+// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
+//------------------------------------------------------------
+int e_mail_check (unsigned char *email)
+{
+    char ch;
+    unsigned char *last_arobas;
+
+    // athena limits
+    if (strlen (email) < 3 || strlen (email) > 39)
+        return 0;
+
+    // part of RFC limits (official reference of e-mail description)
+    if (strchr (email, '@') == NULL || email[strlen (email) - 1] == '@')
+        return 0;
+
+    if (email[strlen (email) - 1] == '.')
+        return 0;
+
+    last_arobas = strrchr (email, '@');
+
+    if (strstr (last_arobas, "@.") != NULL ||
+        strstr (last_arobas, "..") != NULL)
+        return 0;
+
+    for (ch = 1; ch < 32; ch++)
+    {
+        if (strchr (last_arobas, ch) != NULL)
+        {
+            return 0;
+            break;
+        }
+    }
+
+    if (strchr (last_arobas, ' ') != NULL ||
+        strchr (last_arobas, ';') != NULL)
+        return 0;
+
+    // all correct
+    return 1;
+}
+
+/*==========================================
+ * get_atcommand_level @コマンドの必要レベルを取得
+ *------------------------------------------
+ */
+int get_atcommand_level (const AtCommandType type)
+{
+    int  i;
+
+    for (i = 0; atcommand_info[i].type != AtCommand_None; i++)
+        if (atcommand_info[i].type == type)
+            return atcommand_info[i].level;
+
+    return 100;                 // 100: command can not be used
+}
+
+/*========================================
+ * At-command logging
+ */
+void log_atcommand (struct map_session_data *sd, const char *fmt, ...)
+{
+    char message[512];
+    va_list ap;
+
+    va_start (ap, fmt);
+    vsnprintf (message, 511, fmt, ap);
+    va_end (ap);
+
+    gm_log ("%s(%d,%d) %s(%d) : %s", map[sd->bl.m].name, sd->bl.x,
+                sd->bl.y, sd->status.name, sd->status.account_id, message);
+}
+
+char *gm_logfile_name = NULL;
+/*==========================================
+ * Log a timestamped line to GM log file
+ *------------------------------------------
+ */
+void gm_log (const char *fmt, ...)
+{
+    static int last_logfile_nr = 0;
+    static FILE *gm_logfile = NULL;
+    time_t time_v;
+    struct tm ctime;
+    int  month, year, logfile_nr;
+    char message[512];
+    va_list ap;
+
+    if (!gm_logfile_name)
+        return;
+
+    va_start (ap, fmt);
+    vsnprintf (message, 511, fmt, ap);
+    va_end (ap);
+
+    time (&time_v);
+    gmtime_r (&time_v, &ctime);
+
+    year = ctime.tm_year + 1900;
+    month = ctime.tm_mon + 1;
+    logfile_nr = (year * 12) + month;
+
+    if (logfile_nr != last_logfile_nr)
+    {
+        char *fullname = (char *)malloc (strlen (gm_logfile_name) + 10);
+        sprintf (fullname, "%s.%04d-%02d", gm_logfile_name, year, month);
+
+        if (gm_logfile)
+            fclose_ (gm_logfile);
+
+        gm_logfile = fopen_ (fullname, "a");
+        free (fullname);
+
+        if (!gm_logfile)
+        {
+            perror ("GM log file");
+            gm_logfile_name = NULL;
+        }
+        last_logfile_nr = logfile_nr;
+    }
+
+    fprintf (gm_logfile, "[%04d-%02d-%02d %02d:%02d:%02d] %s\n",
+             year, month, ctime.tm_mday, ctime.tm_hour,
+             ctime.tm_min, ctime.tm_sec, message);
+
+    fflush (gm_logfile);
+}
+
+/*==========================================
+ *is_atcommand @コマンドに存在するかどうか確認する
+ *------------------------------------------
+ */
+AtCommandType
+is_atcommand (const int fd, struct map_session_data *sd, const char *message,
+              int gmlvl)
+{
+    AtCommandInfo info;
+    AtCommandType type;
+
+    nullpo_retr (AtCommand_None, sd);
+
+    if (!message || !*message)
+        return AtCommand_None;
+
+    memset (&info, 0, sizeof (info));
+
+    type = atcommand (gmlvl > 0 ? gmlvl : pc_isGM (sd), message, &info);
+    if (type != AtCommand_None)
+    {
+        char command[100];
+        char output[200];
+        const char *str = message;
+        const char *p = message;
+        memset (command, '\0', sizeof (command));
+        memset (output, '\0', sizeof (output));
+        while (*p && !isspace (*p))
+            p++;
+        if (p - str >= sizeof (command))    // too long
+            return AtCommand_Unknown;
+        strncpy (command, str, p - str);
+        while (isspace (*p))
+            p++;
+
+        if (type == AtCommand_Unknown || info.proc == NULL)
+        {
+            sprintf (output, msg_table[153], command);  // %s is Unknown Command.
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            if (info.proc (fd, sd, command, p) != 0)
+            {
+                // Command can not be executed
+                sprintf (output, msg_table[154], command);  // %s failed.
+                clif_displaymessage (fd, output);
+            }
+            else
+            {
+                if (get_atcommand_level (type) != 0)    // Don't log level 0 commands
+                    log_atcommand (sd, "%s %s", command, p);
+            }
+        }
+
+        return info.type;
+    }
+
+    return AtCommand_None;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+AtCommandType atcommand (const int level, const char *message,
+                         struct AtCommandInfo * info)
+{
+    char *p = (char *) message; // it's 'char' and not 'const char' to have possibility to modify the first character if necessary
+
+    if (!info)
+        return AtCommand_None;
+    if (battle_config.atc_gmonly != 0 && !level)    // level = pc_isGM(sd)
+        return AtCommand_None;
+    if (!p || !*p)
+    {
+        fprintf (stderr, "at command message is empty\n");
+        return AtCommand_None;
+    }
+
+    if (*p == command_symbol)
+    {                           // check first char.
+        char command[101];
+        int  i = 0;
+        memset (info, 0, sizeof (AtCommandInfo));
+        sscanf (p, "%100s", command);
+        command[sizeof (command) - 1] = '\0';
+
+        while (atcommand_info[i].type != AtCommand_Unknown)
+        {
+            if (strcasecmp (command + 1, atcommand_info[i].command + 1) == 0
+                && level >= atcommand_info[i].level)
+            {
+                p[0] = atcommand_info[i].command[0];    // set correct first symbol for after.
+                break;
+            }
+            i++;
+        }
+
+        if (atcommand_info[i].type == AtCommand_Unknown)
+        {
+            // doesn't return Unknown if player is normal player (display the text, not display: unknown command)
+            if (level == 0)
+                return AtCommand_None;
+            else
+                return AtCommand_Unknown;
+        }
+        memcpy (info, &atcommand_info[i], sizeof atcommand_info[i]);
+    }
+    else
+    {
+        return AtCommand_None;
+    }
+
+    return info->type;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int atkillmonster_sub (struct block_list *bl, va_list ap)
+{
+    int  flag = va_arg (ap, int);
+
+    nullpo_retr (0, bl);
+
+    if (flag)
+        mob_damage (NULL, (struct mob_data *) bl,
+                    ((struct mob_data *) bl)->hp, 2);
+    else
+        mob_delete ((struct mob_data *) bl);
+
+    return 0;
+}
+
+/*==========================================
+ * Read Message Data
+ *------------------------------------------
+ */
+int msg_config_read (const char *cfgName)
+{
+    int  msg_number;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    if ((fp = fopen_ (cfgName, "r")) == NULL)
+    {
+        printf ("Messages file not found: %s\n", cfgName);
+        return 1;
+    }
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
+        {
+            if (strcasecmp (w1, "import") == 0)
+            {
+                msg_config_read (w2);
+            }
+            else
+            {
+                msg_number = atoi (w1);
+                if (msg_number >= 0
+                    && msg_number <
+                    (int) (sizeof (msg_table) / sizeof (msg_table[0])))
+                    strcpy (msg_table[msg_number], w2);
+                //  printf("message #%d: '%s'.\n", msg_number, msg_table[msg_number]);
+            }
+        }
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static AtCommandInfo *get_atcommandinfo_byname (const char *name)
+{
+    int  i;
+
+    for (i = 0; atcommand_info[i].type != AtCommand_Unknown; i++)
+        if (strcasecmp (atcommand_info[i].command + 1, name) == 0)
+            return &atcommand_info[i];
+
+    return NULL;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_config_read (const char *cfgName)
+{
+    char line[1024], w1[1024], w2[1024];
+    AtCommandInfo *p;
+    FILE *fp;
+
+    if ((fp = fopen_ (cfgName, "r")) == NULL)
+    {
+        printf ("At commands configuration file not found: %s\n", cfgName);
+        return 1;
+    }
+
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+
+        if (sscanf (line, "%1023[^:]:%1023s", w1, w2) != 2)
+            continue;
+        p = get_atcommandinfo_byname (w1);
+        if (p != NULL)
+        {
+            p->level = atoi (w2);
+            if (p->level > 100)
+                p->level = 100;
+            else if (p->level < 0)
+                p->level = 0;
+        }
+
+        if (strcasecmp (w1, "import") == 0)
+            atcommand_config_read (w2);
+        else if (strcasecmp (w1, "command_symbol") == 0 && w2[0] > 31 && w2[0] != '/' &&   // symbol of standard ragnarok GM commands
+                 w2[0] != '%')  // symbol of party chat speaking
+            command_symbol = w2[0];
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+/*==========================================
+// @ command processing functions
+ *------------------------------------------
+ */
+
+/*==========================================
+ * @setup - Safely set a chars levels and warp them to a special place
+ * TAW Specific
+ *------------------------------------------
+ */
+int atcommand_setup (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char buf[256];
+    char character[100];
+    int  level = 1;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &level, character) < 2)
+    {
+        clif_displaymessage (fd, "Usage: @setup <level> <char name>");
+        return -1;
+    }
+    level--;
+
+    snprintf (buf, 255, "-255 %s", character);
+    atcommand_character_baselevel (fd, sd, "@charbaselvl", buf);
+
+    snprintf (buf, 255, "%d %s", level, character);
+    atcommand_character_baselevel (fd, sd, "@charbaselvl", buf);
+
+    // Emote skill
+    snprintf (buf, 255, "1 1 %s", character);
+    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
+
+    // Trade skill
+    snprintf (buf, 255, "2 1 %s", character);
+    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
+
+    // Party skill
+    snprintf (buf, 255, "2 2 %s", character);
+    atcommand_skill_learn(fd, sd, "@skill-learn", buf);
+
+    snprintf (buf, 255, "018-1.gat 24 98 %s", character);
+    atcommand_charwarp (fd, sd, "@charwarp", buf);
+
+    return (0);
+
+}
+
+/*==========================================
+ * @rura+
+ *------------------------------------------
+ */
+int atcommand_charwarp (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char map_name[100];
+    char character[100];
+    int  x = 0, y = 0;
+    struct map_session_data *pl_sd;
+    int  m;
+
+    memset (map_name, '\0', sizeof (map_name));
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d %d %99[^\n]", map_name, &x, &y,
+                   character) < 4)
+    {
+        clif_displaymessage (fd,
+                             "Usage: @charwarp/@rura+ <mapname> <x> <y> <char name>");
+        return -1;
+    }
+
+    if (x <= 0)
+        x = MRAND (399) + 1;
+    if (y <= 0)
+        y = MRAND (399) + 1;
+    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+        strcat (map_name, ".gat");
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can rura+ only lower or same GM level
+            if (x > 0 && x < 800 && y > 0 && y < 800)
+            {
+                m = map_mapname2mapid (map_name);
+                if (m >= 0 && map[m].flag.nowarpto
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                {
+                    clif_displaymessage (fd,
+                                         "You are not authorised to warp someone to this map.");
+                    return -1;
+                }
+                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                {
+                    clif_displaymessage (fd,
+                                         "You are not authorised to warp this player from its actual map.");
+                    return -1;
+                }
+                if (pc_setpos (pl_sd, map_name, x, y, 3) == 0)
+                {
+                    clif_displaymessage (pl_sd->fd, msg_table[0]);  // Warped.
+                    clif_displaymessage (fd, msg_table[15]);    // Player warped (message sends to player too).
+                }
+                else
+                {
+                    clif_displaymessage (fd, msg_table[1]); // Map not found.
+                    return -1;
+                }
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_warp (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char map_name[100];
+    int  x = 0, y = 0;
+    int  m;
+
+    memset (map_name, '\0', sizeof (map_name));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d %d", map_name, &x, &y) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a map (usage: @warp <mapname> <x> <y>).");
+        return -1;
+    }
+
+    if (x <= 0)
+        x = MRAND (399) + 1;
+    if (y <= 0)
+        y = MRAND (399) + 1;
+
+    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+        strcat (map_name, ".gat");
+
+    if (x > 0 && x < 800 && y > 0 && y < 800)
+    {
+        m = map_mapname2mapid (map_name);
+        if (m >= 0 && map[m].flag.nowarpto
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you to this map.");
+            return -1;
+        }
+        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you from your actual map.");
+            return -1;
+        }
+        if (pc_setpos (sd, map_name, x, y, 3) == 0)
+            clif_displaymessage (fd, msg_table[0]); // Warped.
+        else
+        {
+            clif_displaymessage (fd, msg_table[1]); // Map not found.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_where (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (sscanf (message, "%99[^\n]", character) < 1)
+        strcpy (character, sd->status.name);
+
+    if ((pl_sd = map_nick2sd (character)) != NULL &&
+        !((battle_config.hide_GM_session
+           || (pl_sd->status.option & OPTION_HIDE))
+          && (pc_isGM (pl_sd) > pc_isGM (sd))))
+    {                           // you can look only lower or same level
+        sprintf (output, "%s: %s (%d,%d)", pl_sd->status.name, pl_sd->mapname,
+                 pl_sd->bl.x, pl_sd->bl.y);
+        clif_displaymessage (fd, output);
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_goto (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you to the map of this player.");
+            return -1;
+        }
+        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you from your actual map.");
+            return -1;
+        }
+        pc_setpos (sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y, 3);
+        sprintf (output, msg_table[4], character);  // Jump to %s
+        clif_displaymessage (fd, output);
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_jump (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char output[200];
+    int  x = 0, y = 0;
+
+    memset (output, '\0', sizeof (output));
+
+    sscanf (message, "%d %d", &x, &y);
+
+    if (x <= 0)
+        x = MRAND (399) + 1;
+    if (y <= 0)
+        y = MRAND (399) + 1;
+    if (x > 0 && x < 800 && y > 0 && y < 800)
+    {
+        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you to your actual map.");
+            return -1;
+        }
+        if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+            && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+        {
+            clif_displaymessage (fd,
+                                 "You are not authorised to warp you from your actual map.");
+            return -1;
+        }
+        pc_setpos (sd, sd->mapname, x, y, 3);
+        sprintf (output, msg_table[5], x, y);   // Jump to %d %d
+        clif_displaymessage (fd, output);
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[2]); // Coordinates out of range.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_who (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i, j, count;
+    int  pl_GM_level, GM_level;
+    char match_text[100];
+    char player_name[24];
+
+    memset (output, '\0', sizeof (output));
+    memset (match_text, '\0', sizeof (match_text));
+    memset (player_name, '\0', sizeof (player_name));
+
+    if (sscanf (message, "%99[^\n]", match_text) < 1)
+        strcpy (match_text, "");
+    for (j = 0; match_text[j]; j++)
+        match_text[j] = tolower (match_text[j]);
+
+    count = 0;
+    GM_level = pc_isGM (sd);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            pl_GM_level = pc_isGM (pl_sd);
+            if (!
+                ((battle_config.hide_GM_session
+                  || (pl_sd->status.option & OPTION_HIDE))
+                 && (pl_GM_level > GM_level)))
+            {                   // you can look only lower or same level
+                memcpy (player_name, pl_sd->status.name, 24);
+                for (j = 0; player_name[j]; j++)
+                    player_name[j] = tolower (player_name[j]);
+                if (strstr (player_name, match_text) != NULL)
+                {               // search with no case sensitive
+                    if (pl_GM_level > 0)
+                        sprintf (output,
+                                 "Name: %s (GM:%d) | Location: %s %d %d",
+                                 pl_sd->status.name, pl_GM_level,
+                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+                    else
+                        sprintf (output, "Name: %s | Location: %s %d %d",
+                                 pl_sd->status.name, pl_sd->mapname,
+                                 pl_sd->bl.x, pl_sd->bl.y);
+                    clif_displaymessage (fd, output);
+                    count++;
+                }
+            }
+        }
+    }
+
+    if (count == 0)
+        clif_displaymessage (fd, msg_table[28]);    // No player found.
+    else if (count == 1)
+        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
+    else
+    {
+        sprintf (output, msg_table[30], count); // %d players found.
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_whogroup (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char temp0[100];
+    char temp1[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i, j, count;
+    int  pl_GM_level, GM_level;
+    char match_text[100];
+    char player_name[24];
+    struct guild *g;
+    struct party *p;
+
+    memset (temp0, '\0', sizeof (temp0));
+    memset (temp1, '\0', sizeof (temp1));
+    memset (output, '\0', sizeof (output));
+    memset (match_text, '\0', sizeof (match_text));
+    memset (player_name, '\0', sizeof (player_name));
+
+    if (sscanf (message, "%99[^\n]", match_text) < 1)
+        strcpy (match_text, "");
+    for (j = 0; match_text[j]; j++)
+        match_text[j] = tolower (match_text[j]);
+
+    count = 0;
+    GM_level = pc_isGM (sd);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            pl_GM_level = pc_isGM (pl_sd);
+            if (!
+                ((battle_config.hide_GM_session
+                  || (pl_sd->status.option & OPTION_HIDE))
+                 && (pl_GM_level > GM_level)))
+            {                   // you can look only lower or same level
+                memcpy (player_name, pl_sd->status.name, 24);
+                for (j = 0; player_name[j]; j++)
+                    player_name[j] = tolower (player_name[j]);
+                if (strstr (player_name, match_text) != NULL)
+                {               // search with no case sensitive
+                    g = guild_search (pl_sd->status.guild_id);
+                    if (g == NULL)
+                        sprintf (temp1, "None");
+                    else
+                        sprintf (temp1, "%s", g->name);
+                    p = party_search (pl_sd->status.party_id);
+                    if (p == NULL)
+                        sprintf (temp0, "None");
+                    else
+                        sprintf (temp0, "%s", p->name);
+                    if (pl_GM_level > 0)
+                        sprintf (output,
+                                 "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'",
+                                 pl_sd->status.name, pl_GM_level, temp0,
+                                 temp1);
+                    else
+                        sprintf (output,
+                                 "Name: %s | Party: '%s' | Guild: '%s'",
+                                 pl_sd->status.name, temp0, temp1);
+                    clif_displaymessage (fd, output);
+                    count++;
+                }
+            }
+        }
+    }
+
+    if (count == 0)
+        clif_displaymessage (fd, msg_table[28]);    // No player found.
+    else if (count == 1)
+        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
+    else
+    {
+        sprintf (output, msg_table[30], count); // %d players found.
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_whomap (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i, count;
+    int  pl_GM_level, GM_level;
+    int  map_id;
+    char map_name[100];
+
+    memset (output, '\0', sizeof (output));
+    memset (map_name, '\0', sizeof (map_name));
+
+    if (!message || !*message)
+        map_id = sd->bl.m;
+    else
+    {
+        sscanf (message, "%99s", map_name);
+        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+            strcat (map_name, ".gat");
+        if ((map_id = map_mapname2mapid (map_name)) < 0)
+            map_id = sd->bl.m;
+    }
+
+    count = 0;
+    GM_level = pc_isGM (sd);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            pl_GM_level = pc_isGM (pl_sd);
+            if (!
+                ((battle_config.hide_GM_session
+                  || (pl_sd->status.option & OPTION_HIDE))
+                 && (pl_GM_level > GM_level)))
+            {                   // you can look only lower or same level
+                if (pl_sd->bl.m == map_id)
+                {
+                    if (pl_GM_level > 0)
+                        sprintf (output,
+                                 "Name: %s (GM:%d) | Location: %s %d %d",
+                                 pl_sd->status.name, pl_GM_level,
+                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+                    else
+                        sprintf (output, "Name: %s | Location: %s %d %d",
+                                 pl_sd->status.name, pl_sd->mapname,
+                                 pl_sd->bl.x, pl_sd->bl.y);
+                    clif_displaymessage (fd, output);
+                    count++;
+                }
+            }
+        }
+    }
+
+    if (count == 0)
+        sprintf (output, msg_table[54], map[map_id].name);  // No player found in map '%s'.
+    else if (count == 1)
+        sprintf (output, msg_table[55], map[map_id].name);  // 1 player found in map '%s'.
+    else
+    {
+        sprintf (output, msg_table[56], count, map[map_id].name);   // %d players found in map '%s'.
+    }
+    clif_displaymessage (fd, output);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_whomapgroup (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    char temp0[100];
+    char temp1[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i, count;
+    int  pl_GM_level, GM_level;
+    int  map_id = 0;
+    char map_name[100];
+    struct guild *g;
+    struct party *p;
+
+    memset (temp0, '\0', sizeof (temp0));
+    memset (temp1, '\0', sizeof (temp1));
+    memset (output, '\0', sizeof (output));
+    memset (map_name, '\0', sizeof (map_name));
+
+    if (!message || !*message)
+        map_id = sd->bl.m;
+    else
+    {
+        sscanf (message, "%99s", map_name);
+        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+            strcat (map_name, ".gat");
+        if ((map_id = map_mapname2mapid (map_name)) < 0)
+            map_id = sd->bl.m;
+    }
+
+    count = 0;
+    GM_level = pc_isGM (sd);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            pl_GM_level = pc_isGM (pl_sd);
+            if (!
+                ((battle_config.hide_GM_session
+                  || (pl_sd->status.option & OPTION_HIDE))
+                 && (pl_GM_level > GM_level)))
+            {                   // you can look only lower or same level
+                if (pl_sd->bl.m == map_id)
+                {
+                    g = guild_search (pl_sd->status.guild_id);
+                    if (g == NULL)
+                        sprintf (temp1, "None");
+                    else
+                        sprintf (temp1, "%s", g->name);
+                    p = party_search (pl_sd->status.party_id);
+                    if (p == NULL)
+                        sprintf (temp0, "None");
+                    else
+                        sprintf (temp0, "%s", p->name);
+                    if (pl_GM_level > 0)
+                        sprintf (output,
+                                 "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'",
+                                 pl_sd->status.name, pl_GM_level, temp0,
+                                 temp1);
+                    else
+                        sprintf (output,
+                                 "Name: %s | Party: '%s' | Guild: '%s'",
+                                 pl_sd->status.name, temp0, temp1);
+                    clif_displaymessage (fd, output);
+                    count++;
+                }
+            }
+        }
+    }
+
+    if (count == 0)
+        sprintf (output, msg_table[54], map[map_id].name);  // No player found in map '%s'.
+    else if (count == 1)
+        sprintf (output, msg_table[55], map[map_id].name);  // 1 player found in map '%s'.
+    else
+    {
+        sprintf (output, msg_table[56], count, map[map_id].name);   // %d players found in map '%s'.
+    }
+    clif_displaymessage (fd, output);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_whogm (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char temp0[100];
+    char temp1[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i, j, count;
+    int  pl_GM_level, GM_level;
+    char match_text[100];
+    char player_name[24];
+    struct guild *g;
+    struct party *p;
+
+    memset (temp0, '\0', sizeof (temp0));
+    memset (temp1, '\0', sizeof (temp1));
+    memset (output, '\0', sizeof (output));
+    memset (match_text, '\0', sizeof (match_text));
+    memset (player_name, '\0', sizeof (player_name));
+
+    if (sscanf (message, "%99[^\n]", match_text) < 1)
+        strcpy (match_text, "");
+    for (j = 0; match_text[j]; j++)
+        match_text[j] = tolower (match_text[j]);
+
+    count = 0;
+    GM_level = pc_isGM (sd);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            pl_GM_level = pc_isGM (pl_sd);
+            if (pl_GM_level > 0)
+            {
+                if (!
+                    ((battle_config.hide_GM_session
+                      || (pl_sd->status.option & OPTION_HIDE))
+                     && (pl_GM_level > GM_level)))
+                {               // you can look only lower or same level
+                    memcpy (player_name, pl_sd->status.name, 24);
+                    for (j = 0; player_name[j]; j++)
+                        player_name[j] = tolower (player_name[j]);
+                    if (strstr (player_name, match_text) != NULL)
+                    {           // search with no case sensitive
+                        sprintf (output,
+                                 "Name: %s (GM:%d) | Location: %s %d %d",
+                                 pl_sd->status.name, pl_GM_level,
+                                 pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y);
+                        clif_displaymessage (fd, output);
+                        sprintf (output,
+                                 "       BLvl: %d | Job: %s (Lvl: %d)",
+                                 pl_sd->status.base_level,
+                                 job_name (pl_sd->status.pc_class),
+                                 pl_sd->status.job_level);
+                        clif_displaymessage (fd, output);
+                        g = guild_search (pl_sd->status.guild_id);
+                        if (g == NULL)
+                            sprintf (temp1, "None");
+                        else
+                            sprintf (temp1, "%s", g->name);
+                        p = party_search (pl_sd->status.party_id);
+                        if (p == NULL)
+                            sprintf (temp0, "None");
+                        else
+                            sprintf (temp0, "%s", p->name);
+                        sprintf (output, "       Party: '%s' | Guild: '%s'",
+                                 temp0, temp1);
+                        clif_displaymessage (fd, output);
+                        count++;
+                    }
+                }
+            }
+        }
+    }
+
+    if (count == 0)
+        clif_displaymessage (fd, msg_table[150]);   // No GM found.
+    else if (count == 1)
+        clif_displaymessage (fd, msg_table[151]);   // 1 GM found.
+    else
+    {
+        sprintf (output, msg_table[152], count);    // %d GMs found.
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_save (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    nullpo_retr (-1, sd);
+
+    pc_setsavepoint (sd, sd->mapname, sd->bl.x, sd->bl.y);
+    pc_makesavestatus (sd);
+    chrif_save (sd);
+    clif_displaymessage (fd, msg_table[6]); // Character data respawn point saved.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_load (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  m;
+
+    m = map_mapname2mapid (sd->status.save_point.map);
+    if (m >= 0 && map[m].flag.nowarpto
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp you to your save map.");
+        return -1;
+    }
+    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp you from your actual map.");
+        return -1;
+    }
+
+    pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
+               sd->status.save_point.y, 0);
+    clif_displaymessage (fd, msg_table[7]); // Warping to respawn point.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_speed (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char output[200];
+    int  speed;
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message)
+    {
+        sprintf (output,
+                 "Please, enter a speed value (usage: @speed <%d-%d>).",
+                 MIN_WALK_SPEED, MAX_WALK_SPEED);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    speed = atoi (message);
+    if (speed >= MIN_WALK_SPEED && speed <= MAX_WALK_SPEED)
+    {
+        sd->speed = speed;
+        //sd->walktimer = x;
+        //この文を追加 by れ
+        clif_updatestatus (sd, SP_SPEED);
+        clif_displaymessage (fd, msg_table[8]); // Speed changed.
+    }
+    else
+    {
+        sprintf (output,
+                 "Please, enter a valid speed value (usage: @speed <%d-%d>).",
+                 MIN_WALK_SPEED, MAX_WALK_SPEED);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_storage (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct storage *stor;       //changes from Freya/Yor
+    nullpo_retr (-1, sd);
+
+    if (sd->state.storage_flag)
+    {
+        clif_displaymessage (fd, msg_table[250]);
+        return -1;
+    }
+
+    if ((stor = account2storage2 (sd->status.account_id)) != NULL
+        && stor->storage_status == 1)
+    {
+        clif_displaymessage (fd, msg_table[250]);
+        return -1;
+    }
+
+    storage_storageopen (sd);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_guildstorage (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    struct storage *stor;       //changes from Freya/Yor
+    nullpo_retr (-1, sd);
+
+    if (sd->status.guild_id > 0)
+    {
+        if (sd->state.storage_flag)
+        {
+            clif_displaymessage (fd, msg_table[251]);
+            return -1;
+        }
+        if ((stor = account2storage2 (sd->status.account_id)) != NULL
+            && stor->storage_status == 1)
+        {
+            clif_displaymessage (fd, msg_table[251]);
+            return -1;
+        }
+        storage_guild_storageopen (sd);
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[252]);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_option (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    int  param1 = 0, param2 = 0, param3 = 0;
+    nullpo_retr (-1, sd);
+
+    if (!message || !*message
+        || sscanf (message, "%d %d %d", &param1, &param2, &param3) < 1
+        || param1 < 0 || param2 < 0 || param3 < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter at least a option (usage: @option <param1:0+> <param2:0+> <param3:0+>).");
+        return -1;
+    }
+
+    sd->opt1 = param1;
+    sd->opt2 = param2;
+    if (!(sd->status.option & CART_MASK) && param3 & CART_MASK)
+    {
+        clif_cart_itemlist (sd);
+        clif_cart_equiplist (sd);
+        clif_updatestatus (sd, SP_CARTINFO);
+    }
+    sd->status.option = param3;
+    // fix pecopeco display
+    if (sd->status.pc_class == 13 || sd->status.pc_class == 21
+        || sd->status.pc_class == 4014 || sd->status.pc_class == 4022)
+    {
+        if (!pc_isriding (sd))
+        {                       // sd have the new value...
+            if (sd->status.pc_class == 13)
+                sd->status.pc_class = sd->view_class = 7;
+            else if (sd->status.pc_class == 21)
+                sd->status.pc_class = sd->view_class = 14;
+            else if (sd->status.pc_class == 4014)
+                sd->status.pc_class = sd->view_class = 4008;
+            else if (sd->status.pc_class == 4022)
+                sd->status.pc_class = sd->view_class = 4015;
+        }
+    }
+    else
+    {
+        if (pc_isriding (sd))
+        {                       // sd have the new value...
+            if (sd->disguise > 0)
+            {                   // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
+                sd->status.option &= ~0x0020;
+            }
+            else
+            {
+                if (sd->status.pc_class == 7)
+                    sd->status.pc_class = sd->view_class = 13;
+                else if (sd->status.pc_class == 14)
+                    sd->status.pc_class = sd->view_class = 21;
+                else if (sd->status.pc_class == 4008)
+                    sd->status.pc_class = sd->view_class = 4014;
+                else if (sd->status.pc_class == 4015)
+                    sd->status.pc_class = sd->view_class = 4022;
+                else
+                    sd->status.option &= ~0x0020;
+            }
+        }
+    }
+
+    clif_changeoption (&sd->bl);
+    pc_calcstatus (sd, 0);
+    clif_displaymessage (fd, msg_table[9]); // Options changed.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_hide (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    if (sd->status.option & OPTION_HIDE)
+    {
+        sd->status.option &= ~OPTION_HIDE;
+        clif_displaymessage (fd, msg_table[10]);    // Invisible: Off
+    }
+    else
+    {
+        sd->status.option |= OPTION_HIDE;
+        clif_displaymessage (fd, msg_table[11]);    // Invisible: On
+    }
+    clif_changeoption (&sd->bl);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_die (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    pc_damage (NULL, sd, sd->status.hp + 1);
+    clif_displaymessage (fd, msg_table[13]);    // A pity! You've died.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_kill (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @kill <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can kill only lower or same level
+            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
+            clif_displaymessage (fd, msg_table[14]);    // Character killed.
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_alive (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    sd->status.hp = sd->status.max_hp;
+    sd->status.sp = sd->status.max_sp;
+    pc_setstand (sd);
+    if (battle_config.pc_invincible_time > 0)
+        pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
+    clif_updatestatus (sd, SP_HP);
+    clif_updatestatus (sd, SP_SP);
+    clif_resurrection (&sd->bl, 1);
+    clif_displaymessage (fd, msg_table[16]);    // You've been revived! It's a miracle!
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_kami (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a message (usage: @kami <message>).");
+        return -1;
+    }
+
+    sscanf (message, "%199[^\n]", output);
+    intif_GMmessage (output, strlen (output) + 1, 0);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_heal (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  hp = 0, sp = 0;        // [Valaris] thanks to fov
+
+    sscanf (message, "%d %d", &hp, &sp);
+
+    if (hp == 0 && sp == 0)
+    {
+        hp = sd->status.max_hp - sd->status.hp;
+        sp = sd->status.max_sp - sd->status.sp;
+    }
+    else
+    {
+        if (hp > 0 && (hp > sd->status.max_hp || hp > (sd->status.max_hp - sd->status.hp))) // fix positiv overflow
+            hp = sd->status.max_hp - sd->status.hp;
+        else if (hp < 0 && (hp < -sd->status.max_hp || hp < (1 - sd->status.hp)))   // fix negativ overflow
+            hp = 1 - sd->status.hp;
+        if (sp > 0 && (sp > sd->status.max_sp || sp > (sd->status.max_sp - sd->status.sp))) // fix positiv overflow
+            sp = sd->status.max_sp - sd->status.sp;
+        else if (sp < 0 && (sp < -sd->status.max_sp || sp < (1 - sd->status.sp)))   // fix negativ overflow
+            sp = 1 - sd->status.sp;
+    }
+
+    if (hp > 0)                 // display like heal
+        clif_heal (fd, SP_HP, hp);
+    else if (hp < 0)            // display like damage
+        clif_damage (&sd->bl, &sd->bl, gettick (), 0, 0, -hp, 0, 4, 0);
+    if (sp > 0)                 // no display when we lost SP
+        clif_heal (fd, SP_SP, sp);
+
+    if (hp != 0 || sp != 0)
+    {
+        pc_heal (sd, hp, sp);
+        if (hp >= 0 && sp >= 0)
+            clif_displaymessage (fd, msg_table[17]);    // HP, SP recovered.
+        else
+            clif_displaymessage (fd, msg_table[156]);   // HP or/and SP modified.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[157]);   // HP and SP are already with the good value.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @item command (usage: @item <name/id_of_item> <quantity>)
+ *------------------------------------------
+ */
+int atcommand_item (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char item_name[100];
+    int  number = 0, item_id, flag;
+    struct item item_tmp;
+    struct item_data *item_data;
+    int  get_count, i;
+
+    memset (item_name, '\0', sizeof (item_name));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d", item_name, &number) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter an item name/id (usage: @item <item name or ID> [quantity]).");
+        return -1;
+    }
+
+    if (number <= 0)
+        number = 1;
+
+    item_id = 0;
+    if ((item_data = itemdb_searchname (item_name)) != NULL ||
+        (item_data = itemdb_exists (atoi (item_name))) != NULL)
+        item_id = item_data->nameid;
+
+    if (item_id >= 500)
+    {
+        get_count = number;
+        if (item_data->type == 4 || item_data->type == 5 ||
+            item_data->type == 7 || item_data->type == 8)
+        {
+            get_count = 1;
+        }
+        for (i = 0; i < number; i += get_count)
+        {
+            memset (&item_tmp, 0, sizeof (item_tmp));
+            item_tmp.nameid = item_id;
+            item_tmp.identify = 1;
+            if ((flag =
+                 pc_additem ((struct map_session_data *) sd, &item_tmp,
+                             get_count)))
+                clif_additem ((struct map_session_data *) sd, 0, 0, flag);
+        }
+        clif_displaymessage (fd, msg_table[18]);    // Item created.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[19]);    // Invalid item ID or name.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_itemreset (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    int  i;
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].amount
+            && sd->status.inventory[i].equip == 0)
+            pc_delitem (sd, i, sd->status.inventory[i].amount, 0);
+    }
+    clif_displaymessage (fd, msg_table[20]);    // All of your items have been removed.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_itemcheck (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    pc_checkitem (sd);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_baselevelup (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    int  level, i;
+
+    if (!message || !*message || (level = atoi (message)) == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a level adjustement (usage: @blvl <number of levels>).");
+        return -1;
+    }
+
+    if (level > 0)
+    {
+        if (sd->status.base_level == battle_config.maximum_level)
+        {                       // check for max level by Valaris
+            clif_displaymessage (fd, msg_table[47]);    // Base level can't go any higher.
+            return -1;
+        }                       // End Addition
+        if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level))   // fix positiv overflow
+            level = battle_config.maximum_level - sd->status.base_level;
+        for (i = 1; i <= level; i++)
+            sd->status.status_point += (sd->status.base_level + i + 14) / 4;
+        sd->status.base_level += level;
+        clif_updatestatus (sd, SP_BASELEVEL);
+        clif_updatestatus (sd, SP_NEXTBASEEXP);
+        clif_updatestatus (sd, SP_STATUSPOINT);
+        pc_calcstatus (sd, 0);
+        pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
+        clif_misceffect (&sd->bl, 0);
+        clif_displaymessage (fd, msg_table[21]);    // Base level raised.
+    }
+    else
+    {
+        if (sd->status.base_level == 1)
+        {
+            clif_displaymessage (fd, msg_table[158]);   // Base level can't go any lower.
+            return -1;
+        }
+        if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level))    // fix negativ overflow
+            level = 1 - sd->status.base_level;
+        if (sd->status.status_point > 0)
+        {
+            for (i = 0; i > level; i--)
+                sd->status.status_point -=
+                    (sd->status.base_level + i + 14) / 4;
+            if (sd->status.status_point < 0)
+                sd->status.status_point = 0;
+            clif_updatestatus (sd, SP_STATUSPOINT);
+        }                       // to add: remove status points from stats
+        sd->status.base_level += level;
+        clif_updatestatus (sd, SP_BASELEVEL);
+        clif_updatestatus (sd, SP_NEXTBASEEXP);
+        pc_calcstatus (sd, 0);
+        clif_displaymessage (fd, msg_table[22]);    // Base level lowered.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_joblevelup (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    int  up_level = 50, level;
+
+    if (!message || !*message || (level = atoi (message)) == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a level adjustement (usage: @jlvl <number of levels>).");
+        return -1;
+    }
+
+    if (sd->status.pc_class == 0 || sd->status.pc_class == 4001)
+        up_level -= 40;
+    else if ((sd->status.pc_class > 4007 && sd->status.pc_class < 4024)
+             || sd->status.pc_class == 23)
+        up_level += 20;
+
+    if (level > 0)
+    {
+        if (sd->status.job_level == up_level)
+        {
+            clif_displaymessage (fd, msg_table[23]);    // Job level can't go any higher.
+            return -1;
+        }
+        if (level > up_level || level > (up_level - sd->status.job_level))  // fix positiv overflow
+            level = up_level - sd->status.job_level;
+        sd->status.job_level += level;
+        clif_updatestatus (sd, SP_JOBLEVEL);
+        clif_updatestatus (sd, SP_NEXTJOBEXP);
+        sd->status.skill_point += level;
+        clif_updatestatus (sd, SP_SKILLPOINT);
+        pc_calcstatus (sd, 0);
+        clif_misceffect (&sd->bl, 1);
+        clif_displaymessage (fd, msg_table[24]);    // Job level raised.
+    }
+    else
+    {
+        if (sd->status.job_level == 1)
+        {
+            clif_displaymessage (fd, msg_table[159]);   // Job level can't go any lower.
+            return -1;
+        }
+        if (level < -up_level || level < (1 - sd->status.job_level))    // fix negativ overflow
+            level = 1 - sd->status.job_level;
+        sd->status.job_level += level;
+        clif_updatestatus (sd, SP_JOBLEVEL);
+        clif_updatestatus (sd, SP_NEXTJOBEXP);
+        if (sd->status.skill_point > 0)
+        {
+            sd->status.skill_point += level;
+            if (sd->status.skill_point < 0)
+                sd->status.skill_point = 0;
+            clif_updatestatus (sd, SP_SKILLPOINT);
+        }                       // to add: remove status points from skills
+        pc_calcstatus (sd, 0);
+        clif_displaymessage (fd, msg_table[25]);    // Job level lowered.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_help (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char buf[2048], w1[2048], w2[2048];
+    int  i, gm_level;
+    FILE *fp;
+
+    memset (buf, '\0', sizeof (buf));
+
+    if ((fp = fopen_ (help_txt, "r")) != NULL)
+    {
+        clif_displaymessage (fd, msg_table[26]);    // Help commands:
+        gm_level = pc_isGM (sd);
+        while (fgets (buf, sizeof (buf) - 1, fp) != NULL)
+        {
+            if (buf[0] == '/' && buf[1] == '/')
+                continue;
+            for (i = 0; buf[i] != '\0'; i++)
+            {
+                if (buf[i] == '\r' || buf[i] == '\n')
+                {
+                    buf[i] = '\0';
+                    break;
+                }
+            }
+            if (sscanf (buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2)
+                clif_displaymessage (fd, buf);
+            else if (gm_level >= atoi (w1))
+                clif_displaymessage (fd, w2);
+        }
+        fclose_ (fp);
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[27]);    // File help.txt not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_gm (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+    char password[100];
+
+    memset (password, '\0', sizeof (password));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", password) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a password (usage: @gm <password>).");
+        return -1;
+    }
+
+    if (pc_isGM (sd))
+    {                           // a GM can not use this function. only a normal player (become gm is not for gm!)
+        clif_displaymessage (fd, msg_table[50]);    // You already have some GM powers.
+        return -1;
+    }
+    else
+        chrif_changegm (sd->status.account_id, password,
+                        strlen (password) + 1);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_pvpoff (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    if (battle_config.pk_mode)
+    {                           //disable command if server is in PK mode [Valaris]
+        clif_displaymessage (fd, msg_table[52]);    // This option cannot be used in PK Mode.
+        return -1;
+    }
+
+    if (map[sd->bl.m].flag.pvp)
+    {
+        map[sd->bl.m].flag.pvp = 0;
+        clif_send0199 (sd->bl.m, 0);
+        for (i = 0; i < fd_max; i++)
+        {                       //人数分ループ
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                if (sd->bl.m == pl_sd->bl.m)
+                {
+                    clif_pvpset (pl_sd, 0, 0, 2);
+                    if (pl_sd->pvp_timer != -1)
+                    {
+                        delete_timer (pl_sd->pvp_timer,
+                                      pc_calc_pvprank_timer);
+                        pl_sd->pvp_timer = -1;
+                    }
+                }
+            }
+        }
+        clif_displaymessage (fd, msg_table[31]);    // PvP: Off.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[160]);   // PvP is already Off.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_pvpon (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    if (battle_config.pk_mode)
+    {                           //disable command if server is in PK mode [Valaris]
+        clif_displaymessage (fd, msg_table[52]);    // This option cannot be used in PK Mode.
+        return -1;
+    }
+
+    if (!map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.nopvp)
+    {
+        map[sd->bl.m].flag.pvp = 1;
+        clif_send0199 (sd->bl.m, 1);
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                if (sd->bl.m == pl_sd->bl.m && pl_sd->pvp_timer == -1)
+                {
+                    pl_sd->pvp_timer = add_timer (gettick () + 200,
+                                                  pc_calc_pvprank_timer,
+                                                  pl_sd->bl.id, 0);
+                    pl_sd->pvp_rank = 0;
+                    pl_sd->pvp_lastusers = 0;
+                    pl_sd->pvp_point = 5;
+                }
+            }
+        }
+        clif_displaymessage (fd, msg_table[32]);    // PvP: On.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[161]);   // PvP is already On.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_gvgoff (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    if (map[sd->bl.m].flag.gvg)
+    {
+        map[sd->bl.m].flag.gvg = 0;
+        clif_send0199 (sd->bl.m, 0);
+        clif_displaymessage (fd, msg_table[33]);    // GvG: Off.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[162]);   // GvG is already Off.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_gvgon (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    if (!map[sd->bl.m].flag.gvg)
+    {
+        map[sd->bl.m].flag.gvg = 1;
+        clif_send0199 (sd->bl.m, 3);
+        clif_displaymessage (fd, msg_table[34]);    // GvG: On.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[163]);   // GvG is already On.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_model (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    int  hair_style = 0, hair_color = 0, cloth_color = 0;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message
+        || sscanf (message, "%d %d %d", &hair_style, &hair_color,
+                   &cloth_color) < 1)
+    {
+        sprintf (output,
+                 "Please, enter at least a value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).",
+                 MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR,
+                 MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
+        hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
+        cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
+    {
+        //服の色変更
+        if (cloth_color != 0 && sd->status.sex == 1
+            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
+        {
+            //服の色未実装職の判定
+            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
+            return -1;
+        }
+        else
+        {
+            pc_changelook (sd, LOOK_HAIR, hair_style);
+            pc_changelook (sd, LOOK_HAIR_COLOR, hair_color);
+            pc_changelook (sd, LOOK_CLOTHES_COLOR, cloth_color);
+            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @dye && @ccolor
+ *------------------------------------------
+ */
+int atcommand_dye (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    int  cloth_color = 0;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%d", &cloth_color) < 1)
+    {
+        sprintf (output,
+                 "Please, enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).",
+                 MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
+    {
+        if (cloth_color != 0 && sd->status.sex == 1
+            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
+        {
+            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
+            return -1;
+        }
+        else
+        {
+            pc_changelook (sd, LOOK_CLOTHES_COLOR, cloth_color);
+            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @chardye by [MouseJstr]
+ *------------------------------------------
+ */
+int
+atcommand_chardye (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    return 0;
+}
+
+/*==========================================
+ * @hairstyle && @hstyle
+ *------------------------------------------
+ */
+int atcommand_hair_style (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    int  hair_style = 0;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%d", &hair_style) < 1)
+    {
+        sprintf (output,
+                 "Please, enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).",
+                 MIN_HAIR_STYLE, MAX_HAIR_STYLE);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE)
+    {
+        if (hair_style != 0 && sd->status.sex == 1
+            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
+        {
+            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
+            return -1;
+        }
+        else
+        {
+            pc_changelook (sd, LOOK_HAIR, hair_style);
+            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charhairstyle by [MouseJstr]
+ *------------------------------------------
+ */
+int
+atcommand_charhairstyle (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    return 0;
+}
+
+/*==========================================
+ * @haircolor && @hcolor
+ *------------------------------------------
+ */
+int atcommand_hair_color (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    int  hair_color = 0;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%d", &hair_color) < 1)
+    {
+        sprintf (output,
+                 "Please, enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).",
+                 MIN_HAIR_COLOR, MAX_HAIR_COLOR);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR)
+    {
+        if (hair_color != 0 && sd->status.sex == 1
+            && (sd->status.pc_class == 12 || sd->status.pc_class == 17))
+        {
+            clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
+            return -1;
+        }
+        else
+        {
+            pc_changelook (sd, LOOK_HAIR_COLOR, hair_color);
+            clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charhaircolor by [MouseJstr]
+ *------------------------------------------
+ */
+int
+atcommand_charhaircolor (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    return 0;
+}
+
+/*==========================================
+ * @go [city_number/city_name]: improved by [yor] to add city names and help
+ *------------------------------------------
+ */
+int atcommand_go (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+    int  i;
+    int  town;
+    char map_name[100];
+    char output[200];
+    int  m;
+
+    struct
+    {
+        char map[16];
+        int  x, y;
+    } data[] =
+    {
+        {
+        "prontera.gat", 156, 191},  //   0=Prontera
+        {
+        "morocc.gat", 156, 93}, //   1=Morroc
+        {
+        "geffen.gat", 119, 59}, //   2=Geffen
+        {
+        "payon.gat", 162, 233}, //   3=Payon
+        {
+        "alberta.gat", 192, 147},   //   4=Alberta
+        {
+        "izlude.gat", 128, 114},    //   5=Izlude
+        {
+        "aldebaran.gat", 140, 131}, //   6=Al de Baran
+        {
+        "xmas.gat", 147, 134},  //   7=Lutie
+        {
+        "comodo.gat", 209, 143},    //   8=Comodo
+        {
+        "yuno.gat", 157, 51},   //   9=Yuno
+        {
+        "amatsu.gat", 198, 84}, //  10=Amatsu
+        {
+        "gonryun.gat", 160, 120},   //  11=Gon Ryun
+        {
+        "umbala.gat", 89, 157}, //  12=Umbala
+        {
+        "niflheim.gat", 21, 153},   //  13=Niflheim
+        {
+        "louyang.gat", 217, 40},    //  14=Lou Yang
+        {
+        "new_1-1.gat", 53, 111},    //  15=Start point
+        {
+        "sec_pri.gat", 23, 61}, //  16=Prison
+    };
+
+    memset (map_name, '\0', sizeof (map_name));
+    memset (output, '\0', sizeof (output));
+
+    // get the number
+    town = atoi (message);
+
+    // if no value, display all value
+    if (!message || !*message || sscanf (message, "%99s", map_name) < 1
+        || town < -3 || town >= (int) (sizeof (data) / sizeof (data[0])))
+    {
+        clif_displaymessage (fd, msg_table[38]);    // Invalid location number or name.
+        clif_displaymessage (fd, msg_table[82]);    // Please, use one of this number/name:
+        clif_displaymessage (fd,
+                             "-3=(Memo point 2)   4=Alberta       11=Gon Ryun");
+        clif_displaymessage (fd,
+                             "-2=(Memo point 1)   5=Izlude        12=Umbala");
+        clif_displaymessage (fd,
+                             "-1=(Memo point 0)   6=Al de Baran   13=Niflheim");
+        clif_displaymessage (fd,
+                             " 0=Prontera         7=Lutie         14=Lou Yang");
+        clif_displaymessage (fd,
+                             " 1=Morroc           8=Comodo        15=Start point");
+        clif_displaymessage (fd,
+                             " 2=Geffen           9=Yuno          16=Prison");
+        clif_displaymessage (fd, " 3=Payon           10=Amatsu");
+        return -1;
+    }
+    else
+    {
+        // get possible name of the city and add .gat if not in the name
+        map_name[sizeof (map_name) - 1] = '\0';
+        for (i = 0; map_name[i]; i++)
+            map_name[i] = tolower (map_name[i]);
+        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+            strcat (map_name, ".gat");
+        // try to see if it's a name, and not a number (try a lot of possibilities, write errors and abbreviations too)
+        if (strncmp (map_name, "prontera.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 0;
+        }
+        else if (strncmp (map_name, "morocc.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 1;
+        }
+        else if (strncmp (map_name, "geffen.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 2;
+        }
+        else if (strncmp (map_name, "payon.gat", 3) == 0 || // 3 first characters
+                 strncmp (map_name, "paion.gat", 3) == 0)
+        {                       // writing error (3 first characters)
+            town = 3;
+        }
+        else if (strncmp (map_name, "alberta.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 4;
+        }
+        else if (strncmp (map_name, "izlude.gat", 3) == 0 ||    // 3 first characters
+                 strncmp (map_name, "islude.gat", 3) == 0)
+        {                       // writing error (3 first characters)
+            town = 5;
+        }
+        else if (strncmp (map_name, "aldebaran.gat", 3) == 0 || // 3 first characters
+                 strcmp (map_name, "al.gat") == 0)
+        {                       // al (de baran)
+            town = 6;
+        }
+        else if (strncmp (map_name, "lutie.gat", 3) == 0 || // name of the city, not name of the map (3 first characters)
+                 strcmp (map_name, "christmas.gat") == 0 || // name of the symbol
+                 strncmp (map_name, "xmas.gat", 3) == 0 ||  // 3 first characters
+                 strncmp (map_name, "x-mas.gat", 3) == 0)
+        {                       // writing error (3 first characters)
+            town = 7;
+        }
+        else if (strncmp (map_name, "comodo.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 8;
+        }
+        else if (strncmp (map_name, "yuno.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 9;
+        }
+        else if (strncmp (map_name, "amatsu.gat", 3) == 0 ||    // 3 first characters
+                 strncmp (map_name, "ammatsu.gat", 3) == 0)
+        {                       // writing error (3 first characters)
+            town = 10;
+        }
+        else if (strncmp (map_name, "gonryun.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 11;
+        }
+        else if (strncmp (map_name, "umbala.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 12;
+        }
+        else if (strncmp (map_name, "niflheim.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 13;
+        }
+        else if (strncmp (map_name, "louyang.gat", 3) == 0)
+        {                       // 3 first characters
+            town = 14;
+        }
+        else if (strncmp (map_name, "new_1-1.gat", 3) == 0 ||   // 3 first characters (or "newbies")
+                 strncmp (map_name, "startpoint.gat", 3) == 0 ||    // name of the position (3 first characters)
+                 strncmp (map_name, "begining.gat", 3) == 0)
+        {                       // name of the position (3 first characters)
+            town = 15;
+        }
+        else if (strncmp (map_name, "sec_pri.gat", 3) == 0 ||   // 3 first characters
+                 strncmp (map_name, "prison.gat", 3) == 0 ||    // name of the position (3 first characters)
+                 strncmp (map_name, "jails.gat", 3) == 0)
+        {                       // name of the position
+            town = 16;
+        }
+
+        if (town >= -3 && town <= -1)
+        {
+            if (sd->status.memo_point[-town - 1].map[0])
+            {
+                m = map_mapname2mapid (sd->status.memo_point[-town - 1].map);
+                if (m >= 0 && map[m].flag.nowarpto
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                {
+                    clif_displaymessage (fd,
+                                         "You are not authorised to warp you to this memo map.");
+                    return -1;
+                }
+                if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                {
+                    clif_displaymessage (fd,
+                                         "You are not authorised to warp you from your actual map.");
+                    return -1;
+                }
+                if (pc_setpos
+                    (sd, sd->status.memo_point[-town - 1].map,
+                     sd->status.memo_point[-town - 1].x,
+                     sd->status.memo_point[-town - 1].y, 3) == 0)
+                {
+                    clif_displaymessage (fd, msg_table[0]); // Warped.
+                }
+                else
+                {
+                    clif_displaymessage (fd, msg_table[1]); // Map not found.
+                    return -1;
+                }
+            }
+            else
+            {
+                sprintf (output, msg_table[164], -town - 1);    // Your memo point #%d doesn't exist.
+                clif_displaymessage (fd, output);
+                return -1;
+            }
+        }
+        else if (town >= 0 && town < (int) (sizeof (data) / sizeof (data[0])))
+        {
+            m = map_mapname2mapid (data[town].map);
+            if (m >= 0 && map[m].flag.nowarpto
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+            {
+                clif_displaymessage (fd,
+                                     "You are not authorised to warp you to this destination map.");
+                return -1;
+            }
+            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+            {
+                clif_displaymessage (fd,
+                                     "You are not authorised to warp you from your actual map.");
+                return -1;
+            }
+            if (pc_setpos (sd, data[town].map, data[town].x, data[town].y, 3)
+                == 0)
+            {
+                clif_displaymessage (fd, msg_table[0]); // Warped.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[1]); // Map not found.
+                return -1;
+            }
+        }
+        else
+        {                       // if you arrive here, you have an error in town variable when reading of names
+            clif_displaymessage (fd, msg_table[38]);    // Invalid location number or name.
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_spawn (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char monster[100];
+    char output[200];
+    int  mob_id;
+    int  number = 0;
+    int  x = 0, y = 0;
+    int  count;
+    int  i, j, k;
+    int  mx, my, range;
+
+    memset (monster, '\0', sizeof (monster));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d %d %d", monster, &number, &x, &y) < 1)
+    {
+        clif_displaymessage (fd, msg_table[143]);   // Give a monster name/id please.
+        return -1;
+    }
+
+    // If monster identifier/name argument is a name
+    if ((mob_id = mobdb_searchname (monster)) == 0) // check name first (to avoid possible name begining by a number)
+        mob_id = mobdb_checkid (atoi (monster));
+
+    if (mob_id == 0)
+    {
+        clif_displaymessage (fd, msg_table[40]);    // Invalid monster ID or name.
+        return -1;
+    }
+
+    if (mob_id == 1288)
+    {
+        clif_displaymessage (fd, msg_table[83]);    // Cannot spawn emperium.
+        return -1;
+    }
+
+    if (number <= 0)
+        number = 1;
+
+    // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
+    if (battle_config.atc_spawn_quantity_limit >= 1
+        && number > battle_config.atc_spawn_quantity_limit)
+        number = battle_config.atc_spawn_quantity_limit;
+
+    if (battle_config.etc_log)
+        printf ("%s monster='%s' id=%d count=%d (%d,%d)\n", command, monster,
+                mob_id, number, x, y);
+
+    count = 0;
+    range = sqrt (number) / 2;
+    range = range * 2 + 5;      // calculation of an odd number (+ 4 area around)
+    for (i = 0; i < number; i++)
+    {
+        j = 0;
+        k = 0;
+        while (j++ < 8 && k == 0)
+        {                       // try 8 times to spawn the monster (needed for close area)
+            if (x <= 0)
+                mx = sd->bl.x + (MRAND (range) - (range / 2));
+            else
+                mx = x;
+            if (y <= 0)
+                my = sd->bl.y + (MRAND (range) - (range / 2));
+            else
+                my = y;
+            k = mob_once_spawn ((struct map_session_data *) sd, "this", mx,
+                                my, "", mob_id, 1, "");
+        }
+        count += (k != 0) ? 1 : 0;
+    }
+
+    if (count != 0)
+        if (number == count)
+            clif_displaymessage (fd, msg_table[39]);    // All monster summoned!
+        else
+        {
+            sprintf (output, msg_table[240], count);    // %d monster(s) summoned!
+            clif_displaymessage (fd, output);
+        }
+    else
+    {
+        clif_displaymessage (fd, msg_table[40]);    // Invalid monster ID or name.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void atcommand_killmonster_sub (const int fd, struct map_session_data *sd,
+                                const char *message, const int drop)
+{
+    int  map_id;
+    char map_name[100];
+
+    memset (map_name, '\0', sizeof (map_name));
+
+    if (!message || !*message || sscanf (message, "%99s", map_name) < 1)
+        map_id = sd->bl.m;
+    else
+    {
+        if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+            strcat (map_name, ".gat");
+        if ((map_id = map_mapname2mapid (map_name)) < 0)
+            map_id = sd->bl.m;
+    }
+
+    map_foreachinarea (atkillmonster_sub, map_id, 0, 0, map[map_id].xs,
+                       map[map_id].ys, BL_MOB, drop);
+
+    clif_displaymessage (fd, msg_table[165]);   // All monsters killed!
+
+    return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_killmonster (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    atcommand_killmonster_sub (fd, sd, message, 1);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int atlist_nearby_sub (struct block_list *bl, va_list ap)
+{
+    char buf[32];
+    int  fd = va_arg (ap, int);
+    nullpo_retr (0, bl);
+
+    sprintf (buf, " - \"%s\"", ((struct map_session_data *) bl)->status.name);
+    clif_displaymessage (fd, buf);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_list_nearby (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    clif_displaymessage (fd, "Nearby players:");
+    map_foreachinarea (atlist_nearby_sub, sd->bl.m, sd->bl.x - 1,
+                       sd->bl.y - 1, sd->bl.x + 1, sd->bl.x + 1, BL_PC, fd);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_killmonster2 (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    atcommand_killmonster_sub (fd, sd, message, 0);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_produce (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    char item_name[100];
+    int  item_id, attribute = 0, star = 0;
+    int  flag = 0;
+    struct item_data *item_data;
+    struct item tmp_item;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+    memset (item_name, '\0', sizeof (item_name));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d %d", item_name, &attribute, &star) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter at least an item name/id (usage: @produce <equip name or equip ID> <element> <# of very's>).");
+        return -1;
+    }
+
+    item_id = 0;
+    if ((item_data = itemdb_searchname (item_name)) != NULL ||
+        (item_data = itemdb_exists (atoi (item_name))) != NULL)
+        item_id = item_data->nameid;
+
+    if (itemdb_exists (item_id) &&
+        (item_id <= 500 || item_id > 1099) &&
+        (item_id < 4001 || item_id > 4148) &&
+        (item_id < 7001 || item_id > 10019) && itemdb_isequip (item_id))
+    {
+        if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE)
+            attribute = ATTRIBUTE_NORMAL;
+        if (star < MIN_STAR || star > MAX_STAR)
+            star = 0;
+        memset (&tmp_item, 0, sizeof tmp_item);
+        tmp_item.nameid = item_id;
+        tmp_item.amount = 1;
+        tmp_item.identify = 1;
+        tmp_item.card[0] = 0x00ff;
+        tmp_item.card[1] = ((star * 5) << 8) + attribute;
+        *((unsigned long *) (&tmp_item.card[2])) = sd->char_id;
+        clif_produceeffect (sd, 0, item_id);    // 製造エフェクトパケット
+        clif_misceffect (&sd->bl, 3);   // 他人にも成功を通知
+        if ((flag = pc_additem (sd, &tmp_item, 1)))
+            clif_additem (sd, 0, 0, flag);
+    }
+    else
+    {
+        if (battle_config.error_log)
+            printf ("@produce NOT WEAPON [%d]\n", item_id);
+        if (item_id != 0 && itemdb_exists (item_id))
+            sprintf (output, msg_table[169], item_id, item_data->name); // This item (%d: '%s') is not an equipment.
+        else
+            sprintf (output, "%s", msg_table[170]);   // This item is not an equipment.
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Sub-function to display actual memo points
+ *------------------------------------------
+ */
+void atcommand_memo_sub (struct map_session_data *sd)
+{
+    int  i;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    clif_displaymessage (sd->fd,
+                         "Your actual memo positions are (except respawn point):");
+    for (i = MIN_PORTAL_MEMO; i <= MAX_PORTAL_MEMO; i++)
+    {
+        if (sd->status.memo_point[i].map[0])
+            sprintf (output, "%d - %s (%d,%d)", i,
+                     sd->status.memo_point[i].map, sd->status.memo_point[i].x,
+                     sd->status.memo_point[i].y);
+        else
+            sprintf (output, msg_table[171], i);    // %d - void
+        clif_displaymessage (sd->fd, output);
+    }
+
+    return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_memo (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  position = 0;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%d", &position) < 1)
+        atcommand_memo_sub (sd);
+    else
+    {
+        if (position >= MIN_PORTAL_MEMO && position <= MAX_PORTAL_MEMO)
+        {
+            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+            {
+                clif_displaymessage (fd,
+                                     "You are not authorised to memo this map.");
+                return -1;
+            }
+            if (sd->status.memo_point[position].map[0])
+            {
+                sprintf (output, msg_table[172], position, sd->status.memo_point[position].map, sd->status.memo_point[position].x, sd->status.memo_point[position].y);  // You replace previous memo position %d - %s (%d,%d).
+                clif_displaymessage (fd, output);
+            }
+            memcpy (sd->status.memo_point[position].map, map[sd->bl.m].name,
+                    24);
+            sd->status.memo_point[position].x = sd->bl.x;
+            sd->status.memo_point[position].y = sd->bl.y;
+            clif_skill_memo (sd, 0);
+            if (pc_checkskill (sd, AL_WARP) <= (position + 1))
+                clif_displaymessage (fd, msg_table[173]);   // Note: you don't have the 'Warp' skill level to use it.
+            atcommand_memo_sub (sd);
+        }
+        else
+        {
+            sprintf (output,
+                     "Please, enter a valid position (usage: @memo <memo_position:%d-%d>).",
+                     MIN_PORTAL_MEMO, MAX_PORTAL_MEMO);
+            clif_displaymessage (fd, output);
+            atcommand_memo_sub (sd);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_gat (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    char output[200];
+    int  y;
+
+    memset (output, '\0', sizeof (output));
+
+    for (y = 2; y >= -2; y--)
+    {
+        sprintf (output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
+                 map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
+                 map_getcell (sd->bl.m, sd->bl.x - 2, sd->bl.y + y),
+                 map_getcell (sd->bl.m, sd->bl.x - 1, sd->bl.y + y),
+                 map_getcell (sd->bl.m, sd->bl.x, sd->bl.y + y),
+                 map_getcell (sd->bl.m, sd->bl.x + 1, sd->bl.y + y),
+                 map_getcell (sd->bl.m, sd->bl.x + 2, sd->bl.y + y));
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_packet (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    int  x = 0, y = 0;
+
+    if (!message || !*message || sscanf (message, "%d %d", &x, &y) < 2)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a status type/flag (usage: @packet <status type> <flag>).");
+        return -1;
+    }
+
+    clif_status_change (&sd->bl, x, y);
+
+    return 0;
+}
+
+/*==========================================
+ * @stpoint (Rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_statuspoint (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    int  point, new_status_point;
+
+    if (!message || !*message || (point = atoi (message)) == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a number (usage: @stpoint <number of points>).");
+        return -1;
+    }
+
+    new_status_point = (int) sd->status.status_point + point;
+    if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
+        new_status_point = 0x7FFF;
+    else if (point < 0 && (point < -0x7FFF || new_status_point < 0))    // fix negativ overflow
+        new_status_point = 0;
+
+    if (new_status_point != (int) sd->status.status_point)
+    {
+        sd->status.status_point = (short) new_status_point;
+        clif_updatestatus (sd, SP_STATUSPOINT);
+        clif_displaymessage (fd, msg_table[174]);   // Number of status points changed!
+    }
+    else
+    {
+        if (point < 0)
+            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+        else
+            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @skpoint (Rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_skillpoint (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    int  point, new_skill_point;
+
+    if (!message || !*message || (point = atoi (message)) == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a number (usage: @skpoint <number of points>).");
+        return -1;
+    }
+
+    new_skill_point = (int) sd->status.skill_point + point;
+    if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))  // fix positiv overflow
+        new_skill_point = 0x7FFF;
+    else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow
+        new_skill_point = 0;
+
+    if (new_skill_point != (int) sd->status.skill_point)
+    {
+        sd->status.skill_point = (short) new_skill_point;
+        clif_updatestatus (sd, SP_SKILLPOINT);
+        clif_displaymessage (fd, msg_table[175]);   // Number of skill points changed!
+    }
+    else
+    {
+        if (point < 0)
+            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+        else
+            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @zeny (Rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_zeny (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  zeny, new_zeny;
+
+    if (!message || !*message || (zeny = atoi (message)) == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter an amount (usage: @zeny <amount>).");
+        return -1;
+    }
+
+    new_zeny = sd->status.zeny + zeny;
+    if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))   // fix positiv overflow
+        new_zeny = MAX_ZENY;
+    else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))    // fix negativ overflow
+        new_zeny = 0;
+
+    if (new_zeny != sd->status.zeny)
+    {
+        sd->status.zeny = new_zeny;
+        clif_updatestatus (sd, SP_ZENY);
+        clif_displaymessage (fd, msg_table[176]);   // Number of zenys changed!
+    }
+    else
+    {
+        if (zeny < 0)
+            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+        else
+            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_param (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    int  i, index, value = 0, new_value;
+    const char *param[] =
+        { "@str", "@agi", "@vit", "@int", "@dex", "@luk", NULL };
+    short *status[] = {
+        &sd->status.str, &sd->status.agi, &sd->status.vit,
+        &sd->status.int_, &sd->status.dex, &sd->status.luk
+    };
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%d", &value) < 1
+        || value == 0)
+    {
+        sprintf (output,
+                 "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    index = -1;
+    for (i = 0; param[i] != NULL; i++)
+    {
+        if (strcasecmp (command, param[i]) == 0)
+        {
+            index = i;
+            break;
+        }
+    }
+    if (index < 0 || index > MAX_STATUS_TYPE)
+    {                           // normaly impossible...
+        sprintf (output,
+                 "Please, enter a valid value (usage: @str,@agi,@vit,@int,@dex,@luk <+/-adjustement>).");
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    new_value = (int) *status[index] + value;
+    if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))  // fix positiv overflow
+        new_value = battle_config.max_parameter;
+    else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))  // fix negativ overflow
+        new_value = 1;
+
+    if (new_value != (int) *status[index])
+    {
+        *status[index] = new_value;
+        clif_updatestatus (sd, SP_STR + index);
+        clif_updatestatus (sd, SP_USTR + index);
+        pc_calcstatus (sd, 0);
+        clif_displaymessage (fd, msg_table[42]);    // Stat changed.
+    }
+    else
+    {
+        if (value < 0)
+            clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+        else
+            clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+//** Stat all by fritz (rewritten by [Yor])
+int atcommand_all_stats (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    int  index, count, value = 0, new_value;
+    short *status[] = {
+        &sd->status.str, &sd->status.agi, &sd->status.vit,
+        &sd->status.int_, &sd->status.dex, &sd->status.luk
+    };
+
+    if (!message || !*message || sscanf (message, "%d", &value) < 1
+        || value == 0)
+        value = battle_config.max_parameter;
+
+    count = 0;
+    for (index = 0; index < (int) (sizeof (status) / sizeof (status[0]));
+         index++)
+    {
+
+        new_value = (int) *status[index] + value;
+        if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))  // fix positiv overflow
+            new_value = battle_config.max_parameter;
+        else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))  // fix negativ overflow
+            new_value = 1;
+
+        if (new_value != (int) *status[index])
+        {
+            *status[index] = new_value;
+            clif_updatestatus (sd, SP_STR + index);
+            clif_updatestatus (sd, SP_USTR + index);
+            pc_calcstatus (sd, 0);
+            count++;
+        }
+    }
+
+    if (count > 0)              // if at least 1 stat modified
+        clif_displaymessage (fd, msg_table[84]);    // All stats changed!
+    else
+    {
+        if (value < 0)
+            clif_displaymessage (fd, msg_table[177]);   // Impossible to decrease a stat.
+        else
+            clif_displaymessage (fd, msg_table[178]);   // Impossible to increase a stat.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_guildlevelup (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    int  level = 0;
+    short added_level;
+    struct guild *guild_info;
+
+    if (!message || !*message || sscanf (message, "%d", &level) < 1
+        || level == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a valid level (usage: @guildlvl <# of levels>).");
+        return -1;
+    }
+
+    if (sd->status.guild_id <= 0
+        || (guild_info = guild_search (sd->status.guild_id)) == NULL)
+    {
+        clif_displaymessage (fd, msg_table[43]);    // You're not in a guild.
+        return -1;
+    }
+    if (strcmp (sd->status.name, guild_info->master) != 0)
+    {
+        clif_displaymessage (fd, msg_table[44]);    // You're not the master of your guild.
+        return -1;
+    }
+
+    added_level = (short) level;
+    if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short) MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow
+        added_level = (short) MAX_GUILDLEVEL - guild_info->guild_lv;
+    else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv)))    // fix negativ overflow
+        added_level = 1 - guild_info->guild_lv;
+
+    if (added_level != 0)
+    {
+        intif_guild_change_basicinfo (guild_info->guild_id, GBI_GUILDLV,
+                                      &added_level, 2);
+        clif_displaymessage (fd, msg_table[179]);   // Guild level changed.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[45]);    // Guild level change failed.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_recall (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @recall <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can recall only lower or same level
+            if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+            {
+                clif_displaymessage (fd,
+                                     "You are not authorised to warp somenone to your actual map.");
+                return -1;
+            }
+            if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+            {
+                clif_displaymessage (fd,
+                                     "You are not authorised to warp this player from its actual map.");
+                return -1;
+            }
+            pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+            sprintf (output, msg_table[46], character); // %s recalled!
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_revive (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @revive <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        pl_sd->status.hp = pl_sd->status.max_hp;
+        pc_setstand (pl_sd);
+        if (battle_config.pc_invincible_time > 0)
+            pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
+        clif_updatestatus (pl_sd, SP_HP);
+        clif_updatestatus (pl_sd, SP_SP);
+        clif_resurrection (&pl_sd->bl, 1);
+        clif_displaymessage (fd, msg_table[51]);    // Character revived.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_character_stats (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    char character[100];
+    char job_jobname[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+    int  i;
+
+    memset (character, '\0', sizeof (character));
+    memset (job_jobname, '\0', sizeof (job_jobname));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charstats <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        struct
+        {
+            const char *format;
+            int  value;
+        } output_table[] =
+        {
+            {
+            "Base Level - %d", pl_sd->status.base_level},
+            {
+            job_jobname, pl_sd->status.job_level},
+            {
+            "Hp - %d", pl_sd->status.hp},
+            {
+            "MaxHp - %d", pl_sd->status.max_hp},
+            {
+            "Sp - %d", pl_sd->status.sp},
+            {
+            "MaxSp - %d", pl_sd->status.max_sp},
+            {
+            "Str - %3d", pl_sd->status.str},
+            {
+            "Agi - %3d", pl_sd->status.agi},
+            {
+            "Vit - %3d", pl_sd->status.vit},
+            {
+            "Int - %3d", pl_sd->status.int_},
+            {
+            "Dex - %3d", pl_sd->status.dex},
+            {
+            "Luk - %3d", pl_sd->status.luk},
+            {
+            "Zeny - %d", pl_sd->status.zeny},
+            {
+            NULL, 0}
+        };
+        sprintf (job_jobname, "Job - %s %s", job_name (pl_sd->status.pc_class),
+                 "(level %d)");
+        sprintf (output, msg_table[53], pl_sd->status.name);    // '%s' stats:
+        clif_displaymessage (fd, output);
+        for (i = 0; output_table[i].format != NULL; i++)
+        {
+            sprintf (output, output_table[i].format, output_table[i].value);
+            clif_displaymessage (fd, output);
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+//** Character Stats All by fritz
+int atcommand_character_stats_all (const int fd, struct map_session_data *sd,
+                                   const char *command, const char *message)
+{
+    char output[1024], gmlevel[1024];
+    int  i;
+    int  count;
+    struct map_session_data *pl_sd;
+
+    memset (output, '\0', sizeof (output));
+    memset (gmlevel, '\0', sizeof (gmlevel));
+
+    count = 0;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+
+            if (pc_isGM (pl_sd) > 0)
+                sprintf (gmlevel, "| GM Lvl: %d", pc_isGM (pl_sd));
+            else
+                sprintf (gmlevel, " ");
+
+            sprintf (output,
+                     "Name: %s | BLvl: %d | Job: %s (Lvl: %d) | HP: %d/%d | SP: %d/%d",
+                     pl_sd->status.name, pl_sd->status.base_level,
+                     job_name (pl_sd->status.pc_class), pl_sd->status.job_level,
+                     pl_sd->status.hp, pl_sd->status.max_hp, pl_sd->status.sp,
+                     pl_sd->status.max_sp);
+            clif_displaymessage (fd, output);
+            sprintf (output,
+                     "STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s",
+                     pl_sd->status.str, pl_sd->status.agi, pl_sd->status.vit,
+                     pl_sd->status.int_, pl_sd->status.dex, pl_sd->status.luk,
+                     pl_sd->status.zeny, gmlevel);
+            clif_displaymessage (fd, output);
+            clif_displaymessage (fd, "--------");
+            count++;
+        }
+    }
+
+    if (count == 0)
+        clif_displaymessage (fd, msg_table[28]);    // No player found.
+    else if (count == 1)
+        clif_displaymessage (fd, msg_table[29]);    // 1 player found.
+    else
+    {
+        sprintf (output, msg_table[30], count); // %d players found.
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_character_option (const int fd, struct map_session_data *sd,
+                                const char *command, const char *message)
+{
+    char character[100];
+    int  opt1 = 0, opt2 = 0, opt3 = 0;
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %d %d %99[^\n]", &opt1, &opt2, &opt3,
+                   character) < 4 || opt1 < 0 || opt2 < 0 || opt3 < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter valid options and a player name (usage: @charoption <param1> <param2> <param3> <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change option only to lower or same level
+            pl_sd->opt1 = opt1;
+            pl_sd->opt2 = opt2;
+            pl_sd->status.option = opt3;
+            // fix pecopeco display
+            if (pl_sd->status.pc_class == 13 || pl_sd->status.pc_class == 21
+                || pl_sd->status.pc_class == 4014 || pl_sd->status.pc_class == 4022)
+            {
+                if (!pc_isriding (pl_sd))
+                {               // pl_sd have the new value...
+                    if (pl_sd->status.pc_class == 13)
+                        pl_sd->status.pc_class = pl_sd->view_class = 7;
+                    else if (pl_sd->status.pc_class == 21)
+                        pl_sd->status.pc_class = pl_sd->view_class = 14;
+                    else if (pl_sd->status.pc_class == 4014)
+                        pl_sd->status.pc_class = pl_sd->view_class = 4008;
+                    else if (pl_sd->status.pc_class == 4022)
+                        pl_sd->status.pc_class = pl_sd->view_class = 4015;
+                }
+            }
+            else
+            {
+                if (pc_isriding (pl_sd))
+                {               // pl_sd have the new value...
+                    if (pl_sd->disguise > 0)
+                    {           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris] (code added by [Yor])
+                        pl_sd->status.option &= ~0x0020;
+                    }
+                    else
+                    {
+                        if (pl_sd->status.pc_class == 7)
+                            pl_sd->status.pc_class = pl_sd->view_class = 13;
+                        else if (pl_sd->status.pc_class == 14)
+                            pl_sd->status.pc_class = pl_sd->view_class = 21;
+                        else if (pl_sd->status.pc_class == 4008)
+                            pl_sd->status.pc_class = pl_sd->view_class = 4014;
+                        else if (pl_sd->status.pc_class == 4015)
+                            pl_sd->status.pc_class = pl_sd->view_class = 4022;
+                        else
+                            pl_sd->status.option &= ~0x0020;
+                    }
+                }
+            }
+            clif_changeoption (&pl_sd->bl);
+            pc_calcstatus (pl_sd, 0);
+            clif_displaymessage (fd, msg_table[58]);    // Character's options changed.
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * charchangesex command (usage: charchangesex <player_name>)
+ *------------------------------------------
+ */
+int atcommand_char_change_sex (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    char character[100];
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charchangesex <name>).");
+        return -1;
+    }
+
+    // check player name
+    if (strlen (character) < 4)
+    {
+        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
+        return -1;
+    }
+    else if (strlen (character) > 23)
+    {
+        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
+        return -1;
+    }
+    else
+    {
+        chrif_char_ask_name (sd->status.account_id, character, 5, 0, 0, 0, 0, 0, 0);    // type: 5 - changesex
+        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * charblock command (usage: charblock <player_name>)
+ * This command do a definitiv ban on a player
+ *------------------------------------------
+ */
+int atcommand_char_block (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    char character[100];
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @block <name>).");
+        return -1;
+    }
+
+    // check player name
+    if (strlen (character) < 4)
+    {
+        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
+        return -1;
+    }
+    else if (strlen (character) > 23)
+    {
+        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
+        return -1;
+    }
+    else
+    {
+        chrif_char_ask_name (sd->status.account_id, character, 1, 0, 0, 0, 0, 0, 0);    // type: 1 - block
+        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * charban command (usage: charban <time> <player_name>)
+ * This command do a limited ban on a player
+ * Time is done as follows:
+ *   Adjustment value (-1, 1, +1, etc...)
+ *   Modified element:
+ *     a or y: year
+ *     m:  month
+ *     j or d: day
+ *     h:  hour
+ *     mn: minute
+ *     s:  second
+ * <example> @ban +1m-2mn1s-6y test_player
+ *           this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
+ *------------------------------------------
+ */
+int atcommand_char_ban (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char modif[100], character[100];
+    char *modif_p;
+    int  year, month, day, hour, minute, second, value;
+
+    memset (modif, '\0', sizeof (modif));
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%s %99[^\n]", modif, character) < 2)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <name>).");
+        return -1;
+    }
+
+    modif[sizeof (modif) - 1] = '\0';
+    character[sizeof (character) - 1] = '\0';
+
+    modif_p = modif;
+    year = month = day = hour = minute = second = 0;
+    while (modif_p[0] != '\0')
+    {
+        value = atoi (modif_p);
+        if (value == 0)
+            modif_p++;
+        else
+        {
+            if (modif_p[0] == '-' || modif_p[0] == '+')
+                modif_p++;
+            while (modif_p[0] >= '0' && modif_p[0] <= '9')
+                modif_p++;
+            if (modif_p[0] == 's')
+            {
+                second = value;
+                modif_p++;
+            }
+            else if (modif_p[0] == 'm' && modif_p[1] == 'n')
+            {
+                minute = value;
+                modif_p = modif_p + 2;
+            }
+            else if (modif_p[0] == 'h')
+            {
+                hour = value;
+                modif_p++;
+            }
+            else if (modif_p[0] == 'd' || modif_p[0] == 'j')
+            {
+                day = value;
+                modif_p++;
+            }
+            else if (modif_p[0] == 'm')
+            {
+                month = value;
+                modif_p++;
+            }
+            else if (modif_p[0] == 'y' || modif_p[0] == 'a')
+            {
+                year = value;
+                modif_p++;
+            }
+            else if (modif_p[0] != '\0')
+            {
+                modif_p++;
+            }
+        }
+    }
+    if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0
+        && second == 0)
+    {
+        clif_displaymessage (fd, msg_table[85]);    // Invalid time for ban command.
+        return -1;
+    }
+
+    // check player name
+    if (strlen (character) < 4)
+    {
+        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
+        return -1;
+    }
+    else if (strlen (character) > 23)
+    {
+        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
+        return -1;
+    }
+    else
+    {
+        chrif_char_ask_name (sd->status.account_id, character, 2, year, month, day, hour, minute, second);  // type: 2 - ban
+        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * charunblock command (usage: charunblock <player_name>)
+ *------------------------------------------
+ */
+int atcommand_char_unblock (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    char character[100];
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charunblock <player_name>).");
+        return -1;
+    }
+
+    // check player name
+    if (strlen (character) < 4)
+    {
+        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
+        return -1;
+    }
+    else if (strlen (character) > 23)
+    {
+        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
+        return -1;
+    }
+    else
+    {
+        // send answer to login server via char-server
+        chrif_char_ask_name (sd->status.account_id, character, 3, 0, 0, 0, 0, 0, 0);    // type: 3 - unblock
+        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * charunban command (usage: charunban <player_name>)
+ *------------------------------------------
+ */
+int atcommand_char_unban (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    char character[100];
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charunban <player_name>).");
+        return -1;
+    }
+
+    // check player name
+    if (strlen (character) < 4)
+    {
+        clif_displaymessage (fd, msg_table[86]);    // Sorry, but a player name have at least 4 characters.
+        return -1;
+    }
+    else if (strlen (character) > 23)
+    {
+        clif_displaymessage (fd, msg_table[87]);    // Sorry, but a player name have 23 characters maximum.
+        return -1;
+    }
+    else
+    {
+        // send answer to login server via char-server
+        chrif_char_ask_name (sd->status.account_id, character, 4, 0, 0, 0, 0, 0, 0);    // type: 4 - unban
+        clif_displaymessage (fd, msg_table[88]);    // Character name sends to char-server to ask it.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_character_save (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char map_name[100];
+    char character[100];
+    struct map_session_data *pl_sd;
+    int  x = 0, y = 0;
+    int  m;
+
+    memset (map_name, '\0', sizeof (map_name));
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %d %d %99[^\n]", map_name, &x, &y,
+                   character) < 4 || x < 0 || y < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a valid save point and a player name (usage: @charsave <map> <x> <y> <charname>).");
+        return -1;
+    }
+
+    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+        strcat (map_name, ".gat");
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change save point only to lower or same gm level
+            m = map_mapname2mapid (map_name);
+            if (m < 0)
+            {
+                clif_displaymessage (fd, msg_table[1]); // Map not found.
+                return -1;
+            }
+            else
+            {
+                if (m >= 0 && map[m].flag.nowarpto
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                {
+                    clif_displaymessage (fd,
+                                         "You are not authorised to set this map as a save map.");
+                    return -1;
+                }
+                pc_setsavepoint (pl_sd, map_name, x, y);
+                clif_displaymessage (fd, msg_table[57]);    // Character's respawn point changed.
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_night (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    if (night_flag != 1)
+    {
+        night_flag = 1;         // 0=day, 1=night [Yor]
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                pl_sd->opt2 |= STATE_BLIND;
+                clif_changeoption (&pl_sd->bl);
+                clif_displaymessage (pl_sd->fd, msg_table[59]); // Night has fallen.
+            }
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[89]);    // Sorry, it's already the night. Impossible to execute the command.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_day (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    if (night_flag != 0)
+    {
+        night_flag = 0;         // 0=day, 1=night [Yor]
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                pl_sd->opt2 &= ~STATE_BLIND;
+                clif_changeoption (&pl_sd->bl);
+                clif_displaymessage (pl_sd->fd, msg_table[60]); // Day has arrived.
+            }
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[90]);    // Sorry, it's already the day. Impossible to execute the command.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_doom (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth && i != fd
+            && pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can doom only lower or same gm level
+            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
+            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
+        }
+    }
+    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_doommap (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m
+            && pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can doom only lower or same gm level
+            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
+            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
+        }
+    }
+    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static void atcommand_raise_sub (struct map_session_data *sd)
+{
+    if (sd && sd->state.auth && pc_isdead (sd))
+    {
+        sd->status.hp = sd->status.max_hp;
+        sd->status.sp = sd->status.max_sp;
+        pc_setstand (sd);
+        clif_updatestatus (sd, SP_HP);
+        clif_updatestatus (sd, SP_SP);
+        clif_resurrection (&sd->bl, 1);
+        clif_displaymessage (sd->fd, msg_table[63]);    // Mercy has been shown.
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_raise (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i])
+            atcommand_raise_sub ((struct map_session_data *)session[i]->session_data);
+    }
+    clif_displaymessage (fd, msg_table[64]);    // Mercy has been granted.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_raisemap (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth && sd->bl.m == pl_sd->bl.m)
+            atcommand_raise_sub (pl_sd);
+    }
+    clif_displaymessage (fd, msg_table[64]);    // Mercy has been granted.
+
+    return 0;
+}
+
+/*==========================================
+ * atcommand_character_baselevel @charbaselvlで対象キャラのレベルを上げる
+ *------------------------------------------
+*/
+int atcommand_character_baselevel (const int fd, struct map_session_data *sd,
+                                   const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    int  level = 0, i;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &level, character) < 2
+        || level == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a level adjustement and a player name (usage: @charblvl <#> <nickname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change base level only lower or same gm level
+
+            if (level > 0)
+            {
+                if (pl_sd->status.base_level == battle_config.maximum_level)
+                {               // check for max level by Valaris
+                    clif_displaymessage (fd, msg_table[91]);    // Character's base level can't go any higher.
+                    return 0;
+                }               // End Addition
+                if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level))    // fix positiv overflow
+                    level =
+                        battle_config.maximum_level -
+                        pl_sd->status.base_level;
+                for (i = 1; i <= level; i++)
+                    pl_sd->status.status_point +=
+                        (pl_sd->status.base_level + i + 14) / 4;
+                pl_sd->status.base_level += level;
+                clif_updatestatus (pl_sd, SP_BASELEVEL);
+                clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
+                clif_updatestatus (pl_sd, SP_STATUSPOINT);
+                pc_calcstatus (pl_sd, 0);
+                pc_heal (pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp);
+                clif_misceffect (&pl_sd->bl, 0);
+                clif_displaymessage (fd, msg_table[65]);    // Character's base level raised.
+            }
+            else
+            {
+                if (pl_sd->status.base_level == 1)
+                {
+                    clif_displaymessage (fd, msg_table[193]);   // Character's base level can't go any lower.
+                    return -1;
+                }
+                if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level)) // fix negativ overflow
+                    level = 1 - pl_sd->status.base_level;
+                if (pl_sd->status.status_point > 0)
+                {
+                    for (i = 0; i > level; i--)
+                        pl_sd->status.status_point -=
+                            (pl_sd->status.base_level + i + 14) / 4;
+                    if (pl_sd->status.status_point < 0)
+                        pl_sd->status.status_point = 0;
+                    clif_updatestatus (pl_sd, SP_STATUSPOINT);
+                }               // to add: remove status points from stats
+                pl_sd->status.base_level += level;
+                pl_sd->status.base_exp = 0;
+                clif_updatestatus (pl_sd, SP_BASELEVEL);
+                clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
+                clif_updatestatus (pl_sd, SP_BASEEXP);
+                pc_calcstatus (pl_sd, 0);
+                clif_displaymessage (fd, msg_table[66]);    // Character's base level lowered.
+            }
+	    // Reset their stat points to prevent extra points from stacking
+	    atcommand_charstreset(fd, sd,"@charstreset", character);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;                   //正常終了
+}
+
+/*==========================================
+ * atcommand_character_joblevel @charjoblvlで対象キャラのJobレベルを上げる
+ *------------------------------------------
+ */
+int atcommand_character_joblevel (const int fd, struct map_session_data *sd,
+                                  const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    int  max_level = 50, level = 0;
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job pl_s_class;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &level, character) < 2
+        || level == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a level adjustement and a player name (usage: @charjlvl <#> <nickname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        pl_s_class = pc_calc_base_job (pl_sd->status.pc_class);
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change job level only lower or same gm level
+            if (pl_s_class.job == 0)
+                max_level -= 40;
+            if ((pl_s_class.job == 23) || (pl_s_class.upper == 1 && pl_s_class.type == 2))  //スパノビと転生職はJobレベルの最高が70
+                max_level += 20;
+
+            if (level > 0)
+            {
+                if (pl_sd->status.job_level == max_level)
+                {
+                    clif_displaymessage (fd, msg_table[67]);    // Character's job level can't go any higher.
+                    return -1;
+                }
+                if (pl_sd->status.job_level + level > max_level)
+                    level = max_level - pl_sd->status.job_level;
+                pl_sd->status.job_level += level;
+                clif_updatestatus (pl_sd, SP_JOBLEVEL);
+                clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
+                pl_sd->status.skill_point += level;
+                clif_updatestatus (pl_sd, SP_SKILLPOINT);
+                pc_calcstatus (pl_sd, 0);
+                clif_misceffect (&pl_sd->bl, 1);
+                clif_displaymessage (fd, msg_table[68]);    // character's job level raised.
+            }
+            else
+            {
+                if (pl_sd->status.job_level == 1)
+                {
+                    clif_displaymessage (fd, msg_table[194]);   // Character's job level can't go any lower.
+                    return -1;
+                }
+                if (pl_sd->status.job_level + level < 1)
+                    level = 1 - pl_sd->status.job_level;
+                pl_sd->status.job_level += level;
+                clif_updatestatus (pl_sd, SP_JOBLEVEL);
+                clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
+                if (pl_sd->status.skill_point > 0)
+                {
+                    pl_sd->status.skill_point += level;
+                    if (pl_sd->status.skill_point < 0)
+                        pl_sd->status.skill_point = 0;
+                    clif_updatestatus (pl_sd, SP_SKILLPOINT);
+                }               // to add: remove status points from skills
+                pc_calcstatus (pl_sd, 0);
+                clif_displaymessage (fd, msg_table[69]);    // Character's job level lowered.
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_kick (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @kick <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))    // you can kick only lower or same gm level
+            clif_GM_kick (sd, pl_sd, 1);
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_kickall (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth && pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can kick only lower or same gm level
+            if (sd->status.account_id != pl_sd->status.account_id)
+                clif_GM_kick (sd, pl_sd, 0);
+        }
+    }
+
+    clif_displaymessage (fd, msg_table[195]);   // All players have been kicked!
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_allskills (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    pc_allskillup (sd);         // all skills
+    sd->status.skill_point = 0; // 0 skill points
+    clif_updatestatus (sd, SP_SKILLPOINT);  // update
+    clif_displaymessage (fd, msg_table[76]);    // You have received all skills.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_questskill (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    int  skill_id;
+
+    if (!message || !*message || (skill_id = atoi (message)) < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a quest skill number (usage: @questskill <#:0+>).");
+        return -1;
+    }
+
+    if (skill_id >= 0 && skill_id < MAX_SKILL_DB)
+    {
+        if (skill_get_inf2 (skill_id) & 0x01)
+        {
+            if (pc_checkskill (sd, skill_id) == 0)
+            {
+                pc_skill (sd, skill_id, 1, 0);
+                clif_displaymessage (fd, msg_table[70]);    // You have learned the skill.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[196]);   // You already have this quest skill.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_charquestskill (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+    int  skill_id = 0;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &skill_id, character) < 2
+        || skill_id < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a quest skill number and a player name (usage: @charquestskill <#:0+> <char_name>).");
+        return -1;
+    }
+
+    if (skill_id >= 0 && skill_id < MAX_SKILL_DB)
+    {
+        if (skill_get_inf2 (skill_id) & 0x01)
+        {
+            if ((pl_sd = map_nick2sd (character)) != NULL)
+            {
+                if (pc_checkskill (pl_sd, skill_id) == 0)
+                {
+                    pc_skill (pl_sd, skill_id, 1, 0);
+                    clif_displaymessage (fd, msg_table[199]);   // This player has learned the skill.
+                }
+                else
+                {
+                    clif_displaymessage (fd, msg_table[200]);   // This player already has this quest skill.
+                    return -1;
+                }
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[3]); // Character not found.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_lostskill (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    int  skill_id;
+
+    if (!message || !*message || (skill_id = atoi (message)) < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a quest skill number (usage: @lostskill <#:0+>).");
+        return -1;
+    }
+
+    if (skill_id >= 0 && skill_id < MAX_SKILL)
+    {
+        if (skill_get_inf2 (skill_id) & 0x01)
+        {
+            if (pc_checkskill (sd, skill_id) > 0)
+            {
+                sd->status.skill[skill_id].lv = 0;
+                sd->status.skill[skill_id].flags = 0;
+                clif_skillinfoblock (sd);
+                clif_displaymessage (fd, msg_table[71]);    // You have forgotten the skill.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[201]);   // You don't have this quest skill.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_charlostskill (const int fd, struct map_session_data *sd,
+                             const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+    int  skill_id = 0;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &skill_id, character) < 2
+        || skill_id < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a quest skill number and a player name (usage: @charlostskill <#:0+> <char_name>).");
+        return -1;
+    }
+
+    if (skill_id >= 0 && skill_id < MAX_SKILL)
+    {
+        if (skill_get_inf2 (skill_id) & 0x01)
+        {
+            if ((pl_sd = map_nick2sd (character)) != NULL)
+            {
+                if (pc_checkskill (pl_sd, skill_id) > 0)
+                {
+                    pl_sd->status.skill[skill_id].lv = 0;
+                    pl_sd->status.skill[skill_id].flags = 0;
+                    clif_skillinfoblock (pl_sd);
+                    clif_displaymessage (fd, msg_table[202]);   // This player has forgotten the skill.
+                }
+                else
+                {
+                    clif_displaymessage (fd, msg_table[203]);   // This player doesn't have this quest skill.
+                    return -1;
+                }
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[3]); // Character not found.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[197]);   // This skill number doesn't exist or isn't a quest skill.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[198]);   // This skill number doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_party (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char party[100];
+
+    memset (party, '\0', sizeof (party));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", party) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a party name (usage: @party <party_name>).");
+        return -1;
+    }
+
+    party_create (sd, party);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_guild (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char guild[100];
+    int  prev;
+
+    memset (guild, '\0', sizeof (guild));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", guild) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a guild name (usage: @guild <guild_name>).");
+        return -1;
+    }
+
+    prev = battle_config.guild_emperium_check;
+    battle_config.guild_emperium_check = 0;
+    guild_create (sd, guild);
+    battle_config.guild_emperium_check = prev;
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_agitstart (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    if (agit_flag == 1)
+    {
+        clif_displaymessage (fd, msg_table[73]);    // Already it has started siege warfare.
+        return -1;
+    }
+
+    agit_flag = 1;
+    guild_agit_start ();
+    clif_displaymessage (fd, msg_table[72]);    // Guild siege warfare start!
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_agitend (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    if (agit_flag == 0)
+    {
+        clif_displaymessage (fd, msg_table[75]);    // Siege warfare hasn't started yet.
+        return -1;
+    }
+
+    agit_flag = 0;
+    guild_agit_end ();
+    clif_displaymessage (fd, msg_table[74]);    // Guild siege warfare end!
+
+    return 0;
+}
+
+/*==========================================
+ * @mapexitでマップサーバーを終了させる
+ *------------------------------------------
+ */
+int atcommand_mapexit (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            if (sd->status.account_id != pl_sd->status.account_id)
+                clif_GM_kick (sd, pl_sd, 0);
+        }
+    }
+    clif_GM_kick (sd, sd, 0);
+
+    runflag = 0;
+
+    return 0;
+}
+
+/*==========================================
+ * idsearch <part_of_name>: revrited by [Yor]
+ *------------------------------------------
+ */
+int atcommand_idsearch (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char item_name[100];
+    char output[200];
+    int  i, match;
+    struct item_data *item;
+
+    memset (item_name, '\0', sizeof (item_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99s", item_name) < 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a part of item name (usage: @idsearch <part_of_item_name>).");
+        return -1;
+    }
+
+    sprintf (output, msg_table[77], item_name); // The reference result of '%s' (name: id):
+    clif_displaymessage (fd, output);
+    match = 0;
+    for (i = 0; i < 20000; i++)
+    {
+        if ((item = itemdb_exists (i)) != NULL
+            && strstr (item->jname, item_name) != NULL)
+        {
+            match++;
+            sprintf (output, msg_table[78], item->jname, item->nameid); // %s: %d
+            clif_displaymessage (fd, output);
+        }
+    }
+    sprintf (output, msg_table[79], match); // It is %d affair above.
+    clif_displaymessage (fd, output);
+
+    return 0;
+}
+
+/*==========================================
+ * Character Skill Reset
+ *------------------------------------------
+ */
+int atcommand_charskreset (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charskreset <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can reset skill points only lower or same gm level
+            pc_resetskill (pl_sd);
+            sprintf (output, msg_table[206], character);    // '%s' skill points reseted!
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Stat Reset
+ *------------------------------------------
+ */
+int atcommand_charstreset (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charstreset <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can reset stats points only lower or same gm level
+            pc_resetstate (pl_sd);
+            sprintf (output, msg_table[207], character);    // '%s' stats points reseted!
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Reset
+ *------------------------------------------
+ */
+int atcommand_charreset (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charreset <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can reset a character only for lower or same GM level
+            pc_resetstate (pl_sd);
+            pc_resetskill (pl_sd);
+            pc_setglobalreg (pl_sd, "MAGIC_FLAGS", 0);  // [Fate] Reset magic quest variables
+            pc_setglobalreg (pl_sd, "MAGIC_EXP", 0);    // [Fate] Reset magic experience
+            sprintf (output, msg_table[208], character);    // '%s' skill and stats points reseted!
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Wipe
+ *------------------------------------------
+ */
+int atcommand_char_wipe (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charwipe <charname>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can reset a character only for lower or same GM level
+            int  i;
+
+            // Reset base level
+            pl_sd->status.base_level = 1;
+            pl_sd->status.base_exp = 0;
+            clif_updatestatus (pl_sd, SP_BASELEVEL);
+            clif_updatestatus (pl_sd, SP_NEXTBASEEXP);
+            clif_updatestatus (pl_sd, SP_BASEEXP);
+
+            // Reset job level
+            pl_sd->status.job_level = 1;
+            pl_sd->status.job_exp = 0;
+            clif_updatestatus (pl_sd, SP_JOBLEVEL);
+            clif_updatestatus (pl_sd, SP_NEXTJOBEXP);
+            clif_updatestatus (pl_sd, SP_JOBEXP);
+
+            // Zeny to 50
+            pl_sd->status.zeny = 50;
+            clif_updatestatus (pl_sd, SP_ZENY);
+
+            // Clear inventory
+            for (i = 0; i < MAX_INVENTORY; i++)
+            {
+                if (sd->status.inventory[i].amount)
+                {
+                    if (sd->status.inventory[i].equip)
+                        pc_unequipitem (pl_sd, i, 0);
+                    pc_delitem (pl_sd, i, sd->status.inventory[i].amount, 0);
+                }
+            }
+
+            // Give knife and shirt
+            struct item item;
+            item.nameid = 1201; // knife
+            item.identify = 1;
+            item.broken = 0;
+            pc_additem (pl_sd, &item, 1);
+            item.nameid = 1202; // shirt
+            pc_additem (pl_sd, &item, 1);
+
+            // Reset stats and skills
+            pc_calcstatus (pl_sd, 0);
+            pc_resetstate (pl_sd);
+            pc_resetskill (pl_sd);
+            pc_setglobalreg (pl_sd, "MAGIC_FLAGS", 0);  // [Fate] Reset magic quest variables
+            pc_setglobalreg (pl_sd, "MAGIC_EXP", 0);    // [Fate] Reset magic experience
+
+            sprintf (output, "%s:  wiped.", character); // '%s' skill and stats points reseted!
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Model by chbrules
+ *------------------------------------------
+ */
+int atcommand_charmodel (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    int  hair_style = 0, hair_color = 0, cloth_color = 0;
+    struct map_session_data *pl_sd;
+    char character[100];
+    char output[200];
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message
+        || sscanf (message, "%d %d %d %99[^\n]", &hair_style, &hair_color,
+                   &cloth_color, character) < 4 || hair_style < 0
+        || hair_color < 0 || cloth_color < 0)
+    {
+        sprintf (output,
+                 "Please, enter a valid model and a player name (usage: @charmodel <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d> <name>).",
+                 MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR,
+                 MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
+        clif_displaymessage (fd, output);
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
+            hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
+            cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
+        {
+
+            if (cloth_color != 0 &&
+                pl_sd->status.sex == 1 &&
+                (pl_sd->status.pc_class == 12 || pl_sd->status.pc_class == 17))
+            {
+                clif_displaymessage (fd, msg_table[35]);    // You can't use this command with this class.
+                return -1;
+            }
+            else
+            {
+                pc_changelook (pl_sd, LOOK_HAIR, hair_style);
+                pc_changelook (pl_sd, LOOK_HAIR_COLOR, hair_color);
+                pc_changelook (pl_sd, LOOK_CLOTHES_COLOR, cloth_color);
+                clif_displaymessage (fd, msg_table[36]);    // Appearence changed.
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[37]);    // An invalid number was specified.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Skill Point (Rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_charskpoint (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    int  new_skill_point;
+    int  point = 0;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &point, character) < 2
+        || point == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a number and a player name (usage: @charskpoint <amount> <name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        new_skill_point = (int) pl_sd->status.skill_point + point;
+        if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))  // fix positiv overflow
+            new_skill_point = 0x7FFF;
+        else if (point < 0 && (point < -0x7FFF || new_skill_point < 0)) // fix negativ overflow
+            new_skill_point = 0;
+        if (new_skill_point != (int) pl_sd->status.skill_point)
+        {
+            pl_sd->status.skill_point = new_skill_point;
+            clif_updatestatus (pl_sd, SP_SKILLPOINT);
+            clif_displaymessage (fd, msg_table[209]);   // Character's number of skill points changed!
+        }
+        else
+        {
+            if (point < 0)
+                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+            else
+                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Status Point (rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_charstpoint (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    int  new_status_point;
+    int  point = 0;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &point, character) < 2
+        || point == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a number and a player name (usage: @charstpoint <amount> <name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        new_status_point = (int) pl_sd->status.status_point + point;
+        if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF)) // fix positiv overflow
+            new_status_point = 0x7FFF;
+        else if (point < 0 && (point < -0x7FFF || new_status_point < 0))    // fix negativ overflow
+            new_status_point = 0;
+        if (new_status_point != (int) pl_sd->status.status_point)
+        {
+            pl_sd->status.status_point = new_status_point;
+            clif_updatestatus (pl_sd, SP_STATUSPOINT);
+            clif_displaymessage (fd, msg_table[210]);   // Character's number of status points changed!
+        }
+        else
+        {
+            if (point < 0)
+                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+            else
+                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Character Zeny Point (Rewritten by [Yor])
+ *------------------------------------------
+ */
+int atcommand_charzeny (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    int  zeny = 0, new_zeny;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &zeny, character) < 2 || zeny == 0)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a number and a player name (usage: @charzeny <zeny> <name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        new_zeny = pl_sd->status.zeny + zeny;
+        if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))   // fix positiv overflow
+            new_zeny = MAX_ZENY;
+        else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))    // fix negativ overflow
+            new_zeny = 0;
+        if (new_zeny != pl_sd->status.zeny)
+        {
+            pl_sd->status.zeny = new_zeny;
+            clif_updatestatus (pl_sd, SP_ZENY);
+            clif_displaymessage (fd, msg_table[211]);   // Character's number of zenys changed!
+        }
+        else
+        {
+            if (zeny < 0)
+                clif_displaymessage (fd, msg_table[41]);    // Impossible to decrease the number/value.
+            else
+                clif_displaymessage (fd, msg_table[149]);   // Impossible to increase the number/value.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Recall All Characters Online To Your Location
+ *------------------------------------------
+ */
+int atcommand_recallall (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+    int  count;
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp somenone to your actual map.");
+        return -1;
+    }
+
+    count = 0;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth
+            && sd->status.account_id != pl_sd->status.account_id
+            && pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can recall only lower or same level
+            if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
+                && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                count++;
+            else
+                pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+        }
+    }
+
+    clif_displaymessage (fd, msg_table[92]);    // All characters recalled!
+    if (count)
+    {
+        sprintf (output,
+                 "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
+                 count);
+        clif_displaymessage (fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Recall online characters of a guild to your location
+ *------------------------------------------
+ */
+int atcommand_guildrecall (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+    char guild_name[100];
+    char output[200];
+    struct guild *g;
+    int  count;
+
+    memset (guild_name, '\0', sizeof (guild_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", guild_name) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a guild name/id (usage: @guildrecall <guild_name/id>).");
+        return -1;
+    }
+
+    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp somenone to your actual map.");
+        return -1;
+    }
+
+    if ((g = guild_searchname (guild_name)) != NULL ||  // name first to avoid error when name begin with a number
+        (g = guild_search (atoi (message))) != NULL)
+    {
+        count = 0;
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth
+                && sd->status.account_id != pl_sd->status.account_id
+                && pl_sd->status.guild_id == g->guild_id)
+            {
+                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                    count++;
+                else
+                    pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+            }
+        }
+        sprintf (output, msg_table[93], g->name);   // All online characters of the %s guild are near you.
+        clif_displaymessage (fd, output);
+        if (count)
+        {
+            sprintf (output,
+                     "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
+                     count);
+            clif_displaymessage (fd, output);
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[94]);    // Incorrect name/ID, or no one from the guild is online.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Recall online characters of a party to your location
+ *------------------------------------------
+ */
+int atcommand_partyrecall (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    int  i;
+    struct map_session_data *pl_sd;
+    char party_name[100];
+    char output[200];
+    struct party *p;
+    int  count;
+
+    memset (party_name, '\0', sizeof (party_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", party_name) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a party name/id (usage: @partyrecall <party_name/id>).");
+        return -1;
+    }
+
+    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp somenone to your actual map.");
+        return -1;
+    }
+
+    if ((p = party_searchname (party_name)) != NULL ||  // name first to avoid error when name begin with a number
+        (p = party_search (atoi (message))) != NULL)
+    {
+        count = 0;
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth
+                && sd->status.account_id != pl_sd->status.account_id
+                && pl_sd->status.party_id == p->party_id)
+            {
+                if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp
+                    && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+                    count++;
+                else
+                    pc_setpos (pl_sd, sd->mapname, sd->bl.x, sd->bl.y, 2);
+            }
+        }
+        sprintf (output, msg_table[95], p->name);   // All online characters of the %s party are near you.
+        clif_displaymessage (fd, output);
+        if (count)
+        {
+            sprintf (output,
+                     "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
+                     count);
+            clif_displaymessage (fd, output);
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[96]);    // Incorrect name or ID, or no one from the party is online.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_reloaditemdb (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    itemdb_reload ();
+    clif_displaymessage (fd, msg_table[97]);    // Item database reloaded.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_reloadmobdb (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    mob_reload ();
+    clif_displaymessage (fd, msg_table[98]);    // Monster database reloaded.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_reloadskilldb (const int fd, struct map_session_data *sd,
+                             const char *command, const char *message)
+{
+    skill_reload ();
+    clif_displaymessage (fd, msg_table[99]);    // Skill database reloaded.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_reloadscript (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    do_init_npc ();
+    do_init_script ();
+
+    npc_event_do_oninit ();
+
+    clif_displaymessage (fd, msg_table[100]);   // Scripts reloaded.
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_reloadgmdb (      // by [Yor]
+                             const int fd, struct map_session_data *sd,
+                             const char *command, const char *message)
+{
+    chrif_reloadGMdb ();
+
+    clif_displaymessage (fd, msg_table[101]);   // Login-server asked to reload GM accounts and their level.
+
+    return 0;
+}
+
+/*==========================================
+ * @mapinfo <map name> [0-3] by MC_Cameri
+ * => Shows information about the map [map name]
+ * 0 = no additional information
+ * 1 = Show users in that map and their location
+ * 2 = Shows NPCs in that map
+ * 3 = Shows the shops/chats in that map (not implemented)
+ *------------------------------------------
+ */
+int atcommand_mapinfo (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    struct npc_data *nd = NULL;
+    struct chat_data *cd = NULL;
+    char output[200], map_name[100];
+    char direction[12];
+    int  m_id, i, chat_num, list = 0;
+
+    memset (output, '\0', sizeof (output));
+    memset (map_name, '\0', sizeof (map_name));
+    memset (direction, '\0', sizeof (direction));
+
+    sscanf (message, "%d %99[^\n]", &list, map_name);
+
+    if (list < 0 || list > 3)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
+        return -1;
+    }
+
+    if (map_name[0] == '\0')
+        strcpy (map_name, sd->mapname);
+    if (strstr (map_name, ".gat") == NULL && strstr (map_name, ".afm") == NULL && strlen (map_name) < 13)   // 16 - 4 (.gat)
+        strcat (map_name, ".gat");
+
+    if ((m_id = map_mapname2mapid (map_name)) < 0)
+    {
+        clif_displaymessage (fd, msg_table[1]); // Map not found.
+        return -1;
+    }
+
+    clif_displaymessage (fd, "------ Map Info ------");
+    sprintf (output, "Map Name: %s", map_name);
+    clif_displaymessage (fd, output);
+    sprintf (output, "Players In Map: %d", map[m_id].users);
+    clif_displaymessage (fd, output);
+    sprintf (output, "NPCs In Map: %d", map[m_id].npc_num);
+    clif_displaymessage (fd, output);
+    chat_num = 0;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth
+            && (cd = (struct chat_data *) map_id2bl (pl_sd->chatID)))
+        {
+            chat_num++;
+        }
+    }
+    sprintf (output, "Chats In Map: %d", chat_num);
+    clif_displaymessage (fd, output);
+    clif_displaymessage (fd, "------ Map Flags ------");
+    sprintf (output, "Player vs Player: %s | No Guild: %s | No Party: %s",
+             (map[m_id].flag.pvp) ? "True" : "False",
+             (map[m_id].flag.pvp_noguild) ? "True" : "False",
+             (map[m_id].flag.pvp_noparty) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "Guild vs Guild: %s | No Party: %s",
+             (map[m_id].flag.gvg) ? "True" : "False",
+             (map[m_id].flag.gvg_noparty) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Dead Branch: %s",
+             (map[m_id].flag.nobranch) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Memo: %s",
+             (map[m_id].flag.nomemo) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Penalty: %s",
+             (map[m_id].flag.nopenalty) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Return: %s",
+             (map[m_id].flag.noreturn) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Save: %s",
+             (map[m_id].flag.nosave) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Teleport: %s",
+             (map[m_id].flag.noteleport) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Monster Teleport: %s",
+             (map[m_id].flag.monster_noteleport) ? "True" : "False");
+    clif_displaymessage (fd, output);
+    sprintf (output, "No Zeny Penalty: %s",
+             (map[m_id].flag.nozenypenalty) ? "True" : "False");
+    clif_displaymessage (fd, output);
+
+    switch (list)
+    {
+        case 0:
+            // Do nothing. It's list 0, no additional display.
+            break;
+        case 1:
+            clif_displaymessage (fd, "----- Players in Map -----");
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                    && pl_sd->state.auth
+                    && strcmp (pl_sd->mapname, map_name) == 0)
+                {
+                    sprintf (output,
+                             "Player '%s' (session #%d) | Location: %d,%d",
+                             pl_sd->status.name, i, pl_sd->bl.x, pl_sd->bl.y);
+                    clif_displaymessage (fd, output);
+                }
+            }
+            break;
+        case 2:
+            clif_displaymessage (fd, "----- NPCs in Map -----");
+            for (i = 0; i < map[m_id].npc_num;)
+            {
+                nd = map[m_id].npc[i];
+                switch (nd->dir)
+                {
+                    case 0:
+                        strcpy (direction, "North");
+                        break;
+                    case 1:
+                        strcpy (direction, "North West");
+                        break;
+                    case 2:
+                        strcpy (direction, "West");
+                        break;
+                    case 3:
+                        strcpy (direction, "South West");
+                        break;
+                    case 4:
+                        strcpy (direction, "South");
+                        break;
+                    case 5:
+                        strcpy (direction, "South East");
+                        break;
+                    case 6:
+                        strcpy (direction, "East");
+                        break;
+                    case 7:
+                        strcpy (direction, "North East");
+                        break;
+                    case 9:
+                        strcpy (direction, "North");
+                        break;
+                    default:
+                        strcpy (direction, "Unknown");
+                        break;
+                }
+                sprintf (output,
+                         "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d",
+                         ++i, nd->name, direction, nd->npc_class, nd->bl.x,
+                         nd->bl.y);
+                clif_displaymessage (fd, output);
+            }
+            break;
+        case 3:
+            clif_displaymessage (fd, "----- Chats in Map -----");
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                    && pl_sd->state.auth
+                    && (cd = (struct chat_data *) map_id2bl (pl_sd->chatID))
+                    && strcmp (pl_sd->mapname, map_name) == 0
+                    && cd->usersd[0] == pl_sd)
+                {
+                    sprintf (output,
+                             "Chat %d: %s | Player: %s | Location: %d %d", i,
+                             cd->title, pl_sd->status.name, cd->bl.x,
+                             cd->bl.y);
+                    clif_displaymessage (fd, output);
+                    sprintf (output,
+                             "   Users: %d/%d | Password: %s | Public: %s",
+                             cd->users, cd->limit, cd->pass,
+                             (cd->pub) ? "Yes" : "No");
+                    clif_displaymessage (fd, output);
+                }
+            }
+            break;
+        default:               // normally impossible to arrive here
+            clif_displaymessage (fd,
+                                 "Please, enter at least a valid list number (usage: @mapinfo <0-3> [map]).");
+            return -1;
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_mount_peco (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    if (sd->disguise > 0)
+    {                           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+        clif_displaymessage (fd, msg_table[212]);   // Cannot mount a Peco while in disguise.
+        return -1;
+    }
+
+    if (!pc_isriding (sd))
+    {                           // if actually no peco
+        if (sd->status.pc_class == 7 || sd->status.pc_class == 14
+            || sd->status.pc_class == 4008 || sd->status.pc_class == 4015)
+        {
+            if (sd->status.pc_class == 7)
+                sd->status.pc_class = sd->view_class = 13;
+            else if (sd->status.pc_class == 14)
+                sd->status.pc_class = sd->view_class = 21;
+            else if (sd->status.pc_class == 4008)
+                sd->status.pc_class = sd->view_class = 4014;
+            else if (sd->status.pc_class == 4015)
+                sd->status.pc_class = sd->view_class = 4022;
+            pc_setoption (sd, sd->status.option | 0x0020);
+            clif_displaymessage (fd, msg_table[102]);   // Mounted Peco.
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[213]);   // You can not mount a peco with your job.
+            return -1;
+        }
+    }
+    else
+    {
+        if (sd->status.pc_class == 13)
+            sd->status.pc_class = sd->view_class = 7;
+        else if (sd->status.pc_class == 21)
+            sd->status.pc_class = sd->view_class = 14;
+        else if (sd->status.pc_class == 4014)
+            sd->status.pc_class = sd->view_class = 4008;
+        else if (sd->status.pc_class == 4022)
+            sd->status.pc_class = sd->view_class = 4015;
+        pc_setoption (sd, sd->status.option & ~0x0020);
+        clif_displaymessage (fd, msg_table[214]);   // Unmounted Peco.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_char_mount_peco (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charmountpeco <char_name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pl_sd->disguise > 0)
+        {                       // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+            clif_displaymessage (fd, msg_table[215]);   // This player cannot mount a Peco while in disguise.
+            return -1;
+        }
+
+        if (!pc_isriding (pl_sd))
+        {                       // if actually no peco
+            if (pl_sd->status.pc_class == 7 || pl_sd->status.pc_class == 14
+                || pl_sd->status.pc_class == 4008 || pl_sd->status.pc_class == 4015)
+            {
+                if (pl_sd->status.pc_class == 7)
+                    pl_sd->status.pc_class = pl_sd->view_class = 13;
+                else if (pl_sd->status.pc_class == 14)
+                    pl_sd->status.pc_class = pl_sd->view_class = 21;
+                else if (pl_sd->status.pc_class == 4008)
+                    pl_sd->status.pc_class = pl_sd->view_class = 4014;
+                else if (pl_sd->status.pc_class == 4015)
+                    pl_sd->status.pc_class = pl_sd->view_class = 4022;
+                pc_setoption (pl_sd, pl_sd->status.option | 0x0020);
+                clif_displaymessage (fd, msg_table[216]);   // Now, this player mounts a peco.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[217]);   // This player can not mount a peco with his/her job.
+                return -1;
+            }
+        }
+        else
+        {
+            if (pl_sd->status.pc_class == 13)
+                pl_sd->status.pc_class = pl_sd->view_class = 7;
+            else if (pl_sd->status.pc_class == 21)
+                pl_sd->status.pc_class = pl_sd->view_class = 14;
+            else if (pl_sd->status.pc_class == 4014)
+                pl_sd->status.pc_class = pl_sd->view_class = 4008;
+            else if (pl_sd->status.pc_class == 4022)
+                pl_sd->status.pc_class = pl_sd->view_class = 4015;
+            pc_setoption (pl_sd, pl_sd->status.option & ~0x0020);
+            clif_displaymessage (fd, msg_table[218]);   // Now, this player has not more peco.
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *Spy Commands by Syrus22
+ *------------------------------------------
+ */
+int atcommand_guildspy (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char guild_name[100];
+    char output[200];
+    struct guild *g;
+
+    memset (guild_name, '\0', sizeof (guild_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", guild_name) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a guild name/id (usage: @guildspy <guild_name/id>).");
+        return -1;
+    }
+
+    if ((g = guild_searchname (guild_name)) != NULL ||  // name first to avoid error when name begin with a number
+        (g = guild_search (atoi (message))) != NULL)
+    {
+        if (sd->guildspy == g->guild_id)
+        {
+            sd->guildspy = 0;
+            sprintf (output, msg_table[103], g->name);  // No longer spying on the %s guild.
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            sd->guildspy = g->guild_id;
+            sprintf (output, msg_table[104], g->name);  // Spying on the %s guild.
+            clif_displaymessage (fd, output);
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[94]);    // Incorrect name/ID, or no one from the guild is online.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_partyspy (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    char party_name[100];
+    char output[200];
+    struct party *p;
+
+    memset (party_name, '\0', sizeof (party_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", party_name) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a party name/id (usage: @partyspy <party_name/id>).");
+        return -1;
+    }
+
+    if ((p = party_searchname (party_name)) != NULL ||  // name first to avoid error when name begin with a number
+        (p = party_search (atoi (message))) != NULL)
+    {
+        if (sd->partyspy == p->party_id)
+        {
+            sd->partyspy = 0;
+            sprintf (output, msg_table[105], p->name);  // No longer spying on the %s party.
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            sd->partyspy = p->party_id;
+            sprintf (output, msg_table[106], p->name);  // Spying on the %s party.
+            clif_displaymessage (fd, output);
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[96]);    // Incorrect name or ID, or no one from the party is online.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_enablenpc (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    char NPCname[100];
+
+    memset (NPCname, '\0', sizeof (NPCname));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", NPCname) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a NPC name (usage: @npcon <NPC_name>).");
+        return -1;
+    }
+
+    if (npc_name2id (NPCname) != NULL)
+    {
+        npc_enable (NPCname, 1);
+        clif_displaymessage (fd, msg_table[110]);   // Npc Enabled.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[111]);   // This NPC doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_disablenpc (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    char NPCname[100];
+
+    memset (NPCname, '\0', sizeof (NPCname));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", NPCname) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a NPC name (usage: @npcoff <NPC_name>).");
+        return -1;
+    }
+
+    if (npc_name2id (NPCname) != NULL)
+    {
+        npc_enable (NPCname, 0);
+        clif_displaymessage (fd, msg_table[112]);   // Npc Disabled.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[111]);   // This NPC doesn't exist.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * time in txt for time command (by [Yor])
+ *------------------------------------------
+ */
+char *txt_time (unsigned int duration)
+{
+    int  days, hours, minutes, seconds;
+    char temp[256];
+    static char temp1[256];
+
+    memset (temp, '\0', sizeof (temp));
+    memset (temp1, '\0', sizeof (temp1));
+
+    if (duration < 0)
+        duration = 0;
+
+    days = duration / (60 * 60 * 24);
+    duration = duration - (60 * 60 * 24 * days);
+    hours = duration / (60 * 60);
+    duration = duration - (60 * 60 * hours);
+    minutes = duration / 60;
+    seconds = duration - (60 * minutes);
+
+    if (days < 2)
+        sprintf (temp, msg_table[219], days);   // %d day
+    else
+        sprintf (temp, msg_table[220], days);   // %d days
+    if (hours < 2)
+        sprintf (temp1, msg_table[221], temp, hours);   // %s %d hour
+    else
+        sprintf (temp1, msg_table[222], temp, hours);   // %s %d hours
+    if (minutes < 2)
+        sprintf (temp, msg_table[223], temp1, minutes); // %s %d minute
+    else
+        sprintf (temp, msg_table[224], temp1, minutes); // %s %d minutes
+    if (seconds < 2)
+        sprintf (temp1, msg_table[225], temp, seconds); // %s and %d second
+    else
+        sprintf (temp1, msg_table[226], temp, seconds); // %s and %d seconds
+
+    return temp1;
+}
+
+/*==========================================
+ * @time/@date/@server_date/@serverdate/@server_time/@servertime: Display the date/time of the server (by [Yor]
+ * Calculation management of GM modification (@day/@night GM commands) is done
+ *------------------------------------------
+ */
+int atcommand_servertime (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    struct TimerData *timer_data;
+    struct TimerData *timer_data2;
+    time_t time_server;         // variable for number of seconds (used with time() function)
+    struct tm *datetime;        // variable for time in structure ->tm_mday, ->tm_sec, ...
+    char temp[256];
+
+    memset (temp, '\0', sizeof (temp));
+
+    time (&time_server);        // get time in seconds since 1/1/1970
+    datetime = gmtime (&time_server);   // convert seconds in structure
+    // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52)
+    strftime (temp, sizeof (temp) - 1, msg_table[230], datetime);   // Server time (normal time): %A, %B %d %Y %X.
+    clif_displaymessage (fd, temp);
+
+    if (battle_config.night_duration == 0 && battle_config.day_duration == 0)
+    {
+        if (night_flag == 0)
+            clif_displaymessage (fd, msg_table[231]);   // Game time: The game is in permanent daylight.
+        else
+            clif_displaymessage (fd, msg_table[232]);   // Game time: The game is in permanent night.
+    }
+    else if (battle_config.night_duration == 0)
+        if (night_flag == 1)
+        {                       // we start with night
+            timer_data = get_timer (day_timer_tid);
+            sprintf (temp, msg_table[233], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in night for %s.
+            clif_displaymessage (fd, temp);
+            clif_displaymessage (fd, msg_table[234]);   // Game time: After, the game will be in permanent daylight.
+        }
+        else
+            clif_displaymessage (fd, msg_table[231]);   // Game time: The game is in permanent daylight.
+    else if (battle_config.day_duration == 0)
+        if (night_flag == 0)
+        {                       // we start with day
+            timer_data = get_timer (night_timer_tid);
+            sprintf (temp, msg_table[235], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in daylight for %s.
+            clif_displaymessage (fd, temp);
+            clif_displaymessage (fd, msg_table[236]);   // Game time: After, the game will be in permanent night.
+        }
+        else
+            clif_displaymessage (fd, msg_table[232]);   // Game time: The game is in permanent night.
+    else
+    {
+        if (night_flag == 0)
+        {
+            timer_data = get_timer (night_timer_tid);
+            timer_data2 = get_timer (day_timer_tid);
+            sprintf (temp, msg_table[235], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in daylight for %s.
+            clif_displaymessage (fd, temp);
+            if (timer_data->tick > timer_data2->tick)
+                sprintf (temp, msg_table[237], txt_time ((timer_data->interval - abs (timer_data->tick - timer_data2->tick)) / 1000));  // Game time: After, the game will be in night for %s.
+            else
+                sprintf (temp, msg_table[237], txt_time (abs (timer_data->tick - timer_data2->tick) / 1000));   // Game time: After, the game will be in night for %s.
+            clif_displaymessage (fd, temp);
+            sprintf (temp, msg_table[238], txt_time (timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
+            clif_displaymessage (fd, temp);
+        }
+        else
+        {
+            timer_data = get_timer (day_timer_tid);
+            timer_data2 = get_timer (night_timer_tid);
+            sprintf (temp, msg_table[233], txt_time ((timer_data->tick - gettick ()) / 1000));  // Game time: The game is actualy in night for %s.
+            clif_displaymessage (fd, temp);
+            if (timer_data->tick > timer_data2->tick)
+                sprintf (temp, msg_table[239], txt_time ((timer_data->interval - abs (timer_data->tick - timer_data2->tick)) / 1000));  // Game time: After, the game will be in daylight for %s.
+            else
+                sprintf (temp, msg_table[239], txt_time (abs (timer_data->tick - timer_data2->tick) / 1000));   // Game time: After, the game will be in daylight for %s.
+            clif_displaymessage (fd, temp);
+            sprintf (temp, msg_table[238], txt_time (timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s.
+            clif_displaymessage (fd, temp);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @chardelitem <item_name_or_ID> <quantity> <player> (by [Yor]
+ * removes <quantity> item from a character
+ * item can be equiped or not.
+ * Inspired from a old command created by RoVeRT
+ *------------------------------------------
+ */
+int atcommand_chardelitem (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    char character[100];
+    char item_name[100];
+    int  i, number = 0, item_id, item_position, count;
+    char output[200];
+    struct item_data *item_data;
+
+    memset (character, '\0', sizeof (character));
+    memset (item_name, '\0', sizeof (item_name));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message
+        || sscanf (message, "%s %d %99[^\n]", item_name, &number,
+                   character) < 3 || number < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter an item name/id, a quantity and a player name (usage: @chardelitem <item_name_or_ID> <quantity> <player>).");
+        return -1;
+    }
+
+    item_id = 0;
+    if ((item_data = itemdb_searchname (item_name)) != NULL ||
+        (item_data = itemdb_exists (atoi (item_name))) != NULL)
+        item_id = item_data->nameid;
+
+    if (item_id > 500)
+    {
+        if ((pl_sd = map_nick2sd (character)) != NULL)
+        {
+            if (pc_isGM (sd) >= pc_isGM (pl_sd))
+            {                   // you can kill only lower or same level
+                item_position = pc_search_inventory (pl_sd, item_id);
+                if (item_position >= 0)
+                {
+                    count = 0;
+                    for (i = 0; i < number && item_position >= 0; i++)
+                    {
+                        pc_delitem (pl_sd, item_position, 1, 0);
+                        count++;
+                        item_position = pc_search_inventory (pl_sd, item_id);   // for next loop
+                    }
+                    sprintf (output, msg_table[113], count);    // %d item(s) removed by a GM.
+                    clif_displaymessage (pl_sd->fd, output);
+                    if (number == count)
+                        sprintf (output, msg_table[114], count);    // %d item(s) removed from the player.
+                    else
+                        sprintf (output, msg_table[115], count, count, number); // %d item(s) removed. Player had only %d on %d items.
+                    clif_displaymessage (fd, output);
+                }
+                else
+                {
+                    clif_displaymessage (fd, msg_table[116]);   // Character does not have the item.
+                    return -1;
+                }
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[3]); // Character not found.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[19]);    // Invalid item ID or name.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @jail <char_name> by [Yor]
+ * Special warp! No check with nowarp and nowarpto flag
+ *------------------------------------------
+ */
+int atcommand_jail (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+    int  x, y;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @jail <char_name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can jail only lower or same GM
+            switch (MRAND (2))
+            {
+                case 0:
+                    x = 24;
+                    y = 75;
+                    break;
+                default:
+                    x = 49;
+                    y = 75;
+                    break;
+            }
+            if (pc_setpos (pl_sd, "sec_pri.gat", x, y, 3) == 0)
+            {
+                pc_setsavepoint (pl_sd, "sec_pri.gat", x, y);   // Save Char Respawn Point in the jail room [Lupus]
+                clif_displaymessage (pl_sd->fd, msg_table[117]);    // GM has send you in jails.
+                clif_displaymessage (fd, msg_table[118]);   // Player warped in jails.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[1]); // Map not found.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @unjail/@discharge <char_name> by [Yor]
+ * Special warp! No check with nowarp and nowarpto flag
+ *------------------------------------------
+ */
+int atcommand_unjail (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @unjail/@discharge <char_name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can jail only lower or same GM
+            if (pl_sd->bl.m != map_mapname2mapid ("sec_pri.gat"))
+            {
+                clif_displaymessage (fd, msg_table[119]);   // This player is not in jails.
+                return -1;
+            }
+            else if (pc_setpos (pl_sd, "prontera.gat", 156, 191, 3) == 0)
+            {
+                pc_setsavepoint (pl_sd, "prontera.gat", 156, 191);  // Save char respawn point in Prontera
+                clif_displaymessage (pl_sd->fd, msg_table[120]);    // GM has discharge you.
+                clif_displaymessage (fd, msg_table[121]);   // Player warped to Prontera.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[1]); // Map not found.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @disguise <mob_id> by [Valaris] (simplified by [Yor])
+ *------------------------------------------
+ */
+int atcommand_disguise (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    int  mob_id;
+
+    if (!message || !*message)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a Monster/NPC name/id (usage: @disguise <monster_name_or_monster_ID>).");
+        return -1;
+    }
+
+    if ((mob_id = mobdb_searchname (message)) == 0) // check name first (to avoid possible name begining by a number)
+        mob_id = atoi (message);
+
+    if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) ||  // NPC
+        (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
+        (mob_id >= 813 && mob_id <= 834) || // NPC
+        (mob_id > 1000 && mob_id < 1521))
+    {                           // monsters
+        if (pc_isriding (sd))
+        {                       // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+            clif_displaymessage (fd, msg_table[227]);   // Cannot wear disguise while riding a Peco.
+            return -1;
+        }
+        sd->disguiseflag = 1;   // set to override items with disguise script [Valaris]
+        sd->disguise = mob_id;
+        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+        clif_displaymessage (fd, msg_table[122]);   // Disguise applied.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[123]);   // Monster/NPC name/id hasn't been found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @undisguise by [Yor]
+ *------------------------------------------
+ */
+int atcommand_undisguise (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    if (sd->disguise)
+    {
+        clif_clearchar (&sd->bl, 9);
+        sd->disguise = 0;
+        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+        clif_displaymessage (fd, msg_table[124]);   // Undisguise applied.
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[125]);   // You're not disguised.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @broadcast by [Valaris]
+ *------------------------------------------
+ */
+int atcommand_broadcast (const int fd, struct map_session_data *sd,
+                         const char *command, const char *message)
+{
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a message (usage: @broadcast <message>).");
+        return -1;
+    }
+
+    snprintf (output, 199, "%s : %s", sd->status.name, message);
+    intif_GMmessage (output, strlen (output) + 1, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * @localbroadcast by [Valaris]
+ *------------------------------------------
+ */
+int atcommand_localbroadcast (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char output[200];
+
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a message (usage: @localbroadcast <message>).");
+        return -1;
+    }
+
+    snprintf (output, 199, "%s : %s", sd->status.name, message);
+
+    clif_GMmessage (&sd->bl, output, strlen (output) + 1, 1);   // 1: ALL_SAMEMAP
+
+    return 0;
+}
+
+/*==========================================
+ * @ignorelist by [Yor]
+ *------------------------------------------
+ */
+int atcommand_ignorelist (const int fd, struct map_session_data *sd,
+                          const char *command, const char *message)
+{
+    char output[200];
+    int  count;
+    int  i;
+
+    memset (output, '\0', sizeof (output));
+
+    count = 0;
+    for (i = 0; i < (int) (sizeof (sd->ignore) / sizeof (sd->ignore[0])); i++)
+        if (sd->ignore[i].name[0])
+            count++;
+
+    if (sd->ignoreAll == 0)
+        if (count == 0)
+            clif_displaymessage (fd, msg_table[126]);   // You accept any wisp (no wisper is refused).
+        else
+        {
+            sprintf (output, msg_table[127], count);    // You accept any wisp, except thoses from %d player(s):
+            clif_displaymessage (fd, output);
+        }
+    else if (count == 0)
+        clif_displaymessage (fd, msg_table[128]);   // You refuse all wisps (no specifical wisper is refused).
+    else
+    {
+        sprintf (output, msg_table[129], count);    // You refuse all wisps, AND refuse wisps from %d player(s):
+        clif_displaymessage (fd, output);
+    }
+
+    if (count > 0)
+        for (i = 0; i < (int) (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
+             i++)
+            if (sd->ignore[i].name[0])
+                clif_displaymessage (fd, sd->ignore[i].name);
+
+    return 0;
+}
+
+/*==========================================
+ * @charignorelist <player_name> by [Yor]
+ *------------------------------------------
+ */
+int atcommand_charignorelist (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+    char output[200];
+    int  count;
+    int  i;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charignorelist <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        count = 0;
+        for (i = 0;
+             i < (int) (sizeof (pl_sd->ignore) / sizeof (pl_sd->ignore[0]));
+             i++)
+            if (pl_sd->ignore[i].name[0])
+                count++;
+
+        if (pl_sd->ignoreAll == 0)
+            if (count == 0)
+            {
+                sprintf (output, msg_table[130], pl_sd->status.name);   // '%s' accept any wisp (no wisper is refused).
+                clif_displaymessage (fd, output);
+            }
+            else
+            {
+                sprintf (output, msg_table[131], pl_sd->status.name, count);    // '%s' accept any wisp, except thoses from %d player(s):
+                clif_displaymessage (fd, output);
+            }
+        else if (count == 0)
+        {
+            sprintf (output, msg_table[132], pl_sd->status.name);   // '%s' refuse all wisps (no specifical wisper is refused).
+            clif_displaymessage (fd, output);
+        }
+        else
+        {
+            sprintf (output, msg_table[133], pl_sd->status.name, count);    // '%s' refuse all wisps, AND refuse wisps from %d player(s):
+            clif_displaymessage (fd, output);
+        }
+
+        if (count > 0)
+            for (i = 0;
+                 i <
+                 (int) (sizeof (pl_sd->ignore) / sizeof (pl_sd->ignore[0]));
+                 i++)
+                if (pl_sd->ignore[i].name[0])
+                    clif_displaymessage (fd, pl_sd->ignore[i].name);
+
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @inall <player_name> by [Yor]
+ *------------------------------------------
+ */
+int atcommand_inall (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @inall <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change wisp option only to lower or same level
+            if (pl_sd->ignoreAll == 0)
+            {
+                sprintf (output, msg_table[134], pl_sd->status.name);   // '%s' already accepts all wispers.
+                clif_displaymessage (fd, output);
+                return -1;
+            }
+            else
+            {
+                pl_sd->ignoreAll = 0;
+                sprintf (output, msg_table[135], pl_sd->status.name);   // '%s' now accepts all wispers.
+                clif_displaymessage (fd, output);
+                // message to player
+                clif_displaymessage (pl_sd->fd, msg_table[136]);    // A GM has authorised all wispers for you.
+                WFIFOW (pl_sd->fd, 0) = 0x0d2;  // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+                WFIFOB (pl_sd->fd, 2) = 1;
+                WFIFOB (pl_sd->fd, 3) = 0;  // success
+                WFIFOSET (pl_sd->fd, 4);    // packet_len_table[0x0d2]
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @exall <player_name> by [Yor]
+ *------------------------------------------
+ */
+int atcommand_exall (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char character[100];
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @exall <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can change wisp option only to lower or same level
+            if (pl_sd->ignoreAll == 1)
+            {
+                sprintf (output, msg_table[137], pl_sd->status.name);   // '%s' already blocks all wispers.
+                clif_displaymessage (fd, output);
+                return -1;
+            }
+            else
+            {
+                pl_sd->ignoreAll = 1;
+                sprintf (output, msg_table[138], pl_sd->status.name);   // '%s' blocks now all wispers.
+                clif_displaymessage (fd, output);
+                // message to player
+                clif_displaymessage (pl_sd->fd, msg_table[139]);    // A GM has blocked all wispers for you.
+                WFIFOW (pl_sd->fd, 0) = 0x0d2;  // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+                WFIFOB (pl_sd->fd, 2) = 0;
+                WFIFOB (pl_sd->fd, 3) = 0;  // success
+                WFIFOSET (pl_sd->fd, 4);    // packet_len_table[0x0d2]
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @chardisguise <mob_id> <character> by Kalaspuff (based off Valaris' and Yor's work)
+ *------------------------------------------
+ */
+int atcommand_chardisguise (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message)
+{
+    int  mob_id;
+    char character[100];
+    char mob_name[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+    memset (mob_name, '\0', sizeof (mob_name));
+
+    if (!message || !*message
+        || sscanf (message, "%s %99[^\n]", mob_name, character) < 2)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a Monster/NPC name/id and a player name (usage: @chardisguise <monster_name_or_monster_ID> <char name>).");
+        return -1;
+    }
+
+    if ((mob_id = mobdb_searchname (mob_name)) == 0)    // check name first (to avoid possible name begining by a number)
+        mob_id = atoi (mob_name);
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can disguise only lower or same level
+            if ((mob_id >= 46 && mob_id <= 125) || (mob_id >= 700 && mob_id <= 718) ||  // NPC
+                (mob_id >= 721 && mob_id <= 755) || (mob_id >= 757 && mob_id <= 811) || // NPC
+                (mob_id >= 813 && mob_id <= 834) || // NPC
+                (mob_id > 1000 && mob_id < 1521))
+            {                   // monsters
+                if (pc_isriding (pl_sd))
+                {               // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+                    clif_displaymessage (fd, msg_table[228]);   // Character cannot wear disguise while riding a Peco.
+                    return -1;
+                }
+                pl_sd->disguiseflag = 1;    // set to override items with disguise script [Valaris]
+                pl_sd->disguise = mob_id;
+                pc_setpos (pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y,
+                           3);
+                clif_displaymessage (fd, msg_table[140]);   // Character's disguise applied.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[123]);   // Monster/NPC name/id hasn't been found.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charundisguise <character> by Kalaspuff (based off Yor's work)
+ *------------------------------------------
+ */
+int atcommand_charundisguise (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charundisguise <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can undisguise only lower or same level
+            if (pl_sd->disguise)
+            {
+                clif_clearchar (&pl_sd->bl, 9);
+                pl_sd->disguise = 0;
+                pc_setpos (pl_sd, pl_sd->mapname, pl_sd->bl.x, pl_sd->bl.y,
+                           3);
+                clif_displaymessage (fd, msg_table[141]);   // Character's undisguise applied.
+            }
+            else
+            {
+                clif_displaymessage (fd, msg_table[142]);   // Character is not disguised.
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @email <actual@email> <new@email> by [Yor]
+ *------------------------------------------
+ */
+int atcommand_email (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char actual_email[100];
+    char new_email[100];
+
+    memset (actual_email, '\0', sizeof (actual_email));
+    memset (new_email, '\0', sizeof (new_email));
+
+    if (!message || !*message
+        || sscanf (message, "%99s %99s", actual_email, new_email) < 2)
+    {
+        clif_displaymessage (fd,
+                             "Please enter 2 emails (usage: @email <actual@email> <new@email>).");
+        return -1;
+    }
+
+    if (e_mail_check (actual_email) == 0)
+    {
+        clif_displaymessage (fd, msg_table[144]);   // Invalid actual email. If you have default e-mail, give a@a.com.
+        return -1;
+    }
+    else if (e_mail_check (new_email) == 0)
+    {
+        clif_displaymessage (fd, msg_table[145]);   // Invalid new email. Please enter a real e-mail.
+        return -1;
+    }
+    else if (strcasecmp (new_email, "a@a.com") == 0)
+    {
+        clif_displaymessage (fd, msg_table[146]);   // New email must be a real e-mail.
+        return -1;
+    }
+    else if (strcasecmp (actual_email, new_email) == 0)
+    {
+        clif_displaymessage (fd, msg_table[147]);   // New email must be different of the actual e-mail.
+        return -1;
+    }
+    else
+    {
+        chrif_changeemail (sd->status.account_id, actual_email, new_email);
+        clif_displaymessage (fd, msg_table[148]);   // Information sended to login-server via char-server.
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *@effect
+ *------------------------------------------
+ */
+int atcommand_effect (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  type = 0, flag = 0, i;
+
+    if (!message || !*message || sscanf (message, "%d %d", &type, &flag) < 2)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter at least a option (usage: @effect <type+>).");
+        return -1;
+    }
+    if (flag <= 0)
+    {
+        clif_specialeffect (&sd->bl, type, flag);
+        clif_displaymessage (fd, msg_table[229]);   // Your effect has changed.
+    }
+    else
+    {
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                clif_specialeffect (&pl_sd->bl, type, flag);
+                clif_displaymessage (pl_sd->fd, msg_table[229]);    // Your effect has changed.
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charitemlist <character>: Displays the list of a player's items.
+ *------------------------------------------
+ */
+int
+atcommand_character_item_list (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    struct item_data *item_data, *item_temp;
+    int  i, j, equip, count, counter, counter2;
+    char character[100], output[200], equipstr[100], outputtmp[200];
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+    memset (equipstr, '\0', sizeof (equipstr));
+    memset (outputtmp, '\0', sizeof (outputtmp));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charitemlist <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can look items only lower or same level
+            counter = 0;
+            count = 0;
+            for (i = 0; i < MAX_INVENTORY; i++)
+            {
+                if (pl_sd->status.inventory[i].nameid > 0
+                    && (item_data =
+                        itemdb_search (pl_sd->status.inventory[i].nameid)) !=
+                    NULL)
+                {
+                    counter = counter + pl_sd->status.inventory[i].amount;
+                    count++;
+                    if (count == 1)
+                    {
+                        sprintf (output, "------ Items list of '%s' ------",
+                                 pl_sd->status.name);
+                        clif_displaymessage (fd, output);
+                    }
+                    if ((equip = pl_sd->status.inventory[i].equip))
+                    {
+                        strcpy (equipstr, "| equiped: ");
+                        if (equip & 4)
+                            strcat (equipstr, "robe/gargment, ");
+                        if (equip & 8)
+                            strcat (equipstr, "left accessory, ");
+                        if (equip & 16)
+                            strcat (equipstr, "body/armor, ");
+                        if ((equip & 34) == 2)
+                            strcat (equipstr, "right hand, ");
+                        if ((equip & 34) == 32)
+                            strcat (equipstr, "left hand, ");
+                        if ((equip & 34) == 34)
+                            strcat (equipstr, "both hands, ");
+                        if (equip & 64)
+                            strcat (equipstr, "feet, ");
+                        if (equip & 128)
+                            strcat (equipstr, "right accessory, ");
+                        if ((equip & 769) == 1)
+                            strcat (equipstr, "lower head, ");
+                        if ((equip & 769) == 256)
+                            strcat (equipstr, "top head, ");
+                        if ((equip & 769) == 257)
+                            strcat (equipstr, "lower/top head, ");
+                        if ((equip & 769) == 512)
+                            strcat (equipstr, "mid head, ");
+                        if ((equip & 769) == 512)
+                            strcat (equipstr, "lower/mid head, ");
+                        if ((equip & 769) == 769)
+                            strcat (equipstr, "lower/mid/top head, ");
+                        // remove final ', '
+                        equipstr[strlen (equipstr) - 2] = '\0';
+                    }
+                    else
+                        memset (equipstr, '\0', sizeof (equipstr));
+                    if (sd->status.inventory[i].refine)
+                        sprintf (output, "%d %s %+d (%s %+d, id: %d) %s",
+                                 pl_sd->status.inventory[i].amount,
+                                 item_data->name,
+                                 pl_sd->status.inventory[i].refine,
+                                 item_data->jname,
+                                 pl_sd->status.inventory[i].refine,
+                                 pl_sd->status.inventory[i].nameid, equipstr);
+                    else
+                        sprintf (output, "%d %s (%s, id: %d) %s",
+                                 pl_sd->status.inventory[i].amount,
+                                 item_data->name, item_data->jname,
+                                 pl_sd->status.inventory[i].nameid, equipstr);
+                    clif_displaymessage (fd, output);
+                    memset (output, '\0', sizeof (output));
+                    counter2 = 0;
+                    for (j = 0; j < item_data->slot; j++)
+                    {
+                        if (pl_sd->status.inventory[i].card[j])
+                        {
+                            if ((item_temp =
+                                 itemdb_search (pl_sd->status.
+                                                inventory[i].card[j])) !=
+                                NULL)
+                            {
+                                if (output[0] == '\0')
+                                    sprintf (outputtmp,
+                                             " -> (card(s): #%d %s (%s), ",
+                                             ++counter2, item_temp->name,
+                                             item_temp->jname);
+                                else
+                                    sprintf (outputtmp, "#%d %s (%s), ",
+                                             ++counter2, item_temp->name,
+                                             item_temp->jname);
+                                strcat (output, outputtmp);
+                            }
+                        }
+                    }
+                    if (output[0] != '\0')
+                    {
+                        output[strlen (output) - 2] = ')';
+                        output[strlen (output) - 1] = '\0';
+                        clif_displaymessage (fd, output);
+                    }
+                }
+            }
+            if (count == 0)
+                clif_displaymessage (fd, "No item found on this player.");
+            else
+            {
+                sprintf (output, "%d item(s) found in %d kind(s) of items.",
+                         counter, count);
+                clif_displaymessage (fd, output);
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charstoragelist <character>: Displays the items list of a player's storage.
+ *------------------------------------------
+ */
+int
+atcommand_character_storage_list (const int fd, struct map_session_data *sd,
+                                  const char *command, const char *message)
+{
+    struct storage *stor;
+    struct map_session_data *pl_sd;
+    struct item_data *item_data, *item_temp;
+    int  i, j, count, counter, counter2;
+    char character[100], output[200], outputtmp[200];
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+    memset (outputtmp, '\0', sizeof (outputtmp));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charitemlist <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can look items only lower or same level
+            if ((stor = account2storage2 (pl_sd->status.account_id)) != NULL)
+            {
+                counter = 0;
+                count = 0;
+                for (i = 0; i < MAX_STORAGE; i++)
+                {
+                    if (stor->storage_[i].nameid > 0
+                        && (item_data =
+                            itemdb_search (stor->storage_[i].nameid)) != NULL)
+                    {
+                        counter = counter + stor->storage_[i].amount;
+                        count++;
+                        if (count == 1)
+                        {
+                            sprintf (output,
+                                     "------ Storage items list of '%s' ------",
+                                     pl_sd->status.name);
+                            clif_displaymessage (fd, output);
+                        }
+                        if (stor->storage_[i].refine)
+                            sprintf (output, "%d %s %+d (%s %+d, id: %d)",
+                                     stor->storage_[i].amount,
+                                     item_data->name,
+                                     stor->storage_[i].refine,
+                                     item_data->jname,
+                                     stor->storage_[i].refine,
+                                     stor->storage_[i].nameid);
+                        else
+                            sprintf (output, "%d %s (%s, id: %d)",
+                                     stor->storage_[i].amount,
+                                     item_data->name, item_data->jname,
+                                     stor->storage_[i].nameid);
+                        clif_displaymessage (fd, output);
+                        memset (output, '\0', sizeof (output));
+                        counter2 = 0;
+                        for (j = 0; j < item_data->slot; j++)
+                        {
+                            if (stor->storage_[i].card[j])
+                            {
+                                if ((item_temp =
+                                     itemdb_search (stor->
+                                                    storage_[i].card[j])) !=
+                                    NULL)
+                                {
+                                    if (output[0] == '\0')
+                                        sprintf (outputtmp,
+                                                 " -> (card(s): #%d %s (%s), ",
+                                                 ++counter2, item_temp->name,
+                                                 item_temp->jname);
+                                    else
+                                        sprintf (outputtmp, "#%d %s (%s), ",
+                                                 ++counter2, item_temp->name,
+                                                 item_temp->jname);
+                                    strcat (output, outputtmp);
+                                }
+                            }
+                        }
+                        if (output[0] != '\0')
+                        {
+                            output[strlen (output) - 2] = ')';
+                            output[strlen (output) - 1] = '\0';
+                            clif_displaymessage (fd, output);
+                        }
+                    }
+                }
+                if (count == 0)
+                    clif_displaymessage (fd,
+                                         "No item found in the storage of this player.");
+                else
+                {
+                    sprintf (output,
+                             "%d item(s) found in %d kind(s) of items.",
+                             counter, count);
+                    clif_displaymessage (fd, output);
+                }
+            }
+            else
+            {
+                clif_displaymessage (fd, "This player has no storage.");
+                return -1;
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @charcartlist <character>: Displays the items list of a player's cart.
+ *------------------------------------------
+ */
+int
+atcommand_character_cart_list (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    struct item_data *item_data, *item_temp;
+    int  i, j, count, counter, counter2;
+    char character[100], output[200], outputtmp[200];
+
+    memset (character, '\0', sizeof (character));
+    memset (output, '\0', sizeof (output));
+    memset (outputtmp, '\0', sizeof (outputtmp));
+
+    if (!message || !*message || sscanf (message, "%99[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Please, enter a player name (usage: @charitemlist <char name>).");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can look items only lower or same level
+            counter = 0;
+            count = 0;
+            for (i = 0; i < MAX_CART; i++)
+            {
+                if (pl_sd->status.cart[i].nameid > 0
+                    && (item_data =
+                        itemdb_search (pl_sd->status.cart[i].nameid)) != NULL)
+                {
+                    counter = counter + pl_sd->status.cart[i].amount;
+                    count++;
+                    if (count == 1)
+                    {
+                        sprintf (output,
+                                 "------ Cart items list of '%s' ------",
+                                 pl_sd->status.name);
+                        clif_displaymessage (fd, output);
+                    }
+                    if (pl_sd->status.cart[i].refine)
+                        sprintf (output, "%d %s %+d (%s %+d, id: %d)",
+                                 pl_sd->status.cart[i].amount,
+                                 item_data->name,
+                                 pl_sd->status.cart[i].refine,
+                                 item_data->jname,
+                                 pl_sd->status.cart[i].refine,
+                                 pl_sd->status.cart[i].nameid);
+                    else
+                        sprintf (output, "%d %s (%s, id: %d)",
+                                 pl_sd->status.cart[i].amount,
+                                 item_data->name, item_data->jname,
+                                 pl_sd->status.cart[i].nameid);
+                    clif_displaymessage (fd, output);
+                    memset (output, '\0', sizeof (output));
+                    counter2 = 0;
+                    for (j = 0; j < item_data->slot; j++)
+                    {
+                        if (pl_sd->status.cart[i].card[j])
+                        {
+                            if ((item_temp =
+                                 itemdb_search (pl_sd->status.
+                                                cart[i].card[j])) != NULL)
+                            {
+                                if (output[0] == '\0')
+                                    sprintf (outputtmp,
+                                             " -> (card(s): #%d %s (%s), ",
+                                             ++counter2, item_temp->name,
+                                             item_temp->jname);
+                                else
+                                    sprintf (outputtmp, "#%d %s (%s), ",
+                                             ++counter2, item_temp->name,
+                                             item_temp->jname);
+                                strcat (output, outputtmp);
+                            }
+                        }
+                    }
+                    if (output[0] != '\0')
+                    {
+                        output[strlen (output) - 2] = ')';
+                        output[strlen (output) - 1] = '\0';
+                        clif_displaymessage (fd, output);
+                    }
+                }
+            }
+            if (count == 0)
+                clif_displaymessage (fd,
+                                     "No item found in the cart of this player.");
+            else
+            {
+                sprintf (output, "%d item(s) found in %d kind(s) of items.",
+                         counter, count);
+                clif_displaymessage (fd, output);
+            }
+        }
+        else
+        {
+            clif_displaymessage (fd, msg_table[81]);    // Your GM level don't authorise you to do this action on this player.
+            return -1;
+        }
+    }
+    else
+    {
+        clif_displaymessage (fd, msg_table[3]); // Character not found.
+        return -1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * @killer by MouseJstr
+ * enable killing players even when not in pvp
+ *------------------------------------------
+ */
+int
+atcommand_killer (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+    sd->special_state.killer = !sd->special_state.killer;
+
+    if (sd->special_state.killer)
+        clif_displaymessage (fd, msg_table[241]);
+    else
+        clif_displaymessage (fd, msg_table[242]);
+
+    return 0;
+}
+
+/*==========================================
+ * @killable by MouseJstr
+ * enable other people killing you
+ *------------------------------------------
+ */
+int
+atcommand_killable (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    sd->special_state.killable = !sd->special_state.killable;
+
+    if (sd->special_state.killable)
+        clif_displaymessage (fd, msg_table[242]);
+    else
+        clif_displaymessage (fd, msg_table[241]);
+
+    return 0;
+}
+
+/*==========================================
+ * @charkillable by MouseJstr
+ * enable another player to be killed
+ *------------------------------------------
+ */
+int
+atcommand_charkillable (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    struct map_session_data *pl_sd = NULL;
+
+    if (!message || !*message)
+        return -1;
+
+    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
+        return -1;
+
+    pl_sd->special_state.killable = !pl_sd->special_state.killable;
+
+    if (pl_sd->special_state.killable)
+        clif_displaymessage (fd, "The player is now killable");
+    else
+        clif_displaymessage (fd, "The player is no longer killable");
+
+    return 0;
+}
+
+/*==========================================
+ * @skillon by MouseJstr
+ * turn skills on for the map
+ *------------------------------------------
+ */
+int
+atcommand_skillon (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    map[sd->bl.m].flag.noskill = 0;
+    clif_displaymessage (fd, msg_table[244]);
+    return 0;
+}
+
+/*==========================================
+ * @skilloff by MouseJstr
+ * Turn skills off on the map
+ *------------------------------------------
+ */
+int
+atcommand_skilloff (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    map[sd->bl.m].flag.noskill = 1;
+    clif_displaymessage (fd, msg_table[243]);
+    return 0;
+}
+
+/*==========================================
+ * @npcmove by MouseJstr
+ *
+ * move a npc
+ *------------------------------------------
+ */
+int
+atcommand_npcmove (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    char character[100];
+    int  x = 0, y = 0;
+    struct npc_data *nd = 0;
+
+    if (sd == NULL)
+        return -1;
+
+    if (!message || !*message)
+        return -1;
+
+    memset (character, '\0', sizeof character);
+
+    if (sscanf (message, "%d %d %99[^\n]", &x, &y, character) < 3)
+        return -1;
+
+    nd = npc_name2id (character);
+    if (nd == NULL)
+        return -1;
+
+    npc_enable (character, 0);
+    nd->bl.x = x;
+    nd->bl.y = y;
+    npc_enable (character, 1);
+
+    return 0;
+}
+
+/*==========================================
+ * @addwarp by MouseJstr
+ *
+ * Create a new static warp point.
+ *------------------------------------------
+ */
+int
+atcommand_addwarp (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    char w1[64], w3[64], w4[64];
+    char map[30], output[200];
+    int  x, y, ret;
+
+    if (!message || !*message)
+        return -1;
+
+    if (sscanf (message, "%99s %d %d[^\n]", map, &x, &y) < 3)
+        return -1;
+
+    sprintf (w1, "%s,%d,%d", sd->mapname, sd->bl.x, sd->bl.y);
+    sprintf (w3, "%s%d%d%d%d", map, sd->bl.x, sd->bl.y, x, y);
+    sprintf (w4, "1,1,%s.gat,%d,%d", map, x, y);
+
+    ret = npc_parse_warp (w1, "warp", w3, w4);
+
+    sprintf (output, "New warp NPC => %s", w3);
+
+    clif_displaymessage (fd, output);
+
+    return ret;
+}
+
+/*==========================================
+ * @follow by [MouseJstr]
+ *
+ * Follow a player .. staying no more then 5 spaces away
+ *------------------------------------------
+ */
+int
+atcommand_follow (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+#if 0
+    struct map_session_data *pl_sd = NULL;
+
+    if (!message || !*message)
+        return -1;
+    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
+        pc_follow (sd, pl_sd->bl.id);
+    else
+        return 1;
+#endif
+
+    /*
+     * Command disabled - it's incompatible with the TMW
+     * client.
+     */
+    clif_displaymessage (fd, "@follow command not available");
+
+    return 0;
+
+}
+
+/*==========================================
+ * @chareffect by [MouseJstr]
+ *
+ * Create a effect localized on another character
+ *------------------------------------------
+ */
+int
+atcommand_chareffect (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    struct map_session_data *pl_sd = NULL;
+    char target[255];
+    int  type = 0;
+
+    if (!message || !*message
+        || sscanf (message, "%d %s", &type, target) != 2)
+    {
+        clif_displaymessage (fd, "usage: @chareffect <type+> <target>.");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd ((char *) target)) == NULL)
+        return -1;
+
+    clif_specialeffect (&pl_sd->bl, type, 0);
+    clif_displaymessage (fd, msg_table[229]);   // Your effect has changed.
+
+    return 0;
+}
+
+/*==========================================
+ * @dropall by [MouseJstr]
+ *
+ * Drop all your possession on the ground
+ *------------------------------------------
+ */
+int
+atcommand_dropall (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    int  i;
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].amount)
+        {
+            if (sd->status.inventory[i].equip != 0)
+                pc_unequipitem (sd, i, 0);
+            pc_dropitem (sd, i, sd->status.inventory[i].amount);
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * @chardropall by [MouseJstr]
+ *
+ * Throw all the characters possessions on the ground.  Normally
+ * done in response to them being disrespectful of a GM
+ *------------------------------------------
+ */
+int
+atcommand_chardropall (const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    int  i;
+    struct map_session_data *pl_sd = NULL;
+
+    if (!message || !*message)
+        return -1;
+    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
+        return -1;
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (pl_sd->status.inventory[i].amount)
+        {
+            if (pl_sd->status.inventory[i].equip != 0)
+                pc_unequipitem (pl_sd, i, 0);
+            pc_dropitem (pl_sd, i, pl_sd->status.inventory[i].amount);
+        }
+    }
+
+    clif_displaymessage (pl_sd->fd, "Ever play 52 card pickup?");
+    clif_displaymessage (fd, "It is done");
+    //clif_displaymessage(fd, "It is offical.. your a jerk");
+
+    return 0;
+}
+
+/*==========================================
+ * @storeall by [MouseJstr]
+ *
+ * Put everything into storage to simplify your inventory to make
+ * debugging easie
+ *------------------------------------------
+ */
+int
+atcommand_storeall (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  i;
+    nullpo_retr (-1, sd);
+
+    if (sd->state.storage_flag != 1)
+    {                           //Open storage.
+        switch (storage_storageopen (sd))
+        {
+            case 2:            //Try again
+                clif_displaymessage (fd, "run this command again..");
+                return 0;
+            case 1:            //Failure
+                clif_displaymessage (fd,
+                                     "You can't open the storage currently.");
+                return 1;
+        }
+    }
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].amount)
+        {
+            if (sd->status.inventory[i].equip != 0)
+                pc_unequipitem (sd, i, 0);
+            storage_storageadd (sd, i, sd->status.inventory[i].amount);
+        }
+    }
+    storage_storageclose (sd);
+
+    clif_displaymessage (fd, "It is done");
+    return 0;
+}
+
+/*==========================================
+ * @charstoreall by [MouseJstr]
+ *
+ * A way to screw with players who piss you off
+ *------------------------------------------
+ */
+int
+atcommand_charstoreall (const int fd, struct map_session_data *sd,
+                        const char *command, const char *message)
+{
+    int  i;
+    struct map_session_data *pl_sd = NULL;
+
+    if (!message || !*message)
+        return -1;
+    if ((pl_sd = map_nick2sd ((char *) message)) == NULL)
+        return -1;
+
+    if (storage_storageopen (pl_sd) == 1)
+    {
+        clif_displaymessage (fd,
+                             "Had to open the characters storage window...");
+        clif_displaymessage (fd, "run this command again..");
+        return 0;
+    }
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (pl_sd->status.inventory[i].amount)
+        {
+            if (pl_sd->status.inventory[i].equip != 0)
+                pc_unequipitem (pl_sd, i, 0);
+            storage_storageadd (pl_sd, i, sd->status.inventory[i].amount);
+        }
+    }
+    storage_storageclose (pl_sd);
+
+    clif_displaymessage (pl_sd->fd,
+                         "Everything you own has been put away for safe keeping.");
+    clif_displaymessage (pl_sd->fd,
+                         "go to the nearest kafka to retrieve it..");
+    clif_displaymessage (pl_sd->fd, "   -- the management");
+
+    clif_displaymessage (fd, "It is done");
+
+    return 0;
+}
+
+/*==========================================
+ * @skillid by [MouseJstr]
+ *
+ * lookup a skill by name
+ *------------------------------------------
+ */
+int
+atcommand_skillid (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    int  skillen = 0, idx = 0;
+    if (!message || !*message)
+        return -1;
+    skillen = strlen (message);
+    while (skill_names[idx].id != 0)
+    {
+        if ((strncasecmp (skill_names[idx].name, message, skillen) == 0) ||
+            (strncasecmp (skill_names[idx].desc, message, skillen) == 0))
+        {
+            char output[255];
+            sprintf (output, "skill %d: %s", skill_names[idx].id,
+                     skill_names[idx].desc);
+            clif_displaymessage (fd, output);
+        }
+        idx++;
+    }
+    return 0;
+}
+
+/*==========================================
+ * @useskill by [MouseJstr]
+ *
+ * A way of using skills without having to find them in the skills menu
+ *------------------------------------------
+ */
+int
+atcommand_useskill (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    struct map_session_data *pl_sd = NULL;
+    int  skillnum;
+    int  skilllv;
+    int  inf;
+    char target[255];
+
+    if (!message || !*message)
+        return -1;
+    if (sscanf (message, "%d %d %s", &skillnum, &skilllv, target) != 3)
+    {
+        clif_displaymessage (fd,
+                             "Usage: @useskill <skillnum> <skillv> <target>");
+        return -1;
+    }
+    if ((pl_sd = map_nick2sd (target)) == NULL)
+    {
+        return -1;
+    }
+
+    inf = skill_get_inf (skillnum);
+
+    if ((inf == 2) || (inf == 1))
+        skill_use_pos (sd, pl_sd->bl.x, pl_sd->bl.y, skillnum, skilllv);
+    else
+        skill_use_id (sd, pl_sd->bl.id, skillnum, skilllv);
+
+    return 0;
+}
+
+/*==========================================
+ * It is made to rain.
+ *------------------------------------------
+ */
+int
+atcommand_rain (const int fd, struct map_session_data *sd,
+                const char *command, const char *message)
+{
+    int  effno = 0;
+    effno = 161;
+    nullpo_retr (-1, sd);
+    if (effno < 0 || map[sd->bl.m].flag.rain)
+        return -1;
+
+    map[sd->bl.m].flag.rain = 1;
+    clif_specialeffect (&sd->bl, effno, 2);
+    return 0;
+}
+
+/*==========================================
+ * It is made to snow.
+ *------------------------------------------
+ */
+int
+atcommand_snow (const int fd, struct map_session_data *sd,
+                const char *command, const char *message)
+{
+    int  effno = 0;
+    effno = 162;
+    nullpo_retr (-1, sd);
+    if (effno < 0 || map[sd->bl.m].flag.snow)
+        return -1;
+
+    map[sd->bl.m].flag.snow = 1;
+    clif_specialeffect (&sd->bl, effno, 2);
+    return 0;
+}
+
+/*==========================================
+ * Cherry tree snowstorm is made to fall. (Sakura)
+ *------------------------------------------
+ */
+int
+atcommand_sakura (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+    int  effno = 0;
+    effno = 163;
+    nullpo_retr (-1, sd);
+    if (effno < 0 || map[sd->bl.m].flag.sakura)
+        return -1;
+
+    map[sd->bl.m].flag.sakura = 1;
+    clif_specialeffect (&sd->bl, effno, 2);
+    return 0;
+}
+
+/*==========================================
+ * Fog hangs over.
+ *------------------------------------------
+ */
+int
+atcommand_fog (const int fd, struct map_session_data *sd,
+               const char *command, const char *message)
+{
+    int  effno = 0;
+    effno = 233;
+    nullpo_retr (-1, sd);
+    if (effno < 0 || map[sd->bl.m].flag.fog)
+        return -1;
+
+    map[sd->bl.m].flag.fog = 1;
+    clif_specialeffect (&sd->bl, effno, 2);
+
+    return 0;
+}
+
+/*==========================================
+ * Fallen leaves fall.
+ *------------------------------------------
+ */
+int
+atcommand_leaves (const int fd, struct map_session_data *sd,
+                  const char *command, const char *message)
+{
+    int  effno = 0;
+    effno = 333;
+    nullpo_retr (-1, sd);
+    if (effno < 0 || map[sd->bl.m].flag.leaves)
+        return -1;
+
+    map[sd->bl.m].flag.leaves = 1;
+    clif_specialeffect (&sd->bl, effno, 2);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int atcommand_summon (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char name[100];
+    int  mob_id = 0;
+    int  x = 0;
+    int  y = 0;
+    int  id = 0;
+    struct mob_data *md;
+    unsigned int tick = gettick ();
+
+    nullpo_retr (-1, sd);
+
+    if (!message || !*message)
+        return -1;
+    if (sscanf (message, "%99s", name) < 1)
+        return -1;
+
+    if ((mob_id = atoi (name)) == 0)
+        mob_id = mobdb_searchname (name);
+    if (mob_id == 0)
+        return -1;
+
+    x = sd->bl.x + (MRAND (10) - 5);
+    y = sd->bl.y + (MRAND (10) - 5);
+
+    id = mob_once_spawn (sd, "this", x, y, "--ja--", mob_id, 1, "");
+    if ((md = (struct mob_data *) map_id2bl (id)))
+    {
+        md->master_id = sd->bl.id;
+        md->state.special_mob_ai = 1;
+        md->mode = mob_db[md->mob_class].mode | 0x04;
+        md->deletetimer = add_timer (tick + 60000, mob_timer_delete, id, 0);
+        clif_misceffect (&md->bl, 344);
+    }
+    clif_skill_poseffect (&sd->bl, AM_CALLHOMUN, 1, x, y, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * @adjcmdlvl by [MouseJstr]
+ *
+ * Temp adjust the GM level required to use a GM command
+ *
+ * Used during beta testing to allow players to use GM commands
+ * for short periods of time
+ *------------------------------------------
+ */
+int
+atcommand_adjcmdlvl (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    int  i, newlev;
+    char cmd[100];
+
+    if (!message || !*message || sscanf (message, "%d %s", &newlev, cmd) != 2)
+    {
+        clif_displaymessage (fd, "usage: @adjcmdlvl <lvl> <command>.");
+        return -1;
+    }
+
+    for (i = 0; atcommand_info[i].type != AtCommand_None; i++)
+        if (strcasecmp (cmd, atcommand_info[i].command + 1) == 0)
+        {
+            atcommand_info[i].level = newlev;
+            clif_displaymessage (fd, "@command level changed.");
+            return 0;
+        }
+
+    clif_displaymessage (fd, "@command not found.");
+    return -1;
+}
+
+/*==========================================
+ * @adjgmlvl by [MouseJstr]
+ *
+ * Create a temp GM
+ *
+ * Used during beta testing to allow players to use GM commands
+ * for short periods of time
+ *------------------------------------------
+ */
+int
+atcommand_adjgmlvl (const int fd, struct map_session_data *sd,
+                    const char *command, const char *message)
+{
+    int  newlev;
+    char user[100];
+    struct map_session_data *pl_sd;
+
+    if (!message || !*message
+        || sscanf (message, "%d %s", &newlev, user) != 2)
+    {
+        clif_displaymessage (fd, "usage: @adjgmlvl <lvl> <user>.");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd ((char *) user)) == NULL)
+        return -1;
+
+    pc_set_gm_level (pl_sd->status.account_id, newlev);
+
+    return 0;
+}
+
+/*==========================================
+ * @trade by [MouseJstr]
+ *
+ * Open a trade window with a remote player
+ *
+ * If I have to jump to a remote player one more time, I am
+ * gonna scream!
+ *------------------------------------------
+ */
+int
+atcommand_trade (const int fd, struct map_session_data *sd,
+                 const char *command, const char *message)
+{
+    struct map_session_data *pl_sd = NULL;
+
+    if (!message || !*message)
+        return -1;
+    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
+    {
+        trade_traderequest (sd, pl_sd->bl.id);
+        return 0;
+    }
+    return -1;
+}
+
+/*===========================
+ * @unmute [Valaris]
+ *===========================
+*/
+int atcommand_unmute (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    struct map_session_data *pl_sd = NULL;
+    if (!message || !*message)
+        return -1;
+
+    if ((pl_sd = map_nick2sd ((char *) message)) != NULL)
+    {
+        if (pl_sd->sc_data[SC_NOCHAT].timer != -1)
+        {
+            skill_status_change_end (&pl_sd->bl, SC_NOCHAT, -1);
+            clif_displaymessage (sd->fd, "Player unmuted");
+        }
+        else
+            clif_displaymessage (sd->fd, "Player is not muted");
+    }
+
+    return 0;
+}
+
+/* Magic atcommands by Fate */
+
+static int magic_base = TMW_MAGIC;
+#define magic_skills_nr 6
+static char *magic_skill_names[magic_skills_nr] =
+    { "magic", "life", "war", "transmute", "nature", "astral" };
+
+int
+atcommand_magic_info (const int fd, struct map_session_data *sd,
+                      const char *command, const char *message)
+{
+    char character[100];
+    char buf[200];
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message || sscanf (message, "%99s", character) < 1)
+    {
+        clif_displaymessage (fd, "Usage: @magicinfo <char_name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        int  i;
+
+        sprintf (buf, "`%s' has the following magic skills:", character);
+        clif_displaymessage (fd, buf);
+
+        for (i = 0; i < magic_skills_nr; i++)
+        {
+            sprintf (buf, "%d in %s", pl_sd->status.skill[i + magic_base].lv,
+                     magic_skill_names[i]);
+            if (pl_sd->status.skill[i + magic_base].id == i + magic_base)
+                clif_displaymessage (fd, buf);
+        }
+
+        return 0;
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return -1;
+}
+
+static void set_skill (struct map_session_data *sd, int i, int level)
+{
+    sd->status.skill[i].id = level ? i : 0;
+    sd->status.skill[i].lv = level;
+}
+
+int
+atcommand_set_magic (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    char character[100];
+    char magic_type[20];
+    int  skill_index = -1;      // 0: all
+    int  value;
+    struct map_session_data *pl_sd;
+
+    memset (character, '\0', sizeof (character));
+
+    if (!message || !*message
+        || sscanf (message, "%19s %i %99s", magic_type, &value,
+                   character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'.");
+        return -1;
+    }
+
+    if (!strcasecmp ("all", magic_type))
+        skill_index = 0;
+    else
+    {
+        int  i;
+        for (i = 0; i < magic_skills_nr; i++)
+        {
+            if (!strcasecmp (magic_skill_names[i], magic_type))
+            {
+                skill_index = i + magic_base;
+                break;
+            }
+        }
+    }
+
+    if (skill_index == -1)
+    {
+        clif_displaymessage (fd,
+                             "Incorrect school of magic.  Use `magic', `nature', `life', `war', `transmute', `ether', or `all'.");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        int  i;
+        if (skill_index == 0)
+            for (i = 0; i < magic_skills_nr; i++)
+                set_skill (pl_sd, i + magic_base, value);
+        else
+            set_skill (pl_sd, skill_index, value);
+
+        clif_skillinfoblock (pl_sd);
+        return 0;
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return -1;
+}
+
+int
+atcommand_log (const int fd, struct map_session_data *sd,
+               const char *command, const char *message)
+{
+    return 0;                   // only used for (implicit) logging
+}
+
+int
+atcommand_tee (const int fd, struct map_session_data *sd,
+               const char *command, const char *message)
+{
+    char *data = (char *)malloc (strlen (message) + 28);
+    strcpy (data, sd->status.name);
+    strcat (data, " : ");
+    strcat (data, message);
+    clif_message (&sd->bl, data);
+    return 0;
+}
+
+int
+atcommand_invisible (const int fd, struct map_session_data *sd,
+                     const char *command, const char *message)
+{
+    pc_invisibility (sd, 1);
+    return 0;
+}
+
+int
+atcommand_visible (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    pc_invisibility (sd, 0);
+    return 0;
+}
+
+int atcommand_jump_iterate (const int fd, struct map_session_data *sd,
+                            const char *command, const char *message,
+                            struct map_session_data *(*get_start) (void),
+                            struct map_session_data *(*get_next) (struct
+                                                                  map_session_data
+                                                                  * current))
+{
+    char output[200];
+    struct map_session_data *pl_sd;
+
+    memset (output, '\0', sizeof (output));
+
+    pl_sd = (struct map_session_data *) map_id2bl (sd->followtarget);
+
+    if (pl_sd)
+        pl_sd = get_next (pl_sd);
+
+    if (!pl_sd)
+        pl_sd = get_start ();
+
+    if (pl_sd == sd)
+    {
+        pl_sd = get_next (pl_sd);
+        if (!pl_sd)
+            pl_sd = get_start ();
+    }
+
+    if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp you to the map of this player.");
+        return -1;
+    }
+    if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp
+        && battle_config.any_warp_GM_min_level > pc_isGM (sd))
+    {
+        clif_displaymessage (fd,
+                             "You are not authorised to warp you from your actual map.");
+        return -1;
+    }
+    pc_setpos (sd, map[pl_sd->bl.m].name, pl_sd->bl.x, pl_sd->bl.y, 3);
+    sprintf (output, msg_table[4], pl_sd->status.name); // Jump to %s
+    clif_displaymessage (fd, output);
+
+    sd->followtarget = pl_sd->bl.id;
+
+    return 0;
+}
+
+int
+atcommand_iterate_forward_over_players (const int fd,
+                                        struct map_session_data *sd,
+                                        const char *command,
+                                        const char *message)
+{
+    return atcommand_jump_iterate (fd, sd, command, message,
+                                   map_get_first_session,
+                                   map_get_next_session);
+}
+
+int
+atcommand_iterate_backwards_over_players (const int fd,
+                                          struct map_session_data *sd,
+                                          const char *command,
+                                          const char *message)
+{
+    return atcommand_jump_iterate (fd, sd, command, message,
+                                   map_get_last_session,
+                                   map_get_prev_session);
+}
+
+int atcommand_wgm (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    if (tmw_CheckChatSpam(sd, message))
+        return 0;
+    tmw_GmHackMsg ("%s: %s", sd->status.name, message);
+    if (!pc_isGM (sd))
+        clif_displaymessage (fd, "Message sent.");
+
+    return 0;
+}
+
+
+int atcommand_skillpool_info (const int fd, struct map_session_data *sd,
+                              const char *command, const char *message)
+{
+    char character[100];
+    struct map_session_data *pl_sd;
+
+    if (!message || !*message || sscanf (message, "%99s", character) < 1)
+    {
+        clif_displaymessage (fd, "Usage: @sp-info <char_name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        char buf[200];
+        int  pool_skills[MAX_SKILL_POOL];
+        int  pool_skills_nr = skill_pool (pl_sd, pool_skills);
+        int  i;
+
+        sprintf (buf, "Active skills %d out of %d for %s:", pool_skills_nr,
+                 skill_pool_max (pl_sd), character);
+        clif_displaymessage (fd, buf);
+        for (i = 0; i < pool_skills_nr; ++i)
+        {
+            sprintf (buf, " - %s [%d]: power %d", skill_name (pool_skills[i]),
+                     pool_skills[i], skill_power (pl_sd, pool_skills[i]));
+            clif_displaymessage (fd, buf);
+        }
+
+        sprintf (buf, "Learned skills out of %d for %s:",
+                 skill_pool_skills_size, character);
+        clif_displaymessage (fd, buf);
+
+        for (i = 0; i < skill_pool_skills_size; ++i)
+        {
+            char *name = skill_name (skill_pool_skills[i]);
+            int  lvl = pl_sd->status.skill[skill_pool_skills[i]].lv;
+
+            if (lvl)
+            {
+                sprintf (buf, " - %s [%d]: lvl %d", name,
+                         skill_pool_skills[i], lvl);
+                clif_displaymessage (fd, buf);
+            }
+        }
+
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return 0;
+}
+
+int atcommand_skillpool_focus (const int fd, struct map_session_data *sd,
+                               const char *command, const char *message)
+{
+    char character[100];
+    int  skill;
+    struct map_session_data *pl_sd;
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &skill, character) < 1)
+    {
+        clif_displaymessage (fd, "Usage: @sp-focus <skill-nr> <char_name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (skill_pool_activate (pl_sd, skill))
+            clif_displaymessage (fd, "Activation failed.");
+        else
+            clif_displaymessage (fd, "Activation successful.");
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return 0;
+}
+
+int atcommand_skillpool_unfocus (const int fd, struct map_session_data *sd,
+                                 const char *command, const char *message)
+{
+    char character[100];
+    int  skill;
+    struct map_session_data *pl_sd;
+
+    if (!message || !*message
+        || sscanf (message, "%d %99[^\n]", &skill, character) < 1)
+    {
+        clif_displaymessage (fd, "Usage: @sp-unfocus <skill-nr> <char_name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        if (skill_pool_deactivate (pl_sd, skill))
+            clif_displaymessage (fd, "Deactivation failed.");
+        else
+            clif_displaymessage (fd, "Deactivation successful.");
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return 0;
+}
+
+int atcommand_skill_learn (const int fd, struct map_session_data *sd,
+                           const char *command, const char *message)
+{
+    char character[100];
+    int  skill, level;
+    struct map_session_data *pl_sd;
+
+    if (!message || !*message
+        || sscanf (message, "%d %d %99[^\n]", &skill, &level, character) < 1)
+    {
+        clif_displaymessage (fd,
+                             "Usage: @skill-learn <skill-nr> <level> <char_name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) != NULL)
+    {
+        set_skill (pl_sd, skill, level);
+        clif_skillinfoblock (pl_sd);
+    }
+    else
+        clif_displaymessage (fd, "Character not found.");
+
+    return 0;
+}
+
+int atcommand_ipcheck (const int fd, struct map_session_data *sd,
+                   const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    struct sockaddr_in sai;
+    char output[200];
+    char character[25];
+    int i;
+    socklen_t sa_len = sizeof (struct sockaddr);
+    unsigned long ip;
+
+    memset(character, '\0', sizeof(character));
+
+    if (sscanf (message, "%24[^\n]", character) < 1)
+    {
+        clif_displaymessage (fd, "Usage: @ipcheck <char name>");
+        return -1;
+    }
+
+    if ((pl_sd = map_nick2sd (character)) == NULL)
+    {
+        clif_displaymessage (fd, "Character not found.");
+        return -1;
+    }
+
+    if (getpeername (pl_sd->fd, (struct sockaddr *)&sai, &sa_len))
+    {
+        clif_displaymessage (fd,
+                             "Guru Meditation Error: getpeername() failed");
+        return -1;
+    }
+
+    ip = sai.sin_addr.s_addr;
+
+    // We now have the IP address of a character.
+    // Loop over all logged in sessions looking for matches.
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            if (getpeername (pl_sd->fd, (struct sockaddr *)&sai, &sa_len))
+                continue;
+
+            // Is checking GM levels really needed here?
+            if (ip == sai.sin_addr.s_addr)
+            {
+                snprintf (output, sizeof(output),
+                         "Name: %s | Location: %s %d %d",
+                         pl_sd->status.name, pl_sd->mapname,
+                         pl_sd->bl.x, pl_sd->bl.y);
+                clif_displaymessage (fd, output);
+            }
+        }
+    }
+
+    clif_displaymessage (fd, "End of list");
+    return 0;
+}
+
+int atcommand_doomspot(const int fd, struct map_session_data *sd,
+                       const char *command, const char *message)
+{
+    struct map_session_data *pl_sd;
+    int  i;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth && i != fd && sd->bl.m == pl_sd->bl.m
+            && sd->bl.x == pl_sd->bl.x && sd->bl.y == pl_sd->bl.y
+            && pc_isGM (sd) >= pc_isGM (pl_sd))
+        {                       // you can doom only lower or same gm level
+            pc_damage (NULL, pl_sd, pl_sd->status.hp + 1);
+            clif_displaymessage (pl_sd->fd, msg_table[61]); // The holy messenger has given judgement.
+        }
+    }
+    clif_displaymessage (fd, msg_table[62]);    // Judgement was made.
+
+    return 0;
+}
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
deleted file mode 100644
index 0b141cb..0000000
--- a/src/map/atcommand.h
+++ /dev/null
@@ -1,226 +0,0 @@
-// $Id: atcommand.h 148 2004-09-30 14:05:37Z MouseJstr $
-#ifndef _ATCOMMAND_H_
-#define _ATCOMMAND_H_
-
-#include "map.h"
-
-enum AtCommandType
-{
-    AtCommand_None = -1,
-    AtCommand_Broadcast = 0,
-    AtCommand_Setup,
-    AtCommand_LocalBroadcast,
-    AtCommand_MapMove,
-    AtCommand_ResetState,
-    AtCommand_CharWarp,
-    AtCommand_Warp,
-    AtCommand_Where,
-    AtCommand_Goto,
-    AtCommand_Jump,
-    AtCommand_Who,
-    AtCommand_WhoGroup,
-    AtCommand_WhoMap,
-    AtCommand_WhoMapGroup,
-    AtCommand_WhoGM,
-    AtCommand_Save,
-    AtCommand_Load,
-    AtCommand_Speed,
-    AtCommand_Storage,
-    AtCommand_GuildStorage,
-    AtCommand_Option,
-    AtCommand_Hide,
-    AtCommand_Die,
-    AtCommand_Kill,
-    AtCommand_Alive,
-    AtCommand_Kami,
-    AtCommand_KamiB,
-    AtCommand_Heal,
-    AtCommand_Item,
-    AtCommand_ItemReset,
-    AtCommand_ItemCheck,
-    AtCommand_BaseLevelUp,
-    AtCommand_JobLevelUp,
-    AtCommand_Help,
-    AtCommand_GM,
-    AtCommand_PvPOff,
-    AtCommand_PvPOn,
-    AtCommand_GvGOff,
-    AtCommand_GvGOn,
-    AtCommand_Model,
-    AtCommand_Go,
-    AtCommand_Spawn,
-    AtCommand_Monster,
-    AtCommand_KillMonster,
-    AtCommand_KillMonster2,
-    AtCommand_Produce,
-    AtCommand_Memo,
-    AtCommand_GAT,
-    AtCommand_Packet,
-    AtCommand_StatusPoint,
-    AtCommand_SkillPoint,
-    AtCommand_Zeny,
-    AtCommand_Param,
-    AtCommand_Strength,
-    AtCommand_Agility,
-    AtCommand_Vitality,
-    AtCommand_Intelligence,
-    AtCommand_Dexterity,
-    AtCommand_Luck,
-    AtCommand_GuildLevelUp,
-    AtCommand_Recall,
-    AtCommand_Revive,
-    AtCommand_CharacterStats,
-    AtCommand_CharacterStatsAll,
-    AtCommand_CharacterOption,
-    AtCommand_CharacterSave,
-    AtCommand_CharacterLoad,
-    AtCommand_Night,
-    AtCommand_Day,
-    AtCommand_Doom,
-    AtCommand_DoomMap,
-    AtCommand_Raise,
-    AtCommand_RaiseMap,
-    AtCommand_CharacterBaseLevel,
-    AtCommand_CharacterJobLevel,
-    AtCommand_Kick,
-    AtCommand_KickAll,
-    AtCommand_AllSkills,
-    AtCommand_QuestSkill,
-    AtCommand_CharQuestSkill,
-    AtCommand_LostSkill,
-    AtCommand_CharLostSkill,
-    AtCommand_Party,
-    AtCommand_Guild,
-    AtCommand_AgitStart,
-    AtCommand_AgitEnd,
-    AtCommand_MapExit,
-    AtCommand_IDSearch,
-    AtCommand_CharSkReset,
-    AtCommand_CharStReset,
-    AtCommand_CharReset,
-    //by chbrules
-    AtCommand_CharModel,
-    AtCommand_CharSKPoint,
-    AtCommand_CharSTPoint,
-    AtCommand_CharZeny,
-    AtCommand_RecallAll,
-    AtCommand_ReloadItemDB,
-    AtCommand_ReloadMobDB,
-    AtCommand_ReloadSkillDB,
-    AtCommand_ReloadScript,
-    AtCommand_ReloadGMDB,
-    AtCommand_MapInfo,
-    AtCommand_Dye,
-    AtCommand_HairStyle,
-    AtCommand_HairColor,
-    AtCommand_AllStats,
-    AtCommand_CharChangeSex,    // by Yor
-    AtCommand_CharBlock,        // by Yor
-    AtCommand_CharBan,          // by Yor
-    AtCommand_CharUnBlock,      // by Yor
-    AtCommand_CharUnBan,        // by Yor
-    AtCommand_MountPeco,        // by Valaris
-    AtCommand_CharMountPeco,    // by Yor
-    AtCommand_GuildSpy,         // [Syrus22]
-    AtCommand_PartySpy,         // [Syrus22]
-    AtCommand_GuildRecall,      // by Yor
-    AtCommand_PartyRecall,      // by Yor
-    AtCommand_Enablenpc,
-    AtCommand_Disablenpc,
-    AtCommand_ServerTime,       // by Yor
-    AtCommand_CharDelItem,      // by Yor
-    AtCommand_Jail,             // by Yor
-    AtCommand_UnJail,           // by Yor
-    AtCommand_Disguise,         // [Valaris]
-    AtCommand_UnDisguise,       // by Yor
-    AtCommand_IgnoreList,       // by Yor
-    AtCommand_CharIgnoreList,   // by Yor
-    AtCommand_InAll,            // by Yor
-    AtCommand_ExAll,            // by Yor
-    AtCommand_CharDisguise,     // Kalaspuff
-    AtCommand_CharUnDisguise,   // Kalaspuff
-    AtCommand_EMail,            // by Yor
-    AtCommand_Hatch,
-    AtCommand_Effect,           // by Apple
-    AtCommand_Char_Item_List,   // by Yor
-    AtCommand_Char_Storage_List,    // by Yor
-    AtCommand_Char_Cart_List,   // by Yor
-    AtCommand_AddWarp,          // by MouseJstr
-    AtCommand_Follow,           // by MouseJstr
-    AtCommand_SkillOn,          // by MouseJstr
-    AtCommand_SkillOff,         // by MouseJstr
-    AtCommand_Killer,           // by MouseJstr
-    AtCommand_NpcMove,          // by MouseJstr
-    AtCommand_Killable,         // by MouseJstr
-    AtCommand_CharKillable,     // by MouseJstr
-    AtCommand_Chareffect,       // by MouseJstr
-    AtCommand_Chardye,          // by MouseJstr
-    AtCommand_Charhairstyle,    // by MouseJstr
-    AtCommand_Charhaircolor,    // by MouseJstr
-    AtCommand_Dropall,          // by MouseJstr
-    AtCommand_Chardropall,      // by MouseJstr
-    AtCommand_Storeall,         // by MouseJstr
-    AtCommand_Charstoreall,     // by MouseJstr
-    AtCommand_Skillid,          // by MouseJstr
-    AtCommand_Useskill,         // by MouseJstr
-    AtCommand_Summon,
-    AtCommand_Rain,
-    AtCommand_Snow,
-    AtCommand_Sakura,
-    AtCommand_Fog,
-    AtCommand_Leaves,
-    AtCommand_AdjGmLvl,
-    AtCommand_AdjCmdLvl,
-    AtCommand_Trade,
-    AtCommand_UnMute,
-    AtCommand_CharWipe,
-    AtCommand_SetMagic,
-    AtCommand_MagicInfo,
-    AtCommand_Log,
-    AtCommand_Tee,
-    AtCommand_Invisible,
-    AtCommand_Visible,
-    AtCommand_IterateForward,
-    AtCommand_IterateBackward,
-    AtCommand_Wgm,
-    AtCommand_IpCheck,
-    AtCommand_ListNearby,       // [fate]
-    AtCommand_DoomSpot,
-    // end
-    AtCommand_Unknown,
-    AtCommand_MAX
-};
-
-typedef enum AtCommandType AtCommandType;
-
-typedef struct AtCommandInfo
-{
-    AtCommandType type;
-    const char *command;
-    int  level;
-    int  (*proc) (const int, struct map_session_data *,
-                  const char *command, const char *message);
-} AtCommandInfo;
-
-AtCommandType is_atcommand (const int fd, struct map_session_data *sd,
-                            const char *message, int gmlvl);
-
-AtCommandType atcommand (const int level, const char *message,
-                         AtCommandInfo * info);
-int  get_atcommand_level (const AtCommandType type);
-
-char *msg_txt (int msg_number); // [Yor]
-
-int  atcommand_item (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Valaris]
-int  atcommand_warp (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Yor]
-int  atcommand_spawn (const int fd, struct map_session_data *sd, const char *command, const char *message); // [Valaris]
-int  atcommand_goto (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Yor]
-int  atcommand_recall (const int fd, struct map_session_data *sd, const char *command, const char *message);    // [Yor]
-
-int  atcommand_config_read (const char *cfgName);
-int  msg_config_read (const char *cfgName);
-
-void log_atcommand (struct map_session_data *sd, const char *fmt, ...);
-void gm_log (const char *fmt, ...);
-
-#endif
diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp
new file mode 100644
index 0000000..824a7cf
--- /dev/null
+++ b/src/map/atcommand.hpp
@@ -0,0 +1,226 @@
+// $Id: atcommand.h 148 2004-09-30 14:05:37Z MouseJstr $
+#ifndef ATCOMMAND_HPP
+#define ATCOMMAND_HPP
+
+#include "map.hpp"
+
+enum AtCommandType
+{
+    AtCommand_None = -1,
+    AtCommand_Broadcast = 0,
+    AtCommand_Setup,
+    AtCommand_LocalBroadcast,
+    AtCommand_MapMove,
+    AtCommand_ResetState,
+    AtCommand_CharWarp,
+    AtCommand_Warp,
+    AtCommand_Where,
+    AtCommand_Goto,
+    AtCommand_Jump,
+    AtCommand_Who,
+    AtCommand_WhoGroup,
+    AtCommand_WhoMap,
+    AtCommand_WhoMapGroup,
+    AtCommand_WhoGM,
+    AtCommand_Save,
+    AtCommand_Load,
+    AtCommand_Speed,
+    AtCommand_Storage,
+    AtCommand_GuildStorage,
+    AtCommand_Option,
+    AtCommand_Hide,
+    AtCommand_Die,
+    AtCommand_Kill,
+    AtCommand_Alive,
+    AtCommand_Kami,
+    AtCommand_KamiB,
+    AtCommand_Heal,
+    AtCommand_Item,
+    AtCommand_ItemReset,
+    AtCommand_ItemCheck,
+    AtCommand_BaseLevelUp,
+    AtCommand_JobLevelUp,
+    AtCommand_Help,
+    AtCommand_GM,
+    AtCommand_PvPOff,
+    AtCommand_PvPOn,
+    AtCommand_GvGOff,
+    AtCommand_GvGOn,
+    AtCommand_Model,
+    AtCommand_Go,
+    AtCommand_Spawn,
+    AtCommand_Monster,
+    AtCommand_KillMonster,
+    AtCommand_KillMonster2,
+    AtCommand_Produce,
+    AtCommand_Memo,
+    AtCommand_GAT,
+    AtCommand_Packet,
+    AtCommand_StatusPoint,
+    AtCommand_SkillPoint,
+    AtCommand_Zeny,
+    AtCommand_Param,
+    AtCommand_Strength,
+    AtCommand_Agility,
+    AtCommand_Vitality,
+    AtCommand_Intelligence,
+    AtCommand_Dexterity,
+    AtCommand_Luck,
+    AtCommand_GuildLevelUp,
+    AtCommand_Recall,
+    AtCommand_Revive,
+    AtCommand_CharacterStats,
+    AtCommand_CharacterStatsAll,
+    AtCommand_CharacterOption,
+    AtCommand_CharacterSave,
+    AtCommand_CharacterLoad,
+    AtCommand_Night,
+    AtCommand_Day,
+    AtCommand_Doom,
+    AtCommand_DoomMap,
+    AtCommand_Raise,
+    AtCommand_RaiseMap,
+    AtCommand_CharacterBaseLevel,
+    AtCommand_CharacterJobLevel,
+    AtCommand_Kick,
+    AtCommand_KickAll,
+    AtCommand_AllSkills,
+    AtCommand_QuestSkill,
+    AtCommand_CharQuestSkill,
+    AtCommand_LostSkill,
+    AtCommand_CharLostSkill,
+    AtCommand_Party,
+    AtCommand_Guild,
+    AtCommand_AgitStart,
+    AtCommand_AgitEnd,
+    AtCommand_MapExit,
+    AtCommand_IDSearch,
+    AtCommand_CharSkReset,
+    AtCommand_CharStReset,
+    AtCommand_CharReset,
+    //by chbrules
+    AtCommand_CharModel,
+    AtCommand_CharSKPoint,
+    AtCommand_CharSTPoint,
+    AtCommand_CharZeny,
+    AtCommand_RecallAll,
+    AtCommand_ReloadItemDB,
+    AtCommand_ReloadMobDB,
+    AtCommand_ReloadSkillDB,
+    AtCommand_ReloadScript,
+    AtCommand_ReloadGMDB,
+    AtCommand_MapInfo,
+    AtCommand_Dye,
+    AtCommand_HairStyle,
+    AtCommand_HairColor,
+    AtCommand_AllStats,
+    AtCommand_CharChangeSex,    // by Yor
+    AtCommand_CharBlock,        // by Yor
+    AtCommand_CharBan,          // by Yor
+    AtCommand_CharUnBlock,      // by Yor
+    AtCommand_CharUnBan,        // by Yor
+    AtCommand_MountPeco,        // by Valaris
+    AtCommand_CharMountPeco,    // by Yor
+    AtCommand_GuildSpy,         // [Syrus22]
+    AtCommand_PartySpy,         // [Syrus22]
+    AtCommand_GuildRecall,      // by Yor
+    AtCommand_PartyRecall,      // by Yor
+    AtCommand_Enablenpc,
+    AtCommand_Disablenpc,
+    AtCommand_ServerTime,       // by Yor
+    AtCommand_CharDelItem,      // by Yor
+    AtCommand_Jail,             // by Yor
+    AtCommand_UnJail,           // by Yor
+    AtCommand_Disguise,         // [Valaris]
+    AtCommand_UnDisguise,       // by Yor
+    AtCommand_IgnoreList,       // by Yor
+    AtCommand_CharIgnoreList,   // by Yor
+    AtCommand_InAll,            // by Yor
+    AtCommand_ExAll,            // by Yor
+    AtCommand_CharDisguise,     // Kalaspuff
+    AtCommand_CharUnDisguise,   // Kalaspuff
+    AtCommand_EMail,            // by Yor
+    AtCommand_Hatch,
+    AtCommand_Effect,           // by Apple
+    AtCommand_Char_Item_List,   // by Yor
+    AtCommand_Char_Storage_List,    // by Yor
+    AtCommand_Char_Cart_List,   // by Yor
+    AtCommand_AddWarp,          // by MouseJstr
+    AtCommand_Follow,           // by MouseJstr
+    AtCommand_SkillOn,          // by MouseJstr
+    AtCommand_SkillOff,         // by MouseJstr
+    AtCommand_Killer,           // by MouseJstr
+    AtCommand_NpcMove,          // by MouseJstr
+    AtCommand_Killable,         // by MouseJstr
+    AtCommand_CharKillable,     // by MouseJstr
+    AtCommand_Chareffect,       // by MouseJstr
+    AtCommand_Chardye,          // by MouseJstr
+    AtCommand_Charhairstyle,    // by MouseJstr
+    AtCommand_Charhaircolor,    // by MouseJstr
+    AtCommand_Dropall,          // by MouseJstr
+    AtCommand_Chardropall,      // by MouseJstr
+    AtCommand_Storeall,         // by MouseJstr
+    AtCommand_Charstoreall,     // by MouseJstr
+    AtCommand_Skillid,          // by MouseJstr
+    AtCommand_Useskill,         // by MouseJstr
+    AtCommand_Summon,
+    AtCommand_Rain,
+    AtCommand_Snow,
+    AtCommand_Sakura,
+    AtCommand_Fog,
+    AtCommand_Leaves,
+    AtCommand_AdjGmLvl,
+    AtCommand_AdjCmdLvl,
+    AtCommand_Trade,
+    AtCommand_UnMute,
+    AtCommand_CharWipe,
+    AtCommand_SetMagic,
+    AtCommand_MagicInfo,
+    AtCommand_Log,
+    AtCommand_Tee,
+    AtCommand_Invisible,
+    AtCommand_Visible,
+    AtCommand_IterateForward,
+    AtCommand_IterateBackward,
+    AtCommand_Wgm,
+    AtCommand_IpCheck,
+    AtCommand_ListNearby,       // [fate]
+    AtCommand_DoomSpot,
+    // end
+    AtCommand_Unknown,
+    AtCommand_MAX
+};
+
+typedef enum AtCommandType AtCommandType;
+
+typedef struct AtCommandInfo
+{
+    AtCommandType type;
+    const char *command;
+    int  level;
+    int  (*proc) (const int, struct map_session_data *,
+                  const char *command, const char *message);
+} AtCommandInfo;
+
+AtCommandType is_atcommand (const int fd, struct map_session_data *sd,
+                            const char *message, int gmlvl);
+
+AtCommandType atcommand (const int level, const char *message,
+                         AtCommandInfo * info);
+int  get_atcommand_level (const AtCommandType type);
+
+char *msg_txt (int msg_number); // [Yor]
+
+int  atcommand_item (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Valaris]
+int  atcommand_warp (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Yor]
+int  atcommand_spawn (const int fd, struct map_session_data *sd, const char *command, const char *message); // [Valaris]
+int  atcommand_goto (const int fd, struct map_session_data *sd, const char *command, const char *message);  // [Yor]
+int  atcommand_recall (const int fd, struct map_session_data *sd, const char *command, const char *message);    // [Yor]
+
+int  atcommand_config_read (const char *cfgName);
+int  msg_config_read (const char *cfgName);
+
+void log_atcommand (struct map_session_data *sd, const char *fmt, ...);
+void gm_log (const char *fmt, ...);
+
+#endif
diff --git a/src/map/battle.c b/src/map/battle.c
deleted file mode 100644
index 5e87b07..0000000
--- a/src/map/battle.c
+++ /dev/null
@@ -1,6282 +0,0 @@
-// $Id: battle.c,v 1.10 2004/09/29 21:08:17 Akitasha Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "battle.h"
-
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-
-#include "clif.h"
-#include "guild.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "pc.h"
-#include "skill.h"
-#include "../common/socket.h"
-#include "../common/mt_rand.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-int  attr_fix_table[4][10][10];
-
-struct Battle_Config battle_config;
-
-/*==========================================
- * 二点間の距離を返す
- * 戻りは整数で0以上
- *------------------------------------------
- */
-static int distance (int x0, int y0, int x1, int y1)
-{
-    int  dx, dy;
-
-    dx = abs (x0 - x1);
-    dy = abs (y0 - y1);
-    return dx > dy ? dx : dy;
-}
-
-/*==========================================
- * 自分をロックしている対象の数を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_counttargeted (struct block_list *bl, struct block_list *src,
-                          int target_lv)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC)
-        return pc_counttargeted ((struct map_session_data *) bl, src,
-                                 target_lv);
-    else if (bl->type == BL_MOB)
-        return mob_counttargeted ((struct mob_data *) bl, src, target_lv);
-    return 0;
-}
-
-/*==========================================
- * 対象のClassを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_class (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->mob_class;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->status.pc_class;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象の方向を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_dir (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->dir;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->dir;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のレベルを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_lv (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->stats[MOB_LV];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->status.base_level;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象の射程を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_range (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return mob_db[((struct mob_data *) bl)->mob_class].range;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->attackrange;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のHPを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_hp (struct block_list *bl)
-{
-    nullpo_retr (1, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->hp;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->status.hp;
-    else
-        return 1;
-}
-
-/*==========================================
- * 対象のMHPを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_max_hp (struct block_list *bl)
-{
-    nullpo_retr (1, bl);
-    if (bl->type == BL_PC && ((struct map_session_data *) bl))
-        return ((struct map_session_data *) bl)->status.max_hp;
-    else
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        int  max_hp = 1;
-        if (bl->type == BL_MOB && ((struct mob_data *) bl))
-        {
-            max_hp = ((struct mob_data *) bl)->stats[MOB_MAX_HP];
-            if (mob_db[((struct mob_data *) bl)->mob_class].mexp > 0)
-            {
-                if (battle_config.mvp_hp_rate != 100)
-                    max_hp = (max_hp * battle_config.mvp_hp_rate) / 100;
-            }
-            else
-            {
-                if (battle_config.monster_hp_rate != 100)
-                    max_hp = (max_hp * battle_config.monster_hp_rate) / 100;
-            }
-        }
-        if (sc_data)
-        {
-            if (sc_data[SC_APPLEIDUN].timer != -1)
-                max_hp +=
-                    ((5 + sc_data[SC_APPLEIDUN].val1 * 2 +
-                      ((sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
-                      sc_data[SC_APPLEIDUN].val3 / 10) * max_hp) / 100;
-        }
-        if (max_hp < 1)
-            max_hp = 1;
-        return max_hp;
-    }
-    return 1;
-}
-
-/*==========================================
- * 対象のStrを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_str (struct block_list *bl)
-{
-    int  str = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && ((struct mob_data *) bl))
-        str = ((struct mob_data *) bl)->stats[MOB_STR];
-    else if (bl->type == BL_PC && ((struct map_session_data *) bl))
-        return ((struct map_session_data *) bl)->paramc[0];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_LOUD].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1
-            && bl->type != BL_PC)
-            str += 4;
-        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
-        {                       // ブレッシング
-            int  race = battle_get_race (bl);
-            if (battle_check_undead (race, battle_get_elem_type (bl))
-                || race == 6)
-                str >>= 1;      // 悪 魔/不死
-            else
-                str += sc_data[SC_BLESSING].val1;   // その他
-        }
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            str += 5;
-    }
-    if (str < 0)
-        str = 0;
-    return str;
-}
-
-/*==========================================
- * 対象のAgiを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-
-int battle_get_agi (struct block_list *bl)
-{
-    int  agi = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        agi = ((struct mob_data *) bl)->stats[MOB_AGI];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        agi = ((struct map_session_data *) bl)->paramc[1];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_INCREASEAGI].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1 && bl->type != BL_PC)   // 速度増加(PCはpc.cで)
-            agi += 2 + sc_data[SC_INCREASEAGI].val1;
-
-        if (sc_data[SC_CONCENTRATE].timer != -1
-            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
-            agi += agi * (2 + sc_data[SC_CONCENTRATE].val1) / 100;
-
-        if (sc_data[SC_DECREASEAGI].timer != -1)    // 速度減少
-            agi -= 2 + sc_data[SC_DECREASEAGI].val1;
-
-        if (sc_data[SC_QUAGMIRE].timer != -1)   // クァグマイア
-            agi >>= 1;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            agi += 5;
-    }
-    if (agi < 0)
-        agi = 0;
-    return agi;
-}
-
-/*==========================================
- * 対象のVitを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_vit (struct block_list *bl)
-{
-    int  vit = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        vit = ((struct mob_data *) bl)->stats[MOB_VIT];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        vit = ((struct map_session_data *) bl)->paramc[2];
-    if (sc_data)
-    {
-        if (sc_data[SC_STRIPARMOR].timer != -1 && bl->type != BL_PC)
-            vit = vit * 60 / 100;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            vit += 5;
-    }
-
-    if (vit < 0)
-        vit = 0;
-    return vit;
-}
-
-/*==========================================
- * 対象のIntを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_int (struct block_list *bl)
-{
-    int  int_ = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        int_ = ((struct mob_data *) bl)->stats[MOB_INT];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        int_ = ((struct map_session_data *) bl)->paramc[3];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
-        {                       // ブレッシング
-            int  race = battle_get_race (bl);
-            if (battle_check_undead (race, battle_get_elem_type (bl))
-                || race == 6)
-                int_ >>= 1;     // 悪 魔/不死
-            else
-                int_ += sc_data[SC_BLESSING].val1;  // その他
-        }
-        if (sc_data[SC_STRIPHELM].timer != -1 && bl->type != BL_PC)
-            int_ = int_ * 60 / 100;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            int_ += 5;
-    }
-    if (int_ < 0)
-        int_ = 0;
-    return int_;
-}
-
-/*==========================================
- * 対象のDexを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_dex (struct block_list *bl)
-{
-    int  dex = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        dex = ((struct mob_data *) bl)->stats[MOB_DEX];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        dex = ((struct map_session_data *) bl)->paramc[4];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_CONCENTRATE].timer != -1
-            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
-            dex += dex * (2 + sc_data[SC_CONCENTRATE].val1) / 100;
-
-        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
-        {                       // ブレッシング
-            int  race = battle_get_race (bl);
-            if (battle_check_undead (race, battle_get_elem_type (bl))
-                || race == 6)
-                dex >>= 1;      // 悪 魔/不死
-            else
-                dex += sc_data[SC_BLESSING].val1;   // その他
-        }
-
-        if (sc_data[SC_QUAGMIRE].timer != -1)   // クァグマイア
-            dex >>= 1;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            dex += 5;
-    }
-    if (dex < 0)
-        dex = 0;
-    return dex;
-}
-
-/*==========================================
- * 対象のLukを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_luk (struct block_list *bl)
-{
-    int  luk = 0;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        luk = ((struct mob_data *) bl)->stats[MOB_LUK];
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        luk = ((struct map_session_data *) bl)->paramc[5];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_GLORIA].timer != -1 && bl->type != BL_PC)    // グロリア(PCはpc.cで)
-            luk += 30;
-        if (sc_data[SC_CURSE].timer != -1)  // 呪い
-            luk = 0;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            luk += 5;
-    }
-    if (luk < 0)
-        luk = 0;
-    return luk;
-}
-
-/*==========================================
- * 対象のFleeを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_flee (struct block_list *bl)
-{
-    int  flee = 1;
-    struct status_change *sc_data;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        flee = ((struct map_session_data *) bl)->flee;
-    else
-        flee = battle_get_agi (bl) + battle_get_lv (bl);
-
-    if (sc_data)
-    {
-        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
-            flee +=
-                flee * (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2 +
-                        (sc_data[SC_WHISTLE].val3 >> 16)) / 100;
-        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC)
-            flee -= flee * 25 / 100;
-        if (sc_data[SC_WINDWALK].timer != -1 && bl->type != BL_PC)  // ウィンドウォーク
-            flee += flee * (sc_data[SC_WINDWALK].val2) / 100;
-        if (sc_data[SC_SPIDERWEB].timer != -1 && bl->type != BL_PC) //スパイダーウェブ
-            flee -= flee * 50 / 100;
-
-        if (battle_is_unarmed (bl))
-            flee += (skill_power_bl (bl, TMW_BRAWLING) >> 3);   // +25 for 200
-        flee += skill_power_bl (bl, TMW_SPEED) >> 3;
-    }
-    if (flee < 1)
-        flee = 1;
-    return flee;
-}
-
-/*==========================================
- * 対象のHitを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_hit (struct block_list *bl)
-{
-    int  hit = 1;
-    struct status_change *sc_data;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        hit = ((struct map_session_data *) bl)->hit;
-    else
-        hit = battle_get_dex (bl) + battle_get_lv (bl);
-
-    if (sc_data)
-    {
-        if (sc_data[SC_HUMMING].timer != -1 && bl->type != BL_PC)   //
-            hit +=
-                hit * (sc_data[SC_HUMMING].val1 * 2 +
-                       sc_data[SC_HUMMING].val2 +
-                       sc_data[SC_HUMMING].val3) / 100;
-        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC) // 呪い
-            hit -= hit * 25 / 100;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
-            hit += 3 * (sc_data[SC_TRUESIGHT].val1);
-        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
-            hit += (hit * (10 * (sc_data[SC_CONCENTRATION].val1))) / 100;
-
-        if (battle_is_unarmed (bl))
-            hit += (skill_power_bl (bl, TMW_BRAWLING) >> 4);    // +12 for 200
-    }
-    if (hit < 1)
-        hit = 1;
-    return hit;
-}
-
-/*==========================================
- * 対象の完全回避を返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_flee2 (struct block_list *bl)
-{
-    int  flee2 = 1;
-    struct status_change *sc_data;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        flee2 = battle_get_luk (bl) + 10;
-        flee2 +=
-            ((struct map_session_data *) bl)->flee2 -
-            (((struct map_session_data *) bl)->paramc[5] + 10);
-    }
-    else
-        flee2 = battle_get_luk (bl) + 1;
-
-    if (sc_data)
-    {
-        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
-            flee2 += (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2
-                      + (sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;
-
-        if (battle_is_unarmed (bl))
-            flee2 += (skill_power_bl (bl, TMW_BRAWLING) >> 3);  // +25 for 200
-        flee2 += skill_power_bl (bl, TMW_SPEED) >> 3;
-    }
-    if (flee2 < 1)
-        flee2 = 1;
-    return flee2;
-}
-
-/*==========================================
- * 対象のクリティカルを返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_critical (struct block_list *bl)
-{
-    int  critical = 1;
-    struct status_change *sc_data;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        critical = battle_get_luk (bl) * 2 + 10;
-        critical +=
-            ((struct map_session_data *) bl)->critical -
-            ((((struct map_session_data *) bl)->paramc[5] * 3) + 10);
-    }
-    else
-        critical = battle_get_luk (bl) * 3 + 1;
-
-    if (sc_data)
-    {
-        if (sc_data[SC_FORTUNE].timer != -1 && bl->type != BL_PC)
-            critical +=
-                (10 + sc_data[SC_FORTUNE].val1 + sc_data[SC_FORTUNE].val2 +
-                 sc_data[SC_FORTUNE].val3) * 10;
-        if (sc_data[SC_EXPLOSIONSPIRITS].timer != -1 && bl->type != BL_PC)
-            critical += sc_data[SC_EXPLOSIONSPIRITS].val2;
-        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) //トゥルーサイト
-            critical += critical * sc_data[SC_TRUESIGHT].val1 / 100;
-    }
-    if (critical < 1)
-        critical = 1;
-    return critical;
-}
-
-/*==========================================
- * base_atkの取得
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_baseatk (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    int  batk = 1;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        batk = ((struct map_session_data *) bl)->base_atk;  //設定されているbase_atk
-    else
-    {                           //それ以外なら
-        int  str, dstr;
-        str = battle_get_str (bl);  //STR
-        dstr = str / 10;
-        batk = dstr * dstr + str;   //base_atkを計算する
-    }
-    if (sc_data)
-    {                           //状態異常あり
-        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)   //PCでプロボック(SM_PROVOKE)状態
-            batk = batk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;   //base_atk増加
-        if (sc_data[SC_CURSE].timer != -1)  //呪われていたら
-            batk -= batk * 25 / 100;    //base_atkが25%減少
-        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
-            batk += batk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
-    }
-    if (batk < 1)
-        batk = 1;               //base_atkは最低でも1
-    return batk;
-}
-
-/*==========================================
- * 対象のAtkを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    int  atk = 0;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        atk = ((struct map_session_data *) bl)->watk;
-    else if (bl->type == BL_MOB && (struct mob_data *) bl)
-        atk = ((struct mob_data *) bl)->stats[MOB_ATK1];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
-            atk = atk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
-        if (sc_data[SC_CURSE].timer != -1)
-            atk -= atk * 25 / 100;
-        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
-            atk += atk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
-    }
-    if (atk < 0)
-        atk = 0;
-    return atk;
-}
-
-/*==========================================
- * 対象の左手Atkを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk_ (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        int  atk = ((struct map_session_data *) bl)->watk_;
-
-        if (((struct map_session_data *) bl)->sc_data[SC_CURSE].timer != -1)
-            atk -= atk * 25 / 100;
-        return atk;
-    }
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のAtk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk2 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->watk2;
-    else
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        int  atk2 = 0;
-        if (bl->type == BL_MOB && (struct mob_data *) bl)
-            atk2 = ((struct mob_data *) bl)->stats[MOB_ATK2];
-        if (sc_data)
-        {
-            if (sc_data[SC_IMPOSITIO].timer != -1)
-                atk2 += sc_data[SC_IMPOSITIO].val1 * 5;
-            if (sc_data[SC_PROVOKE].timer != -1)
-                atk2 = atk2 * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
-            if (sc_data[SC_CURSE].timer != -1)
-                atk2 -= atk2 * 25 / 100;
-            if (sc_data[SC_DRUMBATTLE].timer != -1)
-                atk2 += sc_data[SC_DRUMBATTLE].val2;
-            if (sc_data[SC_NIBELUNGEN].timer != -1
-                && (battle_get_element (bl) / 10) >= 8)
-                atk2 += sc_data[SC_NIBELUNGEN].val2;
-            if (sc_data[SC_STRIPWEAPON].timer != -1)
-                atk2 = atk2 * 90 / 100;
-            if (sc_data[SC_CONCENTRATION].timer != -1)  //コンセントレーション
-                atk2 += atk2 * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
-        }
-
-        if (atk2 < 0)
-            atk2 = 0;
-        return atk2;
-    }
-    return 0;
-}
-
-/*==========================================
- * 対象の左手Atk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_atk_2 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC)
-        return ((struct map_session_data *) bl)->watk_2;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のMAtk1を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_matk1 (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB)
-    {
-        int  matk, int_ = battle_get_int (bl);
-        matk = int_ + (int_ / 5) * (int_ / 5);
-
-        if (sc_data)
-            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
-                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
-        return matk;
-    }
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->matk1;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のMAtk2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_matk2 (struct block_list *bl)
-{
-    struct status_change *sc_data = battle_get_sc_data (bl);
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB)
-    {
-        int  matk, int_ = battle_get_int (bl);
-        matk = int_ + (int_ / 7) * (int_ / 7);
-
-        if (sc_data)
-            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
-                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
-        return matk;
-    }
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->matk2;
-    else
-        return 0;
-}
-
-/*==========================================
- * 対象のDefを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_def (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    int  def = 0, skilltimer = -1, skillid = 0;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        def = ((struct map_session_data *) bl)->def;
-        skilltimer = ((struct map_session_data *) bl)->skilltimer;
-        skillid = ((struct map_session_data *) bl)->skillid;
-    }
-    else if (bl->type == BL_MOB && (struct mob_data *) bl)
-    {
-        def = ((struct mob_data *) bl)->stats[MOB_DEF];
-        skilltimer = ((struct mob_data *) bl)->skilltimer;
-        skillid = ((struct mob_data *) bl)->skillid;
-    }
-
-    if (def < 1000000)
-    {
-        if (sc_data)
-        {
-            //キーピング時はDEF100
-            if (sc_data[SC_KEEPING].timer != -1)
-                def = 100;
-            //プロボック時は減算
-            if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
-                def = (def * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
-            //戦太鼓の響き時は加算
-            if (sc_data[SC_DRUMBATTLE].timer != -1 && bl->type != BL_PC)
-                def += sc_data[SC_DRUMBATTLE].val3;
-            //毒にかかっている時は減算
-            if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
-                def = def * 75 / 100;
-            //ストリップシールド時は減算
-            if (sc_data[SC_STRIPSHIELD].timer != -1 && bl->type != BL_PC)
-                def = def * 85 / 100;
-            //シグナムクルシス時は減算
-            if (sc_data[SC_SIGNUMCRUCIS].timer != -1 && bl->type != BL_PC)
-                def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2) / 100;
-            //永遠の混沌時はDEF0になる
-            if (sc_data[SC_ETERNALCHAOS].timer != -1 && bl->type != BL_PC)
-                def = 0;
-            //凍結、石化時は右シフト
-            if (sc_data[SC_FREEZE].timer != -1
-                || (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0))
-                def >>= 1;
-            //コンセントレーション時は減算
-            if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
-                def =
-                    (def * (100 - 5 * sc_data[SC_CONCENTRATION].val1)) / 100;
-        }
-        //詠唱中は詠唱時減算率に基づいて減算
-        if (skilltimer != -1)
-        {
-            int  def_rate = skill_get_castdef (skillid);
-            if (def_rate != 0)
-                def = (def * (100 - def_rate)) / 100;
-        }
-    }
-    if (def < 0)
-        def = 0;
-    return def;
-}
-
-/*==========================================
- * 対象のMDefを返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_mdef (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    int  mdef = 0;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        mdef = ((struct map_session_data *) bl)->mdef;
-    else if (bl->type == BL_MOB && (struct mob_data *) bl)
-        mdef = ((struct mob_data *) bl)->stats[MOB_MDEF];
-
-    if (mdef < 1000000)
-    {
-        if (sc_data)
-        {
-            //バリアー状態時はMDEF100
-            if (mdef < 90 && sc_data[SC_MBARRIER].timer != -1)
-            {
-                mdef += sc_data[SC_MBARRIER].val1;
-                if (mdef > 90)
-                    mdef = 90;
-            }
-            if (sc_data[SC_BARRIER].timer != -1)
-                mdef = 100;
-            //凍結、石化時は1.25倍
-            if (sc_data[SC_FREEZE].timer != -1
-                || (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0))
-                mdef = mdef * 125 / 100;
-            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
-                mdef -= (mdef * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
-        }
-    }
-    if (mdef < 0)
-        mdef = 0;
-    return mdef;
-}
-
-/*==========================================
- * 対象のDef2を返す(汎用)
- * 戻りは整数で1以上
- *------------------------------------------
- */
-int battle_get_def2 (struct block_list *bl)
-{
-    struct status_change *sc_data;
-    int  def2 = 1;
-
-    nullpo_retr (1, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_PC)
-        def2 = ((struct map_session_data *) bl)->def2;
-    else if (bl->type == BL_MOB)
-        def2 = ((struct mob_data *) bl)->stats[MOB_VIT];
-
-    if (sc_data)
-    {
-        if (sc_data[SC_ANGELUS].timer != -1 && bl->type != BL_PC)
-            def2 = def2 * (110 + 5 * sc_data[SC_ANGELUS].val1) / 100;
-        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
-            def2 = (def2 * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
-        if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
-            def2 = def2 * 75 / 100;
-        //コンセントレーション時は減算
-        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
-            def2 = def2 * (100 - 5 * sc_data[SC_CONCENTRATION].val1) / 100;
-    }
-    if (def2 < 1)
-        def2 = 1;
-    return def2;
-}
-
-/*==========================================
- * 対象のMDef2を返す(汎用)
- * 戻りは整数で0以上
- *------------------------------------------
- */
-int battle_get_mdef2 (struct block_list *bl)
-{
-    int  mdef2 = 0;
-    struct status_change *sc_data = battle_get_sc_data (bl);
-
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB)
-        mdef2 =
-            ((struct mob_data *) bl)->stats[MOB_INT] +
-            (((struct mob_data *) bl)->stats[MOB_VIT] >> 1);
-    else if (bl->type == BL_PC)
-        mdef2 =
-            ((struct map_session_data *) bl)->mdef2 +
-            (((struct map_session_data *) bl)->paramc[2] >> 1);
-    if (sc_data)
-    {
-        if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
-            mdef2 -= (mdef2 * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
-    }
-    if (mdef2 < 0)
-        mdef2 = 0;
-    return mdef2;
-}
-
-/*==========================================
- * 対象のSpeed(移動速度)を返す(汎用)
- * 戻りは整数で1以上
- * Speedは小さいほうが移動速度が速い
- *------------------------------------------
- */
-int battle_get_speed (struct block_list *bl)
-{
-    nullpo_retr (1000, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->speed;
-    else
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        int  speed = 1000;
-        if (bl->type == BL_MOB && (struct mob_data *) bl)
-            speed = ((struct mob_data *) bl)->stats[MOB_SPEED];
-
-        if (sc_data)
-        {
-            //速度増加時は25%減算
-            if (sc_data[SC_INCREASEAGI].timer != -1
-                && sc_data[SC_DONTFORGETME].timer == -1)
-                speed -= speed * 25 / 100;
-            //速度減少時は25%加算
-            if (sc_data[SC_DECREASEAGI].timer != -1)
-                speed = speed * 125 / 100;
-            //クァグマイア時は50%加算
-            if (sc_data[SC_QUAGMIRE].timer != -1)
-                speed = speed * 3 / 2;
-            //私を忘れないで…時は加算
-            if (sc_data[SC_DONTFORGETME].timer != -1)
-                speed =
-                    speed * (100 + sc_data[SC_DONTFORGETME].val1 * 2 +
-                             sc_data[SC_DONTFORGETME].val2 +
-                             (sc_data[SC_DONTFORGETME].val3 & 0xffff)) / 100;
-            //金剛時は25%加算
-            if (sc_data[SC_STEELBODY].timer != -1)
-                speed = speed * 125 / 100;
-            //ディフェンダー時は加算
-            if (sc_data[SC_DEFENDER].timer != -1)
-                speed = (speed * (155 - sc_data[SC_DEFENDER].val1 * 5)) / 100;
-            //踊り状態は4倍遅い
-            if (sc_data[SC_DANCING].timer != -1)
-                speed *= 4;
-            //呪い時は450加算
-            if (sc_data[SC_CURSE].timer != -1)
-                speed = speed + 450;
-            //ウィンドウォーク時はLv*2%減算
-            if (sc_data[SC_WINDWALK].timer != -1)
-                speed -= (speed * (sc_data[SC_WINDWALK].val1 * 2)) / 100;
-        }
-        if (speed < 1)
-            speed = 1;
-        return speed;
-    }
-
-    return 1000;
-}
-
-/*==========================================
- * 対象のaDelay(攻撃時ディレイ)を返す(汎用)
- * aDelayは小さいほうが攻撃速度が速い
- *------------------------------------------
- */
-int battle_get_adelay (struct block_list *bl)
-{
-    nullpo_retr (4000, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return (((struct map_session_data *) bl)->aspd << 1);
-    else
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        int  adelay = 4000, aspd_rate = 100, i;
-        if (bl->type == BL_MOB && (struct mob_data *) bl)
-            adelay = ((struct mob_data *) bl)->stats[MOB_ADELAY];
-
-        if (sc_data)
-        {
-            //ツーハンドクイッケン使用時でクァグマイアでも私を忘れないで…でもない時は3割減算
-            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
-                aspd_rate -= 30;
-            //アドレナリンラッシュ使用時でツーハンドクイッケンでもクァグマイアでも私を忘れないで…でもない時は
-            if (sc_data[SC_ADRENALINE].timer != -1
-                && sc_data[SC_TWOHANDQUICKEN].timer == -1
-                && sc_data[SC_QUAGMIRE].timer == -1
-                && sc_data[SC_DONTFORGETME].timer == -1)
-            {                   // アドレナリンラッシュ
-                //使用者とパーティメンバーで格差が出る設定でなければ3割減算
-                if (sc_data[SC_ADRENALINE].val2
-                    || !battle_config.party_skill_penaly)
-                    aspd_rate -= 30;
-                //そうでなければ2.5割減算
-                else
-                    aspd_rate -= 25;
-            }
-            //スピアクィッケン時は減算
-            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
-                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
-            //夕日のアサシンクロス時は減算
-            if (sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
-                sc_data[SC_TWOHANDQUICKEN].timer == -1
-                && sc_data[SC_ADRENALINE].timer == -1
-                && sc_data[SC_SPEARSQUICKEN].timer == -1
-                && sc_data[SC_DONTFORGETME].timer == -1)
-                aspd_rate -=
-                    5 + sc_data[SC_ASSNCROS].val1 +
-                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
-            //私を忘れないで…時は加算
-            if (sc_data[SC_DONTFORGETME].timer != -1)   // 私を忘れないで
-                aspd_rate +=
-                    sc_data[SC_DONTFORGETME].val1 * 3 +
-                    sc_data[SC_DONTFORGETME].val2 +
-                    (sc_data[SC_DONTFORGETME].val3 >> 16);
-            //金剛時25%加算
-            if (sc_data[SC_STEELBODY].timer != -1)  // 金剛
-                aspd_rate += 25;
-            //増速ポーション使用時は減算
-            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
-                || sc_data[i = SC_SPEEDPOTION1].timer != -1
-                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
-                aspd_rate -= sc_data[i].val1;
-            // Fate's `haste' spell works the same as the above
-            if (sc_data[SC_HASTE].timer != -1)
-                aspd_rate -= sc_data[SC_HASTE].val1;
-            //ディフェンダー時は加算
-            if (sc_data[SC_DEFENDER].timer != -1)
-                adelay += (1100 - sc_data[SC_DEFENDER].val1 * 100);
-        }
-
-        if (aspd_rate != 100)
-            adelay = adelay * aspd_rate / 100;
-        if (adelay < battle_config.monster_max_aspd << 1)
-            adelay = battle_config.monster_max_aspd << 1;
-        return adelay;
-    }
-    return 4000;
-}
-
-int battle_get_amotion (struct block_list *bl)
-{
-    nullpo_retr (2000, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->amotion;
-    else
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        int  amotion = 2000, aspd_rate = 100, i;
-        if (bl->type == BL_MOB && (struct mob_data *) bl)
-            amotion = mob_db[((struct mob_data *) bl)->mob_class].amotion;
-
-        if (sc_data)
-        {
-            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
-                aspd_rate -= 30;
-            if (sc_data[SC_ADRENALINE].timer != -1
-                && sc_data[SC_TWOHANDQUICKEN].timer == -1
-                && sc_data[SC_QUAGMIRE].timer == -1
-                && sc_data[SC_DONTFORGETME].timer == -1)
-            {                   // アドレナリンラッシュ
-                if (sc_data[SC_ADRENALINE].val2
-                    || !battle_config.party_skill_penaly)
-                    aspd_rate -= 30;
-                else
-                    aspd_rate -= 25;
-            }
-            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
-                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
-            if (sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
-                sc_data[SC_TWOHANDQUICKEN].timer == -1
-                && sc_data[SC_ADRENALINE].timer == -1
-                && sc_data[SC_SPEARSQUICKEN].timer == -1
-                && sc_data[SC_DONTFORGETME].timer == -1)
-                aspd_rate -=
-                    5 + sc_data[SC_ASSNCROS].val1 +
-                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
-            if (sc_data[SC_DONTFORGETME].timer != -1)   // 私を忘れないで
-                aspd_rate +=
-                    sc_data[SC_DONTFORGETME].val1 * 3 +
-                    sc_data[SC_DONTFORGETME].val2 +
-                    (sc_data[SC_DONTFORGETME].val3 >> 16);
-            if (sc_data[SC_STEELBODY].timer != -1)  // 金剛
-                aspd_rate += 25;
-            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
-                || sc_data[i = SC_SPEEDPOTION1].timer != -1
-                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
-                aspd_rate -= sc_data[i].val1;
-            if (sc_data[SC_HASTE].timer != -1)
-                aspd_rate -= sc_data[SC_HASTE].val1;
-            if (sc_data[SC_DEFENDER].timer != -1)
-                amotion += (550 - sc_data[SC_DEFENDER].val1 * 50);
-        }
-
-        if (aspd_rate != 100)
-            amotion = amotion * aspd_rate / 100;
-        if (amotion < battle_config.monster_max_aspd)
-            amotion = battle_config.monster_max_aspd;
-        return amotion;
-    }
-    return 2000;
-}
-
-int battle_get_dmotion (struct block_list *bl)
-{
-    int  ret;
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-    {
-        ret = mob_db[((struct mob_data *) bl)->mob_class].dmotion;
-        if (battle_config.monster_damage_delay_rate != 100)
-            ret = ret * battle_config.monster_damage_delay_rate / 400;
-    }
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        ret = ((struct map_session_data *) bl)->dmotion;
-        if (battle_config.pc_damage_delay_rate != 100)
-            ret = ret * battle_config.pc_damage_delay_rate / 400;
-    }
-    else
-        return 2000;
-
-    if ((sc_data && sc_data[SC_ENDURE].timer != -1) ||
-        (bl->type == BL_PC
-         && ((struct map_session_data *) bl)->special_state.infinite_endure))
-        ret = 0;
-
-    return ret;
-}
-
-int battle_get_element (struct block_list *bl)
-{
-    int  ret = 20;
-    struct status_change *sc_data;
-
-    nullpo_retr (ret, bl);
-    sc_data = battle_get_sc_data (bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)   // 10の位=Lv*2、1の位=属性
-        ret = ((struct mob_data *) bl)->def_ele;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        ret = 20 + ((struct map_session_data *) bl)->def_ele;   // 防御属性Lv1
-
-    if (sc_data)
-    {
-        if (sc_data[SC_BENEDICTIO].timer != -1) // 聖体降福
-            ret = 26;
-        if (sc_data[SC_FREEZE].timer != -1) // 凍結
-            ret = 21;
-        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
-            ret = 22;
-    }
-
-    return ret;
-}
-
-int battle_get_attack_element (struct block_list *bl)
-{
-    int  ret = 0;
-    struct status_change *sc_data = battle_get_sc_data (bl);
-
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        ret = 0;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        ret = ((struct map_session_data *) bl)->atk_ele;
-
-    if (sc_data)
-    {
-        if (sc_data[SC_FROSTWEAPON].timer != -1)    // フロストウェポン
-            ret = 1;
-        if (sc_data[SC_SEISMICWEAPON].timer != -1)  // サイズミックウェポン
-            ret = 2;
-        if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // フレームランチャー
-            ret = 3;
-        if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ライトニングローダー
-            ret = 4;
-        if (sc_data[SC_ENCPOISON].timer != -1)  // エンチャントポイズン
-            ret = 5;
-        if (sc_data[SC_ASPERSIO].timer != -1)   // アスペルシオ
-            ret = 6;
-    }
-
-    return ret;
-}
-
-int battle_get_attack_element2 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-    {
-        int  ret = ((struct map_session_data *) bl)->atk_ele_;
-        struct status_change *sc_data =
-            ((struct map_session_data *) bl)->sc_data;
-
-        if (sc_data)
-        {
-            if (sc_data[SC_FROSTWEAPON].timer != -1)    // フロストウェポン
-                ret = 1;
-            if (sc_data[SC_SEISMICWEAPON].timer != -1)  // サイズミックウェポン
-                ret = 2;
-            if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // フレームランチャー
-                ret = 3;
-            if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ライトニングローダー
-                ret = 4;
-            if (sc_data[SC_ENCPOISON].timer != -1)  // エンチャントポイズン
-                ret = 5;
-            if (sc_data[SC_ASPERSIO].timer != -1)   // アスペルシオ
-                ret = 6;
-        }
-        return ret;
-    }
-    return 0;
-}
-
-int battle_get_party_id (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->status.party_id;
-    else if (bl->type == BL_MOB && (struct mob_data *) bl)
-    {
-        struct mob_data *md = (struct mob_data *) bl;
-        if (md->master_id > 0)
-            return -md->master_id;
-        return -md->bl.id;
-    }
-    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
-        return ((struct skill_unit *) bl)->group->party_id;
-    else
-        return 0;
-}
-
-int battle_get_guild_id (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->status.guild_id;
-    else if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->mob_class;
-    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
-        return ((struct skill_unit *) bl)->group->guild_id;
-    else
-        return 0;
-}
-
-int battle_get_race (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return mob_db[((struct mob_data *) bl)->mob_class].race;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return 7;
-    else
-        return 0;
-}
-
-int battle_get_size (struct block_list *bl)
-{
-    nullpo_retr (1, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return mob_db[((struct mob_data *) bl)->mob_class].size;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return 1;
-    else
-        return 1;
-}
-
-int battle_get_mode (struct block_list *bl)
-{
-    nullpo_retr (0x01, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return mob_db[((struct mob_data *) bl)->mob_class].mode;
-    else
-        return 0x01;            // とりあえず動くということで1
-}
-
-int battle_get_mexp (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-    {
-        const struct mob_data *mob = (struct mob_data *) bl;
-        const int retval =
-            (mob_db[mob->mob_class].mexp *
-             (int) (mob->stats[MOB_XP_BONUS])) >> MOB_XP_BONUS_SHIFT;
-        fprintf (stderr, "Modifier of %x: -> %d\n", mob->stats[MOB_XP_BONUS],
-                 retval);
-        return retval;
-    }
-    else
-        return 0;
-}
-
-int battle_get_stat (int stat_id /* SP_VIT or similar */ ,
-                     struct block_list *bl)
-{
-    switch (stat_id)
-    {
-        case SP_STR:
-            return battle_get_str (bl);
-        case SP_AGI:
-            return battle_get_agi (bl);
-        case SP_DEX:
-            return battle_get_dex (bl);
-        case SP_VIT:
-            return battle_get_vit (bl);
-        case SP_INT:
-            return battle_get_int (bl);
-        case SP_LUK:
-            return battle_get_luk (bl);
-        default:
-            return 0;
-    }
-}
-
-// StatusChange系の所得
-struct status_change *battle_get_sc_data (struct block_list *bl)
-{
-    nullpo_retr (NULL, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return ((struct mob_data *) bl)->sc_data;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return ((struct map_session_data *) bl)->sc_data;
-    return NULL;
-}
-
-short *battle_get_sc_count (struct block_list *bl)
-{
-    nullpo_retr (NULL, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return &((struct mob_data *) bl)->sc_count;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return &((struct map_session_data *) bl)->sc_count;
-    return NULL;
-}
-
-short *battle_get_opt1 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return &((struct mob_data *) bl)->opt1;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return &((struct map_session_data *) bl)->opt1;
-    else if (bl->type == BL_NPC && (struct npc_data *) bl)
-        return &((struct npc_data *) bl)->opt1;
-    return 0;
-}
-
-short *battle_get_opt2 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return &((struct mob_data *) bl)->opt2;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return &((struct map_session_data *) bl)->opt2;
-    else if (bl->type == BL_NPC && (struct npc_data *) bl)
-        return &((struct npc_data *) bl)->opt2;
-    return 0;
-}
-
-short *battle_get_opt3 (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return &((struct mob_data *) bl)->opt3;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return &((struct map_session_data *) bl)->opt3;
-    else if (bl->type == BL_NPC && (struct npc_data *) bl)
-        return &((struct npc_data *) bl)->opt3;
-    return 0;
-}
-
-short *battle_get_option (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB && (struct mob_data *) bl)
-        return &((struct mob_data *) bl)->option;
-    else if (bl->type == BL_PC && (struct map_session_data *) bl)
-        return &((struct map_session_data *) bl)->status.option;
-    else if (bl->type == BL_NPC && (struct npc_data *) bl)
-        return &((struct npc_data *) bl)->option;
-    return 0;
-}
-
-//-------------------------------------------------------------------
-
-// ダメージの遅延
-struct battle_delay_damage_
-{
-    struct block_list *src, *target;
-    int  damage;
-    int  flag;
-};
-void battle_delay_damage_sub (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct battle_delay_damage_ *dat = (struct battle_delay_damage_ *) data;
-    if (dat && map_id2bl (id) == dat->src && dat->target->prev != NULL)
-        battle_damage (dat->src, dat->target, dat->damage, dat->flag);
-    free (dat);
-}
-
-int battle_delay_damage (unsigned int tick, struct block_list *src,
-                         struct block_list *target, int damage, int flag)
-{
-    struct battle_delay_damage_ *dat;
-    CREATE (dat, struct battle_delay_damage_, 1);
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, target);
-
-    dat->src = src;
-    dat->target = target;
-    dat->damage = damage;
-    dat->flag = flag;
-    add_timer (tick, battle_delay_damage_sub, src->id, (int) dat);
-    return 0;
-}
-
-// 実際にHPを操作
-int battle_damage (struct block_list *bl, struct block_list *target,
-                   int damage, int flag)
-{
-    struct map_session_data *sd = NULL;
-    struct status_change *sc_data = battle_get_sc_data (target);
-    short *sc_count;
-    int  i;
-
-    nullpo_retr (0, target);    //blはNULLで呼ばれることがあるので他でチェック
-
-    if (damage == 0)
-        return 0;
-
-    if (target->prev == NULL)
-        return 0;
-
-    if (bl)
-    {
-        if (bl->prev == NULL)
-            return 0;
-
-        if (bl->type == BL_PC)
-            sd = (struct map_session_data *) bl;
-    }
-
-    if (damage < 0)
-        return battle_heal (bl, target, -damage, 0, flag);
-
-    if (!flag && (sc_count = battle_get_sc_count (target)) != NULL
-        && *sc_count > 0)
-    {
-        // 凍結、石化、睡眠を消去
-        if (sc_data[SC_FREEZE].timer != -1)
-            skill_status_change_end (target, SC_FREEZE, -1);
-        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
-            skill_status_change_end (target, SC_STONE, -1);
-        if (sc_data[SC_SLEEP].timer != -1)
-            skill_status_change_end (target, SC_SLEEP, -1);
-    }
-
-    if (target->type == BL_MOB)
-    {                           // MOB
-        struct mob_data *md = (struct mob_data *) target;
-        if (md && md->skilltimer != -1 && md->state.skillcastcancel)    // 詠唱妨害
-            skill_castcancel (target, 0);
-        return mob_damage (bl, md, damage, 0);
-    }
-    else if (target->type == BL_PC)
-    {                           // PC
-
-        struct map_session_data *tsd = (struct map_session_data *) target;
-
-        if (tsd && tsd->sc_data && tsd->sc_data[SC_DEVOTION].val1)
-        {                       // ディボーションをかけられている
-            struct map_session_data *md =
-                map_id2sd (tsd->sc_data[SC_DEVOTION].val1);
-            if (md && skill_devotion3 (&md->bl, target->id))
-            {
-                skill_devotion (md, target->id);
-            }
-            else if (md && bl)
-                for (i = 0; i < 5; i++)
-                    if (md->dev.val1[i] == target->id)
-                    {
-                        clif_damage (bl, &md->bl, gettick (), 0, 0,
-                                     damage, 0, 0, 0);
-                        pc_damage (&md->bl, md, damage);
-
-                        return 0;
-                    }
-        }
-
-        if (tsd && tsd->skilltimer != -1)
-        {                       // 詠唱妨害
-            // フェンカードや妨害されないスキルかの検査
-            if ((!tsd->special_state.no_castcancel || map[bl->m].flag.gvg)
-                && tsd->state.skillcastcancel
-                && !tsd->special_state.no_castcancel2)
-                skill_castcancel (target, 0);
-        }
-
-        return pc_damage (bl, tsd, damage);
-
-    }
-    else if (target->type == BL_SKILL)
-        return skill_unit_ondamaged ((struct skill_unit *) target, bl, damage,
-                                     gettick ());
-    return 0;
-}
-
-int battle_heal (struct block_list *bl, struct block_list *target, int hp,
-                 int sp, int flag)
-{
-    nullpo_retr (0, target);    //blはNULLで呼ばれることがあるので他でチェック
-
-    if (target->type == BL_PC
-        && pc_isdead ((struct map_session_data *) target))
-        return 0;
-    if (hp == 0 && sp == 0)
-        return 0;
-
-    if (hp < 0)
-        return battle_damage (bl, target, -hp, flag);
-
-    if (target->type == BL_MOB)
-        return mob_heal ((struct mob_data *) target, hp);
-    else if (target->type == BL_PC)
-        return pc_heal ((struct map_session_data *) target, hp, sp);
-    return 0;
-}
-
-// 攻撃停止
-int battle_stopattack (struct block_list *bl)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB)
-        return mob_stopattack ((struct mob_data *) bl);
-    else if (bl->type == BL_PC)
-        return pc_stopattack ((struct map_session_data *) bl);
-    return 0;
-}
-
-// 移動停止
-int battle_stopwalking (struct block_list *bl, int type)
-{
-    nullpo_retr (0, bl);
-    if (bl->type == BL_MOB)
-        return mob_stop_walking ((struct mob_data *) bl, type);
-    else if (bl->type == BL_PC)
-        return pc_stop_walking ((struct map_session_data *) bl, type);
-    return 0;
-}
-
-/*==========================================
- * ダメージの属性修正
- *------------------------------------------
- */
-int battle_attr_fix (int damage, int atk_elem, int def_elem)
-{
-    int  def_type = def_elem % 10, def_lv = def_elem / 10 / 2;
-
-    if (atk_elem < 0 || atk_elem > 9 || def_type < 0 || def_type > 9 ||
-        def_lv < 1 || def_lv > 4)
-    {                           // 属 性値がおかしいのでとりあえずそのまま返す
-        if (battle_config.error_log)
-            printf
-                ("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",
-                 atk_elem, def_type, def_lv);
-        return damage;
-    }
-
-    return damage * attr_fix_table[def_lv - 1][atk_elem][def_type] / 100;
-}
-
-/*==========================================
- * ダメージ最終計算
- *------------------------------------------
- */
-int battle_calc_damage (struct block_list *src, struct block_list *bl,
-                        int damage, int div_, int skill_num, int skill_lv,
-                        int flag)
-{
-    struct map_session_data *sd = NULL;
-    struct mob_data *md = NULL;
-    struct status_change *sc_data, *sc;
-    short *sc_count;
-    int  class_;
-
-    nullpo_retr (0, bl);
-
-    class_ = battle_get_class (bl);
-    if (bl->type == BL_MOB)
-        md = (struct mob_data *) bl;
-    else
-        sd = (struct map_session_data *) bl;
-
-    sc_data = battle_get_sc_data (bl);
-    sc_count = battle_get_sc_count (bl);
-
-    if (sc_count != NULL && *sc_count > 0)
-    {
-
-        if (sc_data[SC_SAFETYWALL].timer != -1 && damage > 0
-            && flag & BF_WEAPON && flag & BF_SHORT
-            && skill_num != NPC_GUIDEDATTACK)
-        {
-            // セーフティウォール
-            struct skill_unit *unit =
-                (struct skill_unit *) sc_data[SC_SAFETYWALL].val2;
-            if (unit && unit->alive && (--unit->group->val2) <= 0)
-                skill_delunit (unit);
-            skill_unit_move (bl, gettick (), 1);    // 重ね掛けチェック
-            damage = 0;
-        }
-        if (sc_data[SC_PNEUMA].timer != -1 && damage > 0 && flag & BF_WEAPON
-            && flag & BF_LONG && skill_num != NPC_GUIDEDATTACK)
-        {
-            // ニューマ
-            damage = 0;
-        }
-
-        if (sc_data[SC_ROKISWEIL].timer != -1 && damage > 0 &&
-            flag & BF_MAGIC)
-        {
-            // ニューマ
-            damage = 0;
-        }
-
-        if (sc_data[SC_AETERNA].timer != -1 && damage > 0)
-        {                       // レックスエーテルナ
-            damage <<= 1;
-            skill_status_change_end (bl, SC_AETERNA, -1);
-        }
-
-        //属性場のダメージ増加
-        if (sc_data[SC_VOLCANO].timer != -1)
-        {                       // ボルケーノ
-            if (flag & BF_SKILL && skill_get_pl (skill_num) == 3)
-                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
-            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 3))
-                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
-        }
-
-        if (sc_data[SC_VIOLENTGALE].timer != -1)
-        {                       // バイオレントゲイル
-            if (flag & BF_SKILL && skill_get_pl (skill_num) == 4)
-                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
-            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 4))
-                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
-        }
-
-        if (sc_data[SC_DELUGE].timer != -1)
-        {                       // デリュージ
-            if (flag & BF_SKILL && skill_get_pl (skill_num) == 1)
-                damage += damage * sc_data[SC_DELUGE].val4 / 100;
-            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 1))
-                damage += damage * sc_data[SC_DELUGE].val4 / 100;
-        }
-
-        if (sc_data[SC_ENERGYCOAT].timer != -1 && damage > 0
-            && flag & BF_WEAPON)
-        {                       // エナジーコート
-            if (sd)
-            {
-                if (sd->status.sp > 0)
-                {
-                    int  per = sd->status.sp * 5 / (sd->status.max_sp + 1);
-                    sd->status.sp -= sd->status.sp * (per * 5 + 10) / 1000;
-                    if (sd->status.sp < 0)
-                        sd->status.sp = 0;
-                    damage -= damage * ((per + 1) * 6) / 100;
-                    clif_updatestatus (sd, SP_SP);
-                }
-                if (sd->status.sp <= 0)
-                    skill_status_change_end (bl, SC_ENERGYCOAT, -1);
-            }
-            else
-                damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100;
-        }
-
-        if (sc_data[SC_KYRIE].timer != -1 && damage > 0)
-        {                       // キリエエレイソン
-            sc = &sc_data[SC_KYRIE];
-            sc->val2 -= damage;
-            if (flag & BF_WEAPON)
-            {
-                if (sc->val2 >= 0)
-                    damage = 0;
-                else
-                    damage = -sc->val2;
-            }
-            if ((--sc->val3) <= 0 || (sc->val2 <= 0)
-                || skill_num == AL_HOLYLIGHT)
-                skill_status_change_end (bl, SC_KYRIE, -1);
-        }
-
-        if (sc_data[SC_BASILICA].timer != -1 && damage > 0)
-        {
-            // ニューマ
-            damage = 0;
-        }
-        if (sc_data[SC_LANDPROTECTOR].timer != -1 && damage > 0
-            && flag & BF_MAGIC)
-        {
-            // ニューマ
-            damage = 0;
-        }
-
-        if (sc_data[SC_AUTOGUARD].timer != -1 && damage > 0
-            && flag & BF_WEAPON)
-        {
-            if (MRAND (100) < sc_data[SC_AUTOGUARD].val2)
-            {
-                damage = 0;
-                clif_skill_nodamage (bl, bl, CR_AUTOGUARD,
-                                     sc_data[SC_AUTOGUARD].val1, 1);
-                if (sd)
-                    sd->canmove_tick = gettick () + 300;
-                else if (md)
-                    md->canmove_tick = gettick () + 300;
-            }
-        }
-// -- moonsoul (chance to block attacks with new Lord Knight skill parrying)
-//
-        if (sc_data[SC_PARRYING].timer != -1 && damage > 0
-            && flag & BF_WEAPON)
-        {
-            if (MRAND (100) < sc_data[SC_PARRYING].val2)
-            {
-                damage = 0;
-                clif_skill_nodamage (bl, bl, LK_PARRYING,
-                                     sc_data[SC_PARRYING].val1, 1);
-            }
-        }
-        // リジェクトソード
-        if (sc_data[SC_REJECTSWORD].timer != -1 && damage > 0
-            && flag & BF_WEAPON
-            &&
-            ((src->type == BL_PC
-              && ((struct map_session_data *) src)->status.weapon == (1 || 2
-                                                                      || 3))
-             || src->type == BL_MOB))
-        {
-            if (MRAND (100) < (10 + 5 * sc_data[SC_REJECTSWORD].val1))
-            {                   //反射確率は10+5*Lv
-                damage = damage * 50 / 100;
-                battle_damage (bl, src, damage, 0);
-                //ダメージを与えたのは良いんだが、ここからどうして表示するんだかわかんねぇ
-                //エフェクトもこれでいいのかわかんねぇ
-                clif_skill_nodamage (bl, bl, ST_REJECTSWORD,
-                                     sc_data[SC_REJECTSWORD].val1, 1);
-                if ((--sc_data[SC_REJECTSWORD].val2) <= 0)
-                    skill_status_change_end (bl, SC_REJECTSWORD, -1);
-            }
-        }
-    }
-
-    if (class_ == 1288 || class_ == 1287 || class_ == 1286 || class_ == 1285)
-    {
-//  if(class == 1288) {
-        if (class_ == 1288 && flag & BF_SKILL)
-            damage = 0;
-        if (src->type == BL_PC)
-        {
-            struct guild *g =
-                guild_search (((struct map_session_data *) src)->
-                              status.guild_id);
-            struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
-            if (!((struct map_session_data *) src)->status.guild_id)
-                damage = 0;
-            if (gc && agit_flag == 0 && class_ != 1288)  // guardians cannot be damaged during non-woe [Valaris]
-                damage = 0;     // end woe check [Valaris]
-            if (g == NULL)
-                damage = 0;     //ギルド未加入ならダメージ無し
-            else if ((gc != NULL) && guild_isallied (g, gc))
-                damage = 0;     //自占領ギルドのエンペならダメージ無し
-            else if (g && guild_checkskill (g, GD_APPROVAL) <= 0)
-                damage = 0;     //正規ギルド承認がないとダメージ無し
-            else if (battle_config.guild_max_castles != 0
-                     && guild_checkcastles (g) >=
-                     battle_config.guild_max_castles)
-                damage = 0;     // [MouseJstr]
-        }
-        else
-            damage = 0;
-    }
-
-    if (map[bl->m].flag.gvg && damage > 0)
-    {                           //GvG
-        if (flag & BF_WEAPON)
-        {
-            if (flag & BF_SHORT)
-                damage = damage * battle_config.gvg_short_damage_rate / 100;
-            if (flag & BF_LONG)
-                damage = damage * battle_config.gvg_long_damage_rate / 100;
-        }
-        if (flag & BF_MAGIC)
-            damage = damage * battle_config.gvg_magic_damage_rate / 100;
-        if (flag & BF_MISC)
-            damage = damage * battle_config.gvg_misc_damage_rate / 100;
-        if (damage < 1)
-            damage = 1;
-    }
-
-    if (battle_config.skill_min_damage || flag & BF_MISC)
-    {
-        if (div_ < 255)
-        {
-            if (damage > 0 && damage < div_)
-                damage = div_;
-        }
-        else if (damage > 0 && damage < 3)
-            damage = 3;
-    }
-
-    if (md != NULL && md->hp > 0 && damage > 0) // 反撃などのMOBスキル判定
-        mobskill_event (md, flag);
-
-    return damage;
-}
-
-/*==========================================
- * 修練ダメージ
- *------------------------------------------
- */
-int battle_addmastery (struct map_session_data *sd, struct block_list *target,
-                       int dmg, int type)
-{
-    int  damage, skill;
-    int  race = battle_get_race (target);
-    int  weapon;
-    damage = 0;
-
-    nullpo_retr (0, sd);
-
-    // デーモンベイン(+3 〜 +30) vs 不死 or 悪魔 (死人は含めない?)
-    if ((skill = pc_checkskill (sd, AL_DEMONBANE)) > 0
-        && (battle_check_undead (race, battle_get_elem_type (target))
-            || race == 6))
-        damage += (skill * 3);
-
-    // ビーストベイン(+4 〜 +40) vs 動物 or 昆虫
-    if ((skill = pc_checkskill (sd, HT_BEASTBANE)) > 0
-        && (race == 2 || race == 4))
-        damage += (skill * 4);
-
-    if (type == 0)
-        weapon = sd->weapontype1;
-    else
-        weapon = sd->weapontype2;
-    switch (weapon)
-    {
-        case 0x01:             // 短剣 (Updated By AppleGirl)
-        case 0x02:             // 1HS
-        {
-            // 剣修練(+4 〜 +40) 片手剣 短剣含む
-            if ((skill = pc_checkskill (sd, SM_SWORD)) > 0)
-            {
-                damage += (skill * 4);
-            }
-            break;
-        }
-        case 0x03:             // 2HS
-        {
-            // 両手剣修練(+4 〜 +40) 両手剣
-            if ((skill = pc_checkskill (sd, SM_TWOHAND)) > 0)
-            {
-                damage += (skill * 4);
-            }
-            break;
-        }
-        case 0x04:             // 1HL
-        {
-            // 槍修練(+4 〜 +40,+5 〜 +50) 槍
-            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
-            {
-                if (!pc_isriding (sd))
-                    damage += (skill * 4);  // ペコに乗ってない
-                else
-                    damage += (skill * 5);  // ペコに乗ってる
-            }
-            break;
-        }
-        case 0x05:             // 2HL
-        {
-            // 槍修練(+4 〜 +40,+5 〜 +50) 槍
-            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
-            {
-                if (!pc_isriding (sd))
-                    damage += (skill * 4);  // ペコに乗ってない
-                else
-                    damage += (skill * 5);  // ペコに乗ってる
-            }
-            break;
-        }
-        case 0x06:             // 片手斧
-        {
-            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x07:             // Axe by Tato
-        {
-            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x08:             // メイス
-        {
-            // メイス修練(+3 〜 +30) メイス
-            if ((skill = pc_checkskill (sd, PR_MACEMASTERY)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x09:             // なし?
-            break;
-        case 0x0a:             // 杖
-            break;
-        case 0x0b:             // 弓
-            break;
-        case 0x00:             // 素手
-        case 0x0c:             // Knuckles
-        {
-            // 鉄拳(+3 〜 +30) 素手,ナックル
-            if ((skill = pc_checkskill (sd, MO_IRONHAND)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x0d:             // Musical Instrument
-        {
-            // 楽器の練習(+3 〜 +30) 楽器
-            if ((skill = pc_checkskill (sd, BA_MUSICALLESSON)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x0e:             // Dance Mastery
-        {
-            // Dance Lesson Skill Effect(+3 damage for every lvl = +30) 鞭
-            if ((skill = pc_checkskill (sd, DC_DANCINGLESSON)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x0f:             // Book
-        {
-            // Advance Book Skill Effect(+3 damage for every lvl = +30) {
-            if ((skill = pc_checkskill (sd, SA_ADVANCEDBOOK)) > 0)
-            {
-                damage += (skill * 3);
-            }
-            break;
-        }
-        case 0x10:             // Katars
-        {
-            // カタール修練(+3 〜 +30) カタール
-            if ((skill = pc_checkskill (sd, AS_KATAR)) > 0)
-            {
-                //ソニックブロー時は別処理(1撃に付き1/8適応)
-                damage += (skill * 3);
-            }
-            break;
-        }
-    }
-    damage = dmg + damage;
-    return (damage);
-}
-
-static struct Damage battle_calc_mob_weapon_attack (struct block_list *src,
-                                                    struct block_list *target,
-                                                    int skill_num,
-                                                    int skill_lv, int wflag)
-{
-    struct map_session_data *tsd = NULL;
-    struct mob_data *md = (struct mob_data *) src, *tmd = NULL;
-    int  hitrate, flee, cri = 0, atkmin, atkmax;
-    int  luk, target_count = 1;
-    int  def1 = battle_get_def (target);
-    int  def2 = battle_get_def2 (target);
-    int  t_vit = battle_get_vit (target);
-    struct Damage wd;
-    int  damage, damage2 = 0, type, div_, blewcount =
-        skill_get_blewcount (skill_num, skill_lv);
-    int  flag, skill, ac_flag = 0, dmg_lv = 0;
-    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 0, s_ele = 0;
-    struct status_change *sc_data, *t_sc_data;
-    short *sc_count;
-    short *option, *opt1, *opt2;
-
-    //return前の処理があるので情報出力部のみ変更
-    if (src == NULL || target == NULL || md == NULL)
-    {
-        nullpo_info (NLP_MARK);
-        memset (&wd, 0, sizeof (wd));
-        return wd;
-    }
-
-    s_race = battle_get_race (src);
-    s_ele = battle_get_attack_element (src);
-    sc_data = battle_get_sc_data (src);
-    sc_count = battle_get_sc_count (src);
-    option = battle_get_option (src);
-    opt1 = battle_get_opt1 (src);
-    opt2 = battle_get_opt2 (src);
-
-    // ターゲット
-    if (target->type == BL_PC)
-        tsd = (struct map_session_data *) target;
-    else if (target->type == BL_MOB)
-        tmd = (struct mob_data *) target;
-    t_race = battle_get_race (target);
-    t_size = battle_get_size (target);
-    t_mode = battle_get_mode (target);
-    t_sc_data = battle_get_sc_data (target);
-
-    if ((skill_num == 0
-         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
-         || (target->type == BL_MOB
-             && battle_config.monster_auto_counter_type & 2))
-        && skill_lv >= 0)
-    {
-        if (skill_num != CR_GRANDCROSS && t_sc_data
-            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
-        {
-            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
-                battle_get_dir (target);
-            int  dist = distance (src->x, src->y, target->x, target->y);
-            if (dist <= 0 || map_check_dir (dir, t_dir))
-            {
-                memset (&wd, 0, sizeof (wd));
-                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
-                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
-                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
-                {
-                    int  range = battle_get_range (target);
-                    if ((target->type == BL_PC
-                         && ((struct map_session_data *) target)->
-                         status.weapon != 11 && dist <= range + 1)
-                        || (target->type == BL_MOB && range <= 3
-                            && dist <= range + 1))
-                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
-                }
-                return wd;
-            }
-            else
-                ac_flag = 1;
-        }
-    }
-    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // 攻撃の種類の設定
-
-    // 回避率計算、回避判定は後で
-    flee = battle_get_flee (target);
-    if (battle_config.agi_penaly_type > 0
-        || battle_config.vit_penaly_type > 0)
-        target_count +=
-            battle_counttargeted (target, src,
-                                  battle_config.agi_penaly_count_lv);
-    if (battle_config.agi_penaly_type > 0)
-    {
-        if (target_count >= battle_config.agi_penaly_count)
-        {
-            if (battle_config.agi_penaly_type == 1)
-                flee =
-                    (flee *
-                     (100 -
-                      (target_count -
-                       (battle_config.agi_penaly_count -
-                        1)) * battle_config.agi_penaly_num)) / 100;
-            else if (battle_config.agi_penaly_type == 2)
-                flee -=
-                    (target_count -
-                     (battle_config.agi_penaly_count -
-                      1)) * battle_config.agi_penaly_num;
-            if (flee < 1)
-                flee = 1;
-        }
-    }
-    hitrate = battle_get_hit (src) - flee + 80;
-
-    type = 0;                   // normal
-    div_ = 1;                   // single attack
-
-    luk = battle_get_luk (src);
-
-    if (battle_config.enemy_str)
-        damage = battle_get_baseatk (src);
-    else
-        damage = 0;
-    if (skill_num == HW_MAGICCRASHER)
-    {                           /* マジッククラッシャーはMATKで殴る */
-        atkmin = battle_get_matk1 (src);
-        atkmax = battle_get_matk2 (src);
-    }
-    else
-    {
-        atkmin = battle_get_atk (src);
-        atkmax = battle_get_atk2 (src);
-    }
-    if (mob_db[md->mob_class].range > 3)
-        flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-
-    if (atkmin > atkmax)
-        atkmin = atkmax;
-
-    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
-    {                           // マキシマイズパワー
-        atkmin = atkmax;
-    }
-
-    cri = battle_get_critical (src);
-    cri -= battle_get_luk (target) * 3;
-    if (battle_config.enemy_critical_rate != 100)
-    {
-        cri = cri * battle_config.enemy_critical_rate / 100;
-        if (cri < 1)
-            cri = 1;
-    }
-    if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // 睡眠中はクリティカルが倍に
-        cri <<= 1;
-
-    if (ac_flag)
-        cri = 1000;
-
-    if (skill_num == KN_AUTOCOUNTER)
-    {
-        if (!(battle_config.monster_auto_counter_type & 1))
-            cri = 1000;
-        else
-            cri <<= 1;
-    }
-
-    if (tsd && tsd->critical_def)
-        cri = cri * (100 - tsd->critical_def) / 100;
-
-    if ((skill_num == 0 || skill_num == KN_AUTOCOUNTER) && skill_lv >= 0 && battle_config.enemy_critical && (MRAND (1000)) < cri)   // 判定(スキルの場合は無視)
-        // 敵の判定
-    {
-        damage += atkmax;
-        type = 0x0a;
-    }
-    else
-    {
-        int  vitbonusmax;
-
-        if (atkmax > atkmin)
-            damage += atkmin + MRAND ((atkmax - atkmin + 1));
-        else
-            damage += atkmin;
-        // スキル修正1(攻撃力倍化系)
-        // オーバートラスト(+5% 〜 +25%),他攻撃系スキルの場合ここで補正
-        // バッシュ,マグナムブレイク,
-        // ボーリングバッシュ,スピアブーメラン,ブランディッシュスピア,スピアスタッブ,
-        // メマーナイト,カートレボリューション
-        // ダブルストレイフィング,アローシャワー,チャージアロー,
-        // ソニックブロー
-        if (sc_data)
-        {                       //状態異常中のダメージ追加
-            if (sc_data[SC_OVERTHRUST].timer != -1) // オーバートラスト
-                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
-            if (sc_data[SC_TRUESIGHT].timer != -1)  // トゥルーサイト
-                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
-            if (sc_data[SC_BERSERK].timer != -1)    // バーサーク
-                damage += damage * 50 / 100;
-        }
-
-        if (skill_num > 0)
-        {
-            int  i;
-            if ((i = skill_get_pl (skill_num)) > 0)
-                s_ele = i;
-
-            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
-            switch (skill_num)
-            {
-                case SM_BASH:  // バッシュ
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
-                    break;
-                case SM_MAGNUM:    // マグナムブレイク
-                    damage =
-                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
-                    break;
-                case MC_MAMMONITE: // メマーナイト
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    break;
-                case AC_DOUBLE:    // ダブルストレイフィング
-                    damage = damage * (180 + 20 * skill_lv) / 100;
-                    div_ = 2;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case AC_SHOWER:    // アローシャワー
-                    damage = damage * (75 + 5 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case AC_CHARGEARROW:   // チャージアロー
-                    damage = damage * 150 / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case KN_PIERCE:    // ピアース
-                    damage = damage * (100 + 10 * skill_lv) / 100;
-                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
-                    div_ = t_size + 1;
-                    damage *= div_;
-                    break;
-                case KN_SPEARSTAB: // スピアスタブ
-                    damage = damage * (100 + 15 * skill_lv) / 100;
-                    break;
-                case KN_SPEARBOOMERANG:    // スピアブーメラン
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case KN_BRANDISHSPEAR: // ブランディッシュスピア
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    if (skill_lv > 3 && wflag == 1)
-                        damage2 += damage / 2;
-                    if (skill_lv > 6 && wflag == 1)
-                        damage2 += damage / 4;
-                    if (skill_lv > 9 && wflag == 1)
-                        damage2 += damage / 8;
-                    if (skill_lv > 6 && wflag == 2)
-                        damage2 += damage / 2;
-                    if (skill_lv > 9 && wflag == 2)
-                        damage2 += damage / 4;
-                    if (skill_lv > 9 && wflag == 3)
-                        damage2 += damage / 2;
-                    damage += damage2;
-                    blewcount = 0;
-                    break;
-                case KN_BOWLINGBASH:   // ボウリングバッシュ
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    blewcount = 0;
-                    break;
-                case KN_AUTOCOUNTER:
-                    if (battle_config.monster_auto_counter_type & 1)
-                        hitrate += 20;
-                    else
-                        hitrate = 1000000;
-                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
-                    break;
-                case AS_SONICBLOW: // ソニックブロウ
-                    damage = damage * (300 + 50 * skill_lv) / 100;
-                    div_ = 8;
-                    break;
-                case TF_SPRINKLESAND:  // 砂まき
-                    damage = damage * 125 / 100;
-                    break;
-                case MC_CARTREVOLUTION:    // カートレボリューション
-                    damage = (damage * 150) / 100;
-                    break;
-                    // 以下MOB
-                case NPC_COMBOATTACK:  // 多段攻撃
-                    div_ = skill_get_num (skill_num, skill_lv);
-                    damage *= div_;
-                    break;
-                case NPC_RANDOMATTACK: // ランダムATK攻撃
-                    damage = damage * (MPRAND (50, 150)) / 100;
-                    break;
-                    // 属性攻撃(適当)
-                case NPC_WATERATTACK:
-                case NPC_GROUNDATTACK:
-                case NPC_FIREATTACK:
-                case NPC_WINDATTACK:
-                case NPC_POISONATTACK:
-                case NPC_HOLYATTACK:
-                case NPC_DARKNESSATTACK:
-                case NPC_TELEKINESISATTACK:
-                    damage = damage * (100 + 25 * (skill_lv - 1)) / 100;
-                    break;
-                case NPC_GUIDEDATTACK:
-                    hitrate = 1000000;
-                    break;
-                case NPC_RANGEATTACK:
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case NPC_PIERCINGATT:
-                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
-                    break;
-                case RG_BACKSTAP:  // バックスタブ
-                    damage = damage * (300 + 40 * skill_lv) / 100;
-                    hitrate = 1000000;
-                    break;
-                case RG_RAID:  // サプライズアタック
-                    damage = damage * (100 + 40 * skill_lv) / 100;
-                    break;
-                case RG_INTIMIDATE:    // インティミデイト
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    break;
-                case CR_SHIELDCHARGE:  // シールドチャージ
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
-                    s_ele = 0;
-                    break;
-                case CR_SHIELDBOOMERANG:   // シールドブーメラン
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    s_ele = 0;
-                    break;
-                case CR_HOLYCROSS: // ホーリークロス
-                    damage = damage * (100 + 35 * skill_lv) / 100;
-                    div_ = 2;
-                    break;
-                case CR_GRANDCROSS:
-                    hitrate = 1000000;
-                    break;
-                case AM_DEMONSTRATION: // デモンストレーション
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    break;
-                case AM_ACIDTERROR:    // アシッドテラー
-                    damage = damage * (100 + 40 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
-                    break;
-                case MO_FINGEROFFENSIVE:   //指弾
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    div_ = 1;
-                    break;
-                case MO_INVESTIGATE:   // 発 勁
-                    if (def1 < 1000000)
-                        damage =
-                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
-                                                                    def2) /
-                            100;
-                    hitrate = 1000000;
-                    s_ele = 0;
-                    break;
-                case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
-                    damage = damage * 8 + 250 + (skill_lv * 150);
-                    hitrate = 1000000;
-                    s_ele = 0;
-                    break;
-                case MO_CHAINCOMBO:    // 連打掌
-                    damage = damage * (150 + 50 * skill_lv) / 100;
-                    div_ = 4;
-                    break;
-                case BA_MUSICALSTRIKE: // ミュージカルストライク
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case DC_THROWARROW:    // 矢撃ち
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case MO_COMBOFINISH:   // 猛龍拳
-                    damage = damage * (240 + 60 * skill_lv) / 100;
-                    break;
-                case CH_TIGERFIST: // 伏虎拳
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    break;
-                case CH_CHAINCRUSH:    // 連柱崩撃
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    div_ = skill_get_num (skill_num, skill_lv);
-                    break;
-                case CH_PALMSTRIKE:    // 猛虎硬派山
-                    damage = damage * (50 + 100 * skill_lv) / 100;
-                    break;
-                case LK_SPIRALPIERCE:  /* スパイラルピアース */
-                    damage = damage * (100 + 50 * skill_lv) / 100;  //増加量が分からないので適当に
-                    div_ = 5;
-                    if (tsd)
-                        tsd->canmove_tick = gettick () + 1000;
-                    else if (tmd)
-                        tmd->canmove_tick = gettick () + 1000;
-                    break;
-                case LK_HEADCRUSH: /* ヘッドクラッシュ */
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    break;
-                case LK_JOINTBEAT: /* ジョイントビート */
-                    damage = damage * (50 + 10 * skill_lv) / 100;
-                    break;
-                case ASC_METEORASSAULT:    /* メテオアサルト */
-                    damage = damage * (40 + 40 * skill_lv) / 100;
-                    break;
-                case SN_SHARPSHOOTING: /* シャープシューティング */
-                    damage += damage * (30 * skill_lv) / 100;
-                    break;
-                case CG_ARROWVULCAN:   /* アローバルカン */
-                    damage = damage * (160 + 40 * skill_lv) / 100;
-                    div_ = 9;
-                    break;
-                case AS_SPLASHER:  /* ベナムスプラッシャー */
-                    damage = damage * (200 + 20 * skill_lv) / 100;
-                    break;
-            }
-        }
-
-        if (skill_num != NPC_CRITICALSLASH)
-        {
-            // 対 象の防御力によるダメージの減少
-            // ディバインプロテクション(ここでいいのかな?)
-            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
-                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
-            {                   //DEF, VIT無視
-                int  t_def;
-                target_count =
-                    1 + battle_counttargeted (target, src,
-                                              battle_config.vit_penaly_count_lv);
-                if (battle_config.vit_penaly_type > 0)
-                {
-                    if (target_count >= battle_config.vit_penaly_count)
-                    {
-                        if (battle_config.vit_penaly_type == 1)
-                        {
-                            def1 =
-                                (def1 *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                            def2 =
-                                (def2 *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                            t_vit =
-                                (t_vit *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                        }
-                        else if (battle_config.vit_penaly_type == 2)
-                        {
-                            def1 -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                            def2 -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                            t_vit -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                        }
-                        if (def1 < 0)
-                            def1 = 0;
-                        if (def2 < 1)
-                            def2 = 1;
-                        if (t_vit < 1)
-                            t_vit = 1;
-                    }
-                }
-                t_def = def2 * 8 / 10;
-                if (battle_check_undead (s_race, battle_get_elem_type (src))
-                    || s_race == 6)
-                    if (tsd && (skill = pc_checkskill (tsd, AL_DP)) > 0)
-                        t_def += skill * 3;
-
-                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
-                if (battle_config.monster_defense_type)
-                {
-                    damage =
-                        damage - (def1 * battle_config.monster_defense_type) -
-                        t_def -
-                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
-                }
-                else
-                {
-                    damage =
-                        damage * (100 - def1) / 100 - t_def -
-                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
-                }
-            }
-        }
-    }
-
-    // 0未満だった場合1に補正
-    if (damage < 1)
-        damage = 1;
-
-    // 回避修正
-    if (hitrate < 1000000)
-        hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
-    if (hitrate < 1000000 &&    // 必中攻撃
-        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // 睡眠は必中
-                               t_sc_data[SC_STAN].timer != -1 ||    // スタンは必中
-                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // 凍結は必中
-        hitrate = 1000000;
-    if (type == 0 && MRAND (100) >= hitrate)
-    {
-        damage = damage2 = 0;
-        dmg_lv = ATK_FLEE;
-    }
-    else
-    {
-        dmg_lv = ATK_DEF;
-    }
-
-    if (tsd)
-    {
-        int  cardfix = 100, i;
-        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // 属 性によるダメージ耐性
-        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // 種族によるダメージ耐性
-        if (mob_db[md->mob_class].mode & 0x20)
-            cardfix = cardfix * (100 - tsd->subrace[10]) / 100;
-        else
-            cardfix = cardfix * (100 - tsd->subrace[11]) / 100;
-        for (i = 0; i < tsd->add_def_class_count; i++)
-        {
-            if (tsd->add_def_classid[i] == md->mob_class)
-            {
-                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
-                break;
-            }
-        }
-        if (flag & BF_LONG)
-            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;
-        if (flag & BF_SHORT)
-            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;
-        damage = damage * cardfix / 100;
-    }
-    if (t_sc_data)
-    {
-        int  cardfix = 100;
-        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)
-            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;
-        if (cardfix != 100)
-            damage = damage * cardfix / 100;
-    }
-    if (t_sc_data && t_sc_data[SC_ASSUMPTIO].timer != -1)
-    {                           //アシャンプティオ
-        if (!map[target->m].flag.pvp)
-            damage = damage / 3;
-        else
-            damage = damage / 2;
-    }
-
-    if (damage < 0)
-        damage = 0;
-
-    // 属 性の適用
-    if (!((battle_config.mob_ghostring_fix == 1) && (battle_get_element (target) == 8) && (target->type == BL_PC))) // [MouseJstr]
-        if (skill_num != 0 || s_ele != 0
-            || !battle_config.mob_attack_attr_none)
-            damage =
-                battle_attr_fix (damage, s_ele, battle_get_element (target));
-
-    if (sc_data && sc_data[SC_AURABLADE].timer != -1)   /* オーラブレード 必中 */
-        damage += sc_data[SC_AURABLADE].val1 * 10;
-    if (skill_num == PA_PRESSURE)   /* プレッシャー 必中? */
-        damage = 700 + 100 * skill_lv;
-
-    // インベナム修正
-    if (skill_num == TF_POISON)
-    {
-        damage =
-            battle_attr_fix (damage + 15 * skill_lv, s_ele,
-                             battle_get_element (target));
-    }
-    if (skill_num == MC_CARTREVOLUTION)
-    {
-        damage = battle_attr_fix (damage, 0, battle_get_element (target));
-    }
-
-    // 完全回避の判定
-    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL
-        && MRAND (1000) < battle_get_flee2 (target))
-    {
-        damage = 0;
-        type = 0x0b;
-        dmg_lv = ATK_LUCKY;
-    }
-
-    if (battle_config.enemy_perfect_flee)
-    {
-        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL
-            && MRAND (1000) < battle_get_flee2 (target))
-        {
-            damage = 0;
-            type = 0x0b;
-            dmg_lv = ATK_LUCKY;
-        }
-    }
-
-//  if(def1 >= 1000000 && damage > 0)
-    if (t_mode & 0x40 && damage > 0)
-        damage = 1;
-
-    if (tsd && tsd->special_state.no_weapon_damage)
-        damage = 0;
-
-    if (skill_num != CR_GRANDCROSS)
-        damage =
-            battle_calc_damage (src, target, damage, div_, skill_num,
-                                skill_lv, flag);
-
-    wd.damage = damage;
-    wd.damage2 = 0;
-    wd.type = type;
-    wd.div_ = div_;
-    wd.amotion = battle_get_amotion (src);
-    if (skill_num == KN_AUTOCOUNTER)
-        wd.amotion >>= 1;
-    wd.dmotion = battle_get_dmotion (target);
-    wd.blewcount = blewcount;
-    wd.flag = flag;
-    wd.dmg_lv = dmg_lv;
-    return wd;
-}
-
-int battle_is_unarmed (struct block_list *bl)
-{
-    if (!bl)
-        return 0;
-    if (bl->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) bl;
-
-        return (sd->equip_index[EQUIP_SHIELD] == -1
-                && sd->equip_index[EQUIP_WEAPON] == -1);
-    }
-    else
-        return 0;
-}
-
-/*
- * =========================================================================
- * PCの武器による攻撃
- *-------------------------------------------------------------------------
- */
-static struct Damage battle_calc_pc_weapon_attack (struct block_list *src,
-                                                   struct block_list *target,
-                                                   int skill_num,
-                                                   int skill_lv, int wflag)
-{
-    struct map_session_data *sd = (struct map_session_data *) src, *tsd =
-        NULL;
-    struct mob_data *tmd = NULL;
-    int  hitrate, flee, cri = 0, atkmin, atkmax;
-    int  dex, luk, target_count = 1;
-    int  def1 = battle_get_def (target);
-    int  def2 = battle_get_def2 (target);
-    int  t_vit = battle_get_vit (target);
-    struct Damage wd;
-    int  damage, damage2, damage3 = 0, damage4 = 0, type, div_, blewcount =
-        skill_get_blewcount (skill_num, skill_lv);
-    int  flag, skill, dmg_lv = 0;
-    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 7, s_ele = 0;
-    struct status_change *sc_data, *t_sc_data;
-    short *sc_count;
-    short *option, *opt1, *opt2;
-    int  atkmax_ = 0, atkmin_ = 0, s_ele_;  //二刀流用
-    int  watk, watk_, cardfix, t_ele;
-    int  da = 0, i, t_class, ac_flag = 0;
-    int  idef_flag = 0, idef_flag_ = 0;
-    int  target_distance;
-
-    //return前の処理があるので情報出力部のみ変更
-    if (src == NULL || target == NULL || sd == NULL)
-    {
-        nullpo_info (NLP_MARK);
-        memset (&wd, 0, sizeof (wd));
-        return wd;
-    }
-
-    // アタッカー
-    s_race = battle_get_race (src); //種族
-    s_ele = battle_get_attack_element (src);    //属性
-    s_ele_ = battle_get_attack_element2 (src);  //左手属性
-    sc_data = battle_get_sc_data (src); //ステータス異常
-    sc_count = battle_get_sc_count (src);   //ステータス異常の数
-    option = battle_get_option (src);   //鷹とかペコとかカートとか
-    opt1 = battle_get_opt1 (src);   //石化、凍結、スタン、睡眠、暗闇
-    opt2 = battle_get_opt2 (src);   //毒、呪い、沈黙、暗闇?
-
-    if (skill_num != CR_GRANDCROSS) //グランドクロスでないなら
-        sd->state.attack_type = BF_WEAPON;  //攻撃タイプは武器攻撃
-
-    // ターゲット
-    if (target->type == BL_PC)  //対象がPCなら
-        tsd = (struct map_session_data *) target;   //tsdに代入(tmdはNULL)
-    else if (target->type == BL_MOB)    //対象がMobなら
-        tmd = (struct mob_data *) target;   //tmdに代入(tsdはNULL)
-    t_race = battle_get_race (target);  //対象の種族
-    t_ele = battle_get_elem_type (target);  //対象の属性
-    t_size = battle_get_size (target);  //対象のサイズ
-    t_mode = battle_get_mode (target);  //対象のMode
-    t_sc_data = battle_get_sc_data (target);    //対象のステータス異常
-
-//オートカウンター処理ここから
-    if ((skill_num == 0
-         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
-         || (target->type == BL_MOB
-             && battle_config.monster_auto_counter_type & 2))
-        && skill_lv >= 0)
-    {
-        if (skill_num != CR_GRANDCROSS && t_sc_data
-            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
-        {                       //グランドクロスでなく、対象がオートカウンター状態の場合
-            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
-                battle_get_dir (target);
-            int  dist = distance (src->x, src->y, target->x, target->y);
-            if (dist <= 0 || map_check_dir (dir, t_dir))
-            {                   //対象との距離が0以下、または対象の正面?
-                memset (&wd, 0, sizeof (wd));
-                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
-                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
-                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
-                {               //自分がオートカウンター状態
-                    int  range = battle_get_range (target);
-                    if ((target->type == BL_PC && ((struct map_session_data *) target)->status.weapon != 11 && dist <= range + 1) ||    //対象がPCで武器が弓矢でなく射程内
-                        (target->type == BL_MOB && range <= 3 && dist <= range + 1))    //または対象がMobで射程が3以下で射程内
-                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
-                }
-                return wd;      //ダメージ構造体を返して終了
-            }
-            else
-                ac_flag = 1;
-        }
-    }
-//オートカウンター処理ここまで
-
-    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // 攻撃の種類の設定
-
-    // 回避率計算、回避判定は後で
-    flee = battle_get_flee (target);
-    if (battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) //AGI、VITペナルティ設定が有効
-        target_count += battle_counttargeted (target, src, battle_config.agi_penaly_count_lv);  //対象の数を算出
-    if (battle_config.agi_penaly_type > 0)
-    {
-        if (target_count >= battle_config.agi_penaly_count)
-        {                       //ペナルティ設定より対象が多い
-            if (battle_config.agi_penaly_type == 1) //回避率がagi_penaly_num%ずつ減少
-                flee =
-                    (flee *
-                     (100 -
-                      (target_count -
-                       (battle_config.agi_penaly_count -
-                        1)) * battle_config.agi_penaly_num)) / 100;
-            else if (battle_config.agi_penaly_type == 2)    //回避率がagi_penaly_num分減少
-                flee -=
-                    (target_count -
-                     (battle_config.agi_penaly_count -
-                      1)) * battle_config.agi_penaly_num;
-            if (flee < 1)
-                flee = 1;       //回避率は最低でも1
-        }
-    }
-    hitrate = battle_get_hit (src) - flee + 80; //命中率計算
-
-    {                           // [fate] Reduce hit chance by distance
-        int  dx = abs (src->x - target->x);
-        int  dy = abs (src->y - target->y);
-        int  malus_dist;
-
-        target_distance = MAX (dx, dy);
-        malus_dist =
-            MAX (0, target_distance - (skill_power (sd, AC_OWL) / 75));
-        hitrate -= (malus_dist * (malus_dist + 1));
-    }
-
-    dex = battle_get_dex (src); //DEX
-    luk = battle_get_luk (src); //LUK
-    watk = battle_get_atk (src);    //ATK
-    watk_ = battle_get_atk_ (src);  //ATK左手
-
-    type = 0;                   // normal
-    div_ = 1;                   // single attack
-
-    if (skill_num == HW_MAGICCRASHER)
-    {                           /* マジッククラッシャーはMATKで殴る */
-        damage = damage2 = battle_get_matk1 (src);  //damega,damega2初登場、base_atkの取得
-    }
-    else
-    {
-        damage = damage2 = battle_get_baseatk (&sd->bl);    //damega,damega2初登場、base_atkの取得
-    }
-    if (sd->attackrange > 2)
-    {                           // [fate] ranged weapon?
-        const int range_damage_bonus = 80;  // up to 31.25% bonus for long-range hit
-        damage =
-            damage * (256 +
-                      ((range_damage_bonus * target_distance) /
-                       sd->attackrange)) >> 8;
-        damage2 =
-            damage2 * (256 +
-                       ((range_damage_bonus * target_distance) /
-                        sd->attackrange)) >> 8;
-    }
-
-    atkmin = atkmin_ = dex;     //最低ATKはDEXで初期化?
-    sd->state.arrow_atk = 0;    //arrow_atk初期化
-    if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]])
-        atkmin =
-            atkmin * (80 +
-                      sd->inventory_data[sd->equip_index[9]]->wlv * 20) / 100;
-    if (sd->equip_index[8] >= 0 && sd->inventory_data[sd->equip_index[8]])
-        atkmin_ =
-            atkmin_ * (80 +
-                       sd->inventory_data[sd->equip_index[8]]->wlv * 20) /
-            100;
-    if (sd->status.weapon == 11)
-    {                           //武器が弓矢の場合
-        atkmin = watk * ((atkmin < watk) ? atkmin : watk) / 100;    //弓用最低ATK計算
-        flag = (flag & ~BF_RANGEMASK) | BF_LONG;    //遠距離攻撃フラグを有効
-        if (sd->arrow_ele > 0)  //属性矢なら属性を矢の属性に変更
-            s_ele = sd->arrow_ele;
-        sd->state.arrow_atk = 1;    //arrow_atk有効化
-    }
-
-    // サイズ修正
-    // ペコ騎乗していて、槍で攻撃した場合は中型のサイズ修正を100にする
-    // ウェポンパーフェクション,ドレイクC
-    if (((sd->special_state.no_sizefix)
-         || (pc_isriding (sd)
-             && (sd->status.weapon == 4 || sd->status.weapon == 5)
-             && t_size == 1) || skill_num == MO_EXTREMITYFIST))
-    {                           //ペコ騎乗していて、槍で中型を攻撃
-        atkmax = watk;
-        atkmax_ = watk_;
-    }
-    else
-    {
-        atkmax = (watk * sd->atkmods[t_size]) / 100;
-        atkmin = (atkmin * sd->atkmods[t_size]) / 100;
-        atkmax_ = (watk_ * sd->atkmods_[t_size]) / 100;
-        atkmin_ = (atkmin_ * sd->atkmods[t_size]) / 100;
-    }
-    if ((sc_data != NULL && sc_data[SC_WEAPONPERFECTION].timer != -1)
-        || (sd->special_state.no_sizefix))
-    {                           // ウェポンパーフェクション || ドレイクカード
-        atkmax = watk;
-        atkmax_ = watk_;
-    }
-
-    if (atkmin > atkmax && !(sd->state.arrow_atk))
-        atkmin = atkmax;        //弓は最低が上回る場合あり
-    if (atkmin_ > atkmax_)
-        atkmin_ = atkmax_;
-
-    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
-    {                           // マキシマイズパワー
-        atkmin = atkmax;
-        atkmin_ = atkmax_;
-    }
-
-    //ダブルアタック判定
-    if (sd->weapontype1 == 0x01)
-    {
-        if (skill_num == 0 && skill_lv >= 0
-            && (skill = pc_checkskill (sd, TF_DOUBLE)) > 0)
-            da = (MRAND (100) < (skill * 5)) ? 1 : 0;
-    }
-
-    //三段掌
-    if (skill_num == 0 && skill_lv >= 0
-        && (skill = pc_checkskill (sd, MO_TRIPLEATTACK)) > 0
-        && sd->status.weapon <= 16 && !sd->state.arrow_atk)
-    {
-        da = (MRAND (100) < (30 - skill)) ? 2 : 0;
-    }
-
-    if (sd->double_rate > 0 && da == 0 && skill_num == 0 && skill_lv >= 0)
-        da = (MRAND (100) < sd->double_rate) ? 1 : 0;
-
-    // 過剰精錬ボーナス
-    if (sd->overrefine > 0)
-        damage += MPRAND (1, sd->overrefine);
-    if (sd->overrefine_ > 0)
-        damage2 += MPRAND (1, sd->overrefine_);
-
-    if (da == 0)
-    {                           //ダブルアタックが発動していない
-        // クリティカル計算
-        cri = battle_get_critical (src);
-
-        if (sd->state.arrow_atk)
-            cri += sd->arrow_cri;
-        if (sd->status.weapon == 16)
-            // カタールの場合、クリティカルを倍に
-            cri <<= 1;
-        cri -= battle_get_luk (target) * 3;
-        if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // 睡眠中はクリティカルが倍に
-            cri <<= 1;
-        if (ac_flag)
-            cri = 1000;
-
-        if (skill_num == KN_AUTOCOUNTER)
-        {
-            if (!(battle_config.pc_auto_counter_type & 1))
-                cri = 1000;
-            else
-                cri <<= 1;
-        }
-
-        if (skill_num == SN_SHARPSHOOTING && MRAND (100) < 50)
-            cri = 1000;
-    }
-
-    if (tsd && tsd->critical_def)
-        cri = cri * (100 - tsd->critical_def) / 100;
-
-    if (da == 0 && (skill_num == 0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && skill_lv >= 0 && //ダブルアタックが発動していない
-        (MRAND (1000)) < cri)   // 判定(スキルの場合は無視)
-    {
-        damage += atkmax;
-        damage2 += atkmax_;
-        if (sd->atk_rate != 100)
-        {
-            damage = (damage * sd->atk_rate) / 100;
-            damage2 = (damage2 * sd->atk_rate) / 100;
-        }
-        if (sd->state.arrow_atk)
-            damage += sd->arrow_atk;
-        type = 0x0a;
-
-/*		if(def1 < 1000000) {
-			if(sd->def_ratio_atk_ele & (1<<t_ele) || sd->def_ratio_atk_race & (1<<t_race)) {
-				damage = (damage * (def1 + def2))/100;
-				idef_flag = 1;
-			}
-			if(sd->def_ratio_atk_ele_ & (1<<t_ele) || sd->def_ratio_atk_race_ & (1<<t_race)) {
-				damage2 = (damage2 * (def1 + def2))/100;
-				idef_flag_ = 1;
-			}
-			if(t_mode & 0x20) {
-				if(!idef_flag && sd->def_ratio_atk_race & (1<<10)) {
-					damage = (damage * (def1 + def2))/100;
-					idef_flag = 1;
-				}
-				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<10)) {
-					damage2 = (damage2 * (def1 + def2))/100;
-					idef_flag_ = 1;
-				}
-			}
-			else {
-				if(!idef_flag && sd->def_ratio_atk_race & (1<<11)) {
-					damage = (damage * (def1 + def2))/100;
-					idef_flag = 1;
-				}
-				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<11)) {
-					damage2 = (damage2 * (def1 + def2))/100;
-					idef_flag_ = 1;
-				}
-			}
-		}*/
-    }
-    else
-    {
-        int  vitbonusmax;
-
-        if (atkmax > atkmin)
-            damage += atkmin + MRAND ((atkmax - atkmin + 1));
-        else
-            damage += atkmin;
-        if (atkmax_ > atkmin_)
-            damage2 += atkmin_ + MRAND ((atkmax_ - atkmin_ + 1));
-        else
-            damage2 += atkmin_;
-        if (sd->atk_rate != 100)
-        {
-            damage = (damage * sd->atk_rate) / 100;
-            damage2 = (damage2 * sd->atk_rate) / 100;
-        }
-
-        if (sd->state.arrow_atk)
-        {
-            if (sd->arrow_atk > 0)
-                damage += MRAND ((sd->arrow_atk + 1));
-            hitrate += sd->arrow_hit;
-        }
-
-        if (skill_num != MO_INVESTIGATE && def1 < 1000000)
-        {
-            if (sd->def_ratio_atk_ele & (1 << t_ele)
-                || sd->def_ratio_atk_race & (1 << t_race))
-            {
-                damage = (damage * (def1 + def2)) / 100;
-                idef_flag = 1;
-            }
-            if (sd->def_ratio_atk_ele_ & (1 << t_ele)
-                || sd->def_ratio_atk_race_ & (1 << t_race))
-            {
-                damage2 = (damage2 * (def1 + def2)) / 100;
-                idef_flag_ = 1;
-            }
-            if (t_mode & 0x20)
-            {
-                if (!idef_flag && sd->def_ratio_atk_race & (1 << 10))
-                {
-                    damage = (damage * (def1 + def2)) / 100;
-                    idef_flag = 1;
-                }
-                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 10))
-                {
-                    damage2 = (damage2 * (def1 + def2)) / 100;
-                    idef_flag_ = 1;
-                }
-            }
-            else
-            {
-                if (!idef_flag && sd->def_ratio_atk_race & (1 << 11))
-                {
-                    damage = (damage * (def1 + def2)) / 100;
-                    idef_flag = 1;
-                }
-                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 11))
-                {
-                    damage2 = (damage2 * (def1 + def2)) / 100;
-                    idef_flag_ = 1;
-                }
-            }
-        }
-
-        // スキル修正1(攻撃力倍化系)
-        // オーバートラスト(+5% 〜 +25%),他攻撃系スキルの場合ここで補正
-        // バッシュ,マグナムブレイク,
-        // ボーリングバッシュ,スピアブーメラン,ブランディッシュスピア,スピアスタッブ,
-        // メマーナイト,カートレボリューション
-        // ダブルストレイフィング,アローシャワー,チャージアロー,
-        // ソニックブロー
-        if (sc_data)
-        {                       //状態異常中のダメージ追加
-            if (sc_data[SC_OVERTHRUST].timer != -1)
-            {                   // オーバートラスト
-                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
-                damage2 += damage2 * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
-            }
-            if (sc_data[SC_TRUESIGHT].timer != -1)
-            {                   // トゥルーサイト
-                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
-                damage2 += damage2 * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
-            }
-            if (sc_data[SC_BERSERK].timer != -1)
-            {                   // バーサーク
-                damage += damage * 50 / 100;
-                damage2 += damage2 * 50 / 100;
-            }
-        }
-
-        if (skill_num > 0)
-        {
-            int  i;
-            if ((i = skill_get_pl (skill_num)) > 0)
-                s_ele = s_ele_ = i;
-
-            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
-            switch (skill_num)
-            {
-                case SM_BASH:  // バッシュ
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
-                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
-                    break;
-                case SM_MAGNUM:    // マグナムブレイク
-                    damage =
-                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
-                    damage2 =
-                        damage2 * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
-                    break;
-                case MC_MAMMONITE: // メマーナイト
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                    break;
-                case AC_DOUBLE:    // ダブルストレイフィング
-                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
-                    {
-                        int  arr = MRAND ((sd->arrow_atk + 1));
-                        damage += arr;
-                        damage2 += arr;
-                    }
-                    damage = damage * (180 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (180 + 20 * skill_lv) / 100;
-                    div_ = 2;
-                    if (sd->arrow_ele > 0)
-                    {
-                        s_ele = sd->arrow_ele;
-                        s_ele_ = sd->arrow_ele;
-                    }
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    sd->state.arrow_atk = 1;
-                    break;
-                case AC_SHOWER:    // アローシャワー
-                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
-                    {
-                        int  arr = MRAND ((sd->arrow_atk + 1));
-                        damage += arr;
-                        damage2 += arr;
-                    }
-                    damage = damage * (75 + 5 * skill_lv) / 100;
-                    damage2 = damage2 * (75 + 5 * skill_lv) / 100;
-                    if (sd->arrow_ele > 0)
-                    {
-                        s_ele = sd->arrow_ele;
-                        s_ele_ = sd->arrow_ele;
-                    }
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    sd->state.arrow_atk = 1;
-                    break;
-                case AC_CHARGEARROW:   // チャージアロー
-                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
-                    {
-                        int  arr = MRAND ((sd->arrow_atk + 1));
-                        damage += arr;
-                        damage2 += arr;
-                    }
-                    damage = damage * 150 / 100;
-                    damage2 = damage2 * 150 / 100;
-                    if (sd->arrow_ele > 0)
-                    {
-                        s_ele = sd->arrow_ele;
-                        s_ele_ = sd->arrow_ele;
-                    }
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    sd->state.arrow_atk = 1;
-                    break;
-                case KN_PIERCE:    // ピアース
-                    damage = damage * (100 + 10 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 10 * skill_lv) / 100;
-                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
-                    div_ = t_size + 1;
-                    damage *= div_;
-                    damage2 *= div_;
-                    break;
-                case KN_SPEARSTAB: // スピアスタブ
-                    damage = damage * (100 + 15 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 15 * skill_lv) / 100;
-                    break;
-                case KN_SPEARBOOMERANG:    // スピアブーメラン
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case KN_BRANDISHSPEAR: // ブランディッシュスピア
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    if (skill_lv > 3 && wflag == 1)
-                        damage3 += damage / 2;
-                    if (skill_lv > 6 && wflag == 1)
-                        damage3 += damage / 4;
-                    if (skill_lv > 9 && wflag == 1)
-                        damage3 += damage / 8;
-                    if (skill_lv > 6 && wflag == 2)
-                        damage3 += damage / 2;
-                    if (skill_lv > 9 && wflag == 2)
-                        damage3 += damage / 4;
-                    if (skill_lv > 9 && wflag == 3)
-                        damage3 += damage / 2;
-                    damage += damage3;
-                    if (skill_lv > 3 && wflag == 1)
-                        damage4 += damage2 / 2;
-                    if (skill_lv > 6 && wflag == 1)
-                        damage4 += damage2 / 4;
-                    if (skill_lv > 9 && wflag == 1)
-                        damage4 += damage2 / 8;
-                    if (skill_lv > 6 && wflag == 2)
-                        damage4 += damage2 / 2;
-                    if (skill_lv > 9 && wflag == 2)
-                        damage4 += damage2 / 4;
-                    if (skill_lv > 9 && wflag == 3)
-                        damage4 += damage2 / 2;
-                    damage2 += damage4;
-                    blewcount = 0;
-                    break;
-                case KN_BOWLINGBASH:   // ボウリングバッシュ
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                    blewcount = 0;
-                    break;
-                case KN_AUTOCOUNTER:
-                    if (battle_config.pc_auto_counter_type & 1)
-                        hitrate += 20;
-                    else
-                        hitrate = 1000000;
-                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
-                    break;
-                case AS_SONICBLOW: // ソニックブロウ
-                    hitrate += 30;  // hitrate +30, thanks to midas
-                    damage = damage * (300 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (300 + 50 * skill_lv) / 100;
-                    div_ = 8;
-                    break;
-                case TF_SPRINKLESAND:  // 砂まき
-                    damage = damage * 125 / 100;
-                    damage2 = damage2 * 125 / 100;
-                    break;
-                case MC_CARTREVOLUTION:    // カートレボリューション
-                    if (sd->cart_max_weight > 0 && sd->cart_weight > 0)
-                    {
-                        damage =
-                            (damage *
-                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
-                              (sd->cart_weight * 100 /
-                               sd->cart_max_weight))) / 100;
-                        damage2 =
-                            (damage2 *
-                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
-                              (sd->cart_weight * 100 /
-                               sd->cart_max_weight))) / 100;
-                    }
-                    else
-                    {
-                        damage = (damage * 150) / 100;
-                        damage2 = (damage2 * 150) / 100;
-                    }
-                    break;
-                    // 以下MOB
-                case NPC_COMBOATTACK:  // 多段攻撃
-                    div_ = skill_get_num (skill_num, skill_lv);
-                    damage *= div_;
-                    damage2 *= div_;
-                    break;
-                case NPC_RANDOMATTACK: // ランダムATK攻撃
-                    damage = damage * (MPRAND (50, 150)) / 100;
-                    damage2 = damage2 * (MPRAND (50, 150)) / 100;
-                    break;
-                    // 属性攻撃(適当)
-                case NPC_WATERATTACK:
-                case NPC_GROUNDATTACK:
-                case NPC_FIREATTACK:
-                case NPC_WINDATTACK:
-                case NPC_POISONATTACK:
-                case NPC_HOLYATTACK:
-                case NPC_DARKNESSATTACK:
-                case NPC_TELEKINESISATTACK:
-                    damage = damage * (100 + 25 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 25 * skill_lv) / 100;
-                    break;
-                case NPC_GUIDEDATTACK:
-                    hitrate = 1000000;
-                    break;
-                case NPC_RANGEATTACK:
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    break;
-                case NPC_PIERCINGATT:
-                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
-                    break;
-                case RG_BACKSTAP:  // バックスタブ
-                    if (battle_config.backstab_bow_penalty == 1
-                        && sd->status.weapon == 11)
-                    {
-                        damage = (damage * (300 + 40 * skill_lv) / 100) / 2;
-                        damage2 = (damage2 * (300 + 40 * skill_lv) / 100) / 2;
-                    }
-                    else
-                    {
-                        damage = damage * (300 + 40 * skill_lv) / 100;
-                        damage2 = damage2 * (300 + 40 * skill_lv) / 100;
-                    }
-                    hitrate = 1000000;
-                    break;
-                case RG_RAID:  // サプライズアタック
-                    damage = damage * (100 + 40 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
-                    break;
-                case RG_INTIMIDATE:    // インティミデイト
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
-                    break;
-                case CR_SHIELDCHARGE:  // シールドチャージ
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
-                    s_ele = 0;
-                    break;
-                case CR_SHIELDBOOMERANG:   // シールドブーメラン
-                    damage = damage * (100 + 30 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    s_ele = 0;
-                    break;
-                case CR_HOLYCROSS: // ホーリークロス
-                    damage = damage * (100 + 35 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 35 * skill_lv) / 100;
-                    div_ = 2;
-                    break;
-                case CR_GRANDCROSS:
-                    hitrate = 1000000;
-                    break;
-                case AM_DEMONSTRATION: // デモンストレーション
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    break;
-                case AM_ACIDTERROR:    // アシッドテラー
-                    damage = damage * (100 + 40 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
-                    break;
-                case MO_FINGEROFFENSIVE:   //指弾
-                    if (battle_config.finger_offensive_type == 0)
-                    {
-                        damage =
-                            damage * (100 +
-                                      50 * skill_lv) / 100 *
-                            sd->spiritball_old;
-                        damage2 =
-                            damage2 * (100 +
-                                       50 * skill_lv) / 100 *
-                            sd->spiritball_old;
-                        div_ = sd->spiritball_old;
-                    }
-                    else
-                    {
-                        damage = damage * (100 + 50 * skill_lv) / 100;
-                        damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                        div_ = 1;
-                    }
-                    break;
-                case MO_INVESTIGATE:   // 発 勁
-                    if (def1 < 1000000)
-                    {
-                        damage =
-                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
-                                                                    def2) /
-                            100;
-                        damage2 =
-                            damage2 * (100 + 75 * skill_lv) / 100 * (def1 +
-                                                                     def2) /
-                            100;
-                    }
-                    hitrate = 1000000;
-                    s_ele = 0;
-                    s_ele_ = 0;
-                    break;
-                case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
-                    damage =
-                        damage * (8 + ((sd->status.sp) / 10)) + 250 +
-                        (skill_lv * 150);
-                    damage2 =
-                        damage2 * (8 + ((sd->status.sp) / 10)) + 250 +
-                        (skill_lv * 150);
-                    sd->status.sp = 0;
-                    clif_updatestatus (sd, SP_SP);
-                    hitrate = 1000000;
-                    s_ele = 0;
-                    s_ele_ = 0;
-                    break;
-                case MO_CHAINCOMBO:    // 連打掌
-                    damage = damage * (150 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (150 + 50 * skill_lv) / 100;
-                    div_ = 4;
-                    break;
-                case MO_COMBOFINISH:   // 猛龍拳
-                    damage = damage * (240 + 60 * skill_lv) / 100;
-                    damage2 = damage2 * (240 + 60 * skill_lv) / 100;
-                    break;
-                case BA_MUSICALSTRIKE: // ミュージカルストライク
-                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
-                    {
-                        int  arr = MRAND ((sd->arrow_atk + 1));
-                        damage += arr;
-                        damage2 += arr;
-                    }
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                    if (sd->arrow_ele > 0)
-                    {
-                        s_ele = sd->arrow_ele;
-                        s_ele_ = sd->arrow_ele;
-                    }
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    sd->state.arrow_atk = 1;
-                    break;
-                case DC_THROWARROW:    // 矢撃ち
-                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
-                    {
-                        int  arr = MRAND ((sd->arrow_atk + 1));
-                        damage += arr;
-                        damage2 += arr;
-                    }
-                    damage = damage * (100 + 50 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
-                    if (sd->arrow_ele > 0)
-                    {
-                        s_ele = sd->arrow_ele;
-                        s_ele_ = sd->arrow_ele;
-                    }
-                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
-                    sd->state.arrow_atk = 1;
-                    break;
-                case CH_TIGERFIST: // 伏虎拳
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    break;
-                case CH_CHAINCRUSH:    // 連柱崩撃
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    div_ = skill_get_num (skill_num, skill_lv);
-                    break;
-                case CH_PALMSTRIKE:    // 猛虎硬派山
-                    damage = damage * (50 + 100 * skill_lv) / 100;
-                    damage2 = damage2 * (50 + 100 * skill_lv) / 100;
-                    break;
-                case LK_SPIRALPIERCE:  /* スパイラルピアース */
-                    damage = damage * (100 + 50 * skill_lv) / 100;  //増加量が分からないので適当に
-                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;    //増加量が分からないので適当に
-                    div_ = 5;
-                    if (tsd)
-                        tsd->canmove_tick = gettick () + 1000;
-                    else if (tmd)
-                        tmd->canmove_tick = gettick () + 1000;
-                    break;
-                case LK_HEADCRUSH: /* ヘッドクラッシュ */
-                    damage = damage * (100 + 20 * skill_lv) / 100;
-                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
-                    break;
-                case LK_JOINTBEAT: /* ジョイントビート */
-                    damage = damage * (50 + 10 * skill_lv) / 100;
-                    damage2 = damage2 * (50 + 10 * skill_lv) / 100;
-                    break;
-                case ASC_METEORASSAULT:    /* メテオアサルト */
-                    damage = damage * (40 + 40 * skill_lv) / 100;
-                    damage2 = damage2 * (40 + 40 * skill_lv) / 100;
-                    break;
-                case SN_SHARPSHOOTING: /* シャープシューティング */
-                    damage += damage * (30 * skill_lv) / 100;
-                    damage2 += damage2 * (30 * skill_lv) / 100;
-                    break;
-                case CG_ARROWVULCAN:   /* アローバルカン */
-                    damage = damage * (160 + 40 * skill_lv) / 100;
-                    damage2 = damage2 * (160 + 40 * skill_lv) / 100;
-                    div_ = 9;
-                    break;
-                case AS_SPLASHER:  /* ベナムスプラッシャー */
-                    damage =
-                        damage * (200 + 20 * skill_lv +
-                                  20 * pc_checkskill (sd,
-                                                      AS_POISONREACT)) / 100;
-                    damage2 =
-                        damage2 * (200 + 20 * skill_lv +
-                                   20 * pc_checkskill (sd,
-                                                       AS_POISONREACT)) / 100;
-                    break;
-                case PA_SACRIFICE:
-                    if (sd)
-                    {
-                        int  hp, mhp, damage3;
-                        hp = battle_get_hp (src);
-                        mhp = battle_get_max_hp (src);
-                        damage3 = mhp * ((skill_lv / 2) + (50 / 100)) / 100;
-                        damage =
-                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
-                        damage2 =
-                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
-                    }
-                    break;
-                case ASC_BREAKER:  // -- moonsoul (special damage for ASC_BREAKER skill)
-                    if (sd)
-                    {
-                        int  damage3;
-                        int  mdef1 = battle_get_mdef (target);
-                        int  mdef2 = battle_get_mdef2 (target);
-                        int  imdef_flag = 0;
-
-                        damage =
-                            ((damage * 5) +
-                             (skill_lv * battle_get_int (src) * 5) +
-                             MRAND (500) + 500) / 2;
-                        damage2 =
-                            ((damage2 * 5) +
-                             (skill_lv * battle_get_int (src) * 5) +
-                             MRAND (500) + 500) / 2;
-                        damage3 = damage;
-                        hitrate = 1000000;
-
-                        if (sd->ignore_mdef_ele & (1 << t_ele)
-                            || sd->ignore_mdef_race & (1 << t_race))
-                            imdef_flag = 1;
-                        if (t_mode & 0x20)
-                        {
-                            if (sd->ignore_mdef_race & (1 << 10))
-                                imdef_flag = 1;
-                        }
-                        else
-                        {
-                            if (sd->ignore_mdef_race & (1 << 11))
-                                imdef_flag = 1;
-                        }
-                        if (!imdef_flag)
-                        {
-                            if (battle_config.magic_defense_type)
-                            {
-                                damage3 =
-                                    damage3 -
-                                    (mdef1 *
-                                     battle_config.magic_defense_type) -
-                                    mdef2;
-                            }
-                            else
-                            {
-                                damage3 =
-                                    (damage3 * (100 - mdef1)) / 100 - mdef2;
-                            }
-                        }
-
-                        if (damage3 < 1)
-                            damage3 = 1;
-
-                        damage3 =
-                            battle_attr_fix (damage2, s_ele_,
-                                             battle_get_element (target));
-                    }
-                    break;
-            }
-        }
-        if (da == 2)
-        {                       //三段掌が発動しているか
-            type = 0x08;
-            div_ = 255;         //三段掌用に…
-            damage =
-                damage * (100 +
-                          20 * pc_checkskill (sd, MO_TRIPLEATTACK)) / 100;
-        }
-
-        if (skill_num != NPC_CRITICALSLASH)
-        {
-            // 対 象の防御力によるダメージの減少
-            // ディバインプロテクション(ここでいいのかな?)
-            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
-                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
-            {                   //DEF, VIT無視
-                int  t_def;
-                target_count =
-                    1 + battle_counttargeted (target, src,
-                                              battle_config.vit_penaly_count_lv);
-                if (battle_config.vit_penaly_type > 0)
-                {
-                    if (target_count >= battle_config.vit_penaly_count)
-                    {
-                        if (battle_config.vit_penaly_type == 1)
-                        {
-                            def1 =
-                                (def1 *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                            def2 =
-                                (def2 *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                            t_vit =
-                                (t_vit *
-                                 (100 -
-                                  (target_count -
-                                   (battle_config.vit_penaly_count -
-                                    1)) * battle_config.vit_penaly_num)) /
-                                100;
-                        }
-                        else if (battle_config.vit_penaly_type == 2)
-                        {
-                            def1 -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                            def2 -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                            t_vit -=
-                                (target_count -
-                                 (battle_config.vit_penaly_count -
-                                  1)) * battle_config.vit_penaly_num;
-                        }
-                        if (def1 < 0)
-                            def1 = 0;
-                        if (def2 < 1)
-                            def2 = 1;
-                        if (t_vit < 1)
-                            t_vit = 1;
-                    }
-                }
-                t_def = def2 * 8 / 10;
-                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
-                if (sd->ignore_def_ele & (1 << t_ele)
-                    || sd->ignore_def_race & (1 << t_race))
-                    idef_flag = 1;
-                if (sd->ignore_def_ele_ & (1 << t_ele)
-                    || sd->ignore_def_race_ & (1 << t_race))
-                    idef_flag_ = 1;
-                if (t_mode & 0x20)
-                {
-                    if (sd->ignore_def_race & (1 << 10))
-                        idef_flag = 1;
-                    if (sd->ignore_def_race_ & (1 << 10))
-                        idef_flag_ = 1;
-                }
-                else
-                {
-                    if (sd->ignore_def_race & (1 << 11))
-                        idef_flag = 1;
-                    if (sd->ignore_def_race_ & (1 << 11))
-                        idef_flag_ = 1;
-                }
-
-                if (!idef_flag)
-                {
-                    if (battle_config.player_defense_type)
-                    {
-                        damage =
-                            damage -
-                            (def1 * battle_config.player_defense_type) -
-                            t_def -
-                            ((vitbonusmax <
-                              1) ? 0 : MRAND ((vitbonusmax + 1)));
-                    }
-                    else
-                    {
-                        damage =
-                            damage * (100 - def1) / 100 - t_def -
-                            ((vitbonusmax <
-                              1) ? 0 : MRAND ((vitbonusmax + 1)));
-                    }
-                }
-                if (!idef_flag_)
-                {
-                    if (battle_config.player_defense_type)
-                    {
-                        damage2 =
-                            damage2 -
-                            (def1 * battle_config.player_defense_type) -
-                            t_def -
-                            ((vitbonusmax <
-                              1) ? 0 : MRAND ((vitbonusmax + 1)));
-                    }
-                    else
-                    {
-                        damage2 =
-                            damage2 * (100 - def1) / 100 - t_def -
-                            ((vitbonusmax <
-                              1) ? 0 : MRAND ((vitbonusmax + 1)));
-                    }
-                }
-            }
-        }
-    }
-    // 精錬ダメージの追加
-    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST)
-    {                           //DEF, VIT無視
-        damage += battle_get_atk2 (src);
-        damage2 += battle_get_atk_2 (src);
-    }
-    if (skill_num == CR_SHIELDBOOMERANG)
-    {
-        if (sd->equip_index[8] >= 0)
-        {
-            int  index = sd->equip_index[8];
-            if (sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 5)
-            {
-                damage += sd->inventory_data[index]->weight / 10;
-                damage +=
-                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
-                                                                            1);
-            }
-        }
-    }
-    if (skill_num == LK_SPIRALPIERCE)
-    {                           /* スパイラルピアース */
-        if (sd->equip_index[9] >= 0)
-        {                       //重量で追加ダメージらしいのでシールドブーメランを参考に追加
-            int  index = sd->equip_index[9];
-            if (sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 4)
-            {
-                damage +=
-                    (int) (double) (sd->inventory_data[index]->weight *
-                                    (0.8 * skill_lv * 4 / 10));
-                damage +=
-                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
-                                                                            1);
-            }
-        }
-    }
-
-    // 0未満だった場合1に補正
-    if (damage < 1)
-        damage = 1;
-    if (damage2 < 1)
-        damage2 = 1;
-
-    // スキル修正2(修練系)
-    // 修練ダメージ(右手のみ) ソニックブロー時は別処理(1撃に付き1/8適応)
-    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
-        && skill_num != CR_GRANDCROSS)
-    {                           //修練ダメージ無視
-        damage = battle_addmastery (sd, target, damage, 0);
-        damage2 = battle_addmastery (sd, target, damage2, 1);
-    }
-
-    if (sd->perfect_hit > 0)
-    {
-        if (MRAND (100) < sd->perfect_hit)
-            hitrate = 1000000;
-    }
-
-    // 回避修正
-    hitrate = (hitrate < 5) ? 5 : hitrate;
-    if (hitrate < 1000000 &&    // 必中攻撃
-        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // 睡眠は必中
-                               t_sc_data[SC_STAN].timer != -1 ||    // スタンは必中
-                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // 凍結は必中
-        hitrate = 1000000;
-    if (type == 0 && MRAND (100) >= hitrate)
-    {
-        damage = damage2 = 0;
-        dmg_lv = ATK_FLEE;
-    }
-    else
-    {
-        dmg_lv = ATK_DEF;
-    }
-    // スキル修正3(武器研究)
-    if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0)
-    {
-        damage += skill * 2;
-        damage2 += skill * 2;
-    }
-    //Advanced Katar Research by zanetheinsane
-    if (sd->weapontype1 == 0x10 || sd->weapontype2 == 0x10)
-    {
-        if ((skill = pc_checkskill (sd, ASC_KATAR)) > 0)
-        {
-            damage += (damage * ((skill * 2) + 10)) / 100;
-        }
-    }
-
-//スキルによるダメージ補正ここまで
-
-//カードによるダメージ追加処理ここから
-    cardfix = 100;
-    if (!sd->state.arrow_atk)
-    {                           //弓矢以外
-        if (!battle_config.left_cardfix_to_right)
-        {                       //左手カード補正設定無し
-            cardfix = cardfix * (100 + sd->addrace[t_race]) / 100;  // 種族によるダメージ修正
-            cardfix = cardfix * (100 + sd->addele[t_ele]) / 100;    // 属性によるダメージ修正
-            cardfix = cardfix * (100 + sd->addsize[t_size]) / 100;  // サイズによるダメージ修正
-        }
-        else
-        {
-            cardfix = cardfix * (100 + sd->addrace[t_race] + sd->addrace_[t_race]) / 100;   // 種族によるダメージ修正(左手による追加あり)
-            cardfix = cardfix * (100 + sd->addele[t_ele] + sd->addele_[t_ele]) / 100;   // 属性によるダメージ修正(左手による追加あり)
-            cardfix = cardfix * (100 + sd->addsize[t_size] + sd->addsize_[t_size]) / 100;   // サイズによるダメージ修正(左手による追加あり)
-        }
-    }
-    else
-    {                           //弓矢
-        cardfix = cardfix * (100 + sd->addrace[t_race] + sd->arrow_addrace[t_race]) / 100;  // 種族によるダメージ修正(弓矢による追加あり)
-        cardfix = cardfix * (100 + sd->addele[t_ele] + sd->arrow_addele[t_ele]) / 100;  // 属性によるダメージ修正(弓矢による追加あり)
-        cardfix = cardfix * (100 + sd->addsize[t_size] + sd->arrow_addsize[t_size]) / 100;  // サイズによるダメージ修正(弓矢による追加あり)
-    }
-    if (t_mode & 0x20)
-    {                           //ボス
-        if (!sd->state.arrow_atk)
-        {                       //弓矢攻撃以外なら
-            if (!battle_config.left_cardfix_to_right)   //左手カード補正設定無し
-                cardfix = cardfix * (100 + sd->addrace[10]) / 100;  //ボスモンスターに追加ダメージ
-            else                //左手カード補正設定あり
-                cardfix = cardfix * (100 + sd->addrace[10] + sd->addrace_[10]) / 100;   //ボスモンスターに追加ダメージ(左手による追加あり)
-        }
-        else                    //弓矢攻撃
-            cardfix = cardfix * (100 + sd->addrace[10] + sd->arrow_addrace[10]) / 100;  //ボスモンスターに追加ダメージ(弓矢による追加あり)
-    }
-    else
-    {                           //ボスじゃない
-        if (!sd->state.arrow_atk)
-        {                       //弓矢攻撃以外
-            if (!battle_config.left_cardfix_to_right)   //左手カード補正設定無し
-                cardfix = cardfix * (100 + sd->addrace[11]) / 100;  //ボス以外モンスターに追加ダメージ
-            else                //左手カード補正設定あり
-                cardfix = cardfix * (100 + sd->addrace[11] + sd->addrace_[11]) / 100;   //ボス以外モンスターに追加ダメージ(左手による追加あり)
-        }
-        else
-            cardfix = cardfix * (100 + sd->addrace[11] + sd->arrow_addrace[11]) / 100;  //ボス以外モンスターに追加ダメージ(弓矢による追加あり)
-    }
-    //特定Class用補正処理(少女の日記→ボンゴン用?)
-    t_class = battle_get_class (target);
-    for (i = 0; i < sd->add_damage_class_count; i++)
-    {
-        if (sd->add_damage_classid[i] == t_class)
-        {
-            cardfix = cardfix * (100 + sd->add_damage_classrate[i]) / 100;
-            break;
-        }
-    }
-    if (skill_num != CR_GRANDCROSS || !battle_config.gx_cardfix)
-        damage = damage * cardfix / 100;    //カード補正によるダメージ増加
-//カードによるダメージ増加処理ここまで
-
-//カードによるダメージ追加処理(左手)ここから
-    cardfix = 100;
-    if (!battle_config.left_cardfix_to_right)
-    {                           //左手カード補正設定無し
-        cardfix = cardfix * (100 + sd->addrace_[t_race]) / 100; // 種族によるダメージ修正左手
-        cardfix = cardfix * (100 + sd->addele_[t_ele]) / 100;   // 属 性によるダメージ修正左手
-        cardfix = cardfix * (100 + sd->addsize_[t_size]) / 100; // サイズによるダメージ修正左手
-        if (t_mode & 0x20)      //ボス
-            cardfix = cardfix * (100 + sd->addrace_[10]) / 100; //ボスモンスターに追加ダメージ左手
-        else
-            cardfix = cardfix * (100 + sd->addrace_[11]) / 100; //ボス以外モンスターに追加ダメージ左手
-    }
-    //特定Class用補正処理左手(少女の日記→ボンゴン用?)
-    for (i = 0; i < sd->add_damage_class_count_; i++)
-    {
-        if (sd->add_damage_classid_[i] == t_class)
-        {
-            cardfix = cardfix * (100 + sd->add_damage_classrate_[i]) / 100;
-            break;
-        }
-    }
-    if (skill_num != CR_GRANDCROSS)
-        damage2 = damage2 * cardfix / 100;  //カード補正による左手ダメージ増加
-//カードによるダメージ増加処理(左手)ここまで
-
-// -- moonsoul (cardfix for magic damage portion of ASC_BREAKER)
-    if (skill_num == ASC_BREAKER)
-        damage3 = damage3 * cardfix / 100;
-
-//カードによるダメージ減衰処理ここから
-    if (tsd)
-    {                           //対象がPCの場合
-        cardfix = 100;
-        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // 種族によるダメージ耐性
-        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // 属性によるダメージ耐性
-        if (battle_get_mode (src) & 0x20)
-            cardfix = cardfix * (100 - tsd->subrace[10]) / 100; //ボスからの攻撃はダメージ減少
-        else
-            cardfix = cardfix * (100 - tsd->subrace[11]) / 100; //ボス以外からの攻撃はダメージ減少
-        //特定Class用補正処理左手(少女の日記→ボンゴン用?)
-        for (i = 0; i < tsd->add_def_class_count; i++)
-        {
-            if (tsd->add_def_classid[i] == sd->status.pc_class)
-            {
-                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
-                break;
-            }
-        }
-        if (flag & BF_LONG)
-            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;    //遠距離攻撃はダメージ減少(ホルンCとか)
-        if (flag & BF_SHORT)
-            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;    //近距離攻撃はダメージ減少(該当無し?)
-        damage = damage * cardfix / 100;    //カード補正によるダメージ減少
-        damage2 = damage2 * cardfix / 100;  //カード補正による左手ダメージ減少
-    }
-//カードによるダメージ減衰処理ここまで
-
-//対象にステータス異常がある場合のダメージ減算処理ここから
-    if (t_sc_data)
-    {
-        cardfix = 100;
-        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)   //ディフェンダー状態で遠距離攻撃
-            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;  //ディフェンダーによる減衰
-        if (cardfix != 100)
-        {
-            damage = damage * cardfix / 100;    //ディフェンダー補正によるダメージ減少
-            damage2 = damage2 * cardfix / 100;  //ディフェンダー補正による左手ダメージ減少
-        }
-        if (t_sc_data[SC_ASSUMPTIO].timer != -1)
-        {                       //アスムプティオ
-            if (!map[target->m].flag.pvp)
-            {
-                damage = damage / 3;
-                damage2 = damage2 / 3;
-            }
-            else
-            {
-                damage = damage / 2;
-                damage2 = damage2 / 2;
-            }
-        }
-    }
-//対象にステータス異常がある場合のダメージ減算処理ここまで
-
-    if (damage < 0)
-        damage = 0;
-    if (damage2 < 0)
-        damage2 = 0;
-
-    // 属 性の適用
-    damage = battle_attr_fix (damage, s_ele, battle_get_element (target));
-    damage2 = battle_attr_fix (damage2, s_ele_, battle_get_element (target));
-
-    // 星のかけら、気球の適用
-    damage += sd->star;
-    damage2 += sd->star_;
-    damage += sd->spiritball * 3;
-    damage2 += sd->spiritball * 3;
-
-    if (sc_data && sc_data[SC_AURABLADE].timer != -1)
-    {                           /* オーラブレード 必中 */
-        damage += sc_data[SC_AURABLADE].val1 * 10;
-        damage2 += sc_data[SC_AURABLADE].val1 * 10;
-    }
-    if (skill_num == PA_PRESSURE)
-    {                           /* プレッシャー 必中? */
-        damage = 700 + 100 * skill_lv;
-        damage2 = 700 + 100 * skill_lv;
-    }
-
-    // >二刀流の左右ダメージ計算誰かやってくれぇぇぇぇえええ!
-    // >map_session_data に左手ダメージ(atk,atk2)追加して
-    // >pc_calcstatus()でやるべきかな?
-    // map_session_data に左手武器(atk,atk2,ele,star,atkmods)追加して
-    // pc_calcstatus()でデータを入力しています
-
-    //左手のみ武器装備
-    if (sd->weapontype1 == 0 && sd->weapontype2 > 0)
-    {
-        damage = damage2;
-        damage2 = 0;
-    }
-    // 右手、左手修練の適用
-    if (sd->status.weapon > 16)
-    {                           // 二刀流か?
-        int  dmg = damage, dmg2 = damage2;
-        // 右手修練(60% 〜 100%) 右手全般
-        skill = pc_checkskill (sd, AS_RIGHT);
-        damage = damage * (50 + (skill * 10)) / 100;
-        if (dmg > 0 && damage < 1)
-            damage = 1;
-        // 左手修練(40% 〜 80%) 左手全般
-        skill = pc_checkskill (sd, AS_LEFT);
-        damage2 = damage2 * (30 + (skill * 10)) / 100;
-        if (dmg2 > 0 && damage2 < 1)
-            damage2 = 1;
-    }
-    else                        //二刀流でなければ左手ダメージは0
-        damage2 = 0;
-
-    // 右手,短剣のみ
-    if (da == 1)
-    {                           //ダブルアタックが発動しているか
-        div_ = 2;
-        damage += damage;
-        type = 0x08;
-    }
-
-    if (sd->status.weapon == 16)
-    {
-        // カタール追撃ダメージ
-        skill = pc_checkskill (sd, TF_DOUBLE);
-        damage2 = damage * (1 + (skill * 2)) / 100;
-        if (damage > 0 && damage2 < 1)
-            damage2 = 1;
-    }
-
-    // インベナム修正
-    if (skill_num == TF_POISON)
-    {
-        damage =
-            battle_attr_fix (damage + 15 * skill_lv, s_ele,
-                             battle_get_element (target));
-    }
-    if (skill_num == MC_CARTREVOLUTION)
-    {
-        damage = battle_attr_fix (damage, 0, battle_get_element (target));
-    }
-
-    // 完全回避の判定
-    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL && div_ < 255
-        && MRAND (1000) < battle_get_flee2 (target))
-    {
-        damage = damage2 = 0;
-        type = 0x0b;
-        dmg_lv = ATK_LUCKY;
-    }
-
-    // 対象が完全回避をする設定がONなら
-    if (battle_config.enemy_perfect_flee)
-    {
-        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL && div_ < 255
-            && MRAND (1000) < battle_get_flee2 (target))
-        {
-            damage = damage2 = 0;
-            type = 0x0b;
-            dmg_lv = ATK_LUCKY;
-        }
-    }
-
-    //MobのModeに頑強フラグが立っているときの処理
-    if (t_mode & 0x40)
-    {
-        if (damage > 0)
-            damage = 1;
-        if (damage2 > 0)
-            damage2 = 1;
-    }
-
-    //bNoWeaponDamage(設定アイテム無し?)でグランドクロスじゃない場合はダメージが0
-    if (tsd && tsd->special_state.no_weapon_damage
-        && skill_num != CR_GRANDCROSS)
-        damage = damage2 = 0;
-
-    if (skill_num != CR_GRANDCROSS && (damage > 0 || damage2 > 0))
-    {
-        if (damage2 < 1)        // ダメージ最終修正
-            damage =
-                battle_calc_damage (src, target, damage, div_, skill_num,
-                                    skill_lv, flag);
-        else if (damage < 1)    // 右手がミス?
-            damage2 =
-                battle_calc_damage (src, target, damage2, div_, skill_num,
-                                    skill_lv, flag);
-        else
-        {                       // 両 手/カタールの場合はちょっと計算ややこしい
-            int  d1 = damage + damage2, d2 = damage2;
-            damage =
-                battle_calc_damage (src, target, damage + damage2, div_,
-                                    skill_num, skill_lv, flag);
-            damage2 = (d2 * 100 / d1) * damage / 100;
-            if (damage > 1 && damage2 < 1)
-                damage2 = 1;
-            damage -= damage2;
-        }
-    }
-
-    /*              For executioner card [Valaris]              */
-    if (src->type == BL_PC && sd->random_attack_increase_add > 0
-        && sd->random_attack_increase_per > 0 && skill_num == 0)
-    {
-        if (MRAND (100) < sd->random_attack_increase_per)
-        {
-            if (damage > 0)
-                damage *= sd->random_attack_increase_add / 100;
-            if (damage2 > 0)
-                damage2 *= sd->random_attack_increase_add / 100;
-        }
-    }
-    /*                  End addition                    */
-
-// -- moonsoul (final combination of phys, mag damage for ASC_BREAKER)
-    if (skill_num == ASC_BREAKER)
-    {
-        damage += damage3;
-        damage2 += damage3;
-    }
-
-    wd.damage = damage;
-    wd.damage2 = damage2;
-    wd.type = type;
-    wd.div_ = div_;
-    wd.amotion = battle_get_amotion (src);
-    if (skill_num == KN_AUTOCOUNTER)
-        wd.amotion >>= 1;
-    wd.dmotion = battle_get_dmotion (target);
-    wd.blewcount = blewcount;
-    wd.flag = flag;
-    wd.dmg_lv = dmg_lv;
-
-    return wd;
-}
-
-/*==========================================
- * 武器ダメージ計算
- *------------------------------------------
- */
-struct Damage battle_calc_weapon_attack (struct block_list *src,
-                                         struct block_list *target,
-                                         int skill_num, int skill_lv,
-                                         int wflag)
-{
-    struct Damage wd;
-
-    //return前の処理があるので情報出力部のみ変更
-    if (src == NULL || target == NULL)
-    {
-        nullpo_info (NLP_MARK);
-        memset (&wd, 0, sizeof (wd));
-        return wd;
-    }
-
-    else if (src->type == BL_PC)
-        wd = battle_calc_pc_weapon_attack (src, target, skill_num, skill_lv, wflag);    // weapon breaking [Valaris]
-    else if (src->type == BL_MOB)
-        wd = battle_calc_mob_weapon_attack (src, target, skill_num, skill_lv,
-                                            wflag);
-    else
-        memset (&wd, 0, sizeof (wd));
-
-    if (battle_config.equipment_breaking && src->type == BL_PC
-        && (wd.damage > 0 || wd.damage2 > 0))
-    {
-        struct map_session_data *sd = (struct map_session_data *) src;
-        if (sd->status.weapon && sd->status.weapon != 11)
-        {
-            int  breakrate = 1;
-            if (target->type == BL_PC && sd->sc_data[SC_MELTDOWN].timer != -1)
-            {
-                breakrate += 100 * sd->sc_data[SC_MELTDOWN].val1;
-                if (MRAND (10000) <
-                    breakrate * battle_config.equipment_break_rate / 100
-                    || breakrate >= 10000)
-                    pc_breakweapon ((struct map_session_data *) target);
-            }
-            if (sd->sc_data[SC_OVERTHRUST].timer != -1)
-                breakrate += 20 * sd->sc_data[SC_OVERTHRUST].val1;
-            if (wd.type == 0x0a)
-                breakrate *= 2;
-            if (MRAND (10000) <
-                breakrate * battle_config.equipment_break_rate / 100
-                || breakrate >= 10000)
-            {
-                pc_breakweapon (sd);
-                memset (&wd, 0, sizeof (wd));
-            }
-        }
-    }
-
-    if (battle_config.equipment_breaking && target->type == BL_PC
-        && (wd.damage > 0 || wd.damage2 > 0))
-    {
-        int  breakrate = 1;
-        if (src->type == BL_PC
-            && ((struct map_session_data *) src)->
-            sc_data[SC_MELTDOWN].timer != -1)
-            breakrate +=
-                70 *
-                ((struct map_session_data *) src)->sc_data[SC_MELTDOWN].val1;
-        if (wd.type == 0x0a)
-            breakrate *= 2;
-        if (MRAND (10000) <
-            breakrate * battle_config.equipment_break_rate / 100
-            || breakrate >= 10000)
-        {
-            pc_breakarmor ((struct map_session_data *) target);
-        }
-    }
-
-    return wd;
-}
-
-/*==========================================
- * 魔法ダメージ計算
- *------------------------------------------
- */
-struct Damage battle_calc_magic_attack (struct block_list *bl,
-                                        struct block_list *target,
-                                        int skill_num, int skill_lv, int flag)
-{
-    int  mdef1 = battle_get_mdef (target);
-    int  mdef2 = battle_get_mdef2 (target);
-    int  matk1, matk2, damage = 0, div_ = 1, blewcount =
-        skill_get_blewcount (skill_num, skill_lv), rdamage = 0;
-    struct Damage md;
-    int  aflag;
-    int  normalmagic_flag = 1;
-    int  ele = 0, race = 7, t_ele = 0, t_race = 7, t_mode =
-        0, cardfix, t_class, i;
-    struct map_session_data *sd = NULL, *tsd = NULL;
-    struct mob_data *tmd = NULL;
-
-    //return前の処理があるので情報出力部のみ変更
-    if (bl == NULL || target == NULL)
-    {
-        nullpo_info (NLP_MARK);
-        memset (&md, 0, sizeof (md));
-        return md;
-    }
-
-    matk1 = battle_get_matk1 (bl);
-    matk2 = battle_get_matk2 (bl);
-    ele = skill_get_pl (skill_num);
-    race = battle_get_race (bl);
-    t_ele = battle_get_elem_type (target);
-    t_race = battle_get_race (target);
-    t_mode = battle_get_mode (target);
-
-#define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); }
-
-    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
-    {
-        sd->state.attack_type = BF_MAGIC;
-        if (sd->matk_rate != 100)
-            MATK_FIX (sd->matk_rate, 100);
-        sd->state.arrow_atk = 0;
-    }
-    if (target->type == BL_PC)
-        tsd = (struct map_session_data *) target;
-    else if (target->type == BL_MOB)
-        tmd = (struct mob_data *) target;
-
-    aflag = BF_MAGIC | BF_LONG | BF_SKILL;
-
-    if (skill_num > 0)
-    {
-        switch (skill_num)
-        {                       // 基本ダメージ計算(スキルごとに処理)
-                // ヒールor聖体
-            case AL_HEAL:
-            case PR_BENEDICTIO:
-                damage = skill_calc_heal (bl, skill_lv) / 2;
-                normalmagic_flag = 0;
-                break;
-            case PR_ASPERSIO:  /* アスペルシオ */
-                damage = 40;    //固定ダメージ
-                normalmagic_flag = 0;
-                break;
-            case PR_SANCTUARY: // サンクチュアリ
-                damage = (skill_lv > 6) ? 388 : skill_lv * 50;
-                normalmagic_flag = 0;
-                blewcount |= 0x10000;
-                break;
-            case ALL_RESURRECTION:
-            case PR_TURNUNDEAD:    // 攻撃リザレクションとターンアンデッド
-                if (target->type != BL_PC
-                    && battle_check_undead (t_race, t_ele))
-                {
-                    int  hp, mhp, thres;
-                    hp = battle_get_hp (target);
-                    mhp = battle_get_max_hp (target);
-                    thres = (skill_lv * 20) + battle_get_luk (bl) +
-                        battle_get_int (bl) + battle_get_lv (bl) +
-                        ((200 - hp * 200 / mhp));
-                    if (thres > 700)
-                        thres = 700;
-//              if(battle_config.battle_log)
-//                  printf("ターンアンデッド! 確率%d ‰(千分率)\n", thres);
-                    if (MRAND (1000) < thres && !(t_mode & 0x20))   // 成功
-                        damage = hp;
-                    else        // 失敗
-                        damage =
-                            battle_get_lv (bl) + battle_get_int (bl) +
-                            skill_lv * 10;
-                }
-                normalmagic_flag = 0;
-                break;
-
-            case MG_NAPALMBEAT:    // ナパームビート(分散計算込み)
-                MATK_FIX (70 + skill_lv * 10, 100);
-                if (flag > 0)
-                {
-                    MATK_FIX (1, flag);
-                }
-                else
-                {
-                    if (battle_config.error_log)
-                        printf
-                            ("battle_calc_magic_attack(): napam enemy count=0 !\n");
-                }
-                break;
-            case MG_FIREBALL:  // ファイヤーボール
-            {
-                const int drate[] = { 100, 90, 70 };
-                if (flag > 2)
-                    matk1 = matk2 = 0;
-                else
-                    MATK_FIX ((95 + skill_lv * 5) * drate[flag], 10000);
-            }
-                break;
-            case MG_FIREWALL:  // ファイヤーウォール
-/*
-			if( (t_ele!=3 && !battle_check_undead(t_race,t_ele)) || target->type==BL_PC ) //PCは火属性でも飛ぶ?そもそもダメージ受ける?
-				blewcount |= 0x10000;
-			else
-				blewcount = 0;
-*/
-                if ((t_ele == 3 || battle_check_undead (t_race, t_ele))
-                    && target->type != BL_PC)
-                    blewcount = 0;
-                else
-                    blewcount |= 0x10000;
-                MATK_FIX (1, 2);
-                break;
-            case MG_THUNDERSTORM:  // サンダーストーム
-                MATK_FIX (80, 100);
-                break;
-            case MG_FROSTDIVER:    // フロストダイバ
-                MATK_FIX (100 + skill_lv * 10, 100);
-                break;
-            case WZ_FROSTNOVA: // フロストダイバ
-                MATK_FIX (((100 + skill_lv * 10) * (2 / 3)), 100);
-                break;
-            case WZ_FIREPILLAR:    // ファイヤーピラー
-                if (mdef1 < 1000000)
-                    mdef1 = mdef2 = 0;  // MDEF無視
-                MATK_FIX (1, 5);
-                matk1 += 50;
-                matk2 += 50;
-                break;
-            case WZ_SIGHTRASHER:
-                MATK_FIX (100 + skill_lv * 20, 100);
-                break;
-            case WZ_METEOR:
-            case WZ_JUPITEL:   // ユピテルサンダー
-                break;
-            case WZ_VERMILION: // ロードオブバーミリオン
-                MATK_FIX (skill_lv * 20 + 80, 100);
-                break;
-            case WZ_WATERBALL: // ウォーターボール
-                matk1 += skill_lv * 30;
-                matk2 += skill_lv * 30;
-                break;
-            case WZ_STORMGUST: // ストームガスト
-                MATK_FIX (skill_lv * 40 + 100, 100);
-                blewcount |= 0x10000;
-                break;
-            case AL_HOLYLIGHT: // ホーリーライト
-                MATK_FIX (125, 100);
-                break;
-            case AL_RUWACH:
-                MATK_FIX (145, 100);
-                break;
-            case HW_NAPALMVULCAN:  // ナパームビート(分散計算込み)
-                MATK_FIX (70 + skill_lv * 10, 100);
-                if (flag > 0)
-                {
-                    MATK_FIX (1, flag);
-                }
-                else
-                {
-                    if (battle_config.error_log)
-                        printf
-                            ("battle_calc_magic_attack(): napalmvulcan enemy count=0 !\n");
-                }
-                break;
-        }
-    }
-
-    if (normalmagic_flag)
-    {                           // 一般魔法ダメージ計算
-        int  imdef_flag = 0;
-        if (matk1 > matk2)
-            damage = matk2 + MRAND ((matk1 - matk2 + 1));
-        else
-            damage = matk2;
-        if (sd)
-        {
-            if (sd->ignore_mdef_ele & (1 << t_ele)
-                || sd->ignore_mdef_race & (1 << t_race))
-                imdef_flag = 1;
-            if (t_mode & 0x20)
-            {
-                if (sd->ignore_mdef_race & (1 << 10))
-                    imdef_flag = 1;
-            }
-            else
-            {
-                if (sd->ignore_mdef_race & (1 << 11))
-                    imdef_flag = 1;
-            }
-        }
-        if (!imdef_flag)
-        {
-            if (battle_config.magic_defense_type)
-            {
-                damage =
-                    damage - (mdef1 * battle_config.magic_defense_type) -
-                    mdef2;
-            }
-            else
-            {
-                damage = (damage * (100 - mdef1)) / 100 - mdef2;
-            }
-        }
-
-        if (damage < 1)
-            damage = 1;
-    }
-
-    if (sd)
-    {
-        cardfix = 100;
-        cardfix = cardfix * (100 + sd->magic_addrace[t_race]) / 100;
-        cardfix = cardfix * (100 + sd->magic_addele[t_ele]) / 100;
-        if (t_mode & 0x20)
-            cardfix = cardfix * (100 + sd->magic_addrace[10]) / 100;
-        else
-            cardfix = cardfix * (100 + sd->magic_addrace[11]) / 100;
-        t_class = battle_get_class (target);
-        for (i = 0; i < sd->add_magic_damage_class_count; i++)
-        {
-            if (sd->add_magic_damage_classid[i] == t_class)
-            {
-                cardfix =
-                    cardfix * (100 + sd->add_magic_damage_classrate[i]) / 100;
-                break;
-            }
-        }
-        damage = damage * cardfix / 100;
-    }
-
-    if (tsd)
-    {
-        int  s_class = battle_get_class (bl);
-        cardfix = 100;
-        cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // 属 性によるダメージ耐性
-        cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // 種族によるダメージ耐性
-        cardfix = cardfix * (100 - tsd->magic_subrace[race]) / 100;
-        if (battle_get_mode (bl) & 0x20)
-            cardfix = cardfix * (100 - tsd->magic_subrace[10]) / 100;
-        else
-            cardfix = cardfix * (100 - tsd->magic_subrace[11]) / 100;
-        for (i = 0; i < tsd->add_mdef_class_count; i++)
-        {
-            if (tsd->add_mdef_classid[i] == s_class)
-            {
-                cardfix = cardfix * (100 - tsd->add_mdef_classrate[i]) / 100;
-                break;
-            }
-        }
-        cardfix = cardfix * (100 - tsd->magic_def_rate) / 100;
-        damage = damage * cardfix / 100;
-    }
-    if (damage < 0)
-        damage = 0;
-
-    damage = battle_attr_fix (damage, ele, battle_get_element (target));    // 属 性修正
-
-    if (skill_num == CR_GRANDCROSS)
-    {                           // グランドクロス
-        struct Damage wd;
-        wd = battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
-                                        flag);
-        damage = (damage + wd.damage) * (100 + 40 * skill_lv) / 100;
-        if (battle_config.gx_dupele)
-            damage = battle_attr_fix (damage, ele, battle_get_element (target));    //属性2回かかる
-        if (bl == target)
-            damage = damage / 2;    //反動は半分
-    }
-
-    div_ = skill_get_num (skill_num, skill_lv);
-
-    if (div_ > 1 && skill_num != WZ_VERMILION)
-        damage *= div_;
-
-//  if(mdef1 >= 1000000 && damage > 0)
-    if (t_mode & 0x40 && damage > 0)
-        damage = 1;
-
-    if (tsd && tsd->special_state.no_magic_damage)
-    {
-        if (battle_config.gtb_pvp_only != 0)
-        {                       // [MouseJstr]
-            if ((map[target->m].flag.pvp || map[target->m].flag.gvg)
-                && target->type == BL_PC)
-                damage = (damage * (100 - battle_config.gtb_pvp_only)) / 100;
-        }
-        else
-            damage = 0;         // 黄 金蟲カード(魔法ダメージ0)
-    }
-
-    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // 最終修正
-
-    /* magic_damage_return by [AppleGirl] and [Valaris]     */
-    if (target->type == BL_PC && tsd && tsd->magic_damage_return > 0)
-    {
-        rdamage += damage * tsd->magic_damage_return / 100;
-        if (rdamage < 1)
-            rdamage = 1;
-        clif_damage (target, bl, gettick (), 0, 0, rdamage, 0, 0, 0);
-        battle_damage (target, bl, rdamage, 0);
-    }
-    /*          end magic_damage_return         */
-
-    md.damage = damage;
-    md.div_ = div_;
-    md.amotion = battle_get_amotion (bl);
-    md.dmotion = battle_get_dmotion (target);
-    md.damage2 = 0;
-    md.type = 0;
-    md.blewcount = blewcount;
-    md.flag = aflag;
-
-    return md;
-}
-
-/*==========================================
- * その他ダメージ計算
- *------------------------------------------
- */
-struct Damage battle_calc_misc_attack (struct block_list *bl,
-                                       struct block_list *target,
-                                       int skill_num, int skill_lv, int flag)
-{
-    int  int_ = battle_get_int (bl);
-//  int luk=battle_get_luk(bl);
-    int  dex = battle_get_dex (bl);
-    int  skill, ele, race, cardfix;
-    struct map_session_data *sd = NULL, *tsd = NULL;
-    int  damage = 0, div_ = 1, blewcount =
-        skill_get_blewcount (skill_num, skill_lv);
-    struct Damage md;
-    int  damagefix = 1;
-
-    int  aflag = BF_MISC | BF_LONG | BF_SKILL;
-
-    //return前の処理があるので情報出力部のみ変更
-    if (bl == NULL || target == NULL)
-    {
-        nullpo_info (NLP_MARK);
-        memset (&md, 0, sizeof (md));
-        return md;
-    }
-
-    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
-    {
-        sd->state.attack_type = BF_MISC;
-        sd->state.arrow_atk = 0;
-    }
-
-    if (target->type == BL_PC)
-        tsd = (struct map_session_data *) target;
-
-    switch (skill_num)
-    {
-
-        case HT_LANDMINE:      // ランドマイン
-            damage = skill_lv * (dex + 75) * (100 + int_) / 100;
-            break;
-
-        case HT_BLASTMINE:     // ブラストマイン
-            damage = skill_lv * (dex / 2 + 50) * (100 + int_) / 100;
-            break;
-
-        case HT_CLAYMORETRAP:  // クレイモアートラップ
-            damage = skill_lv * (dex / 2 + 75) * (100 + int_) / 100;
-            break;
-
-        case HT_BLITZBEAT:     // ブリッツビート
-            if (sd == NULL || (skill = pc_checkskill (sd, HT_STEELCROW)) <= 0)
-                skill = 0;
-            damage = (dex / 10 + int_ / 2 + skill * 3 + 40) * 2;
-            if (flag > 1)
-                damage /= flag;
-            break;
-
-        case TF_THROWSTONE:    // 石投げ
-            damage = 30;
-            damagefix = 0;
-            break;
-
-        case BA_DISSONANCE:    // 不協和音
-            damage =
-                (skill_lv) * 20 + pc_checkskill (sd, BA_MUSICALLESSON) * 3;
-            break;
-
-        case NPC_SELFDESTRUCTION:  // 自爆
-            damage = battle_get_hp (bl) - (bl == target ? 1 : 0);
-            damagefix = 0;
-            break;
-
-        case NPC_SMOKING:      // タバコを吸う
-            damage = 3;
-            damagefix = 0;
-            break;
-
-        case NPC_DARKBREATH:
-        {
-            struct status_change *sc_data = battle_get_sc_data (target);
-            int  hitrate =
-                battle_get_hit (bl) - battle_get_flee (target) + 80;
-            hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
-            if (sc_data
-                && (sc_data[SC_SLEEP].timer != -1
-                    || sc_data[SC_STAN].timer != -1
-                    || sc_data[SC_FREEZE].timer != -1
-                    || (sc_data[SC_STONE].timer != -1
-                        && sc_data[SC_STONE].val2 == 0)))
-                hitrate = 1000000;
-            if (MRAND (100) < hitrate)
-            {
-                damage = 500 + (skill_lv - 1) * 1000 + MRAND (1000);
-                if (damage > 9999)
-                    damage = 9999;
-            }
-        }
-            break;
-        case SN_FALCONASSAULT: /* ファルコンアサルト */
-            skill = pc_checkskill (sd, HT_BLITZBEAT);
-            damage =
-                (100 + 50 * skill_lv +
-                 (dex / 10 + int_ / 2 + skill * 3 + 40) * 2);
-            break;
-    }
-
-    ele = skill_get_pl (skill_num);
-    race = battle_get_race (bl);
-
-    if (damagefix)
-    {
-        if (damage < 1 && skill_num != NPC_DARKBREATH)
-            damage = 1;
-
-        if (tsd)
-        {
-            cardfix = 100;
-            cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // 属性によるダメージ耐性
-            cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // 種族によるダメージ耐性
-            cardfix = cardfix * (100 - tsd->misc_def_rate) / 100;
-            damage = damage * cardfix / 100;
-        }
-        if (damage < 0)
-            damage = 0;
-        damage = battle_attr_fix (damage, ele, battle_get_element (target));    // 属性修正
-    }
-
-    div_ = skill_get_num (skill_num, skill_lv);
-    if (div_ > 1)
-        damage *= div_;
-
-    if (damage > 0
-        && (damage < div_
-            || (battle_get_def (target) >= 1000000
-                && battle_get_mdef (target) >= 1000000)))
-    {
-        damage = div_;
-    }
-
-    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // 最終修正
-
-    md.damage = damage;
-    md.div_ = div_;
-    md.amotion = battle_get_amotion (bl);
-    md.dmotion = battle_get_dmotion (target);
-    md.damage2 = 0;
-    md.type = 0;
-    md.blewcount = blewcount;
-    md.flag = aflag;
-    return md;
-
-}
-
-/*==========================================
- * ダメージ計算一括処理用
- *------------------------------------------
- */
-struct Damage battle_calc_attack (int attack_type,
-                                  struct block_list *bl,
-                                  struct block_list *target, int skill_num,
-                                  int skill_lv, int flag)
-{
-    struct Damage d;
-    memset (&d, 0, sizeof (d));
-
-    switch (attack_type)
-    {
-        case BF_WEAPON:
-            return battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
-                                              flag);
-        case BF_MAGIC:
-            return battle_calc_magic_attack (bl, target, skill_num, skill_lv,
-                                             flag);
-        case BF_MISC:
-            return battle_calc_misc_attack (bl, target, skill_num, skill_lv,
-                                            flag);
-        default:
-            if (battle_config.error_log)
-                printf ("battle_calc_attack: unknwon attack type ! %d\n",
-                        attack_type);
-            break;
-    }
-    return d;
-}
-
-/*==========================================
- * 通常攻撃処理まとめ
- *------------------------------------------
- */
-int battle_weapon_attack (struct block_list *src, struct block_list *target,
-                          unsigned int tick, int flag)
-{
-    struct map_session_data *sd = NULL;
-    struct status_change *sc_data = battle_get_sc_data (src), *t_sc_data =
-        battle_get_sc_data (target);
-    short *opt1;
-    int  race = 7, ele = 0;
-    int  damage, rdamage = 0;
-    struct Damage wd;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, target);
-
-    if (src->type == BL_PC)
-        sd = (struct map_session_data *) src;
-
-    if (src->prev == NULL || target->prev == NULL)
-        return 0;
-    if (src->type == BL_PC && pc_isdead (sd))
-        return 0;
-    if (target->type == BL_PC
-        && pc_isdead ((struct map_session_data *) target))
-        return 0;
-
-    opt1 = battle_get_opt1 (src);
-    if (opt1 && *opt1 > 0)
-    {
-        battle_stopattack (src);
-        return 0;
-    }
-    if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
-    {
-        battle_stopattack (src);
-        return 0;
-    }
-
-    race = battle_get_race (target);
-    ele = battle_get_elem_type (target);
-    if (battle_check_target (src, target, BCT_ENEMY) > 0 &&
-        battle_check_range (src, target, 0))
-    {
-        // 攻撃対象となりうるので攻撃
-        if (sd && sd->status.weapon == 11)
-        {
-            if (sd->equip_index[10] >= 0)
-            {
-                if (battle_config.arrow_decrement)
-                    pc_delitem (sd, sd->equip_index[10], 1, 0);
-            }
-            else
-            {
-                clif_arrow_fail (sd, 0);
-                return 0;
-            }
-        }
-        if (flag & 0x8000)
-        {
-            if (sd && battle_config.pc_attack_direction_change)
-                sd->dir = sd->head_dir =
-                    map_calc_dir (src, target->x, target->y);
-            else if (src->type == BL_MOB
-                     && battle_config.monster_attack_direction_change)
-                ((struct mob_data *) src)->dir =
-                    map_calc_dir (src, target->x, target->y);
-            wd = battle_calc_weapon_attack (src, target, KN_AUTOCOUNTER,
-                                            flag & 0xff, 0);
-        }
-        else
-            wd = battle_calc_weapon_attack (src, target, 0, 0, 0);
-
-        // significantly increase injuries for hasted characters
-        if (wd.damage > 0 && (t_sc_data[SC_HASTE].timer != -1))
-        {
-            wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4;
-        }
-
-        if (wd.damage > 0
-            && t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC)
-        {
-            int  reduction = t_sc_data[SC_PHYS_SHIELD].val1;
-            if (reduction > wd.damage)
-                reduction = wd.damage;
-
-            wd.damage -= reduction;
-            MAP_LOG_PC (((struct map_session_data *) target),
-                        "MAGIC-ABSORB-DMG %d", reduction);
-        }
-
-        if ((damage = wd.damage + wd.damage2) > 0 && src != target)
-        {
-            if (wd.flag & BF_SHORT)
-            {
-                if (target->type == BL_PC)
-                {
-                    struct map_session_data *tsd =
-                        (struct map_session_data *) target;
-                    if (tsd && tsd->short_weapon_damage_return > 0)
-                    {
-                        rdamage +=
-                            damage * tsd->short_weapon_damage_return / 100;
-                        if (rdamage < 1)
-                            rdamage = 1;
-                    }
-                }
-                if (t_sc_data && t_sc_data[SC_REFLECTSHIELD].timer != -1)
-                {
-                    rdamage +=
-                        damage * t_sc_data[SC_REFLECTSHIELD].val2 / 100;
-                    if (rdamage < 1)
-                        rdamage = 1;
-                }
-            }
-            else if (wd.flag & BF_LONG)
-            {
-                if (target->type == BL_PC)
-                {
-                    struct map_session_data *tsd =
-                        (struct map_session_data *) target;
-                    if (tsd && tsd->long_weapon_damage_return > 0)
-                    {
-                        rdamage +=
-                            damage * tsd->long_weapon_damage_return / 100;
-                        if (rdamage < 1)
-                            rdamage = 1;
-                    }
-                }
-            }
-
-            if (rdamage > 0)
-                clif_damage (src, src, tick, wd.amotion, 0, rdamage, 1, 4, 0);
-        }
-
-        if (wd.div_ == 255 && sd)
-        {                       //三段掌
-            int  delay =
-                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
-            int  skilllv;
-            if (wd.damage + wd.damage2 < battle_get_hp (target))
-            {
-                if ((skilllv = pc_checkskill (sd, MO_CHAINCOMBO)) > 0)
-                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
-
-                skill_status_change_start (src, SC_COMBO, MO_TRIPLEATTACK,
-                                           skilllv, 0, 0, delay, 0);
-            }
-            sd->attackabletime = sd->canmove_tick = tick + delay;
-            clif_combo_delay (src, delay);
-            clif_skill_damage (src, target, tick, wd.amotion, wd.dmotion,
-                               wd.damage, 3, MO_TRIPLEATTACK,
-                               pc_checkskill (sd, MO_TRIPLEATTACK), -1);
-        }
-        else
-        {
-            clif_damage (src, target, tick, wd.amotion, wd.dmotion,
-                         wd.damage, wd.div_, wd.type, wd.damage2);
-            //二刀流左手とカタール追撃のミス表示(無理やり〜)
-            if (sd && sd->status.weapon >= 16 && wd.damage2 == 0)
-                clif_damage (src, target, tick + 10, wd.amotion, wd.dmotion,
-                             0, 1, 0, 0);
-        }
-        if (sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0))
-            skill_castend_damage_id (src, target, 0, -1, tick, 0);
-        map_freeblock_lock ();
-
-        if (src->type == BL_PC)
-        {
-            int  weapon_index = sd->equip_index[9];
-            int  weapon = 0;
-            if (sd->inventory_data[weapon_index]
-                && sd->status.inventory[weapon_index].equip & 0x2)
-                weapon = sd->inventory_data[weapon_index]->nameid;
-
-            MAP_LOG ("PC%d %d:%d,%d WPNDMG %s%d %d FOR %d WPN %d",
-                     sd->status.char_id, src->m, src->x, src->y,
-                     (target->type == BL_PC) ? "PC" : "MOB",
-                     (target->type ==
-                      BL_PC) ? ((struct map_session_data *) target)->
-                     status.char_id : target->id,
-                     (target->type ==
-                      BL_PC) ? 0 : ((struct mob_data *) target)->mob_class,
-                     wd.damage + wd.damage2, weapon);
-        }
-
-        if (target->type == BL_PC)
-        {
-            struct map_session_data *sd2 = (struct map_session_data *) target;
-            MAP_LOG ("PC%d %d:%d,%d WPNINJURY %s%d %d FOR %d",
-                     sd2->status.char_id, target->m, target->x, target->y,
-                     (src->type == BL_PC) ? "PC" : "MOB",
-                     (src->type ==
-                      BL_PC) ? ((struct map_session_data *) src)->
-                     status.char_id : src->id,
-                     (src->type ==
-                      BL_PC) ? 0 : ((struct mob_data *) src)->mob_class,
-                     wd.damage + wd.damage2);
-        }
-
-        battle_damage (src, target, (wd.damage + wd.damage2), 0);
-        if (target->prev != NULL &&
-            (target->type != BL_PC
-             || (target->type == BL_PC
-                 && !pc_isdead ((struct map_session_data *) target))))
-        {
-            if (wd.damage > 0 || wd.damage2 > 0)
-            {
-                skill_additional_effect (src, target, 0, 0, BF_WEAPON, tick);
-                if (sd)
-                {
-                    if (sd->weapon_coma_ele[ele] > 0
-                        && MRAND (10000) < sd->weapon_coma_ele[ele])
-                        battle_damage (src, target,
-                                       battle_get_max_hp (target), 1);
-                    if (sd->weapon_coma_race[race] > 0
-                        && MRAND (10000) < sd->weapon_coma_race[race])
-                        battle_damage (src, target,
-                                       battle_get_max_hp (target), 1);
-                    if (battle_get_mode (target) & 0x20)
-                    {
-                        if (sd->weapon_coma_race[10] > 0
-                            && MRAND (10000) < sd->weapon_coma_race[10])
-                            battle_damage (src, target,
-                                           battle_get_max_hp (target), 1);
-                    }
-                    else
-                    {
-                        if (sd->weapon_coma_race[11] > 0
-                            && MRAND (10000) < sd->weapon_coma_race[11])
-                            battle_damage (src, target,
-                                           battle_get_max_hp (target), 1);
-                    }
-                }
-            }
-        }
-        if (sc_data && sc_data[SC_AUTOSPELL].timer != -1
-            && MRAND (100) < sc_data[SC_AUTOSPELL].val4)
-        {
-            int  skilllv = sc_data[SC_AUTOSPELL].val3, i, f = 0;
-            i = MRAND (100);
-            if (i >= 50)
-                skilllv -= 2;
-            else if (i >= 15)
-                skilllv--;
-            if (skilllv < 1)
-                skilllv = 1;
-            if (sd)
-            {
-                int  sp = skill_get_sp (sc_data[SC_AUTOSPELL].val2,
-                                        skilllv) * 2 / 3;
-                if (sd->status.sp >= sp)
-                {
-                    if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
-                        || i == 32)
-                        f = skill_castend_pos2 (src, target->x, target->y,
-                                                sc_data[SC_AUTOSPELL].val2,
-                                                skilllv, tick, flag);
-                    else
-                    {
-                        switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
-                        {
-                            case 0:
-                            case 2:
-                                f = skill_castend_damage_id (src, target,
-                                                             sc_data
-                                                             [SC_AUTOSPELL].val2,
-                                                             skilllv, tick,
-                                                             flag);
-                                break;
-                            case 1:    /* 支援系 */
-                                if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
-                                     || (sc_data[SC_AUTOSPELL].val2 ==
-                                         ALL_RESURRECTION
-                                         && target->type != BL_PC))
-                                    && battle_check_undead (race, ele))
-                                    f = skill_castend_damage_id (src, target,
-                                                                 sc_data
-                                                                 [SC_AUTOSPELL].val2,
-                                                                 skilllv,
-                                                                 tick, flag);
-                                else
-                                    f = skill_castend_nodamage_id (src,
-                                                                   target,
-                                                                   sc_data
-                                                                   [SC_AUTOSPELL].val2,
-                                                                   skilllv,
-                                                                   tick,
-                                                                   flag);
-                                break;
-                        }
-                    }
-                    if (!f)
-                        pc_heal (sd, 0, -sp);
-                }
-            }
-            else
-            {
-                if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
-                    || i == 32)
-                    skill_castend_pos2 (src, target->x, target->y,
-                                        sc_data[SC_AUTOSPELL].val2, skilllv,
-                                        tick, flag);
-                else
-                {
-                    switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
-                    {
-                        case 0:
-                        case 2:
-                            skill_castend_damage_id (src, target,
-                                                     sc_data
-                                                     [SC_AUTOSPELL].val2,
-                                                     skilllv, tick, flag);
-                            break;
-                        case 1:    /* 支援系 */
-                            if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
-                                 || (sc_data[SC_AUTOSPELL].val2 ==
-                                     ALL_RESURRECTION
-                                     && target->type != BL_PC))
-                                && battle_check_undead (race, ele))
-                                skill_castend_damage_id (src, target,
-                                                         sc_data
-                                                         [SC_AUTOSPELL].val2,
-                                                         skilllv, tick, flag);
-                            else
-                                skill_castend_nodamage_id (src, target,
-                                                           sc_data
-                                                           [SC_AUTOSPELL].val2,
-                                                           skilllv, tick,
-                                                           flag);
-                            break;
-                    }
-                }
-            }
-        }
-        if (sd)
-        {
-            if (sd->autospell_id > 0 && sd->autospell_lv > 0
-                && MRAND (100) < sd->autospell_rate)
-            {
-                int  skilllv = sd->autospell_lv, i, f = 0, sp;
-                i = MRAND (100);
-                if (i >= 50)
-                    skilllv -= 2;
-                else if (i >= 15)
-                    skilllv--;
-                if (skilllv < 1)
-                    skilllv = 1;
-                sp = skill_get_sp (sd->autospell_id, skilllv) * 2 / 3;
-                if (sd->status.sp >= sp)
-                {
-                    if ((i = skill_get_inf (sd->autospell_id) == 2)
-                        || i == 32)
-                        f = skill_castend_pos2 (src, target->x, target->y,
-                                                sd->autospell_id, skilllv,
-                                                tick, flag);
-                    else
-                    {
-                        switch (skill_get_nk (sd->autospell_id))
-                        {
-                            case 0:
-                            case 2:
-                                f = skill_castend_damage_id (src, target,
-                                                             sd->autospell_id,
-                                                             skilllv, tick,
-                                                             flag);
-                                break;
-                            case 1:    /* 支援系 */
-                                if ((sd->autospell_id == AL_HEAL
-                                     || (sd->autospell_id == ALL_RESURRECTION
-                                         && target->type != BL_PC))
-                                    && battle_check_undead (race, ele))
-                                    f = skill_castend_damage_id (src, target,
-                                                                 sd->autospell_id,
-                                                                 skilllv,
-                                                                 tick, flag);
-                                else
-                                    f = skill_castend_nodamage_id (src,
-                                                                   target,
-                                                                   sd->autospell_id,
-                                                                   skilllv,
-                                                                   tick,
-                                                                   flag);
-                                break;
-                        }
-                    }
-                    if (!f)
-                        pc_heal (sd, 0, -sp);
-                }
-            }
-            if (wd.flag & BF_WEAPON && src != target
-                && (wd.damage > 0 || wd.damage2 > 0))
-            {
-                int  hp = 0, sp = 0;
-                if (sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0
-                    && MRAND (100) < sd->hp_drain_rate)
-                {
-                    hp += (wd.damage * sd->hp_drain_per) / 100;
-                    if (sd->hp_drain_rate > 0 && hp < 1)
-                        hp = 1;
-                    else if (sd->hp_drain_rate < 0 && hp > -1)
-                        hp = -1;
-                }
-                if (sd->hp_drain_rate_ && sd->hp_drain_per_ > 0
-                    && wd.damage2 > 0 && MRAND (100) < sd->hp_drain_rate_)
-                {
-                    hp += (wd.damage2 * sd->hp_drain_per_) / 100;
-                    if (sd->hp_drain_rate_ > 0 && hp < 1)
-                        hp = 1;
-                    else if (sd->hp_drain_rate_ < 0 && hp > -1)
-                        hp = -1;
-                }
-                if (sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0
-                    && MRAND (100) < sd->sp_drain_rate)
-                {
-                    sp += (wd.damage * sd->sp_drain_per) / 100;
-                    if (sd->sp_drain_rate > 0 && sp < 1)
-                        sp = 1;
-                    else if (sd->sp_drain_rate < 0 && sp > -1)
-                        sp = -1;
-                }
-                if (sd->sp_drain_rate_ && sd->sp_drain_per_ > 0
-                    && wd.damage2 > 0 && MRAND (100) < sd->sp_drain_rate_)
-                {
-                    sp += (wd.damage2 * sd->sp_drain_per_) / 100;
-                    if (sd->sp_drain_rate_ > 0 && sp < 1)
-                        sp = 1;
-                    else if (sd->sp_drain_rate_ < 0 && sp > -1)
-                        sp = -1;
-                }
-                if (hp || sp)
-                    pc_heal (sd, hp, sp);
-            }
-        }
-
-        if (rdamage > 0)
-            battle_damage (target, src, rdamage, 0);
-        if (t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1
-            && t_sc_data[SC_AUTOCOUNTER].val4 > 0)
-        {
-            if (t_sc_data[SC_AUTOCOUNTER].val3 == src->id)
-                battle_weapon_attack (target, src, tick,
-                                      0x8000 |
-                                      t_sc_data[SC_AUTOCOUNTER].val1);
-            skill_status_change_end (target, SC_AUTOCOUNTER, -1);
-        }
-        if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1)
-        {
-            int  lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
-            skill_status_change_end (target, SC_BLADESTOP_WAIT, -1);
-            skill_status_change_start (src, SC_BLADESTOP, lv, 1, (int) src,
-                                       (int) target,
-                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
-            skill_status_change_start (target, SC_BLADESTOP, lv, 2,
-                                       (int) target, (int) src,
-                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
-        }
-        if (t_sc_data && t_sc_data[SC_SPLASHER].timer != -1)    //殴ったので対象のベナムスプラッシャー状態を解除
-            skill_status_change_end (target, SC_SPLASHER, -1);
-
-        map_freeblock_unlock ();
-    }
-    return wd.dmg_lv;
-}
-
-int battle_check_undead (int race, int element)
-{
-    if (battle_config.undead_detect_type == 0)
-    {
-        if (element == 9)
-            return 1;
-    }
-    else if (battle_config.undead_detect_type == 1)
-    {
-        if (race == 1)
-            return 1;
-    }
-    else
-    {
-        if (element == 9 || race == 1)
-            return 1;
-    }
-    return 0;
-}
-
-/*==========================================
- * 敵味方判定(1=肯定,0=否定,-1=エラー)
- * flag&0xf0000 = 0x00000:敵じゃないか判定(ret:1=敵ではない)
- *				= 0x10000:パーティー判定(ret:1=パーティーメンバ)
- *				= 0x20000:全て(ret:1=敵味方両方)
- *				= 0x40000:敵か判定(ret:1=敵)
- *				= 0x50000:パーティーじゃないか判定(ret:1=パーティでない)
- *------------------------------------------
- */
-int battle_check_target (struct block_list *src, struct block_list *target,
-                         int flag)
-{
-    int  s_p, s_g, t_p, t_g;
-    struct block_list *ss = src;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, target);
-
-    if (flag & 0x40000)
-    {                           // 反転フラグ
-        int  ret = battle_check_target (src, target, flag & 0x30000);
-        if (ret != -1)
-            return !ret;
-        return -1;
-    }
-
-    if (flag & 0x20000)
-    {
-        if (target->type == BL_MOB || target->type == BL_PC)
-            return 1;
-        else
-            return -1;
-    }
-
-    if (src->type == BL_SKILL && target->type == BL_SKILL)  // 対象がスキルユニットなら無条件肯定
-        return -1;
-
-    if (target->type == BL_PC
-        && ((struct map_session_data *) target)->invincible_timer != -1)
-        return -1;
-
-    if (target->type == BL_SKILL)
-    {
-        switch (((struct skill_unit *) target)->group->unit_id)
-        {
-            case 0x8d:
-            case 0x8f:
-            case 0x98:
-                return 0;
-                break;
-        }
-    }
-
-    // スキルユニットの場合、親を求める
-    if (src->type == BL_SKILL)
-    {
-        int  inf2 =
-            skill_get_inf2 (((struct skill_unit *) src)->group->skill_id);
-        if ((ss =
-             map_id2bl (((struct skill_unit *) src)->group->src_id)) == NULL)
-            return -1;
-        if (ss->prev == NULL)
-            return -1;
-        if (inf2 & 0x80 && (map[src->m].flag.pvp || pc_iskiller ((struct map_session_data *) src, (struct map_session_data *) target)) &&   // [MouseJstr]
-            !(target->type == BL_PC
-              && pc_isinvisible ((struct map_session_data *) target)))
-            return 0;
-        if (ss == target)
-        {
-            if (inf2 & 0x100)
-                return 0;
-            if (inf2 & 0x200)
-                return -1;
-        }
-    }
-    // Mobでmaster_idがあってspecial_mob_aiなら、召喚主を求める
-    if (src->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) src;
-        if (md && md->master_id > 0)
-        {
-            if (md->master_id == target->id)    // 主なら肯定
-                return 1;
-            if (md->state.special_mob_ai)
-            {
-                if (target->type == BL_MOB)
-                {               //special_mob_aiで対象がMob
-                    struct mob_data *tmd = (struct mob_data *) target;
-                    if (tmd)
-                    {
-                        if (tmd->master_id != md->master_id)    //召喚主が一緒でなければ否定
-                            return 0;
-                        else
-                        {       //召喚主が一緒なので肯定したいけど自爆は否定
-                            if (md->state.special_mob_ai > 2)
-                                return 0;
-                            else
-                                return 1;
-                        }
-                    }
-                }
-            }
-            if ((ss = map_id2bl (md->master_id)) == NULL)
-                return -1;
-        }
-    }
-
-    if (src == target || ss == target)  // 同じなら肯定
-        return 1;
-
-    if (target->type == BL_PC
-        && pc_isinvisible ((struct map_session_data *) target))
-        return -1;
-
-    if (src->prev == NULL ||    // 死んでるならエラー
-        (src->type == BL_PC && pc_isdead ((struct map_session_data *) src)))
-        return -1;
-
-    if ((ss->type == BL_PC && target->type == BL_MOB) ||
-        (ss->type == BL_MOB && target->type == BL_PC))
-        return 0;               // PCvsMOBなら否定
-
-    s_p = battle_get_party_id (ss);
-    s_g = battle_get_guild_id (ss);
-
-    t_p = battle_get_party_id (target);
-    t_g = battle_get_guild_id (target);
-
-    if (flag & 0x10000)
-    {
-        if (s_p && t_p && s_p == t_p)   // 同じパーティなら肯定(味方)
-            return 1;
-        else                    // パーティ検索なら同じパーティじゃない時点で否定
-            return 0;
-    }
-
-    if (ss->type == BL_MOB && s_g > 0 && t_g > 0 && s_g == t_g) // 同じギルド/mobクラスなら肯定(味方)
-        return 1;
-
-//printf("ss:%d src:%d target:%d flag:0x%x %d %d ",ss->id,src->id,target->id,flag,src->type,target->type);
-//printf("p:%d %d g:%d %d\n",s_p,t_p,s_g,t_g);
-
-    if (ss->type == BL_PC && target->type == BL_PC)
-    {                           // 両方PVPモードなら否定(敵)
-        struct skill_unit *su = NULL;
-        if (src->type == BL_SKILL)
-            su = (struct skill_unit *) src;
-        if (map[ss->m].flag.pvp
-            || pc_iskiller ((struct map_session_data *) ss,
-                            (struct map_session_data *) target))
-        {                       // [MouseJstr]
-            if (su && su->group->target_flag == BCT_NOENEMY)
-                return 1;
-            else if (battle_config.pk_mode
-                     && (((struct map_session_data *) ss)->status.pc_class == 0
-                         || ((struct map_session_data *) target)->
-                         status.pc_class == 0))
-                return 1;       // prevent novice engagement in pk_mode [Valaris]
-            else if (map[ss->m].flag.pvp_noparty && s_p > 0 && t_p > 0
-                     && s_p == t_p)
-                return 1;
-            else if (map[ss->m].flag.pvp_noguild && s_g > 0 && t_g > 0
-                     && s_g == t_g)
-                return 1;
-            return 0;
-        }
-        if (map[src->m].flag.gvg)
-        {
-            struct guild *g = NULL;
-            if (su && su->group->target_flag == BCT_NOENEMY)
-                return 1;
-            if (s_g > 0 && s_g == t_g)
-                return 1;
-            if (map[src->m].flag.gvg_noparty && s_p > 0 && t_p > 0
-                && s_p == t_p)
-                return 1;
-            if ((g = guild_search (s_g)))
-            {
-                int  i;
-                for (i = 0; i < MAX_GUILDALLIANCE; i++)
-                {
-                    if (g->alliance[i].guild_id > 0
-                        && g->alliance[i].guild_id == t_g)
-                    {
-                        if (g->alliance[i].opposition)
-                            return 0;   //敵対ギルドなら無条件に敵
-                        else
-                            return 1;   //同盟ギルドなら無条件に味方
-                    }
-                }
-            }
-            return 0;
-        }
-    }
-
-    return 1;                   // 該当しないので無関係人物(まあ敵じゃないので味方)
-}
-
-/*==========================================
- * 射程判定
- *------------------------------------------
- */
-int battle_check_range (struct block_list *src, struct block_list *bl,
-                        int range)
-{
-
-    int  dx, dy;
-    struct walkpath_data wpd;
-    int  arange;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, bl);
-
-    dx = abs (bl->x - src->x);
-    dy = abs (bl->y - src->y);
-    arange = ((dx > dy) ? dx : dy);
-
-    if (src->m != bl->m)        // 違うマップ
-        return 0;
-
-    if (range > 0 && range < arange)    // 遠すぎる
-        return 0;
-
-    if (arange < 2)             // 同じマスか隣接
-        return 1;
-
-//  if(bl->type == BL_SKILL && ((struct skill_unit *)bl)->group->unit_id == 0x8d)
-//      return 1;
-
-    // 障害物判定
-    wpd.path_len = 0;
-    wpd.path_pos = 0;
-    wpd.path_half = 0;
-    if (path_search (&wpd, src->m, src->x, src->y, bl->x, bl->y, 0x10001) !=
-        -1)
-        return 1;
-
-    dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
-    dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
-    return (path_search (&wpd, src->m, src->x + dx, src->y + dy,
-                         bl->x - dx, bl->y - dy, 0x10001) != -1) ? 1 : 0;
-}
-
-/*==========================================
- * Return numerical value of a switch configuration (modified by [Yor])
- * on/off, english, fran軋is, deutsch, espal
- *------------------------------------------
- */
-int battle_config_switch (const char *str)
-{
-    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
-        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
-        || strcasecmp (str, "si") == 0)
-        return 1;
-    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
-        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
-        return 0;
-    return atoi (str);
-}
-
-/*==========================================
- * 設定ファイルを読み込む
- *------------------------------------------
- */
-int battle_config_read (const char *cfgName)
-{
-    int  i;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-    static int count = 0;
-
-    if ((count++) == 0)
-    {
-        battle_config.warp_point_debug = 0;
-        battle_config.enemy_critical = 0;
-        battle_config.enemy_critical_rate = 100;
-        battle_config.enemy_str = 1;
-        battle_config.enemy_perfect_flee = 0;
-        battle_config.cast_rate = 100;
-        battle_config.delay_rate = 100;
-        battle_config.delay_dependon_dex = 0;
-        battle_config.sdelay_attack_enable = 0;
-        battle_config.left_cardfix_to_right = 0;
-        battle_config.pc_skill_add_range = 0;
-        battle_config.skill_out_range_consume = 1;
-        battle_config.mob_skill_add_range = 0;
-        battle_config.pc_damage_delay = 1;
-        battle_config.pc_damage_delay_rate = 100;
-        battle_config.defnotenemy = 1;
-        battle_config.random_monster_checklv = 1;
-        battle_config.attr_recover = 1;
-        battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
-        battle_config.item_auto_get = 0;
-        battle_config.drop_pickup_safety_zone = 20;
-        battle_config.item_first_get_time = 3000;
-        battle_config.item_second_get_time = 1000;
-        battle_config.item_third_get_time = 1000;
-        battle_config.mvp_item_first_get_time = 10000;
-        battle_config.mvp_item_second_get_time = 10000;
-        battle_config.mvp_item_third_get_time = 2000;
-
-        battle_config.drop_rate0item = 0;
-        battle_config.base_exp_rate = 100;
-        battle_config.job_exp_rate = 100;
-        battle_config.pvp_exp = 1;
-        battle_config.gtb_pvp_only = 0;
-        battle_config.death_penalty_type = 0;
-        battle_config.death_penalty_base = 0;
-        battle_config.death_penalty_job = 0;
-        battle_config.zeny_penalty = 0;
-        battle_config.restart_hp_rate = 0;
-        battle_config.restart_sp_rate = 0;
-        battle_config.mvp_item_rate = 100;
-        battle_config.mvp_exp_rate = 100;
-        battle_config.mvp_hp_rate = 100;
-        battle_config.monster_hp_rate = 100;
-        battle_config.monster_max_aspd = 199;
-        battle_config.atc_gmonly = 0;
-        battle_config.gm_allskill = 0;
-        battle_config.gm_allequip = 0;
-        battle_config.gm_skilluncond = 0;
-        battle_config.guild_max_castles = 0;
-        battle_config.skillfree = 0;
-        battle_config.skillup_limit = 0;
-        battle_config.wp_rate = 100;
-        battle_config.pp_rate = 100;
-        battle_config.monster_active_enable = 1;
-        battle_config.monster_damage_delay_rate = 100;
-        battle_config.monster_loot_type = 0;
-        battle_config.mob_skill_use = 1;
-        battle_config.mob_count_rate = 100;
-        battle_config.quest_skill_learn = 0;
-        battle_config.quest_skill_reset = 1;
-        battle_config.basic_skill_check = 1;
-        battle_config.guild_emperium_check = 1;
-        battle_config.guild_exp_limit = 50;
-        battle_config.pc_invincible_time = 5000;
-        battle_config.skill_min_damage = 0;
-        battle_config.finger_offensive_type = 0;
-        battle_config.heal_exp = 0;
-        battle_config.resurrection_exp = 0;
-        battle_config.shop_exp = 0;
-        battle_config.combo_delay_rate = 100;
-        battle_config.item_check = 1;
-        battle_config.wedding_modifydisplay = 0;
-        battle_config.natural_healhp_interval = 6000;
-        battle_config.natural_healsp_interval = 8000;
-        battle_config.natural_heal_skill_interval = 10000;
-        battle_config.natural_heal_weight_rate = 50;
-        battle_config.itemheal_regeneration_factor = 1;
-        battle_config.item_name_override_grffile = 1;
-        battle_config.arrow_decrement = 1;
-        battle_config.max_aspd = 199;
-        battle_config.max_hp = 32500;
-        battle_config.max_sp = 32500;
-        battle_config.max_lv = 99;  // [MouseJstr]
-        battle_config.max_parameter = 99;
-        battle_config.max_cart_weight = 8000;
-        battle_config.pc_skill_log = 0;
-        battle_config.mob_skill_log = 0;
-        battle_config.battle_log = 0;
-        battle_config.save_log = 0;
-        battle_config.error_log = 1;
-        battle_config.etc_log = 1;
-        battle_config.save_clothcolor = 0;
-        battle_config.undead_detect_type = 0;
-        battle_config.pc_auto_counter_type = 1;
-        battle_config.monster_auto_counter_type = 1;
-        battle_config.agi_penaly_type = 0;
-        battle_config.agi_penaly_count = 3;
-        battle_config.agi_penaly_num = 0;
-        battle_config.agi_penaly_count_lv = ATK_FLEE;
-        battle_config.vit_penaly_type = 0;
-        battle_config.vit_penaly_count = 3;
-        battle_config.vit_penaly_num = 0;
-        battle_config.vit_penaly_count_lv = ATK_DEF;
-        battle_config.player_defense_type = 0;
-        battle_config.monster_defense_type = 0;
-        battle_config.magic_defense_type = 0;
-        battle_config.pc_skill_reiteration = 0;
-        battle_config.monster_skill_reiteration = 0;
-        battle_config.pc_skill_nofootset = 0;
-        battle_config.monster_skill_nofootset = 0;
-        battle_config.pc_cloak_check_type = 0;
-        battle_config.monster_cloak_check_type = 0;
-        battle_config.gvg_short_damage_rate = 100;
-        battle_config.gvg_long_damage_rate = 100;
-        battle_config.gvg_magic_damage_rate = 100;
-        battle_config.gvg_misc_damage_rate = 100;
-        battle_config.gvg_eliminate_time = 7000;
-        battle_config.mob_changetarget_byskill = 0;
-        battle_config.pc_attack_direction_change = 1;
-        battle_config.monster_attack_direction_change = 1;
-        battle_config.pc_undead_nofreeze = 0;
-        battle_config.pc_land_skill_limit = 1;
-        battle_config.monster_land_skill_limit = 1;
-        battle_config.party_skill_penaly = 1;
-        battle_config.monster_class_change_full_recover = 0;
-        battle_config.produce_item_name_input = 1;
-        battle_config.produce_potion_name_input = 1;
-        battle_config.making_arrow_name_input = 1;
-        battle_config.holywater_name_input = 1;
-        battle_config.display_delay_skill_fail = 1;
-        battle_config.chat_warpportal = 0;
-        battle_config.mob_warpportal = 0;
-        battle_config.dead_branch_active = 0;
-        battle_config.show_steal_in_same_party = 0;
-        battle_config.enable_upper_class = 0;
-        battle_config.pc_attack_attr_none = 0;
-        battle_config.mob_attack_attr_none = 1;
-        battle_config.mob_ghostring_fix = 0;
-        battle_config.gx_allhit = 0;
-        battle_config.gx_cardfix = 0;
-        battle_config.gx_dupele = 1;
-        battle_config.gx_disptype = 1;
-        battle_config.player_skill_partner_check = 1;
-        battle_config.hide_GM_session = 0;
-        battle_config.unit_movement_type = 0;
-        battle_config.invite_request_check = 1;
-        battle_config.skill_removetrap_type = 0;
-        battle_config.disp_experience = 0;
-        battle_config.item_rate_common = 100;
-        battle_config.item_rate_equip = 100;
-        battle_config.item_rate_card = 100;
-        battle_config.item_rate_heal = 100; // Added by Valaris
-        battle_config.item_rate_use = 100;  // End
-        battle_config.item_drop_common_min = 1; // Added by TyrNemesis^
-        battle_config.item_drop_common_max = 10000;
-        battle_config.item_drop_equip_min = 1;
-        battle_config.item_drop_equip_max = 10000;
-        battle_config.item_drop_card_min = 1;
-        battle_config.item_drop_card_max = 10000;
-        battle_config.item_drop_mvp_min = 1;
-        battle_config.item_drop_mvp_max = 10000;    // End Addition
-        battle_config.item_drop_heal_min = 1;   // Added by Valaris
-        battle_config.item_drop_heal_max = 10000;
-        battle_config.item_drop_use_min = 1;
-        battle_config.item_drop_use_max = 10000;    // End
-        battle_config.prevent_logout = 1;   // Added by RoVeRT
-        battle_config.maximum_level = 255;  // Added by Valaris
-        battle_config.drops_by_luk = 0; // [Valaris]
-        battle_config.equipment_breaking = 0;   // [Valaris]
-        battle_config.equipment_break_rate = 100;   // [Valaris]
-        battle_config.pk_mode = 0;  // [Valaris]
-        battle_config.multi_level_up = 0;   // [Valaris]
-        battle_config.backstab_bow_penalty = 0; // Akaru
-        battle_config.night_at_start = 0;   // added by [Yor]
-        battle_config.day_duration = 2 * 60 * 60 * 1000;    // added by [Yor] (2 hours)
-        battle_config.night_duration = 30 * 60 * 1000;  // added by [Yor] (30 minutes)
-        battle_config.show_mob_hp = 0;  // [Valaris]
-        battle_config.hack_info_GM_level = 60;  // added by [Yor] (default: 60, GM level)
-        battle_config.any_warp_GM_min_level = 20;   // added by [Yor]
-        battle_config.packet_ver_flag = 63; // added by [Yor]
-        battle_config.min_hair_style = 0;
-        battle_config.max_hair_style = 20;
-        battle_config.min_hair_color = 0;
-        battle_config.max_hair_color = 9;
-        battle_config.min_cloth_color = 0;
-        battle_config.max_cloth_color = 4;
-
-        battle_config.castrate_dex_scale = 150;
-
-        battle_config.area_size = 14;
-
-        battle_config.chat_lame_penalty = 2;
-        battle_config.chat_spam_threshold = 10;
-        battle_config.chat_spam_flood = 10;
-        battle_config.chat_spam_ban = 1;
-        battle_config.chat_spam_warn = 8;
-        battle_config.chat_maxline = 255;
-
-        battle_config.packet_spam_threshold = 2;
-        battle_config.packet_spam_flood = 30;
-        battle_config.packet_spam_kick = 1;
-
-        battle_config.mask_ip_gms = 1;
-
-        battle_config.mob_splash_radius = -1;
-    }
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        printf ("file not found: %s\n", cfgName);
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        const struct
-        {
-            char str[128];
-            int *val;
-        } data[] =
-        {
-            {
-            "warp_point_debug", &battle_config.warp_point_debug},
-            {
-            "enemy_critical", &battle_config.enemy_critical},
-            {
-            "enemy_critical_rate", &battle_config.enemy_critical_rate},
-            {
-            "enemy_str", &battle_config.enemy_str},
-            {
-            "enemy_perfect_flee", &battle_config.enemy_perfect_flee},
-            {
-            "casting_rate", &battle_config.cast_rate},
-            {
-            "delay_rate", &battle_config.delay_rate},
-            {
-            "delay_dependon_dex", &battle_config.delay_dependon_dex},
-            {
-            "skill_delay_attack_enable",
-                    &battle_config.sdelay_attack_enable},
-            {
-            "left_cardfix_to_right", &battle_config.left_cardfix_to_right},
-            {
-            "player_skill_add_range", &battle_config.pc_skill_add_range},
-            {
-            "skill_out_range_consume",
-                    &battle_config.skill_out_range_consume},
-            {
-            "monster_skill_add_range", &battle_config.mob_skill_add_range},
-            {
-            "player_damage_delay", &battle_config.pc_damage_delay},
-            {
-            "player_damage_delay_rate",
-                    &battle_config.pc_damage_delay_rate},
-            {
-            "defunit_not_enemy", &battle_config.defnotenemy},
-            {
-            "random_monster_checklv",
-                    &battle_config.random_monster_checklv},
-            {
-            "attribute_recover", &battle_config.attr_recover},
-            {
-            "flooritem_lifetime", &battle_config.flooritem_lifetime},
-            {
-            "item_auto_get", &battle_config.item_auto_get},
-            {
-            "drop_pickup_safety_zone",
-                    &battle_config.drop_pickup_safety_zone},
-            {
-            "item_first_get_time", &battle_config.item_first_get_time},
-            {
-            "item_second_get_time", &battle_config.item_second_get_time},
-            {
-            "item_third_get_time", &battle_config.item_third_get_time},
-            {
-            "mvp_item_first_get_time",
-                    &battle_config.mvp_item_first_get_time},
-            {
-            "mvp_item_second_get_time",
-                    &battle_config.mvp_item_second_get_time},
-            {
-            "mvp_item_third_get_time",
-                    &battle_config.mvp_item_third_get_time},
-            {
-            "item_rate", &battle_config.item_rate},
-            {
-            "drop_rate0item", &battle_config.drop_rate0item},
-            {
-            "base_exp_rate", &battle_config.base_exp_rate},
-            {
-            "job_exp_rate", &battle_config.job_exp_rate},
-            {
-            "pvp_exp", &battle_config.pvp_exp},
-            {
-            "gtb_pvp_only", &battle_config.gtb_pvp_only},
-            {
-            "guild_max_castles", &battle_config.guild_max_castles},
-            {
-            "death_penalty_type", &battle_config.death_penalty_type},
-            {
-            "death_penalty_base", &battle_config.death_penalty_base},
-            {
-            "death_penalty_job", &battle_config.death_penalty_job},
-            {
-            "zeny_penalty", &battle_config.zeny_penalty},
-            {
-            "restart_hp_rate", &battle_config.restart_hp_rate},
-            {
-            "restart_sp_rate", &battle_config.restart_sp_rate},
-            {
-            "mvp_hp_rate", &battle_config.mvp_hp_rate},
-            {
-            "mvp_item_rate", &battle_config.mvp_item_rate},
-            {
-            "mvp_exp_rate", &battle_config.mvp_exp_rate},
-            {
-            "monster_hp_rate", &battle_config.monster_hp_rate},
-            {
-            "monster_max_aspd", &battle_config.monster_max_aspd},
-            {
-            "atcommand_gm_only", &battle_config.atc_gmonly},
-            {
-            "atcommand_spawn_quantity_limit",
-                    &battle_config.atc_spawn_quantity_limit},
-            {
-            "gm_all_skill", &battle_config.gm_allskill},
-            {
-            "gm_all_skill_add_abra", &battle_config.gm_allskill_addabra},
-            {
-            "gm_all_equipment", &battle_config.gm_allequip},
-            {
-            "gm_skill_unconditional", &battle_config.gm_skilluncond},
-            {
-            "player_skillfree", &battle_config.skillfree},
-            {
-            "player_skillup_limit", &battle_config.skillup_limit},
-            {
-            "weapon_produce_rate", &battle_config.wp_rate},
-            {
-            "potion_produce_rate", &battle_config.pp_rate},
-            {
-            "monster_active_enable", &battle_config.monster_active_enable},
-            {
-            "monster_damage_delay_rate",
-                    &battle_config.monster_damage_delay_rate},
-            {
-            "monster_loot_type", &battle_config.monster_loot_type},
-            {
-            "mob_skill_use", &battle_config.mob_skill_use},
-            {
-            "mob_count_rate", &battle_config.mob_count_rate},
-            {
-            "quest_skill_learn", &battle_config.quest_skill_learn},
-            {
-            "quest_skill_reset", &battle_config.quest_skill_reset},
-            {
-            "basic_skill_check", &battle_config.basic_skill_check},
-            {
-            "guild_emperium_check", &battle_config.guild_emperium_check},
-            {
-            "guild_exp_limit", &battle_config.guild_exp_limit},
-            {
-            "player_invincible_time", &battle_config.pc_invincible_time},
-            {
-            "skill_min_damage", &battle_config.skill_min_damage},
-            {
-            "finger_offensive_type", &battle_config.finger_offensive_type},
-            {
-            "heal_exp", &battle_config.heal_exp},
-            {
-            "resurrection_exp", &battle_config.resurrection_exp},
-            {
-            "shop_exp", &battle_config.shop_exp},
-            {
-            "combo_delay_rate", &battle_config.combo_delay_rate},
-            {
-            "item_check", &battle_config.item_check},
-            {
-            "wedding_modifydisplay", &battle_config.wedding_modifydisplay},
-            {
-            "natural_healhp_interval",
-                    &battle_config.natural_healhp_interval},
-            {
-            "natural_healsp_interval",
-                    &battle_config.natural_healsp_interval},
-            {
-            "natural_heal_skill_interval",
-                    &battle_config.natural_heal_skill_interval},
-            {
-            "natural_heal_weight_rate",
-                    &battle_config.natural_heal_weight_rate},
-            {
-            "itemheal_regeneration_factor",
-                    &battle_config.itemheal_regeneration_factor},
-            {
-            "item_name_override_grffile",
-                    &battle_config.item_name_override_grffile},
-            {
-            "arrow_decrement", &battle_config.arrow_decrement},
-            {
-            "max_aspd", &battle_config.max_aspd},
-            {
-            "max_hp", &battle_config.max_hp},
-            {
-            "max_sp", &battle_config.max_sp},
-            {
-            "max_lv", &battle_config.max_lv},
-            {
-            "max_parameter", &battle_config.max_parameter},
-            {
-            "max_cart_weight", &battle_config.max_cart_weight},
-            {
-            "player_skill_log", &battle_config.pc_skill_log},
-            {
-            "monster_skill_log", &battle_config.mob_skill_log},
-            {
-            "battle_log", &battle_config.battle_log},
-            {
-            "save_log", &battle_config.save_log},
-            {
-            "error_log", &battle_config.error_log},
-            {
-            "etc_log", &battle_config.etc_log},
-            {
-            "save_clothcolor", &battle_config.save_clothcolor},
-            {
-            "undead_detect_type", &battle_config.undead_detect_type},
-            {
-            "player_auto_counter_type",
-                    &battle_config.pc_auto_counter_type},
-            {
-            "monster_auto_counter_type",
-                    &battle_config.monster_auto_counter_type},
-            {
-            "agi_penaly_type", &battle_config.agi_penaly_type},
-            {
-            "agi_penaly_count", &battle_config.agi_penaly_count},
-            {
-            "agi_penaly_num", &battle_config.agi_penaly_num},
-            {
-            "agi_penaly_count_lv", &battle_config.agi_penaly_count_lv},
-            {
-            "vit_penaly_type", &battle_config.vit_penaly_type},
-            {
-            "vit_penaly_count", &battle_config.vit_penaly_count},
-            {
-            "vit_penaly_num", &battle_config.vit_penaly_num},
-            {
-            "vit_penaly_count_lv", &battle_config.vit_penaly_count_lv},
-            {
-            "player_defense_type", &battle_config.player_defense_type},
-            {
-            "monster_defense_type", &battle_config.monster_defense_type},
-            {
-            "magic_defense_type", &battle_config.magic_defense_type},
-            {
-            "player_skill_reiteration",
-                    &battle_config.pc_skill_reiteration},
-            {
-            "monster_skill_reiteration",
-                    &battle_config.monster_skill_reiteration},
-            {
-            "player_skill_nofootset", &battle_config.pc_skill_nofootset},
-            {
-            "monster_skill_nofootset",
-                    &battle_config.monster_skill_nofootset},
-            {
-            "player_cloak_check_type", &battle_config.pc_cloak_check_type},
-            {
-            "monster_cloak_check_type",
-                    &battle_config.monster_cloak_check_type},
-            {
-            "gvg_short_attack_damage_rate",
-                    &battle_config.gvg_short_damage_rate},
-            {
-            "gvg_long_attack_damage_rate",
-                    &battle_config.gvg_long_damage_rate},
-            {
-            "gvg_magic_attack_damage_rate",
-                    &battle_config.gvg_magic_damage_rate},
-            {
-            "gvg_misc_attack_damage_rate",
-                    &battle_config.gvg_misc_damage_rate},
-            {
-            "gvg_eliminate_time", &battle_config.gvg_eliminate_time},
-            {
-            "mob_changetarget_byskill",
-                    &battle_config.mob_changetarget_byskill},
-            {
-            "player_attack_direction_change",
-                    &battle_config.pc_attack_direction_change},
-            {
-            "monster_attack_direction_change",
-                    &battle_config.monster_attack_direction_change},
-            {
-            "player_land_skill_limit", &battle_config.pc_land_skill_limit},
-            {
-            "monster_land_skill_limit",
-                    &battle_config.monster_land_skill_limit},
-            {
-            "party_skill_penaly", &battle_config.party_skill_penaly},
-            {
-            "monster_class_change_full_recover",
-                    &battle_config.monster_class_change_full_recover},
-            {
-            "produce_item_name_input",
-                    &battle_config.produce_item_name_input},
-            {
-            "produce_potion_name_input",
-                    &battle_config.produce_potion_name_input},
-            {
-            "making_arrow_name_input",
-                    &battle_config.making_arrow_name_input},
-            {
-            "holywater_name_input", &battle_config.holywater_name_input},
-            {
-            "display_delay_skill_fail",
-                    &battle_config.display_delay_skill_fail},
-            {
-            "chat_warpportal", &battle_config.chat_warpportal},
-            {
-            "mob_warpportal", &battle_config.mob_warpportal},
-            {
-            "dead_branch_active", &battle_config.dead_branch_active},
-            {
-            "show_steal_in_same_party",
-                    &battle_config.show_steal_in_same_party},
-            {
-            "enable_upper_class", &battle_config.enable_upper_class},
-            {
-            "mob_attack_attr_none", &battle_config.mob_attack_attr_none},
-            {
-            "mob_ghostring_fix", &battle_config.mob_ghostring_fix},
-            {
-            "pc_attack_attr_none", &battle_config.pc_attack_attr_none},
-            {
-            "gx_allhit", &battle_config.gx_allhit},
-            {
-            "gx_cardfix", &battle_config.gx_cardfix},
-            {
-            "gx_dupele", &battle_config.gx_dupele},
-            {
-            "gx_disptype", &battle_config.gx_disptype},
-            {
-            "player_skill_partner_check",
-                    &battle_config.player_skill_partner_check},
-            {
-            "hide_GM_session", &battle_config.hide_GM_session},
-            {
-            "unit_movement_type", &battle_config.unit_movement_type},
-            {
-            "invite_request_check", &battle_config.invite_request_check},
-            {
-            "skill_removetrap_type", &battle_config.skill_removetrap_type},
-            {
-            "disp_experience", &battle_config.disp_experience},
-            {
-            "castle_defense_rate", &battle_config.castle_defense_rate},
-            {
-            "riding_weight", &battle_config.riding_weight},
-            {
-            "item_rate_common", &battle_config.item_rate_common},   // Added by RoVeRT
-            {
-            "item_rate_equip", &battle_config.item_rate_equip},
-            {
-            "item_rate_card", &battle_config.item_rate_card},   // End Addition
-            {
-            "item_rate_heal", &battle_config.item_rate_heal},   // Added by Valaris
-            {
-            "item_rate_use", &battle_config.item_rate_use}, // End
-            {
-            "item_drop_common_min", &battle_config.item_drop_common_min},   // Added by TyrNemesis^
-            {
-            "item_drop_common_max", &battle_config.item_drop_common_max},
-            {
-            "item_drop_equip_min", &battle_config.item_drop_equip_min},
-            {
-            "item_drop_equip_max", &battle_config.item_drop_equip_max},
-            {
-            "item_drop_card_min", &battle_config.item_drop_card_min},
-            {
-            "item_drop_card_max", &battle_config.item_drop_card_max},
-            {
-            "item_drop_mvp_min", &battle_config.item_drop_mvp_min},
-            {
-            "item_drop_mvp_max", &battle_config.item_drop_mvp_max}, // End Addition
-            {
-            "prevent_logout", &battle_config.prevent_logout},   // Added by RoVeRT
-            {
-            "alchemist_summon_reward", &battle_config.alchemist_summon_reward}, // [Valaris]
-            {
-            "maximum_level", &battle_config.maximum_level}, // [Valaris]
-            {
-            "drops_by_luk", &battle_config.drops_by_luk},   // [Valaris]
-            {
-            "monsters_ignore_gm", &battle_config.monsters_ignore_gm},   // [Valaris]
-            {
-            "equipment_breaking", &battle_config.equipment_breaking},   // [Valaris]
-            {
-            "equipment_break_rate", &battle_config.equipment_break_rate},   // [Valaris]
-            {
-            "pk_mode", &battle_config.pk_mode}, // [Valaris]
-            {
-            "multi_level_up", &battle_config.multi_level_up},   // [Valaris]
-            {
-            "backstab_bow_penalty", &battle_config.backstab_bow_penalty},
-            {
-            "night_at_start", &battle_config.night_at_start},   // added by [Yor]
-            {
-            "day_duration", &battle_config.day_duration},   // added by [Yor]
-            {
-            "night_duration", &battle_config.night_duration},   // added by [Yor]
-            {
-            "show_mob_hp", &battle_config.show_mob_hp}, // [Valaris]
-            {
-            "hack_info_GM_level", &battle_config.hack_info_GM_level},   // added by [Yor]
-            {
-            "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level}, // added by [Yor]
-            {
-            "packet_ver_flag", &battle_config.packet_ver_flag}, // added by [Yor]
-            {
-            "min_hair_style", &battle_config.min_hair_style},   // added by [MouseJstr]
-            {
-            "max_hair_style", &battle_config.max_hair_style},   // added by [MouseJstr]
-            {
-            "min_hair_color", &battle_config.min_hair_color},   // added by [MouseJstr]
-            {
-            "max_hair_color", &battle_config.max_hair_color},   // added by [MouseJstr]
-            {
-            "min_cloth_color", &battle_config.min_cloth_color}, // added by [MouseJstr]
-            {
-            "max_cloth_color", &battle_config.max_cloth_color}, // added by [MouseJstr]
-            {
-            "castrate_dex_scale", &battle_config.castrate_dex_scale},   // added by [MouseJstr]
-            {
-            "area_size", &battle_config.area_size}, // added by [MouseJstr]
-            {
-            "muting_players", &battle_config.muting_players},   // added by [Apple]
-            {
-            "chat_lame_penalty", &battle_config.chat_lame_penalty},
-            {
-            "chat_spam_threshold", &battle_config.chat_spam_threshold},
-            {
-            "chat_spam_flood", &battle_config.chat_spam_flood},
-            {
-            "chat_spam_ban", &battle_config.chat_spam_ban},
-            {
-            "chat_spam_warn", &battle_config.chat_spam_warn},
-            {
-            "chat_maxline", &battle_config.chat_maxline},
-            {
-            "packet_spam_threshold", &battle_config.packet_spam_threshold},
-            {
-            "packet_spam_flood", &battle_config.packet_spam_flood},
-            {
-            "packet_spam_kick", &battle_config.packet_spam_kick},
-            {
-            "mask_ip_gms", &battle_config.mask_ip_gms},
-            {
-            "mob_splash_radius", &battle_config.mob_splash_radius},
-        };
-
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (sscanf (line, "%[^:]:%s", w1, w2) != 2)
-            continue;
-        for (i = 0; i < sizeof (data) / (sizeof (data[0])); i++)
-            if (strcasecmp (w1, data[i].str) == 0)
-                *data[i].val = battle_config_switch (w2);
-
-        if (strcasecmp (w1, "import") == 0)
-            battle_config_read (w2);
-    }
-    fclose_ (fp);
-
-    if (--count == 0)
-    {
-        if (battle_config.flooritem_lifetime < 1000)
-            battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
-        if (battle_config.restart_hp_rate < 0)
-            battle_config.restart_hp_rate = 0;
-        else if (battle_config.restart_hp_rate > 100)
-            battle_config.restart_hp_rate = 100;
-        if (battle_config.restart_sp_rate < 0)
-            battle_config.restart_sp_rate = 0;
-        else if (battle_config.restart_sp_rate > 100)
-            battle_config.restart_sp_rate = 100;
-        if (battle_config.natural_healhp_interval < NATURAL_HEAL_INTERVAL)
-            battle_config.natural_healhp_interval = NATURAL_HEAL_INTERVAL;
-        if (battle_config.natural_healsp_interval < NATURAL_HEAL_INTERVAL)
-            battle_config.natural_healsp_interval = NATURAL_HEAL_INTERVAL;
-        if (battle_config.natural_heal_skill_interval < NATURAL_HEAL_INTERVAL)
-            battle_config.natural_heal_skill_interval = NATURAL_HEAL_INTERVAL;
-        if (battle_config.natural_heal_weight_rate < 50)
-            battle_config.natural_heal_weight_rate = 50;
-        if (battle_config.natural_heal_weight_rate > 101)
-            battle_config.natural_heal_weight_rate = 101;
-        battle_config.monster_max_aspd =
-            2000 - battle_config.monster_max_aspd * 10;
-        if (battle_config.monster_max_aspd < 10)
-            battle_config.monster_max_aspd = 10;
-        if (battle_config.monster_max_aspd > 1000)
-            battle_config.monster_max_aspd = 1000;
-        battle_config.max_aspd = 2000 - battle_config.max_aspd * 10;
-        if (battle_config.max_aspd < 10)
-            battle_config.max_aspd = 10;
-        if (battle_config.max_aspd > 1000)
-            battle_config.max_aspd = 1000;
-        if (battle_config.max_hp > 1000000)
-            battle_config.max_hp = 1000000;
-        if (battle_config.max_hp < 100)
-            battle_config.max_hp = 100;
-        if (battle_config.max_sp > 1000000)
-            battle_config.max_sp = 1000000;
-        if (battle_config.max_sp < 100)
-            battle_config.max_sp = 100;
-        if (battle_config.max_parameter < 10)
-            battle_config.max_parameter = 10;
-        if (battle_config.max_parameter > 10000)
-            battle_config.max_parameter = 10000;
-        if (battle_config.max_cart_weight > 1000000)
-            battle_config.max_cart_weight = 1000000;
-        if (battle_config.max_cart_weight < 100)
-            battle_config.max_cart_weight = 100;
-        battle_config.max_cart_weight *= 10;
-
-        if (battle_config.agi_penaly_count < 2)
-            battle_config.agi_penaly_count = 2;
-        if (battle_config.vit_penaly_count < 2)
-            battle_config.vit_penaly_count = 2;
-
-        if (battle_config.guild_exp_limit > 99)
-            battle_config.guild_exp_limit = 99;
-        if (battle_config.guild_exp_limit < 0)
-            battle_config.guild_exp_limit = 0;
-
-        if (battle_config.castle_defense_rate < 0)
-            battle_config.castle_defense_rate = 0;
-        if (battle_config.castle_defense_rate > 100)
-            battle_config.castle_defense_rate = 100;
-        if (battle_config.item_drop_common_min < 1) // Added by TyrNemesis^
-            battle_config.item_drop_common_min = 1;
-        if (battle_config.item_drop_common_max > 10000)
-            battle_config.item_drop_common_max = 10000;
-        if (battle_config.item_drop_equip_min < 1)
-            battle_config.item_drop_equip_min = 1;
-        if (battle_config.item_drop_equip_max > 10000)
-            battle_config.item_drop_equip_max = 10000;
-        if (battle_config.item_drop_card_min < 1)
-            battle_config.item_drop_card_min = 1;
-        if (battle_config.item_drop_card_max > 10000)
-            battle_config.item_drop_card_max = 10000;
-        if (battle_config.item_drop_mvp_min < 1)
-            battle_config.item_drop_mvp_min = 1;
-        if (battle_config.item_drop_mvp_max > 10000)
-            battle_config.item_drop_mvp_max = 10000;    // End Addition
-
-        if (battle_config.night_at_start < 0)   // added by [Yor]
-            battle_config.night_at_start = 0;
-        else if (battle_config.night_at_start > 1)  // added by [Yor]
-            battle_config.night_at_start = 1;
-        if (battle_config.day_duration < 0) // added by [Yor]
-            battle_config.day_duration = 0;
-        if (battle_config.night_duration < 0)   // added by [Yor]
-            battle_config.night_duration = 0;
-
-        if (battle_config.hack_info_GM_level < 0)   // added by [Yor]
-            battle_config.hack_info_GM_level = 0;
-        else if (battle_config.hack_info_GM_level > 100)
-            battle_config.hack_info_GM_level = 100;
-
-        if (battle_config.any_warp_GM_min_level < 0)    // added by [Yor]
-            battle_config.any_warp_GM_min_level = 0;
-        else if (battle_config.any_warp_GM_min_level > 100)
-            battle_config.any_warp_GM_min_level = 100;
-
-        if (battle_config.chat_spam_ban < 0)
-            battle_config.chat_spam_ban = 0;
-        else if (battle_config.chat_spam_ban > 32767)
-            battle_config.chat_spam_ban = 32767;
-
-        if (battle_config.chat_spam_flood < 0)
-            battle_config.chat_spam_flood = 0;
-        else if (battle_config.chat_spam_flood > 32767)
-            battle_config.chat_spam_flood = 32767;
-
-        if (battle_config.chat_spam_warn < 0)
-            battle_config.chat_spam_warn = 0;
-        else if (battle_config.chat_spam_warn > 32767)
-            battle_config.chat_spam_warn = 32767;
-
-        if (battle_config.chat_spam_threshold < 0)
-            battle_config.chat_spam_threshold = 0;
-        else if (battle_config.chat_spam_threshold > 32767)
-            battle_config.chat_spam_threshold = 32767;
-
-        if (battle_config.chat_maxline < 1)
-            battle_config.chat_maxline = 1;
-        else if (battle_config.chat_maxline > 512)
-            battle_config.chat_maxline = 512;
-
-        if (battle_config.packet_spam_threshold < 0)
-            battle_config.packet_spam_threshold = 0;
-        else if (battle_config.packet_spam_threshold > 32767)
-            battle_config.packet_spam_threshold = 32767;
-
-        if (battle_config.packet_spam_flood < 0)
-            battle_config.packet_spam_flood = 0;
-        else if (battle_config.packet_spam_flood > 32767)
-            battle_config.packet_spam_flood = 32767;
-
-        if (battle_config.packet_spam_kick < 0)
-            battle_config.packet_spam_kick = 0;
-        else if (battle_config.packet_spam_kick > 1)
-            battle_config.packet_spam_kick = 1;
-
-        if (battle_config.mask_ip_gms < 0)
-            battle_config.mask_ip_gms = 0;
-        else if (battle_config.mask_ip_gms > 1)
-            battle_config.mask_ip_gms = 1;
-
-        // at least 1 client must be accepted
-        if ((battle_config.packet_ver_flag & 63) == 0)  // added by [Yor]
-            battle_config.packet_ver_flag = 63; // accept all clients
-
-    }
-
-    return 0;
-}
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
new file mode 100644
index 0000000..a46db13
--- /dev/null
+++ b/src/map/battle.cpp
@@ -0,0 +1,6282 @@
+// $Id: battle.c,v 1.10 2004/09/29 21:08:17 Akitasha Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "battle.hpp"
+
+#include "../common/timer.hpp"
+#include "../common/nullpo.hpp"
+
+#include "clif.hpp"
+#include "guild.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "pc.hpp"
+#include "skill.hpp"
+#include "../common/socket.hpp"
+#include "../common/mt_rand.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+int  attr_fix_table[4][10][10];
+
+struct Battle_Config battle_config;
+
+/*==========================================
+ * 二点間の距離を返す
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+static int distance (int x0, int y0, int x1, int y1)
+{
+    int  dx, dy;
+
+    dx = abs (x0 - x1);
+    dy = abs (y0 - y1);
+    return dx > dy ? dx : dy;
+}
+
+/*==========================================
+ * 自分をロックしている対象の数を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_counttargeted (struct block_list *bl, struct block_list *src,
+                          int target_lv)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC)
+        return pc_counttargeted ((struct map_session_data *) bl, src,
+                                 target_lv);
+    else if (bl->type == BL_MOB)
+        return mob_counttargeted ((struct mob_data *) bl, src, target_lv);
+    return 0;
+}
+
+/*==========================================
+ * 対象のClassを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_class (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->mob_class;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->status.pc_class;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象の方向を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_dir (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->dir;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->dir;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のレベルを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_lv (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->stats[MOB_LV];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->status.base_level;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象の射程を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_range (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return mob_db[((struct mob_data *) bl)->mob_class].range;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->attackrange;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のHPを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_hp (struct block_list *bl)
+{
+    nullpo_retr (1, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->hp;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->status.hp;
+    else
+        return 1;
+}
+
+/*==========================================
+ * 対象のMHPを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_max_hp (struct block_list *bl)
+{
+    nullpo_retr (1, bl);
+    if (bl->type == BL_PC && ((struct map_session_data *) bl))
+        return ((struct map_session_data *) bl)->status.max_hp;
+    else
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        int  max_hp = 1;
+        if (bl->type == BL_MOB && ((struct mob_data *) bl))
+        {
+            max_hp = ((struct mob_data *) bl)->stats[MOB_MAX_HP];
+            if (mob_db[((struct mob_data *) bl)->mob_class].mexp > 0)
+            {
+                if (battle_config.mvp_hp_rate != 100)
+                    max_hp = (max_hp * battle_config.mvp_hp_rate) / 100;
+            }
+            else
+            {
+                if (battle_config.monster_hp_rate != 100)
+                    max_hp = (max_hp * battle_config.monster_hp_rate) / 100;
+            }
+        }
+        if (sc_data)
+        {
+            if (sc_data[SC_APPLEIDUN].timer != -1)
+                max_hp +=
+                    ((5 + sc_data[SC_APPLEIDUN].val1 * 2 +
+                      ((sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
+                      sc_data[SC_APPLEIDUN].val3 / 10) * max_hp) / 100;
+        }
+        if (max_hp < 1)
+            max_hp = 1;
+        return max_hp;
+    }
+    return 1;
+}
+
+/*==========================================
+ * 対象のStrを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_str (struct block_list *bl)
+{
+    int  str = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && ((struct mob_data *) bl))
+        str = ((struct mob_data *) bl)->stats[MOB_STR];
+    else if (bl->type == BL_PC && ((struct map_session_data *) bl))
+        return ((struct map_session_data *) bl)->paramc[0];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_LOUD].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1
+            && bl->type != BL_PC)
+            str += 4;
+        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
+        {                       // ブレッシング
+            int  race = battle_get_race (bl);
+            if (battle_check_undead (race, battle_get_elem_type (bl))
+                || race == 6)
+                str >>= 1;      // 悪 魔/不死
+            else
+                str += sc_data[SC_BLESSING].val1;   // その他
+        }
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            str += 5;
+    }
+    if (str < 0)
+        str = 0;
+    return str;
+}
+
+/*==========================================
+ * 対象のAgiを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+
+int battle_get_agi (struct block_list *bl)
+{
+    int  agi = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        agi = ((struct mob_data *) bl)->stats[MOB_AGI];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        agi = ((struct map_session_data *) bl)->paramc[1];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_INCREASEAGI].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1 && bl->type != BL_PC)   // 速度増加(PCはpc.cで)
+            agi += 2 + sc_data[SC_INCREASEAGI].val1;
+
+        if (sc_data[SC_CONCENTRATE].timer != -1
+            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
+            agi += agi * (2 + sc_data[SC_CONCENTRATE].val1) / 100;
+
+        if (sc_data[SC_DECREASEAGI].timer != -1)    // 速度減少
+            agi -= 2 + sc_data[SC_DECREASEAGI].val1;
+
+        if (sc_data[SC_QUAGMIRE].timer != -1)   // クァグマイア
+            agi >>= 1;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            agi += 5;
+    }
+    if (agi < 0)
+        agi = 0;
+    return agi;
+}
+
+/*==========================================
+ * 対象のVitを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_vit (struct block_list *bl)
+{
+    int  vit = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        vit = ((struct mob_data *) bl)->stats[MOB_VIT];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        vit = ((struct map_session_data *) bl)->paramc[2];
+    if (sc_data)
+    {
+        if (sc_data[SC_STRIPARMOR].timer != -1 && bl->type != BL_PC)
+            vit = vit * 60 / 100;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            vit += 5;
+    }
+
+    if (vit < 0)
+        vit = 0;
+    return vit;
+}
+
+/*==========================================
+ * 対象のIntを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_int (struct block_list *bl)
+{
+    int  int_ = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        int_ = ((struct mob_data *) bl)->stats[MOB_INT];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        int_ = ((struct map_session_data *) bl)->paramc[3];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
+        {                       // ブレッシング
+            int  race = battle_get_race (bl);
+            if (battle_check_undead (race, battle_get_elem_type (bl))
+                || race == 6)
+                int_ >>= 1;     // 悪 魔/不死
+            else
+                int_ += sc_data[SC_BLESSING].val1;  // その他
+        }
+        if (sc_data[SC_STRIPHELM].timer != -1 && bl->type != BL_PC)
+            int_ = int_ * 60 / 100;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            int_ += 5;
+    }
+    if (int_ < 0)
+        int_ = 0;
+    return int_;
+}
+
+/*==========================================
+ * 対象のDexを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_dex (struct block_list *bl)
+{
+    int  dex = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        dex = ((struct mob_data *) bl)->stats[MOB_DEX];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        dex = ((struct map_session_data *) bl)->paramc[4];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_CONCENTRATE].timer != -1
+            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
+            dex += dex * (2 + sc_data[SC_CONCENTRATE].val1) / 100;
+
+        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
+        {                       // ブレッシング
+            int  race = battle_get_race (bl);
+            if (battle_check_undead (race, battle_get_elem_type (bl))
+                || race == 6)
+                dex >>= 1;      // 悪 魔/不死
+            else
+                dex += sc_data[SC_BLESSING].val1;   // その他
+        }
+
+        if (sc_data[SC_QUAGMIRE].timer != -1)   // クァグマイア
+            dex >>= 1;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            dex += 5;
+    }
+    if (dex < 0)
+        dex = 0;
+    return dex;
+}
+
+/*==========================================
+ * 対象のLukを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_luk (struct block_list *bl)
+{
+    int  luk = 0;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        luk = ((struct mob_data *) bl)->stats[MOB_LUK];
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        luk = ((struct map_session_data *) bl)->paramc[5];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_GLORIA].timer != -1 && bl->type != BL_PC)    // グロリア(PCはpc.cで)
+            luk += 30;
+        if (sc_data[SC_CURSE].timer != -1)  // 呪い
+            luk = 0;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            luk += 5;
+    }
+    if (luk < 0)
+        luk = 0;
+    return luk;
+}
+
+/*==========================================
+ * 対象のFleeを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_flee (struct block_list *bl)
+{
+    int  flee = 1;
+    struct status_change *sc_data;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        flee = ((struct map_session_data *) bl)->flee;
+    else
+        flee = battle_get_agi (bl) + battle_get_lv (bl);
+
+    if (sc_data)
+    {
+        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
+            flee +=
+                flee * (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2 +
+                        (sc_data[SC_WHISTLE].val3 >> 16)) / 100;
+        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC)
+            flee -= flee * 25 / 100;
+        if (sc_data[SC_WINDWALK].timer != -1 && bl->type != BL_PC)  // ウィンドウォーク
+            flee += flee * (sc_data[SC_WINDWALK].val2) / 100;
+        if (sc_data[SC_SPIDERWEB].timer != -1 && bl->type != BL_PC) //スパイダーウェブ
+            flee -= flee * 50 / 100;
+
+        if (battle_is_unarmed (bl))
+            flee += (skill_power_bl (bl, TMW_BRAWLING) >> 3);   // +25 for 200
+        flee += skill_power_bl (bl, TMW_SPEED) >> 3;
+    }
+    if (flee < 1)
+        flee = 1;
+    return flee;
+}
+
+/*==========================================
+ * 対象のHitを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_hit (struct block_list *bl)
+{
+    int  hit = 1;
+    struct status_change *sc_data;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        hit = ((struct map_session_data *) bl)->hit;
+    else
+        hit = battle_get_dex (bl) + battle_get_lv (bl);
+
+    if (sc_data)
+    {
+        if (sc_data[SC_HUMMING].timer != -1 && bl->type != BL_PC)   //
+            hit +=
+                hit * (sc_data[SC_HUMMING].val1 * 2 +
+                       sc_data[SC_HUMMING].val2 +
+                       sc_data[SC_HUMMING].val3) / 100;
+        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC) // 呪い
+            hit -= hit * 25 / 100;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // トゥルーサイト
+            hit += 3 * (sc_data[SC_TRUESIGHT].val1);
+        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
+            hit += (hit * (10 * (sc_data[SC_CONCENTRATION].val1))) / 100;
+
+        if (battle_is_unarmed (bl))
+            hit += (skill_power_bl (bl, TMW_BRAWLING) >> 4);    // +12 for 200
+    }
+    if (hit < 1)
+        hit = 1;
+    return hit;
+}
+
+/*==========================================
+ * 対象の完全回避を返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_flee2 (struct block_list *bl)
+{
+    int  flee2 = 1;
+    struct status_change *sc_data;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        flee2 = battle_get_luk (bl) + 10;
+        flee2 +=
+            ((struct map_session_data *) bl)->flee2 -
+            (((struct map_session_data *) bl)->paramc[5] + 10);
+    }
+    else
+        flee2 = battle_get_luk (bl) + 1;
+
+    if (sc_data)
+    {
+        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
+            flee2 += (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2
+                      + (sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;
+
+        if (battle_is_unarmed (bl))
+            flee2 += (skill_power_bl (bl, TMW_BRAWLING) >> 3);  // +25 for 200
+        flee2 += skill_power_bl (bl, TMW_SPEED) >> 3;
+    }
+    if (flee2 < 1)
+        flee2 = 1;
+    return flee2;
+}
+
+/*==========================================
+ * 対象のクリティカルを返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_critical (struct block_list *bl)
+{
+    int  critical = 1;
+    struct status_change *sc_data;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        critical = battle_get_luk (bl) * 2 + 10;
+        critical +=
+            ((struct map_session_data *) bl)->critical -
+            ((((struct map_session_data *) bl)->paramc[5] * 3) + 10);
+    }
+    else
+        critical = battle_get_luk (bl) * 3 + 1;
+
+    if (sc_data)
+    {
+        if (sc_data[SC_FORTUNE].timer != -1 && bl->type != BL_PC)
+            critical +=
+                (10 + sc_data[SC_FORTUNE].val1 + sc_data[SC_FORTUNE].val2 +
+                 sc_data[SC_FORTUNE].val3) * 10;
+        if (sc_data[SC_EXPLOSIONSPIRITS].timer != -1 && bl->type != BL_PC)
+            critical += sc_data[SC_EXPLOSIONSPIRITS].val2;
+        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) //トゥルーサイト
+            critical += critical * sc_data[SC_TRUESIGHT].val1 / 100;
+    }
+    if (critical < 1)
+        critical = 1;
+    return critical;
+}
+
+/*==========================================
+ * base_atkの取得
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_baseatk (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    int  batk = 1;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        batk = ((struct map_session_data *) bl)->base_atk;  //設定されているbase_atk
+    else
+    {                           //それ以外なら
+        int  str, dstr;
+        str = battle_get_str (bl);  //STR
+        dstr = str / 10;
+        batk = dstr * dstr + str;   //base_atkを計算する
+    }
+    if (sc_data)
+    {                           //状態異常あり
+        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)   //PCでプロボック(SM_PROVOKE)状態
+            batk = batk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;   //base_atk増加
+        if (sc_data[SC_CURSE].timer != -1)  //呪われていたら
+            batk -= batk * 25 / 100;    //base_atkが25%減少
+        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
+            batk += batk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
+    }
+    if (batk < 1)
+        batk = 1;               //base_atkは最低でも1
+    return batk;
+}
+
+/*==========================================
+ * 対象のAtkを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_atk (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    int  atk = 0;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        atk = ((struct map_session_data *) bl)->watk;
+    else if (bl->type == BL_MOB && (struct mob_data *) bl)
+        atk = ((struct mob_data *) bl)->stats[MOB_ATK1];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
+            atk = atk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
+        if (sc_data[SC_CURSE].timer != -1)
+            atk -= atk * 25 / 100;
+        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //コンセントレーション
+            atk += atk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
+    }
+    if (atk < 0)
+        atk = 0;
+    return atk;
+}
+
+/*==========================================
+ * 対象の左手Atkを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_atk_ (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        int  atk = ((struct map_session_data *) bl)->watk_;
+
+        if (((struct map_session_data *) bl)->sc_data[SC_CURSE].timer != -1)
+            atk -= atk * 25 / 100;
+        return atk;
+    }
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のAtk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_atk2 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->watk2;
+    else
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        int  atk2 = 0;
+        if (bl->type == BL_MOB && (struct mob_data *) bl)
+            atk2 = ((struct mob_data *) bl)->stats[MOB_ATK2];
+        if (sc_data)
+        {
+            if (sc_data[SC_IMPOSITIO].timer != -1)
+                atk2 += sc_data[SC_IMPOSITIO].val1 * 5;
+            if (sc_data[SC_PROVOKE].timer != -1)
+                atk2 = atk2 * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
+            if (sc_data[SC_CURSE].timer != -1)
+                atk2 -= atk2 * 25 / 100;
+            if (sc_data[SC_DRUMBATTLE].timer != -1)
+                atk2 += sc_data[SC_DRUMBATTLE].val2;
+            if (sc_data[SC_NIBELUNGEN].timer != -1
+                && (battle_get_element (bl) / 10) >= 8)
+                atk2 += sc_data[SC_NIBELUNGEN].val2;
+            if (sc_data[SC_STRIPWEAPON].timer != -1)
+                atk2 = atk2 * 90 / 100;
+            if (sc_data[SC_CONCENTRATION].timer != -1)  //コンセントレーション
+                atk2 += atk2 * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
+        }
+
+        if (atk2 < 0)
+            atk2 = 0;
+        return atk2;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 対象の左手Atk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_atk_2 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC)
+        return ((struct map_session_data *) bl)->watk_2;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のMAtk1を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_matk1 (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB)
+    {
+        int  matk, int_ = battle_get_int (bl);
+        matk = int_ + (int_ / 5) * (int_ / 5);
+
+        if (sc_data)
+            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
+                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
+        return matk;
+    }
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->matk1;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のMAtk2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_matk2 (struct block_list *bl)
+{
+    struct status_change *sc_data = battle_get_sc_data (bl);
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB)
+    {
+        int  matk, int_ = battle_get_int (bl);
+        matk = int_ + (int_ / 7) * (int_ / 7);
+
+        if (sc_data)
+            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
+                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
+        return matk;
+    }
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->matk2;
+    else
+        return 0;
+}
+
+/*==========================================
+ * 対象のDefを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_def (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    int  def = 0, skilltimer = -1, skillid = 0;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        def = ((struct map_session_data *) bl)->def;
+        skilltimer = ((struct map_session_data *) bl)->skilltimer;
+        skillid = ((struct map_session_data *) bl)->skillid;
+    }
+    else if (bl->type == BL_MOB && (struct mob_data *) bl)
+    {
+        def = ((struct mob_data *) bl)->stats[MOB_DEF];
+        skilltimer = ((struct mob_data *) bl)->skilltimer;
+        skillid = ((struct mob_data *) bl)->skillid;
+    }
+
+    if (def < 1000000)
+    {
+        if (sc_data)
+        {
+            //キーピング時はDEF100
+            if (sc_data[SC_KEEPING].timer != -1)
+                def = 100;
+            //プロボック時は減算
+            if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
+                def = (def * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
+            //戦太鼓の響き時は加算
+            if (sc_data[SC_DRUMBATTLE].timer != -1 && bl->type != BL_PC)
+                def += sc_data[SC_DRUMBATTLE].val3;
+            //毒にかかっている時は減算
+            if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
+                def = def * 75 / 100;
+            //ストリップシールド時は減算
+            if (sc_data[SC_STRIPSHIELD].timer != -1 && bl->type != BL_PC)
+                def = def * 85 / 100;
+            //シグナムクルシス時は減算
+            if (sc_data[SC_SIGNUMCRUCIS].timer != -1 && bl->type != BL_PC)
+                def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2) / 100;
+            //永遠の混沌時はDEF0になる
+            if (sc_data[SC_ETERNALCHAOS].timer != -1 && bl->type != BL_PC)
+                def = 0;
+            //凍結、石化時は右シフト
+            if (sc_data[SC_FREEZE].timer != -1
+                || (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0))
+                def >>= 1;
+            //コンセントレーション時は減算
+            if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
+                def =
+                    (def * (100 - 5 * sc_data[SC_CONCENTRATION].val1)) / 100;
+        }
+        //詠唱中は詠唱時減算率に基づいて減算
+        if (skilltimer != -1)
+        {
+            int  def_rate = skill_get_castdef (skillid);
+            if (def_rate != 0)
+                def = (def * (100 - def_rate)) / 100;
+        }
+    }
+    if (def < 0)
+        def = 0;
+    return def;
+}
+
+/*==========================================
+ * 対象のMDefを返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_mdef (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    int  mdef = 0;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        mdef = ((struct map_session_data *) bl)->mdef;
+    else if (bl->type == BL_MOB && (struct mob_data *) bl)
+        mdef = ((struct mob_data *) bl)->stats[MOB_MDEF];
+
+    if (mdef < 1000000)
+    {
+        if (sc_data)
+        {
+            //バリアー状態時はMDEF100
+            if (mdef < 90 && sc_data[SC_MBARRIER].timer != -1)
+            {
+                mdef += sc_data[SC_MBARRIER].val1;
+                if (mdef > 90)
+                    mdef = 90;
+            }
+            if (sc_data[SC_BARRIER].timer != -1)
+                mdef = 100;
+            //凍結、石化時は1.25倍
+            if (sc_data[SC_FREEZE].timer != -1
+                || (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0))
+                mdef = mdef * 125 / 100;
+            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
+                mdef -= (mdef * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
+        }
+    }
+    if (mdef < 0)
+        mdef = 0;
+    return mdef;
+}
+
+/*==========================================
+ * 対象のDef2を返す(汎用)
+ * 戻りは整数で1以上
+ *------------------------------------------
+ */
+int battle_get_def2 (struct block_list *bl)
+{
+    struct status_change *sc_data;
+    int  def2 = 1;
+
+    nullpo_retr (1, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_PC)
+        def2 = ((struct map_session_data *) bl)->def2;
+    else if (bl->type == BL_MOB)
+        def2 = ((struct mob_data *) bl)->stats[MOB_VIT];
+
+    if (sc_data)
+    {
+        if (sc_data[SC_ANGELUS].timer != -1 && bl->type != BL_PC)
+            def2 = def2 * (110 + 5 * sc_data[SC_ANGELUS].val1) / 100;
+        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
+            def2 = (def2 * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
+        if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
+            def2 = def2 * 75 / 100;
+        //コンセントレーション時は減算
+        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
+            def2 = def2 * (100 - 5 * sc_data[SC_CONCENTRATION].val1) / 100;
+    }
+    if (def2 < 1)
+        def2 = 1;
+    return def2;
+}
+
+/*==========================================
+ * 対象のMDef2を返す(汎用)
+ * 戻りは整数で0以上
+ *------------------------------------------
+ */
+int battle_get_mdef2 (struct block_list *bl)
+{
+    int  mdef2 = 0;
+    struct status_change *sc_data = battle_get_sc_data (bl);
+
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB)
+        mdef2 =
+            ((struct mob_data *) bl)->stats[MOB_INT] +
+            (((struct mob_data *) bl)->stats[MOB_VIT] >> 1);
+    else if (bl->type == BL_PC)
+        mdef2 =
+            ((struct map_session_data *) bl)->mdef2 +
+            (((struct map_session_data *) bl)->paramc[2] >> 1);
+    if (sc_data)
+    {
+        if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
+            mdef2 -= (mdef2 * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
+    }
+    if (mdef2 < 0)
+        mdef2 = 0;
+    return mdef2;
+}
+
+/*==========================================
+ * 対象のSpeed(移動速度)を返す(汎用)
+ * 戻りは整数で1以上
+ * Speedは小さいほうが移動速度が速い
+ *------------------------------------------
+ */
+int battle_get_speed (struct block_list *bl)
+{
+    nullpo_retr (1000, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->speed;
+    else
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        int  speed = 1000;
+        if (bl->type == BL_MOB && (struct mob_data *) bl)
+            speed = ((struct mob_data *) bl)->stats[MOB_SPEED];
+
+        if (sc_data)
+        {
+            //速度増加時は25%減算
+            if (sc_data[SC_INCREASEAGI].timer != -1
+                && sc_data[SC_DONTFORGETME].timer == -1)
+                speed -= speed * 25 / 100;
+            //速度減少時は25%加算
+            if (sc_data[SC_DECREASEAGI].timer != -1)
+                speed = speed * 125 / 100;
+            //クァグマイア時は50%加算
+            if (sc_data[SC_QUAGMIRE].timer != -1)
+                speed = speed * 3 / 2;
+            //私を忘れないで…時は加算
+            if (sc_data[SC_DONTFORGETME].timer != -1)
+                speed =
+                    speed * (100 + sc_data[SC_DONTFORGETME].val1 * 2 +
+                             sc_data[SC_DONTFORGETME].val2 +
+                             (sc_data[SC_DONTFORGETME].val3 & 0xffff)) / 100;
+            //金剛時は25%加算
+            if (sc_data[SC_STEELBODY].timer != -1)
+                speed = speed * 125 / 100;
+            //ディフェンダー時は加算
+            if (sc_data[SC_DEFENDER].timer != -1)
+                speed = (speed * (155 - sc_data[SC_DEFENDER].val1 * 5)) / 100;
+            //踊り状態は4倍遅い
+            if (sc_data[SC_DANCING].timer != -1)
+                speed *= 4;
+            //呪い時は450加算
+            if (sc_data[SC_CURSE].timer != -1)
+                speed = speed + 450;
+            //ウィンドウォーク時はLv*2%減算
+            if (sc_data[SC_WINDWALK].timer != -1)
+                speed -= (speed * (sc_data[SC_WINDWALK].val1 * 2)) / 100;
+        }
+        if (speed < 1)
+            speed = 1;
+        return speed;
+    }
+
+    return 1000;
+}
+
+/*==========================================
+ * 対象のaDelay(攻撃時ディレイ)を返す(汎用)
+ * aDelayは小さいほうが攻撃速度が速い
+ *------------------------------------------
+ */
+int battle_get_adelay (struct block_list *bl)
+{
+    nullpo_retr (4000, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return (((struct map_session_data *) bl)->aspd << 1);
+    else
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        int  adelay = 4000, aspd_rate = 100, i;
+        if (bl->type == BL_MOB && (struct mob_data *) bl)
+            adelay = ((struct mob_data *) bl)->stats[MOB_ADELAY];
+
+        if (sc_data)
+        {
+            //ツーハンドクイッケン使用時でクァグマイアでも私を忘れないで…でもない時は3割減算
+            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+                aspd_rate -= 30;
+            //アドレナリンラッシュ使用時でツーハンドクイッケンでもクァグマイアでも私を忘れないで…でもない時は
+            if (sc_data[SC_ADRENALINE].timer != -1
+                && sc_data[SC_TWOHANDQUICKEN].timer == -1
+                && sc_data[SC_QUAGMIRE].timer == -1
+                && sc_data[SC_DONTFORGETME].timer == -1)
+            {                   // アドレナリンラッシュ
+                //使用者とパーティメンバーで格差が出る設定でなければ3割減算
+                if (sc_data[SC_ADRENALINE].val2
+                    || !battle_config.party_skill_penaly)
+                    aspd_rate -= 30;
+                //そうでなければ2.5割減算
+                else
+                    aspd_rate -= 25;
+            }
+            //スピアクィッケン時は減算
+            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
+                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
+            //夕日のアサシンクロス時は減算
+            if (sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
+                sc_data[SC_TWOHANDQUICKEN].timer == -1
+                && sc_data[SC_ADRENALINE].timer == -1
+                && sc_data[SC_SPEARSQUICKEN].timer == -1
+                && sc_data[SC_DONTFORGETME].timer == -1)
+                aspd_rate -=
+                    5 + sc_data[SC_ASSNCROS].val1 +
+                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
+            //私を忘れないで…時は加算
+            if (sc_data[SC_DONTFORGETME].timer != -1)   // 私を忘れないで
+                aspd_rate +=
+                    sc_data[SC_DONTFORGETME].val1 * 3 +
+                    sc_data[SC_DONTFORGETME].val2 +
+                    (sc_data[SC_DONTFORGETME].val3 >> 16);
+            //金剛時25%加算
+            if (sc_data[SC_STEELBODY].timer != -1)  // 金剛
+                aspd_rate += 25;
+            //増速ポーション使用時は減算
+            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
+                || sc_data[i = SC_SPEEDPOTION1].timer != -1
+                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
+                aspd_rate -= sc_data[i].val1;
+            // Fate's `haste' spell works the same as the above
+            if (sc_data[SC_HASTE].timer != -1)
+                aspd_rate -= sc_data[SC_HASTE].val1;
+            //ディフェンダー時は加算
+            if (sc_data[SC_DEFENDER].timer != -1)
+                adelay += (1100 - sc_data[SC_DEFENDER].val1 * 100);
+        }
+
+        if (aspd_rate != 100)
+            adelay = adelay * aspd_rate / 100;
+        if (adelay < battle_config.monster_max_aspd << 1)
+            adelay = battle_config.monster_max_aspd << 1;
+        return adelay;
+    }
+    return 4000;
+}
+
+int battle_get_amotion (struct block_list *bl)
+{
+    nullpo_retr (2000, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->amotion;
+    else
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        int  amotion = 2000, aspd_rate = 100, i;
+        if (bl->type == BL_MOB && (struct mob_data *) bl)
+            amotion = mob_db[((struct mob_data *) bl)->mob_class].amotion;
+
+        if (sc_data)
+        {
+            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+                aspd_rate -= 30;
+            if (sc_data[SC_ADRENALINE].timer != -1
+                && sc_data[SC_TWOHANDQUICKEN].timer == -1
+                && sc_data[SC_QUAGMIRE].timer == -1
+                && sc_data[SC_DONTFORGETME].timer == -1)
+            {                   // アドレナリンラッシュ
+                if (sc_data[SC_ADRENALINE].val2
+                    || !battle_config.party_skill_penaly)
+                    aspd_rate -= 30;
+                else
+                    aspd_rate -= 25;
+            }
+            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
+                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
+            if (sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
+                sc_data[SC_TWOHANDQUICKEN].timer == -1
+                && sc_data[SC_ADRENALINE].timer == -1
+                && sc_data[SC_SPEARSQUICKEN].timer == -1
+                && sc_data[SC_DONTFORGETME].timer == -1)
+                aspd_rate -=
+                    5 + sc_data[SC_ASSNCROS].val1 +
+                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
+            if (sc_data[SC_DONTFORGETME].timer != -1)   // 私を忘れないで
+                aspd_rate +=
+                    sc_data[SC_DONTFORGETME].val1 * 3 +
+                    sc_data[SC_DONTFORGETME].val2 +
+                    (sc_data[SC_DONTFORGETME].val3 >> 16);
+            if (sc_data[SC_STEELBODY].timer != -1)  // 金剛
+                aspd_rate += 25;
+            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
+                || sc_data[i = SC_SPEEDPOTION1].timer != -1
+                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
+                aspd_rate -= sc_data[i].val1;
+            if (sc_data[SC_HASTE].timer != -1)
+                aspd_rate -= sc_data[SC_HASTE].val1;
+            if (sc_data[SC_DEFENDER].timer != -1)
+                amotion += (550 - sc_data[SC_DEFENDER].val1 * 50);
+        }
+
+        if (aspd_rate != 100)
+            amotion = amotion * aspd_rate / 100;
+        if (amotion < battle_config.monster_max_aspd)
+            amotion = battle_config.monster_max_aspd;
+        return amotion;
+    }
+    return 2000;
+}
+
+int battle_get_dmotion (struct block_list *bl)
+{
+    int  ret;
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+    {
+        ret = mob_db[((struct mob_data *) bl)->mob_class].dmotion;
+        if (battle_config.monster_damage_delay_rate != 100)
+            ret = ret * battle_config.monster_damage_delay_rate / 400;
+    }
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        ret = ((struct map_session_data *) bl)->dmotion;
+        if (battle_config.pc_damage_delay_rate != 100)
+            ret = ret * battle_config.pc_damage_delay_rate / 400;
+    }
+    else
+        return 2000;
+
+    if ((sc_data && sc_data[SC_ENDURE].timer != -1) ||
+        (bl->type == BL_PC
+         && ((struct map_session_data *) bl)->special_state.infinite_endure))
+        ret = 0;
+
+    return ret;
+}
+
+int battle_get_element (struct block_list *bl)
+{
+    int  ret = 20;
+    struct status_change *sc_data;
+
+    nullpo_retr (ret, bl);
+    sc_data = battle_get_sc_data (bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)   // 10の位=Lv*2、1の位=属性
+        ret = ((struct mob_data *) bl)->def_ele;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        ret = 20 + ((struct map_session_data *) bl)->def_ele;   // 防御属性Lv1
+
+    if (sc_data)
+    {
+        if (sc_data[SC_BENEDICTIO].timer != -1) // 聖体降福
+            ret = 26;
+        if (sc_data[SC_FREEZE].timer != -1) // 凍結
+            ret = 21;
+        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
+            ret = 22;
+    }
+
+    return ret;
+}
+
+int battle_get_attack_element (struct block_list *bl)
+{
+    int  ret = 0;
+    struct status_change *sc_data = battle_get_sc_data (bl);
+
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        ret = 0;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        ret = ((struct map_session_data *) bl)->atk_ele;
+
+    if (sc_data)
+    {
+        if (sc_data[SC_FROSTWEAPON].timer != -1)    // フロストウェポン
+            ret = 1;
+        if (sc_data[SC_SEISMICWEAPON].timer != -1)  // サイズミックウェポン
+            ret = 2;
+        if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // フレームランチャー
+            ret = 3;
+        if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ライトニングローダー
+            ret = 4;
+        if (sc_data[SC_ENCPOISON].timer != -1)  // エンチャントポイズン
+            ret = 5;
+        if (sc_data[SC_ASPERSIO].timer != -1)   // アスペルシオ
+            ret = 6;
+    }
+
+    return ret;
+}
+
+int battle_get_attack_element2 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+    {
+        int  ret = ((struct map_session_data *) bl)->atk_ele_;
+        struct status_change *sc_data =
+            ((struct map_session_data *) bl)->sc_data;
+
+        if (sc_data)
+        {
+            if (sc_data[SC_FROSTWEAPON].timer != -1)    // フロストウェポン
+                ret = 1;
+            if (sc_data[SC_SEISMICWEAPON].timer != -1)  // サイズミックウェポン
+                ret = 2;
+            if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // フレームランチャー
+                ret = 3;
+            if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ライトニングローダー
+                ret = 4;
+            if (sc_data[SC_ENCPOISON].timer != -1)  // エンチャントポイズン
+                ret = 5;
+            if (sc_data[SC_ASPERSIO].timer != -1)   // アスペルシオ
+                ret = 6;
+        }
+        return ret;
+    }
+    return 0;
+}
+
+int battle_get_party_id (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->status.party_id;
+    else if (bl->type == BL_MOB && (struct mob_data *) bl)
+    {
+        struct mob_data *md = (struct mob_data *) bl;
+        if (md->master_id > 0)
+            return -md->master_id;
+        return -md->bl.id;
+    }
+    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
+        return ((struct skill_unit *) bl)->group->party_id;
+    else
+        return 0;
+}
+
+int battle_get_guild_id (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->status.guild_id;
+    else if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->mob_class;
+    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
+        return ((struct skill_unit *) bl)->group->guild_id;
+    else
+        return 0;
+}
+
+int battle_get_race (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return mob_db[((struct mob_data *) bl)->mob_class].race;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return 7;
+    else
+        return 0;
+}
+
+int battle_get_size (struct block_list *bl)
+{
+    nullpo_retr (1, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return mob_db[((struct mob_data *) bl)->mob_class].size;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return 1;
+    else
+        return 1;
+}
+
+int battle_get_mode (struct block_list *bl)
+{
+    nullpo_retr (0x01, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return mob_db[((struct mob_data *) bl)->mob_class].mode;
+    else
+        return 0x01;            // とりあえず動くということで1
+}
+
+int battle_get_mexp (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+    {
+        const struct mob_data *mob = (struct mob_data *) bl;
+        const int retval =
+            (mob_db[mob->mob_class].mexp *
+             (int) (mob->stats[MOB_XP_BONUS])) >> MOB_XP_BONUS_SHIFT;
+        fprintf (stderr, "Modifier of %x: -> %d\n", mob->stats[MOB_XP_BONUS],
+                 retval);
+        return retval;
+    }
+    else
+        return 0;
+}
+
+int battle_get_stat (int stat_id /* SP_VIT or similar */ ,
+                     struct block_list *bl)
+{
+    switch (stat_id)
+    {
+        case SP_STR:
+            return battle_get_str (bl);
+        case SP_AGI:
+            return battle_get_agi (bl);
+        case SP_DEX:
+            return battle_get_dex (bl);
+        case SP_VIT:
+            return battle_get_vit (bl);
+        case SP_INT:
+            return battle_get_int (bl);
+        case SP_LUK:
+            return battle_get_luk (bl);
+        default:
+            return 0;
+    }
+}
+
+// StatusChange系の所得
+struct status_change *battle_get_sc_data (struct block_list *bl)
+{
+    nullpo_retr (NULL, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return ((struct mob_data *) bl)->sc_data;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return ((struct map_session_data *) bl)->sc_data;
+    return NULL;
+}
+
+short *battle_get_sc_count (struct block_list *bl)
+{
+    nullpo_retr (NULL, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return &((struct mob_data *) bl)->sc_count;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return &((struct map_session_data *) bl)->sc_count;
+    return NULL;
+}
+
+short *battle_get_opt1 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return &((struct mob_data *) bl)->opt1;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return &((struct map_session_data *) bl)->opt1;
+    else if (bl->type == BL_NPC && (struct npc_data *) bl)
+        return &((struct npc_data *) bl)->opt1;
+    return 0;
+}
+
+short *battle_get_opt2 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return &((struct mob_data *) bl)->opt2;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return &((struct map_session_data *) bl)->opt2;
+    else if (bl->type == BL_NPC && (struct npc_data *) bl)
+        return &((struct npc_data *) bl)->opt2;
+    return 0;
+}
+
+short *battle_get_opt3 (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return &((struct mob_data *) bl)->opt3;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return &((struct map_session_data *) bl)->opt3;
+    else if (bl->type == BL_NPC && (struct npc_data *) bl)
+        return &((struct npc_data *) bl)->opt3;
+    return 0;
+}
+
+short *battle_get_option (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB && (struct mob_data *) bl)
+        return &((struct mob_data *) bl)->option;
+    else if (bl->type == BL_PC && (struct map_session_data *) bl)
+        return &((struct map_session_data *) bl)->status.option;
+    else if (bl->type == BL_NPC && (struct npc_data *) bl)
+        return &((struct npc_data *) bl)->option;
+    return 0;
+}
+
+//-------------------------------------------------------------------
+
+// ダメージの遅延
+struct battle_delay_damage_
+{
+    struct block_list *src, *target;
+    int  damage;
+    int  flag;
+};
+void battle_delay_damage_sub (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct battle_delay_damage_ *dat = (struct battle_delay_damage_ *) data;
+    if (dat && map_id2bl (id) == dat->src && dat->target->prev != NULL)
+        battle_damage (dat->src, dat->target, dat->damage, dat->flag);
+    free (dat);
+}
+
+int battle_delay_damage (unsigned int tick, struct block_list *src,
+                         struct block_list *target, int damage, int flag)
+{
+    struct battle_delay_damage_ *dat;
+    CREATE (dat, struct battle_delay_damage_, 1);
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, target);
+
+    dat->src = src;
+    dat->target = target;
+    dat->damage = damage;
+    dat->flag = flag;
+    add_timer (tick, battle_delay_damage_sub, src->id, (int) dat);
+    return 0;
+}
+
+// 実際にHPを操作
+int battle_damage (struct block_list *bl, struct block_list *target,
+                   int damage, int flag)
+{
+    struct map_session_data *sd = NULL;
+    struct status_change *sc_data = battle_get_sc_data (target);
+    short *sc_count;
+    int  i;
+
+    nullpo_retr (0, target);    //blはNULLで呼ばれることがあるので他でチェック
+
+    if (damage == 0)
+        return 0;
+
+    if (target->prev == NULL)
+        return 0;
+
+    if (bl)
+    {
+        if (bl->prev == NULL)
+            return 0;
+
+        if (bl->type == BL_PC)
+            sd = (struct map_session_data *) bl;
+    }
+
+    if (damage < 0)
+        return battle_heal (bl, target, -damage, 0, flag);
+
+    if (!flag && (sc_count = battle_get_sc_count (target)) != NULL
+        && *sc_count > 0)
+    {
+        // 凍結、石化、睡眠を消去
+        if (sc_data[SC_FREEZE].timer != -1)
+            skill_status_change_end (target, SC_FREEZE, -1);
+        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
+            skill_status_change_end (target, SC_STONE, -1);
+        if (sc_data[SC_SLEEP].timer != -1)
+            skill_status_change_end (target, SC_SLEEP, -1);
+    }
+
+    if (target->type == BL_MOB)
+    {                           // MOB
+        struct mob_data *md = (struct mob_data *) target;
+        if (md && md->skilltimer != -1 && md->state.skillcastcancel)    // 詠唱妨害
+            skill_castcancel (target, 0);
+        return mob_damage (bl, md, damage, 0);
+    }
+    else if (target->type == BL_PC)
+    {                           // PC
+
+        struct map_session_data *tsd = (struct map_session_data *) target;
+
+        if (tsd && tsd->sc_data && tsd->sc_data[SC_DEVOTION].val1)
+        {                       // ディボーションをかけられている
+            struct map_session_data *md =
+                map_id2sd (tsd->sc_data[SC_DEVOTION].val1);
+            if (md && skill_devotion3 (&md->bl, target->id))
+            {
+                skill_devotion (md, target->id);
+            }
+            else if (md && bl)
+                for (i = 0; i < 5; i++)
+                    if (md->dev.val1[i] == target->id)
+                    {
+                        clif_damage (bl, &md->bl, gettick (), 0, 0,
+                                     damage, 0, 0, 0);
+                        pc_damage (&md->bl, md, damage);
+
+                        return 0;
+                    }
+        }
+
+        if (tsd && tsd->skilltimer != -1)
+        {                       // 詠唱妨害
+            // フェンカードや妨害されないスキルかの検査
+            if ((!tsd->special_state.no_castcancel || map[bl->m].flag.gvg)
+                && tsd->state.skillcastcancel
+                && !tsd->special_state.no_castcancel2)
+                skill_castcancel (target, 0);
+        }
+
+        return pc_damage (bl, tsd, damage);
+
+    }
+    else if (target->type == BL_SKILL)
+        return skill_unit_ondamaged ((struct skill_unit *) target, bl, damage,
+                                     gettick ());
+    return 0;
+}
+
+int battle_heal (struct block_list *bl, struct block_list *target, int hp,
+                 int sp, int flag)
+{
+    nullpo_retr (0, target);    //blはNULLで呼ばれることがあるので他でチェック
+
+    if (target->type == BL_PC
+        && pc_isdead ((struct map_session_data *) target))
+        return 0;
+    if (hp == 0 && sp == 0)
+        return 0;
+
+    if (hp < 0)
+        return battle_damage (bl, target, -hp, flag);
+
+    if (target->type == BL_MOB)
+        return mob_heal ((struct mob_data *) target, hp);
+    else if (target->type == BL_PC)
+        return pc_heal ((struct map_session_data *) target, hp, sp);
+    return 0;
+}
+
+// 攻撃停止
+int battle_stopattack (struct block_list *bl)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB)
+        return mob_stopattack ((struct mob_data *) bl);
+    else if (bl->type == BL_PC)
+        return pc_stopattack ((struct map_session_data *) bl);
+    return 0;
+}
+
+// 移動停止
+int battle_stopwalking (struct block_list *bl, int type)
+{
+    nullpo_retr (0, bl);
+    if (bl->type == BL_MOB)
+        return mob_stop_walking ((struct mob_data *) bl, type);
+    else if (bl->type == BL_PC)
+        return pc_stop_walking ((struct map_session_data *) bl, type);
+    return 0;
+}
+
+/*==========================================
+ * ダメージの属性修正
+ *------------------------------------------
+ */
+int battle_attr_fix (int damage, int atk_elem, int def_elem)
+{
+    int  def_type = def_elem % 10, def_lv = def_elem / 10 / 2;
+
+    if (atk_elem < 0 || atk_elem > 9 || def_type < 0 || def_type > 9 ||
+        def_lv < 1 || def_lv > 4)
+    {                           // 属 性値がおかしいのでとりあえずそのまま返す
+        if (battle_config.error_log)
+            printf
+                ("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",
+                 atk_elem, def_type, def_lv);
+        return damage;
+    }
+
+    return damage * attr_fix_table[def_lv - 1][atk_elem][def_type] / 100;
+}
+
+/*==========================================
+ * ダメージ最終計算
+ *------------------------------------------
+ */
+int battle_calc_damage (struct block_list *src, struct block_list *bl,
+                        int damage, int div_, int skill_num, int skill_lv,
+                        int flag)
+{
+    struct map_session_data *sd = NULL;
+    struct mob_data *md = NULL;
+    struct status_change *sc_data, *sc;
+    short *sc_count;
+    int  class_;
+
+    nullpo_retr (0, bl);
+
+    class_ = battle_get_class (bl);
+    if (bl->type == BL_MOB)
+        md = (struct mob_data *) bl;
+    else
+        sd = (struct map_session_data *) bl;
+
+    sc_data = battle_get_sc_data (bl);
+    sc_count = battle_get_sc_count (bl);
+
+    if (sc_count != NULL && *sc_count > 0)
+    {
+
+        if (sc_data[SC_SAFETYWALL].timer != -1 && damage > 0
+            && flag & BF_WEAPON && flag & BF_SHORT
+            && skill_num != NPC_GUIDEDATTACK)
+        {
+            // セーフティウォール
+            struct skill_unit *unit =
+                (struct skill_unit *) sc_data[SC_SAFETYWALL].val2;
+            if (unit && unit->alive && (--unit->group->val2) <= 0)
+                skill_delunit (unit);
+            skill_unit_move (bl, gettick (), 1);    // 重ね掛けチェック
+            damage = 0;
+        }
+        if (sc_data[SC_PNEUMA].timer != -1 && damage > 0 && flag & BF_WEAPON
+            && flag & BF_LONG && skill_num != NPC_GUIDEDATTACK)
+        {
+            // ニューマ
+            damage = 0;
+        }
+
+        if (sc_data[SC_ROKISWEIL].timer != -1 && damage > 0 &&
+            flag & BF_MAGIC)
+        {
+            // ニューマ
+            damage = 0;
+        }
+
+        if (sc_data[SC_AETERNA].timer != -1 && damage > 0)
+        {                       // レックスエーテルナ
+            damage <<= 1;
+            skill_status_change_end (bl, SC_AETERNA, -1);
+        }
+
+        //属性場のダメージ増加
+        if (sc_data[SC_VOLCANO].timer != -1)
+        {                       // ボルケーノ
+            if (flag & BF_SKILL && skill_get_pl (skill_num) == 3)
+                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
+            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 3))
+                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
+        }
+
+        if (sc_data[SC_VIOLENTGALE].timer != -1)
+        {                       // バイオレントゲイル
+            if (flag & BF_SKILL && skill_get_pl (skill_num) == 4)
+                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
+            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 4))
+                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
+        }
+
+        if (sc_data[SC_DELUGE].timer != -1)
+        {                       // デリュージ
+            if (flag & BF_SKILL && skill_get_pl (skill_num) == 1)
+                damage += damage * sc_data[SC_DELUGE].val4 / 100;
+            else if (!(flag & BF_SKILL) && (battle_get_attack_element (bl) == 1))
+                damage += damage * sc_data[SC_DELUGE].val4 / 100;
+        }
+
+        if (sc_data[SC_ENERGYCOAT].timer != -1 && damage > 0
+            && flag & BF_WEAPON)
+        {                       // エナジーコート
+            if (sd)
+            {
+                if (sd->status.sp > 0)
+                {
+                    int  per = sd->status.sp * 5 / (sd->status.max_sp + 1);
+                    sd->status.sp -= sd->status.sp * (per * 5 + 10) / 1000;
+                    if (sd->status.sp < 0)
+                        sd->status.sp = 0;
+                    damage -= damage * ((per + 1) * 6) / 100;
+                    clif_updatestatus (sd, SP_SP);
+                }
+                if (sd->status.sp <= 0)
+                    skill_status_change_end (bl, SC_ENERGYCOAT, -1);
+            }
+            else
+                damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100;
+        }
+
+        if (sc_data[SC_KYRIE].timer != -1 && damage > 0)
+        {                       // キリエエレイソン
+            sc = &sc_data[SC_KYRIE];
+            sc->val2 -= damage;
+            if (flag & BF_WEAPON)
+            {
+                if (sc->val2 >= 0)
+                    damage = 0;
+                else
+                    damage = -sc->val2;
+            }
+            if ((--sc->val3) <= 0 || (sc->val2 <= 0)
+                || skill_num == AL_HOLYLIGHT)
+                skill_status_change_end (bl, SC_KYRIE, -1);
+        }
+
+        if (sc_data[SC_BASILICA].timer != -1 && damage > 0)
+        {
+            // ニューマ
+            damage = 0;
+        }
+        if (sc_data[SC_LANDPROTECTOR].timer != -1 && damage > 0
+            && flag & BF_MAGIC)
+        {
+            // ニューマ
+            damage = 0;
+        }
+
+        if (sc_data[SC_AUTOGUARD].timer != -1 && damage > 0
+            && flag & BF_WEAPON)
+        {
+            if (MRAND (100) < sc_data[SC_AUTOGUARD].val2)
+            {
+                damage = 0;
+                clif_skill_nodamage (bl, bl, CR_AUTOGUARD,
+                                     sc_data[SC_AUTOGUARD].val1, 1);
+                if (sd)
+                    sd->canmove_tick = gettick () + 300;
+                else if (md)
+                    md->canmove_tick = gettick () + 300;
+            }
+        }
+// -- moonsoul (chance to block attacks with new Lord Knight skill parrying)
+//
+        if (sc_data[SC_PARRYING].timer != -1 && damage > 0
+            && flag & BF_WEAPON)
+        {
+            if (MRAND (100) < sc_data[SC_PARRYING].val2)
+            {
+                damage = 0;
+                clif_skill_nodamage (bl, bl, LK_PARRYING,
+                                     sc_data[SC_PARRYING].val1, 1);
+            }
+        }
+        // リジェクトソード
+        if (sc_data[SC_REJECTSWORD].timer != -1 && damage > 0
+            && flag & BF_WEAPON
+            &&
+            ((src->type == BL_PC
+              && ((struct map_session_data *) src)->status.weapon == (1 || 2
+                                                                      || 3))
+             || src->type == BL_MOB))
+        {
+            if (MRAND (100) < (10 + 5 * sc_data[SC_REJECTSWORD].val1))
+            {                   //反射確率は10+5*Lv
+                damage = damage * 50 / 100;
+                battle_damage (bl, src, damage, 0);
+                //ダメージを与えたのは良いんだが、ここからどうして表示するんだかわかんねぇ
+                //エフェクトもこれでいいのかわかんねぇ
+                clif_skill_nodamage (bl, bl, ST_REJECTSWORD,
+                                     sc_data[SC_REJECTSWORD].val1, 1);
+                if ((--sc_data[SC_REJECTSWORD].val2) <= 0)
+                    skill_status_change_end (bl, SC_REJECTSWORD, -1);
+            }
+        }
+    }
+
+    if (class_ == 1288 || class_ == 1287 || class_ == 1286 || class_ == 1285)
+    {
+//  if(class == 1288) {
+        if (class_ == 1288 && flag & BF_SKILL)
+            damage = 0;
+        if (src->type == BL_PC)
+        {
+            struct guild *g =
+                guild_search (((struct map_session_data *) src)->
+                              status.guild_id);
+            struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
+            if (!((struct map_session_data *) src)->status.guild_id)
+                damage = 0;
+            if (gc && agit_flag == 0 && class_ != 1288)  // guardians cannot be damaged during non-woe [Valaris]
+                damage = 0;     // end woe check [Valaris]
+            if (g == NULL)
+                damage = 0;     //ギルド未加入ならダメージ無し
+            else if ((gc != NULL) && guild_isallied (g, gc))
+                damage = 0;     //自占領ギルドのエンペならダメージ無し
+            else if (g && guild_checkskill (g, GD_APPROVAL) <= 0)
+                damage = 0;     //正規ギルド承認がないとダメージ無し
+            else if (battle_config.guild_max_castles != 0
+                     && guild_checkcastles (g) >=
+                     battle_config.guild_max_castles)
+                damage = 0;     // [MouseJstr]
+        }
+        else
+            damage = 0;
+    }
+
+    if (map[bl->m].flag.gvg && damage > 0)
+    {                           //GvG
+        if (flag & BF_WEAPON)
+        {
+            if (flag & BF_SHORT)
+                damage = damage * battle_config.gvg_short_damage_rate / 100;
+            if (flag & BF_LONG)
+                damage = damage * battle_config.gvg_long_damage_rate / 100;
+        }
+        if (flag & BF_MAGIC)
+            damage = damage * battle_config.gvg_magic_damage_rate / 100;
+        if (flag & BF_MISC)
+            damage = damage * battle_config.gvg_misc_damage_rate / 100;
+        if (damage < 1)
+            damage = 1;
+    }
+
+    if (battle_config.skill_min_damage || flag & BF_MISC)
+    {
+        if (div_ < 255)
+        {
+            if (damage > 0 && damage < div_)
+                damage = div_;
+        }
+        else if (damage > 0 && damage < 3)
+            damage = 3;
+    }
+
+    if (md != NULL && md->hp > 0 && damage > 0) // 反撃などのMOBスキル判定
+        mobskill_event (md, flag);
+
+    return damage;
+}
+
+/*==========================================
+ * 修練ダメージ
+ *------------------------------------------
+ */
+int battle_addmastery (struct map_session_data *sd, struct block_list *target,
+                       int dmg, int type)
+{
+    int  damage, skill;
+    int  race = battle_get_race (target);
+    int  weapon;
+    damage = 0;
+
+    nullpo_retr (0, sd);
+
+    // デーモンベイン(+3 〜 +30) vs 不死 or 悪魔 (死人は含めない?)
+    if ((skill = pc_checkskill (sd, AL_DEMONBANE)) > 0
+        && (battle_check_undead (race, battle_get_elem_type (target))
+            || race == 6))
+        damage += (skill * 3);
+
+    // ビーストベイン(+4 〜 +40) vs 動物 or 昆虫
+    if ((skill = pc_checkskill (sd, HT_BEASTBANE)) > 0
+        && (race == 2 || race == 4))
+        damage += (skill * 4);
+
+    if (type == 0)
+        weapon = sd->weapontype1;
+    else
+        weapon = sd->weapontype2;
+    switch (weapon)
+    {
+        case 0x01:             // 短剣 (Updated By AppleGirl)
+        case 0x02:             // 1HS
+        {
+            // 剣修練(+4 〜 +40) 片手剣 短剣含む
+            if ((skill = pc_checkskill (sd, SM_SWORD)) > 0)
+            {
+                damage += (skill * 4);
+            }
+            break;
+        }
+        case 0x03:             // 2HS
+        {
+            // 両手剣修練(+4 〜 +40) 両手剣
+            if ((skill = pc_checkskill (sd, SM_TWOHAND)) > 0)
+            {
+                damage += (skill * 4);
+            }
+            break;
+        }
+        case 0x04:             // 1HL
+        {
+            // 槍修練(+4 〜 +40,+5 〜 +50) 槍
+            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
+            {
+                if (!pc_isriding (sd))
+                    damage += (skill * 4);  // ペコに乗ってない
+                else
+                    damage += (skill * 5);  // ペコに乗ってる
+            }
+            break;
+        }
+        case 0x05:             // 2HL
+        {
+            // 槍修練(+4 〜 +40,+5 〜 +50) 槍
+            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
+            {
+                if (!pc_isriding (sd))
+                    damage += (skill * 4);  // ペコに乗ってない
+                else
+                    damage += (skill * 5);  // ペコに乗ってる
+            }
+            break;
+        }
+        case 0x06:             // 片手斧
+        {
+            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x07:             // Axe by Tato
+        {
+            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x08:             // メイス
+        {
+            // メイス修練(+3 〜 +30) メイス
+            if ((skill = pc_checkskill (sd, PR_MACEMASTERY)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x09:             // なし?
+            break;
+        case 0x0a:             // 杖
+            break;
+        case 0x0b:             // 弓
+            break;
+        case 0x00:             // 素手
+        case 0x0c:             // Knuckles
+        {
+            // 鉄拳(+3 〜 +30) 素手,ナックル
+            if ((skill = pc_checkskill (sd, MO_IRONHAND)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x0d:             // Musical Instrument
+        {
+            // 楽器の練習(+3 〜 +30) 楽器
+            if ((skill = pc_checkskill (sd, BA_MUSICALLESSON)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x0e:             // Dance Mastery
+        {
+            // Dance Lesson Skill Effect(+3 damage for every lvl = +30) 鞭
+            if ((skill = pc_checkskill (sd, DC_DANCINGLESSON)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x0f:             // Book
+        {
+            // Advance Book Skill Effect(+3 damage for every lvl = +30) {
+            if ((skill = pc_checkskill (sd, SA_ADVANCEDBOOK)) > 0)
+            {
+                damage += (skill * 3);
+            }
+            break;
+        }
+        case 0x10:             // Katars
+        {
+            // カタール修練(+3 〜 +30) カタール
+            if ((skill = pc_checkskill (sd, AS_KATAR)) > 0)
+            {
+                //ソニックブロー時は別処理(1撃に付き1/8適応)
+                damage += (skill * 3);
+            }
+            break;
+        }
+    }
+    damage = dmg + damage;
+    return (damage);
+}
+
+static struct Damage battle_calc_mob_weapon_attack (struct block_list *src,
+                                                    struct block_list *target,
+                                                    int skill_num,
+                                                    int skill_lv, int wflag)
+{
+    struct map_session_data *tsd = NULL;
+    struct mob_data *md = (struct mob_data *) src, *tmd = NULL;
+    int  hitrate, flee, cri = 0, atkmin, atkmax;
+    int  luk, target_count = 1;
+    int  def1 = battle_get_def (target);
+    int  def2 = battle_get_def2 (target);
+    int  t_vit = battle_get_vit (target);
+    struct Damage wd;
+    int  damage, damage2 = 0, type, div_, blewcount =
+        skill_get_blewcount (skill_num, skill_lv);
+    int  flag, skill, ac_flag = 0, dmg_lv = 0;
+    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 0, s_ele = 0;
+    struct status_change *sc_data, *t_sc_data;
+    short *sc_count;
+    short *option, *opt1, *opt2;
+
+    //return前の処理があるので情報出力部のみ変更
+    if (src == NULL || target == NULL || md == NULL)
+    {
+        nullpo_info (NLP_MARK);
+        memset (&wd, 0, sizeof (wd));
+        return wd;
+    }
+
+    s_race = battle_get_race (src);
+    s_ele = battle_get_attack_element (src);
+    sc_data = battle_get_sc_data (src);
+    sc_count = battle_get_sc_count (src);
+    option = battle_get_option (src);
+    opt1 = battle_get_opt1 (src);
+    opt2 = battle_get_opt2 (src);
+
+    // ターゲット
+    if (target->type == BL_PC)
+        tsd = (struct map_session_data *) target;
+    else if (target->type == BL_MOB)
+        tmd = (struct mob_data *) target;
+    t_race = battle_get_race (target);
+    t_size = battle_get_size (target);
+    t_mode = battle_get_mode (target);
+    t_sc_data = battle_get_sc_data (target);
+
+    if ((skill_num == 0
+         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
+         || (target->type == BL_MOB
+             && battle_config.monster_auto_counter_type & 2))
+        && skill_lv >= 0)
+    {
+        if (skill_num != CR_GRANDCROSS && t_sc_data
+            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
+        {
+            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
+                battle_get_dir (target);
+            int  dist = distance (src->x, src->y, target->x, target->y);
+            if (dist <= 0 || map_check_dir (dir, t_dir))
+            {
+                memset (&wd, 0, sizeof (wd));
+                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
+                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
+                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
+                {
+                    int  range = battle_get_range (target);
+                    if ((target->type == BL_PC
+                         && ((struct map_session_data *) target)->
+                         status.weapon != 11 && dist <= range + 1)
+                        || (target->type == BL_MOB && range <= 3
+                            && dist <= range + 1))
+                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
+                }
+                return wd;
+            }
+            else
+                ac_flag = 1;
+        }
+    }
+    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // 攻撃の種類の設定
+
+    // 回避率計算、回避判定は後で
+    flee = battle_get_flee (target);
+    if (battle_config.agi_penaly_type > 0
+        || battle_config.vit_penaly_type > 0)
+        target_count +=
+            battle_counttargeted (target, src,
+                                  battle_config.agi_penaly_count_lv);
+    if (battle_config.agi_penaly_type > 0)
+    {
+        if (target_count >= battle_config.agi_penaly_count)
+        {
+            if (battle_config.agi_penaly_type == 1)
+                flee =
+                    (flee *
+                     (100 -
+                      (target_count -
+                       (battle_config.agi_penaly_count -
+                        1)) * battle_config.agi_penaly_num)) / 100;
+            else if (battle_config.agi_penaly_type == 2)
+                flee -=
+                    (target_count -
+                     (battle_config.agi_penaly_count -
+                      1)) * battle_config.agi_penaly_num;
+            if (flee < 1)
+                flee = 1;
+        }
+    }
+    hitrate = battle_get_hit (src) - flee + 80;
+
+    type = 0;                   // normal
+    div_ = 1;                   // single attack
+
+    luk = battle_get_luk (src);
+
+    if (battle_config.enemy_str)
+        damage = battle_get_baseatk (src);
+    else
+        damage = 0;
+    if (skill_num == HW_MAGICCRASHER)
+    {                           /* マジッククラッシャーはMATKで殴る */
+        atkmin = battle_get_matk1 (src);
+        atkmax = battle_get_matk2 (src);
+    }
+    else
+    {
+        atkmin = battle_get_atk (src);
+        atkmax = battle_get_atk2 (src);
+    }
+    if (mob_db[md->mob_class].range > 3)
+        flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+
+    if (atkmin > atkmax)
+        atkmin = atkmax;
+
+    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
+    {                           // マキシマイズパワー
+        atkmin = atkmax;
+    }
+
+    cri = battle_get_critical (src);
+    cri -= battle_get_luk (target) * 3;
+    if (battle_config.enemy_critical_rate != 100)
+    {
+        cri = cri * battle_config.enemy_critical_rate / 100;
+        if (cri < 1)
+            cri = 1;
+    }
+    if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // 睡眠中はクリティカルが倍に
+        cri <<= 1;
+
+    if (ac_flag)
+        cri = 1000;
+
+    if (skill_num == KN_AUTOCOUNTER)
+    {
+        if (!(battle_config.monster_auto_counter_type & 1))
+            cri = 1000;
+        else
+            cri <<= 1;
+    }
+
+    if (tsd && tsd->critical_def)
+        cri = cri * (100 - tsd->critical_def) / 100;
+
+    if ((skill_num == 0 || skill_num == KN_AUTOCOUNTER) && skill_lv >= 0 && battle_config.enemy_critical && (MRAND (1000)) < cri)   // 判定(スキルの場合は無視)
+        // 敵の判定
+    {
+        damage += atkmax;
+        type = 0x0a;
+    }
+    else
+    {
+        int  vitbonusmax;
+
+        if (atkmax > atkmin)
+            damage += atkmin + MRAND ((atkmax - atkmin + 1));
+        else
+            damage += atkmin;
+        // スキル修正1(攻撃力倍化系)
+        // オーバートラスト(+5% 〜 +25%),他攻撃系スキルの場合ここで補正
+        // バッシュ,マグナムブレイク,
+        // ボーリングバッシュ,スピアブーメラン,ブランディッシュスピア,スピアスタッブ,
+        // メマーナイト,カートレボリューション
+        // ダブルストレイフィング,アローシャワー,チャージアロー,
+        // ソニックブロー
+        if (sc_data)
+        {                       //状態異常中のダメージ追加
+            if (sc_data[SC_OVERTHRUST].timer != -1) // オーバートラスト
+                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
+            if (sc_data[SC_TRUESIGHT].timer != -1)  // トゥルーサイト
+                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
+            if (sc_data[SC_BERSERK].timer != -1)    // バーサーク
+                damage += damage * 50 / 100;
+        }
+
+        if (skill_num > 0)
+        {
+            int  i;
+            if ((i = skill_get_pl (skill_num)) > 0)
+                s_ele = i;
+
+            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
+            switch (skill_num)
+            {
+                case SM_BASH:  // バッシュ
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
+                    break;
+                case SM_MAGNUM:    // マグナムブレイク
+                    damage =
+                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
+                    break;
+                case MC_MAMMONITE: // メマーナイト
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    break;
+                case AC_DOUBLE:    // ダブルストレイフィング
+                    damage = damage * (180 + 20 * skill_lv) / 100;
+                    div_ = 2;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case AC_SHOWER:    // アローシャワー
+                    damage = damage * (75 + 5 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case AC_CHARGEARROW:   // チャージアロー
+                    damage = damage * 150 / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case KN_PIERCE:    // ピアース
+                    damage = damage * (100 + 10 * skill_lv) / 100;
+                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
+                    div_ = t_size + 1;
+                    damage *= div_;
+                    break;
+                case KN_SPEARSTAB: // スピアスタブ
+                    damage = damage * (100 + 15 * skill_lv) / 100;
+                    break;
+                case KN_SPEARBOOMERANG:    // スピアブーメラン
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case KN_BRANDISHSPEAR: // ブランディッシュスピア
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    if (skill_lv > 3 && wflag == 1)
+                        damage2 += damage / 2;
+                    if (skill_lv > 6 && wflag == 1)
+                        damage2 += damage / 4;
+                    if (skill_lv > 9 && wflag == 1)
+                        damage2 += damage / 8;
+                    if (skill_lv > 6 && wflag == 2)
+                        damage2 += damage / 2;
+                    if (skill_lv > 9 && wflag == 2)
+                        damage2 += damage / 4;
+                    if (skill_lv > 9 && wflag == 3)
+                        damage2 += damage / 2;
+                    damage += damage2;
+                    blewcount = 0;
+                    break;
+                case KN_BOWLINGBASH:   // ボウリングバッシュ
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    blewcount = 0;
+                    break;
+                case KN_AUTOCOUNTER:
+                    if (battle_config.monster_auto_counter_type & 1)
+                        hitrate += 20;
+                    else
+                        hitrate = 1000000;
+                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
+                    break;
+                case AS_SONICBLOW: // ソニックブロウ
+                    damage = damage * (300 + 50 * skill_lv) / 100;
+                    div_ = 8;
+                    break;
+                case TF_SPRINKLESAND:  // 砂まき
+                    damage = damage * 125 / 100;
+                    break;
+                case MC_CARTREVOLUTION:    // カートレボリューション
+                    damage = (damage * 150) / 100;
+                    break;
+                    // 以下MOB
+                case NPC_COMBOATTACK:  // 多段攻撃
+                    div_ = skill_get_num (skill_num, skill_lv);
+                    damage *= div_;
+                    break;
+                case NPC_RANDOMATTACK: // ランダムATK攻撃
+                    damage = damage * (MPRAND (50, 150)) / 100;
+                    break;
+                    // 属性攻撃(適当)
+                case NPC_WATERATTACK:
+                case NPC_GROUNDATTACK:
+                case NPC_FIREATTACK:
+                case NPC_WINDATTACK:
+                case NPC_POISONATTACK:
+                case NPC_HOLYATTACK:
+                case NPC_DARKNESSATTACK:
+                case NPC_TELEKINESISATTACK:
+                    damage = damage * (100 + 25 * (skill_lv - 1)) / 100;
+                    break;
+                case NPC_GUIDEDATTACK:
+                    hitrate = 1000000;
+                    break;
+                case NPC_RANGEATTACK:
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case NPC_PIERCINGATT:
+                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
+                    break;
+                case RG_BACKSTAP:  // バックスタブ
+                    damage = damage * (300 + 40 * skill_lv) / 100;
+                    hitrate = 1000000;
+                    break;
+                case RG_RAID:  // サプライズアタック
+                    damage = damage * (100 + 40 * skill_lv) / 100;
+                    break;
+                case RG_INTIMIDATE:    // インティミデイト
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    break;
+                case CR_SHIELDCHARGE:  // シールドチャージ
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
+                    s_ele = 0;
+                    break;
+                case CR_SHIELDBOOMERANG:   // シールドブーメラン
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    s_ele = 0;
+                    break;
+                case CR_HOLYCROSS: // ホーリークロス
+                    damage = damage * (100 + 35 * skill_lv) / 100;
+                    div_ = 2;
+                    break;
+                case CR_GRANDCROSS:
+                    hitrate = 1000000;
+                    break;
+                case AM_DEMONSTRATION: // デモンストレーション
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    break;
+                case AM_ACIDTERROR:    // アシッドテラー
+                    damage = damage * (100 + 40 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
+                    break;
+                case MO_FINGEROFFENSIVE:   //指弾
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    div_ = 1;
+                    break;
+                case MO_INVESTIGATE:   // 発 勁
+                    if (def1 < 1000000)
+                        damage =
+                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
+                                                                    def2) /
+                            100;
+                    hitrate = 1000000;
+                    s_ele = 0;
+                    break;
+                case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
+                    damage = damage * 8 + 250 + (skill_lv * 150);
+                    hitrate = 1000000;
+                    s_ele = 0;
+                    break;
+                case MO_CHAINCOMBO:    // 連打掌
+                    damage = damage * (150 + 50 * skill_lv) / 100;
+                    div_ = 4;
+                    break;
+                case BA_MUSICALSTRIKE: // ミュージカルストライク
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case DC_THROWARROW:    // 矢撃ち
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case MO_COMBOFINISH:   // 猛龍拳
+                    damage = damage * (240 + 60 * skill_lv) / 100;
+                    break;
+                case CH_TIGERFIST: // 伏虎拳
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    break;
+                case CH_CHAINCRUSH:    // 連柱崩撃
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    div_ = skill_get_num (skill_num, skill_lv);
+                    break;
+                case CH_PALMSTRIKE:    // 猛虎硬派山
+                    damage = damage * (50 + 100 * skill_lv) / 100;
+                    break;
+                case LK_SPIRALPIERCE:  /* スパイラルピアース */
+                    damage = damage * (100 + 50 * skill_lv) / 100;  //増加量が分からないので適当に
+                    div_ = 5;
+                    if (tsd)
+                        tsd->canmove_tick = gettick () + 1000;
+                    else if (tmd)
+                        tmd->canmove_tick = gettick () + 1000;
+                    break;
+                case LK_HEADCRUSH: /* ヘッドクラッシュ */
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    break;
+                case LK_JOINTBEAT: /* ジョイントビート */
+                    damage = damage * (50 + 10 * skill_lv) / 100;
+                    break;
+                case ASC_METEORASSAULT:    /* メテオアサルト */
+                    damage = damage * (40 + 40 * skill_lv) / 100;
+                    break;
+                case SN_SHARPSHOOTING: /* シャープシューティング */
+                    damage += damage * (30 * skill_lv) / 100;
+                    break;
+                case CG_ARROWVULCAN:   /* アローバルカン */
+                    damage = damage * (160 + 40 * skill_lv) / 100;
+                    div_ = 9;
+                    break;
+                case AS_SPLASHER:  /* ベナムスプラッシャー */
+                    damage = damage * (200 + 20 * skill_lv) / 100;
+                    break;
+            }
+        }
+
+        if (skill_num != NPC_CRITICALSLASH)
+        {
+            // 対 象の防御力によるダメージの減少
+            // ディバインプロテクション(ここでいいのかな?)
+            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
+                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
+            {                   //DEF, VIT無視
+                int  t_def;
+                target_count =
+                    1 + battle_counttargeted (target, src,
+                                              battle_config.vit_penaly_count_lv);
+                if (battle_config.vit_penaly_type > 0)
+                {
+                    if (target_count >= battle_config.vit_penaly_count)
+                    {
+                        if (battle_config.vit_penaly_type == 1)
+                        {
+                            def1 =
+                                (def1 *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                            def2 =
+                                (def2 *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                            t_vit =
+                                (t_vit *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                        }
+                        else if (battle_config.vit_penaly_type == 2)
+                        {
+                            def1 -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                            def2 -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                            t_vit -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                        }
+                        if (def1 < 0)
+                            def1 = 0;
+                        if (def2 < 1)
+                            def2 = 1;
+                        if (t_vit < 1)
+                            t_vit = 1;
+                    }
+                }
+                t_def = def2 * 8 / 10;
+                if (battle_check_undead (s_race, battle_get_elem_type (src))
+                    || s_race == 6)
+                    if (tsd && (skill = pc_checkskill (tsd, AL_DP)) > 0)
+                        t_def += skill * 3;
+
+                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
+                if (battle_config.monster_defense_type)
+                {
+                    damage =
+                        damage - (def1 * battle_config.monster_defense_type) -
+                        t_def -
+                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
+                }
+                else
+                {
+                    damage =
+                        damage * (100 - def1) / 100 - t_def -
+                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
+                }
+            }
+        }
+    }
+
+    // 0未満だった場合1に補正
+    if (damage < 1)
+        damage = 1;
+
+    // 回避修正
+    if (hitrate < 1000000)
+        hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
+    if (hitrate < 1000000 &&    // 必中攻撃
+        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // 睡眠は必中
+                               t_sc_data[SC_STAN].timer != -1 ||    // スタンは必中
+                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // 凍結は必中
+        hitrate = 1000000;
+    if (type == 0 && MRAND (100) >= hitrate)
+    {
+        damage = damage2 = 0;
+        dmg_lv = ATK_FLEE;
+    }
+    else
+    {
+        dmg_lv = ATK_DEF;
+    }
+
+    if (tsd)
+    {
+        int  cardfix = 100, i;
+        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // 属 性によるダメージ耐性
+        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // 種族によるダメージ耐性
+        if (mob_db[md->mob_class].mode & 0x20)
+            cardfix = cardfix * (100 - tsd->subrace[10]) / 100;
+        else
+            cardfix = cardfix * (100 - tsd->subrace[11]) / 100;
+        for (i = 0; i < tsd->add_def_class_count; i++)
+        {
+            if (tsd->add_def_classid[i] == md->mob_class)
+            {
+                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
+                break;
+            }
+        }
+        if (flag & BF_LONG)
+            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;
+        if (flag & BF_SHORT)
+            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;
+        damage = damage * cardfix / 100;
+    }
+    if (t_sc_data)
+    {
+        int  cardfix = 100;
+        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)
+            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;
+        if (cardfix != 100)
+            damage = damage * cardfix / 100;
+    }
+    if (t_sc_data && t_sc_data[SC_ASSUMPTIO].timer != -1)
+    {                           //アシャンプティオ
+        if (!map[target->m].flag.pvp)
+            damage = damage / 3;
+        else
+            damage = damage / 2;
+    }
+
+    if (damage < 0)
+        damage = 0;
+
+    // 属 性の適用
+    if (!((battle_config.mob_ghostring_fix == 1) && (battle_get_element (target) == 8) && (target->type == BL_PC))) // [MouseJstr]
+        if (skill_num != 0 || s_ele != 0
+            || !battle_config.mob_attack_attr_none)
+            damage =
+                battle_attr_fix (damage, s_ele, battle_get_element (target));
+
+    if (sc_data && sc_data[SC_AURABLADE].timer != -1)   /* オーラブレード 必中 */
+        damage += sc_data[SC_AURABLADE].val1 * 10;
+    if (skill_num == PA_PRESSURE)   /* プレッシャー 必中? */
+        damage = 700 + 100 * skill_lv;
+
+    // インベナム修正
+    if (skill_num == TF_POISON)
+    {
+        damage =
+            battle_attr_fix (damage + 15 * skill_lv, s_ele,
+                             battle_get_element (target));
+    }
+    if (skill_num == MC_CARTREVOLUTION)
+    {
+        damage = battle_attr_fix (damage, 0, battle_get_element (target));
+    }
+
+    // 完全回避の判定
+    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL
+        && MRAND (1000) < battle_get_flee2 (target))
+    {
+        damage = 0;
+        type = 0x0b;
+        dmg_lv = ATK_LUCKY;
+    }
+
+    if (battle_config.enemy_perfect_flee)
+    {
+        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL
+            && MRAND (1000) < battle_get_flee2 (target))
+        {
+            damage = 0;
+            type = 0x0b;
+            dmg_lv = ATK_LUCKY;
+        }
+    }
+
+//  if(def1 >= 1000000 && damage > 0)
+    if (t_mode & 0x40 && damage > 0)
+        damage = 1;
+
+    if (tsd && tsd->special_state.no_weapon_damage)
+        damage = 0;
+
+    if (skill_num != CR_GRANDCROSS)
+        damage =
+            battle_calc_damage (src, target, damage, div_, skill_num,
+                                skill_lv, flag);
+
+    wd.damage = damage;
+    wd.damage2 = 0;
+    wd.type = type;
+    wd.div_ = div_;
+    wd.amotion = battle_get_amotion (src);
+    if (skill_num == KN_AUTOCOUNTER)
+        wd.amotion >>= 1;
+    wd.dmotion = battle_get_dmotion (target);
+    wd.blewcount = blewcount;
+    wd.flag = flag;
+    wd.dmg_lv = dmg_lv;
+    return wd;
+}
+
+int battle_is_unarmed (struct block_list *bl)
+{
+    if (!bl)
+        return 0;
+    if (bl->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) bl;
+
+        return (sd->equip_index[EQUIP_SHIELD] == -1
+                && sd->equip_index[EQUIP_WEAPON] == -1);
+    }
+    else
+        return 0;
+}
+
+/*
+ * =========================================================================
+ * PCの武器による攻撃
+ *-------------------------------------------------------------------------
+ */
+static struct Damage battle_calc_pc_weapon_attack (struct block_list *src,
+                                                   struct block_list *target,
+                                                   int skill_num,
+                                                   int skill_lv, int wflag)
+{
+    struct map_session_data *sd = (struct map_session_data *) src, *tsd =
+        NULL;
+    struct mob_data *tmd = NULL;
+    int  hitrate, flee, cri = 0, atkmin, atkmax;
+    int  dex, luk, target_count = 1;
+    int  def1 = battle_get_def (target);
+    int  def2 = battle_get_def2 (target);
+    int  t_vit = battle_get_vit (target);
+    struct Damage wd;
+    int  damage, damage2, damage3 = 0, damage4 = 0, type, div_, blewcount =
+        skill_get_blewcount (skill_num, skill_lv);
+    int  flag, skill, dmg_lv = 0;
+    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 7, s_ele = 0;
+    struct status_change *sc_data, *t_sc_data;
+    short *sc_count;
+    short *option, *opt1, *opt2;
+    int  atkmax_ = 0, atkmin_ = 0, s_ele_;  //二刀流用
+    int  watk, watk_, cardfix, t_ele;
+    int  da = 0, i, t_class, ac_flag = 0;
+    int  idef_flag = 0, idef_flag_ = 0;
+    int  target_distance;
+
+    //return前の処理があるので情報出力部のみ変更
+    if (src == NULL || target == NULL || sd == NULL)
+    {
+        nullpo_info (NLP_MARK);
+        memset (&wd, 0, sizeof (wd));
+        return wd;
+    }
+
+    // アタッカー
+    s_race = battle_get_race (src); //種族
+    s_ele = battle_get_attack_element (src);    //属性
+    s_ele_ = battle_get_attack_element2 (src);  //左手属性
+    sc_data = battle_get_sc_data (src); //ステータス異常
+    sc_count = battle_get_sc_count (src);   //ステータス異常の数
+    option = battle_get_option (src);   //鷹とかペコとかカートとか
+    opt1 = battle_get_opt1 (src);   //石化、凍結、スタン、睡眠、暗闇
+    opt2 = battle_get_opt2 (src);   //毒、呪い、沈黙、暗闇?
+
+    if (skill_num != CR_GRANDCROSS) //グランドクロスでないなら
+        sd->state.attack_type = BF_WEAPON;  //攻撃タイプは武器攻撃
+
+    // ターゲット
+    if (target->type == BL_PC)  //対象がPCなら
+        tsd = (struct map_session_data *) target;   //tsdに代入(tmdはNULL)
+    else if (target->type == BL_MOB)    //対象がMobなら
+        tmd = (struct mob_data *) target;   //tmdに代入(tsdはNULL)
+    t_race = battle_get_race (target);  //対象の種族
+    t_ele = battle_get_elem_type (target);  //対象の属性
+    t_size = battle_get_size (target);  //対象のサイズ
+    t_mode = battle_get_mode (target);  //対象のMode
+    t_sc_data = battle_get_sc_data (target);    //対象のステータス異常
+
+//オートカウンター処理ここから
+    if ((skill_num == 0
+         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
+         || (target->type == BL_MOB
+             && battle_config.monster_auto_counter_type & 2))
+        && skill_lv >= 0)
+    {
+        if (skill_num != CR_GRANDCROSS && t_sc_data
+            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
+        {                       //グランドクロスでなく、対象がオートカウンター状態の場合
+            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
+                battle_get_dir (target);
+            int  dist = distance (src->x, src->y, target->x, target->y);
+            if (dist <= 0 || map_check_dir (dir, t_dir))
+            {                   //対象との距離が0以下、または対象の正面?
+                memset (&wd, 0, sizeof (wd));
+                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
+                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
+                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
+                {               //自分がオートカウンター状態
+                    int  range = battle_get_range (target);
+                    if ((target->type == BL_PC && ((struct map_session_data *) target)->status.weapon != 11 && dist <= range + 1) ||    //対象がPCで武器が弓矢でなく射程内
+                        (target->type == BL_MOB && range <= 3 && dist <= range + 1))    //または対象がMobで射程が3以下で射程内
+                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
+                }
+                return wd;      //ダメージ構造体を返して終了
+            }
+            else
+                ac_flag = 1;
+        }
+    }
+//オートカウンター処理ここまで
+
+    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // 攻撃の種類の設定
+
+    // 回避率計算、回避判定は後で
+    flee = battle_get_flee (target);
+    if (battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) //AGI、VITペナルティ設定が有効
+        target_count += battle_counttargeted (target, src, battle_config.agi_penaly_count_lv);  //対象の数を算出
+    if (battle_config.agi_penaly_type > 0)
+    {
+        if (target_count >= battle_config.agi_penaly_count)
+        {                       //ペナルティ設定より対象が多い
+            if (battle_config.agi_penaly_type == 1) //回避率がagi_penaly_num%ずつ減少
+                flee =
+                    (flee *
+                     (100 -
+                      (target_count -
+                       (battle_config.agi_penaly_count -
+                        1)) * battle_config.agi_penaly_num)) / 100;
+            else if (battle_config.agi_penaly_type == 2)    //回避率がagi_penaly_num分減少
+                flee -=
+                    (target_count -
+                     (battle_config.agi_penaly_count -
+                      1)) * battle_config.agi_penaly_num;
+            if (flee < 1)
+                flee = 1;       //回避率は最低でも1
+        }
+    }
+    hitrate = battle_get_hit (src) - flee + 80; //命中率計算
+
+    {                           // [fate] Reduce hit chance by distance
+        int  dx = abs (src->x - target->x);
+        int  dy = abs (src->y - target->y);
+        int  malus_dist;
+
+        target_distance = MAX (dx, dy);
+        malus_dist =
+            MAX (0, target_distance - (skill_power (sd, AC_OWL) / 75));
+        hitrate -= (malus_dist * (malus_dist + 1));
+    }
+
+    dex = battle_get_dex (src); //DEX
+    luk = battle_get_luk (src); //LUK
+    watk = battle_get_atk (src);    //ATK
+    watk_ = battle_get_atk_ (src);  //ATK左手
+
+    type = 0;                   // normal
+    div_ = 1;                   // single attack
+
+    if (skill_num == HW_MAGICCRASHER)
+    {                           /* マジッククラッシャーはMATKで殴る */
+        damage = damage2 = battle_get_matk1 (src);  //damega,damega2初登場、base_atkの取得
+    }
+    else
+    {
+        damage = damage2 = battle_get_baseatk (&sd->bl);    //damega,damega2初登場、base_atkの取得
+    }
+    if (sd->attackrange > 2)
+    {                           // [fate] ranged weapon?
+        const int range_damage_bonus = 80;  // up to 31.25% bonus for long-range hit
+        damage =
+            damage * (256 +
+                      ((range_damage_bonus * target_distance) /
+                       sd->attackrange)) >> 8;
+        damage2 =
+            damage2 * (256 +
+                       ((range_damage_bonus * target_distance) /
+                        sd->attackrange)) >> 8;
+    }
+
+    atkmin = atkmin_ = dex;     //最低ATKはDEXで初期化?
+    sd->state.arrow_atk = 0;    //arrow_atk初期化
+    if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]])
+        atkmin =
+            atkmin * (80 +
+                      sd->inventory_data[sd->equip_index[9]]->wlv * 20) / 100;
+    if (sd->equip_index[8] >= 0 && sd->inventory_data[sd->equip_index[8]])
+        atkmin_ =
+            atkmin_ * (80 +
+                       sd->inventory_data[sd->equip_index[8]]->wlv * 20) /
+            100;
+    if (sd->status.weapon == 11)
+    {                           //武器が弓矢の場合
+        atkmin = watk * ((atkmin < watk) ? atkmin : watk) / 100;    //弓用最低ATK計算
+        flag = (flag & ~BF_RANGEMASK) | BF_LONG;    //遠距離攻撃フラグを有効
+        if (sd->arrow_ele > 0)  //属性矢なら属性を矢の属性に変更
+            s_ele = sd->arrow_ele;
+        sd->state.arrow_atk = 1;    //arrow_atk有効化
+    }
+
+    // サイズ修正
+    // ペコ騎乗していて、槍で攻撃した場合は中型のサイズ修正を100にする
+    // ウェポンパーフェクション,ドレイクC
+    if (((sd->special_state.no_sizefix)
+         || (pc_isriding (sd)
+             && (sd->status.weapon == 4 || sd->status.weapon == 5)
+             && t_size == 1) || skill_num == MO_EXTREMITYFIST))
+    {                           //ペコ騎乗していて、槍で中型を攻撃
+        atkmax = watk;
+        atkmax_ = watk_;
+    }
+    else
+    {
+        atkmax = (watk * sd->atkmods[t_size]) / 100;
+        atkmin = (atkmin * sd->atkmods[t_size]) / 100;
+        atkmax_ = (watk_ * sd->atkmods_[t_size]) / 100;
+        atkmin_ = (atkmin_ * sd->atkmods[t_size]) / 100;
+    }
+    if ((sc_data != NULL && sc_data[SC_WEAPONPERFECTION].timer != -1)
+        || (sd->special_state.no_sizefix))
+    {                           // ウェポンパーフェクション || ドレイクカード
+        atkmax = watk;
+        atkmax_ = watk_;
+    }
+
+    if (atkmin > atkmax && !(sd->state.arrow_atk))
+        atkmin = atkmax;        //弓は最低が上回る場合あり
+    if (atkmin_ > atkmax_)
+        atkmin_ = atkmax_;
+
+    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
+    {                           // マキシマイズパワー
+        atkmin = atkmax;
+        atkmin_ = atkmax_;
+    }
+
+    //ダブルアタック判定
+    if (sd->weapontype1 == 0x01)
+    {
+        if (skill_num == 0 && skill_lv >= 0
+            && (skill = pc_checkskill (sd, TF_DOUBLE)) > 0)
+            da = (MRAND (100) < (skill * 5)) ? 1 : 0;
+    }
+
+    //三段掌
+    if (skill_num == 0 && skill_lv >= 0
+        && (skill = pc_checkskill (sd, MO_TRIPLEATTACK)) > 0
+        && sd->status.weapon <= 16 && !sd->state.arrow_atk)
+    {
+        da = (MRAND (100) < (30 - skill)) ? 2 : 0;
+    }
+
+    if (sd->double_rate > 0 && da == 0 && skill_num == 0 && skill_lv >= 0)
+        da = (MRAND (100) < sd->double_rate) ? 1 : 0;
+
+    // 過剰精錬ボーナス
+    if (sd->overrefine > 0)
+        damage += MPRAND (1, sd->overrefine);
+    if (sd->overrefine_ > 0)
+        damage2 += MPRAND (1, sd->overrefine_);
+
+    if (da == 0)
+    {                           //ダブルアタックが発動していない
+        // クリティカル計算
+        cri = battle_get_critical (src);
+
+        if (sd->state.arrow_atk)
+            cri += sd->arrow_cri;
+        if (sd->status.weapon == 16)
+            // カタールの場合、クリティカルを倍に
+            cri <<= 1;
+        cri -= battle_get_luk (target) * 3;
+        if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // 睡眠中はクリティカルが倍に
+            cri <<= 1;
+        if (ac_flag)
+            cri = 1000;
+
+        if (skill_num == KN_AUTOCOUNTER)
+        {
+            if (!(battle_config.pc_auto_counter_type & 1))
+                cri = 1000;
+            else
+                cri <<= 1;
+        }
+
+        if (skill_num == SN_SHARPSHOOTING && MRAND (100) < 50)
+            cri = 1000;
+    }
+
+    if (tsd && tsd->critical_def)
+        cri = cri * (100 - tsd->critical_def) / 100;
+
+    if (da == 0 && (skill_num == 0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && skill_lv >= 0 && //ダブルアタックが発動していない
+        (MRAND (1000)) < cri)   // 判定(スキルの場合は無視)
+    {
+        damage += atkmax;
+        damage2 += atkmax_;
+        if (sd->atk_rate != 100)
+        {
+            damage = (damage * sd->atk_rate) / 100;
+            damage2 = (damage2 * sd->atk_rate) / 100;
+        }
+        if (sd->state.arrow_atk)
+            damage += sd->arrow_atk;
+        type = 0x0a;
+
+/*		if(def1 < 1000000) {
+			if(sd->def_ratio_atk_ele & (1<<t_ele) || sd->def_ratio_atk_race & (1<<t_race)) {
+				damage = (damage * (def1 + def2))/100;
+				idef_flag = 1;
+			}
+			if(sd->def_ratio_atk_ele_ & (1<<t_ele) || sd->def_ratio_atk_race_ & (1<<t_race)) {
+				damage2 = (damage2 * (def1 + def2))/100;
+				idef_flag_ = 1;
+			}
+			if(t_mode & 0x20) {
+				if(!idef_flag && sd->def_ratio_atk_race & (1<<10)) {
+					damage = (damage * (def1 + def2))/100;
+					idef_flag = 1;
+				}
+				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<10)) {
+					damage2 = (damage2 * (def1 + def2))/100;
+					idef_flag_ = 1;
+				}
+			}
+			else {
+				if(!idef_flag && sd->def_ratio_atk_race & (1<<11)) {
+					damage = (damage * (def1 + def2))/100;
+					idef_flag = 1;
+				}
+				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<11)) {
+					damage2 = (damage2 * (def1 + def2))/100;
+					idef_flag_ = 1;
+				}
+			}
+		}*/
+    }
+    else
+    {
+        int  vitbonusmax;
+
+        if (atkmax > atkmin)
+            damage += atkmin + MRAND ((atkmax - atkmin + 1));
+        else
+            damage += atkmin;
+        if (atkmax_ > atkmin_)
+            damage2 += atkmin_ + MRAND ((atkmax_ - atkmin_ + 1));
+        else
+            damage2 += atkmin_;
+        if (sd->atk_rate != 100)
+        {
+            damage = (damage * sd->atk_rate) / 100;
+            damage2 = (damage2 * sd->atk_rate) / 100;
+        }
+
+        if (sd->state.arrow_atk)
+        {
+            if (sd->arrow_atk > 0)
+                damage += MRAND ((sd->arrow_atk + 1));
+            hitrate += sd->arrow_hit;
+        }
+
+        if (skill_num != MO_INVESTIGATE && def1 < 1000000)
+        {
+            if (sd->def_ratio_atk_ele & (1 << t_ele)
+                || sd->def_ratio_atk_race & (1 << t_race))
+            {
+                damage = (damage * (def1 + def2)) / 100;
+                idef_flag = 1;
+            }
+            if (sd->def_ratio_atk_ele_ & (1 << t_ele)
+                || sd->def_ratio_atk_race_ & (1 << t_race))
+            {
+                damage2 = (damage2 * (def1 + def2)) / 100;
+                idef_flag_ = 1;
+            }
+            if (t_mode & 0x20)
+            {
+                if (!idef_flag && sd->def_ratio_atk_race & (1 << 10))
+                {
+                    damage = (damage * (def1 + def2)) / 100;
+                    idef_flag = 1;
+                }
+                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 10))
+                {
+                    damage2 = (damage2 * (def1 + def2)) / 100;
+                    idef_flag_ = 1;
+                }
+            }
+            else
+            {
+                if (!idef_flag && sd->def_ratio_atk_race & (1 << 11))
+                {
+                    damage = (damage * (def1 + def2)) / 100;
+                    idef_flag = 1;
+                }
+                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 11))
+                {
+                    damage2 = (damage2 * (def1 + def2)) / 100;
+                    idef_flag_ = 1;
+                }
+            }
+        }
+
+        // スキル修正1(攻撃力倍化系)
+        // オーバートラスト(+5% 〜 +25%),他攻撃系スキルの場合ここで補正
+        // バッシュ,マグナムブレイク,
+        // ボーリングバッシュ,スピアブーメラン,ブランディッシュスピア,スピアスタッブ,
+        // メマーナイト,カートレボリューション
+        // ダブルストレイフィング,アローシャワー,チャージアロー,
+        // ソニックブロー
+        if (sc_data)
+        {                       //状態異常中のダメージ追加
+            if (sc_data[SC_OVERTHRUST].timer != -1)
+            {                   // オーバートラスト
+                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
+                damage2 += damage2 * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
+            }
+            if (sc_data[SC_TRUESIGHT].timer != -1)
+            {                   // トゥルーサイト
+                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
+                damage2 += damage2 * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
+            }
+            if (sc_data[SC_BERSERK].timer != -1)
+            {                   // バーサーク
+                damage += damage * 50 / 100;
+                damage2 += damage2 * 50 / 100;
+            }
+        }
+
+        if (skill_num > 0)
+        {
+            int  i;
+            if ((i = skill_get_pl (skill_num)) > 0)
+                s_ele = s_ele_ = i;
+
+            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
+            switch (skill_num)
+            {
+                case SM_BASH:  // バッシュ
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
+                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
+                    break;
+                case SM_MAGNUM:    // マグナムブレイク
+                    damage =
+                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
+                    damage2 =
+                        damage2 * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
+                    break;
+                case MC_MAMMONITE: // メマーナイト
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                    break;
+                case AC_DOUBLE:    // ダブルストレイフィング
+                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
+                    {
+                        int  arr = MRAND ((sd->arrow_atk + 1));
+                        damage += arr;
+                        damage2 += arr;
+                    }
+                    damage = damage * (180 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (180 + 20 * skill_lv) / 100;
+                    div_ = 2;
+                    if (sd->arrow_ele > 0)
+                    {
+                        s_ele = sd->arrow_ele;
+                        s_ele_ = sd->arrow_ele;
+                    }
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    sd->state.arrow_atk = 1;
+                    break;
+                case AC_SHOWER:    // アローシャワー
+                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
+                    {
+                        int  arr = MRAND ((sd->arrow_atk + 1));
+                        damage += arr;
+                        damage2 += arr;
+                    }
+                    damage = damage * (75 + 5 * skill_lv) / 100;
+                    damage2 = damage2 * (75 + 5 * skill_lv) / 100;
+                    if (sd->arrow_ele > 0)
+                    {
+                        s_ele = sd->arrow_ele;
+                        s_ele_ = sd->arrow_ele;
+                    }
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    sd->state.arrow_atk = 1;
+                    break;
+                case AC_CHARGEARROW:   // チャージアロー
+                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
+                    {
+                        int  arr = MRAND ((sd->arrow_atk + 1));
+                        damage += arr;
+                        damage2 += arr;
+                    }
+                    damage = damage * 150 / 100;
+                    damage2 = damage2 * 150 / 100;
+                    if (sd->arrow_ele > 0)
+                    {
+                        s_ele = sd->arrow_ele;
+                        s_ele_ = sd->arrow_ele;
+                    }
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    sd->state.arrow_atk = 1;
+                    break;
+                case KN_PIERCE:    // ピアース
+                    damage = damage * (100 + 10 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 10 * skill_lv) / 100;
+                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
+                    div_ = t_size + 1;
+                    damage *= div_;
+                    damage2 *= div_;
+                    break;
+                case KN_SPEARSTAB: // スピアスタブ
+                    damage = damage * (100 + 15 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 15 * skill_lv) / 100;
+                    break;
+                case KN_SPEARBOOMERANG:    // スピアブーメラン
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case KN_BRANDISHSPEAR: // ブランディッシュスピア
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    if (skill_lv > 3 && wflag == 1)
+                        damage3 += damage / 2;
+                    if (skill_lv > 6 && wflag == 1)
+                        damage3 += damage / 4;
+                    if (skill_lv > 9 && wflag == 1)
+                        damage3 += damage / 8;
+                    if (skill_lv > 6 && wflag == 2)
+                        damage3 += damage / 2;
+                    if (skill_lv > 9 && wflag == 2)
+                        damage3 += damage / 4;
+                    if (skill_lv > 9 && wflag == 3)
+                        damage3 += damage / 2;
+                    damage += damage3;
+                    if (skill_lv > 3 && wflag == 1)
+                        damage4 += damage2 / 2;
+                    if (skill_lv > 6 && wflag == 1)
+                        damage4 += damage2 / 4;
+                    if (skill_lv > 9 && wflag == 1)
+                        damage4 += damage2 / 8;
+                    if (skill_lv > 6 && wflag == 2)
+                        damage4 += damage2 / 2;
+                    if (skill_lv > 9 && wflag == 2)
+                        damage4 += damage2 / 4;
+                    if (skill_lv > 9 && wflag == 3)
+                        damage4 += damage2 / 2;
+                    damage2 += damage4;
+                    blewcount = 0;
+                    break;
+                case KN_BOWLINGBASH:   // ボウリングバッシュ
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                    blewcount = 0;
+                    break;
+                case KN_AUTOCOUNTER:
+                    if (battle_config.pc_auto_counter_type & 1)
+                        hitrate += 20;
+                    else
+                        hitrate = 1000000;
+                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
+                    break;
+                case AS_SONICBLOW: // ソニックブロウ
+                    hitrate += 30;  // hitrate +30, thanks to midas
+                    damage = damage * (300 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (300 + 50 * skill_lv) / 100;
+                    div_ = 8;
+                    break;
+                case TF_SPRINKLESAND:  // 砂まき
+                    damage = damage * 125 / 100;
+                    damage2 = damage2 * 125 / 100;
+                    break;
+                case MC_CARTREVOLUTION:    // カートレボリューション
+                    if (sd->cart_max_weight > 0 && sd->cart_weight > 0)
+                    {
+                        damage =
+                            (damage *
+                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
+                              (sd->cart_weight * 100 /
+                               sd->cart_max_weight))) / 100;
+                        damage2 =
+                            (damage2 *
+                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
+                              (sd->cart_weight * 100 /
+                               sd->cart_max_weight))) / 100;
+                    }
+                    else
+                    {
+                        damage = (damage * 150) / 100;
+                        damage2 = (damage2 * 150) / 100;
+                    }
+                    break;
+                    // 以下MOB
+                case NPC_COMBOATTACK:  // 多段攻撃
+                    div_ = skill_get_num (skill_num, skill_lv);
+                    damage *= div_;
+                    damage2 *= div_;
+                    break;
+                case NPC_RANDOMATTACK: // ランダムATK攻撃
+                    damage = damage * (MPRAND (50, 150)) / 100;
+                    damage2 = damage2 * (MPRAND (50, 150)) / 100;
+                    break;
+                    // 属性攻撃(適当)
+                case NPC_WATERATTACK:
+                case NPC_GROUNDATTACK:
+                case NPC_FIREATTACK:
+                case NPC_WINDATTACK:
+                case NPC_POISONATTACK:
+                case NPC_HOLYATTACK:
+                case NPC_DARKNESSATTACK:
+                case NPC_TELEKINESISATTACK:
+                    damage = damage * (100 + 25 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 25 * skill_lv) / 100;
+                    break;
+                case NPC_GUIDEDATTACK:
+                    hitrate = 1000000;
+                    break;
+                case NPC_RANGEATTACK:
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    break;
+                case NPC_PIERCINGATT:
+                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
+                    break;
+                case RG_BACKSTAP:  // バックスタブ
+                    if (battle_config.backstab_bow_penalty == 1
+                        && sd->status.weapon == 11)
+                    {
+                        damage = (damage * (300 + 40 * skill_lv) / 100) / 2;
+                        damage2 = (damage2 * (300 + 40 * skill_lv) / 100) / 2;
+                    }
+                    else
+                    {
+                        damage = damage * (300 + 40 * skill_lv) / 100;
+                        damage2 = damage2 * (300 + 40 * skill_lv) / 100;
+                    }
+                    hitrate = 1000000;
+                    break;
+                case RG_RAID:  // サプライズアタック
+                    damage = damage * (100 + 40 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
+                    break;
+                case RG_INTIMIDATE:    // インティミデイト
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
+                    break;
+                case CR_SHIELDCHARGE:  // シールドチャージ
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
+                    s_ele = 0;
+                    break;
+                case CR_SHIELDBOOMERANG:   // シールドブーメラン
+                    damage = damage * (100 + 30 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    s_ele = 0;
+                    break;
+                case CR_HOLYCROSS: // ホーリークロス
+                    damage = damage * (100 + 35 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 35 * skill_lv) / 100;
+                    div_ = 2;
+                    break;
+                case CR_GRANDCROSS:
+                    hitrate = 1000000;
+                    break;
+                case AM_DEMONSTRATION: // デモンストレーション
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    break;
+                case AM_ACIDTERROR:    // アシッドテラー
+                    damage = damage * (100 + 40 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
+                    break;
+                case MO_FINGEROFFENSIVE:   //指弾
+                    if (battle_config.finger_offensive_type == 0)
+                    {
+                        damage =
+                            damage * (100 +
+                                      50 * skill_lv) / 100 *
+                            sd->spiritball_old;
+                        damage2 =
+                            damage2 * (100 +
+                                       50 * skill_lv) / 100 *
+                            sd->spiritball_old;
+                        div_ = sd->spiritball_old;
+                    }
+                    else
+                    {
+                        damage = damage * (100 + 50 * skill_lv) / 100;
+                        damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                        div_ = 1;
+                    }
+                    break;
+                case MO_INVESTIGATE:   // 発 勁
+                    if (def1 < 1000000)
+                    {
+                        damage =
+                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
+                                                                    def2) /
+                            100;
+                        damage2 =
+                            damage2 * (100 + 75 * skill_lv) / 100 * (def1 +
+                                                                     def2) /
+                            100;
+                    }
+                    hitrate = 1000000;
+                    s_ele = 0;
+                    s_ele_ = 0;
+                    break;
+                case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
+                    damage =
+                        damage * (8 + ((sd->status.sp) / 10)) + 250 +
+                        (skill_lv * 150);
+                    damage2 =
+                        damage2 * (8 + ((sd->status.sp) / 10)) + 250 +
+                        (skill_lv * 150);
+                    sd->status.sp = 0;
+                    clif_updatestatus (sd, SP_SP);
+                    hitrate = 1000000;
+                    s_ele = 0;
+                    s_ele_ = 0;
+                    break;
+                case MO_CHAINCOMBO:    // 連打掌
+                    damage = damage * (150 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (150 + 50 * skill_lv) / 100;
+                    div_ = 4;
+                    break;
+                case MO_COMBOFINISH:   // 猛龍拳
+                    damage = damage * (240 + 60 * skill_lv) / 100;
+                    damage2 = damage2 * (240 + 60 * skill_lv) / 100;
+                    break;
+                case BA_MUSICALSTRIKE: // ミュージカルストライク
+                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
+                    {
+                        int  arr = MRAND ((sd->arrow_atk + 1));
+                        damage += arr;
+                        damage2 += arr;
+                    }
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                    if (sd->arrow_ele > 0)
+                    {
+                        s_ele = sd->arrow_ele;
+                        s_ele_ = sd->arrow_ele;
+                    }
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    sd->state.arrow_atk = 1;
+                    break;
+                case DC_THROWARROW:    // 矢撃ち
+                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
+                    {
+                        int  arr = MRAND ((sd->arrow_atk + 1));
+                        damage += arr;
+                        damage2 += arr;
+                    }
+                    damage = damage * (100 + 50 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
+                    if (sd->arrow_ele > 0)
+                    {
+                        s_ele = sd->arrow_ele;
+                        s_ele_ = sd->arrow_ele;
+                    }
+                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
+                    sd->state.arrow_atk = 1;
+                    break;
+                case CH_TIGERFIST: // 伏虎拳
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    break;
+                case CH_CHAINCRUSH:    // 連柱崩撃
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    div_ = skill_get_num (skill_num, skill_lv);
+                    break;
+                case CH_PALMSTRIKE:    // 猛虎硬派山
+                    damage = damage * (50 + 100 * skill_lv) / 100;
+                    damage2 = damage2 * (50 + 100 * skill_lv) / 100;
+                    break;
+                case LK_SPIRALPIERCE:  /* スパイラルピアース */
+                    damage = damage * (100 + 50 * skill_lv) / 100;  //増加量が分からないので適当に
+                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;    //増加量が分からないので適当に
+                    div_ = 5;
+                    if (tsd)
+                        tsd->canmove_tick = gettick () + 1000;
+                    else if (tmd)
+                        tmd->canmove_tick = gettick () + 1000;
+                    break;
+                case LK_HEADCRUSH: /* ヘッドクラッシュ */
+                    damage = damage * (100 + 20 * skill_lv) / 100;
+                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
+                    break;
+                case LK_JOINTBEAT: /* ジョイントビート */
+                    damage = damage * (50 + 10 * skill_lv) / 100;
+                    damage2 = damage2 * (50 + 10 * skill_lv) / 100;
+                    break;
+                case ASC_METEORASSAULT:    /* メテオアサルト */
+                    damage = damage * (40 + 40 * skill_lv) / 100;
+                    damage2 = damage2 * (40 + 40 * skill_lv) / 100;
+                    break;
+                case SN_SHARPSHOOTING: /* シャープシューティング */
+                    damage += damage * (30 * skill_lv) / 100;
+                    damage2 += damage2 * (30 * skill_lv) / 100;
+                    break;
+                case CG_ARROWVULCAN:   /* アローバルカン */
+                    damage = damage * (160 + 40 * skill_lv) / 100;
+                    damage2 = damage2 * (160 + 40 * skill_lv) / 100;
+                    div_ = 9;
+                    break;
+                case AS_SPLASHER:  /* ベナムスプラッシャー */
+                    damage =
+                        damage * (200 + 20 * skill_lv +
+                                  20 * pc_checkskill (sd,
+                                                      AS_POISONREACT)) / 100;
+                    damage2 =
+                        damage2 * (200 + 20 * skill_lv +
+                                   20 * pc_checkskill (sd,
+                                                       AS_POISONREACT)) / 100;
+                    break;
+                case PA_SACRIFICE:
+                    if (sd)
+                    {
+                        int  hp, mhp, damage3;
+                        hp = battle_get_hp (src);
+                        mhp = battle_get_max_hp (src);
+                        damage3 = mhp * ((skill_lv / 2) + (50 / 100)) / 100;
+                        damage =
+                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
+                        damage2 =
+                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
+                    }
+                    break;
+                case ASC_BREAKER:  // -- moonsoul (special damage for ASC_BREAKER skill)
+                    if (sd)
+                    {
+                        int  damage3;
+                        int  mdef1 = battle_get_mdef (target);
+                        int  mdef2 = battle_get_mdef2 (target);
+                        int  imdef_flag = 0;
+
+                        damage =
+                            ((damage * 5) +
+                             (skill_lv * battle_get_int (src) * 5) +
+                             MRAND (500) + 500) / 2;
+                        damage2 =
+                            ((damage2 * 5) +
+                             (skill_lv * battle_get_int (src) * 5) +
+                             MRAND (500) + 500) / 2;
+                        damage3 = damage;
+                        hitrate = 1000000;
+
+                        if (sd->ignore_mdef_ele & (1 << t_ele)
+                            || sd->ignore_mdef_race & (1 << t_race))
+                            imdef_flag = 1;
+                        if (t_mode & 0x20)
+                        {
+                            if (sd->ignore_mdef_race & (1 << 10))
+                                imdef_flag = 1;
+                        }
+                        else
+                        {
+                            if (sd->ignore_mdef_race & (1 << 11))
+                                imdef_flag = 1;
+                        }
+                        if (!imdef_flag)
+                        {
+                            if (battle_config.magic_defense_type)
+                            {
+                                damage3 =
+                                    damage3 -
+                                    (mdef1 *
+                                     battle_config.magic_defense_type) -
+                                    mdef2;
+                            }
+                            else
+                            {
+                                damage3 =
+                                    (damage3 * (100 - mdef1)) / 100 - mdef2;
+                            }
+                        }
+
+                        if (damage3 < 1)
+                            damage3 = 1;
+
+                        damage3 =
+                            battle_attr_fix (damage2, s_ele_,
+                                             battle_get_element (target));
+                    }
+                    break;
+            }
+        }
+        if (da == 2)
+        {                       //三段掌が発動しているか
+            type = 0x08;
+            div_ = 255;         //三段掌用に…
+            damage =
+                damage * (100 +
+                          20 * pc_checkskill (sd, MO_TRIPLEATTACK)) / 100;
+        }
+
+        if (skill_num != NPC_CRITICALSLASH)
+        {
+            // 対 象の防御力によるダメージの減少
+            // ディバインプロテクション(ここでいいのかな?)
+            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
+                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
+            {                   //DEF, VIT無視
+                int  t_def;
+                target_count =
+                    1 + battle_counttargeted (target, src,
+                                              battle_config.vit_penaly_count_lv);
+                if (battle_config.vit_penaly_type > 0)
+                {
+                    if (target_count >= battle_config.vit_penaly_count)
+                    {
+                        if (battle_config.vit_penaly_type == 1)
+                        {
+                            def1 =
+                                (def1 *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                            def2 =
+                                (def2 *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                            t_vit =
+                                (t_vit *
+                                 (100 -
+                                  (target_count -
+                                   (battle_config.vit_penaly_count -
+                                    1)) * battle_config.vit_penaly_num)) /
+                                100;
+                        }
+                        else if (battle_config.vit_penaly_type == 2)
+                        {
+                            def1 -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                            def2 -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                            t_vit -=
+                                (target_count -
+                                 (battle_config.vit_penaly_count -
+                                  1)) * battle_config.vit_penaly_num;
+                        }
+                        if (def1 < 0)
+                            def1 = 0;
+                        if (def2 < 1)
+                            def2 = 1;
+                        if (t_vit < 1)
+                            t_vit = 1;
+                    }
+                }
+                t_def = def2 * 8 / 10;
+                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
+                if (sd->ignore_def_ele & (1 << t_ele)
+                    || sd->ignore_def_race & (1 << t_race))
+                    idef_flag = 1;
+                if (sd->ignore_def_ele_ & (1 << t_ele)
+                    || sd->ignore_def_race_ & (1 << t_race))
+                    idef_flag_ = 1;
+                if (t_mode & 0x20)
+                {
+                    if (sd->ignore_def_race & (1 << 10))
+                        idef_flag = 1;
+                    if (sd->ignore_def_race_ & (1 << 10))
+                        idef_flag_ = 1;
+                }
+                else
+                {
+                    if (sd->ignore_def_race & (1 << 11))
+                        idef_flag = 1;
+                    if (sd->ignore_def_race_ & (1 << 11))
+                        idef_flag_ = 1;
+                }
+
+                if (!idef_flag)
+                {
+                    if (battle_config.player_defense_type)
+                    {
+                        damage =
+                            damage -
+                            (def1 * battle_config.player_defense_type) -
+                            t_def -
+                            ((vitbonusmax <
+                              1) ? 0 : MRAND ((vitbonusmax + 1)));
+                    }
+                    else
+                    {
+                        damage =
+                            damage * (100 - def1) / 100 - t_def -
+                            ((vitbonusmax <
+                              1) ? 0 : MRAND ((vitbonusmax + 1)));
+                    }
+                }
+                if (!idef_flag_)
+                {
+                    if (battle_config.player_defense_type)
+                    {
+                        damage2 =
+                            damage2 -
+                            (def1 * battle_config.player_defense_type) -
+                            t_def -
+                            ((vitbonusmax <
+                              1) ? 0 : MRAND ((vitbonusmax + 1)));
+                    }
+                    else
+                    {
+                        damage2 =
+                            damage2 * (100 - def1) / 100 - t_def -
+                            ((vitbonusmax <
+                              1) ? 0 : MRAND ((vitbonusmax + 1)));
+                    }
+                }
+            }
+        }
+    }
+    // 精錬ダメージの追加
+    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST)
+    {                           //DEF, VIT無視
+        damage += battle_get_atk2 (src);
+        damage2 += battle_get_atk_2 (src);
+    }
+    if (skill_num == CR_SHIELDBOOMERANG)
+    {
+        if (sd->equip_index[8] >= 0)
+        {
+            int  index = sd->equip_index[8];
+            if (sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 5)
+            {
+                damage += sd->inventory_data[index]->weight / 10;
+                damage +=
+                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
+                                                                            1);
+            }
+        }
+    }
+    if (skill_num == LK_SPIRALPIERCE)
+    {                           /* スパイラルピアース */
+        if (sd->equip_index[9] >= 0)
+        {                       //重量で追加ダメージらしいのでシールドブーメランを参考に追加
+            int  index = sd->equip_index[9];
+            if (sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 4)
+            {
+                damage +=
+                    (int) (double) (sd->inventory_data[index]->weight *
+                                    (0.8 * skill_lv * 4 / 10));
+                damage +=
+                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
+                                                                            1);
+            }
+        }
+    }
+
+    // 0未満だった場合1に補正
+    if (damage < 1)
+        damage = 1;
+    if (damage2 < 1)
+        damage2 = 1;
+
+    // スキル修正2(修練系)
+    // 修練ダメージ(右手のみ) ソニックブロー時は別処理(1撃に付き1/8適応)
+    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
+        && skill_num != CR_GRANDCROSS)
+    {                           //修練ダメージ無視
+        damage = battle_addmastery (sd, target, damage, 0);
+        damage2 = battle_addmastery (sd, target, damage2, 1);
+    }
+
+    if (sd->perfect_hit > 0)
+    {
+        if (MRAND (100) < sd->perfect_hit)
+            hitrate = 1000000;
+    }
+
+    // 回避修正
+    hitrate = (hitrate < 5) ? 5 : hitrate;
+    if (hitrate < 1000000 &&    // 必中攻撃
+        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // 睡眠は必中
+                               t_sc_data[SC_STAN].timer != -1 ||    // スタンは必中
+                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // 凍結は必中
+        hitrate = 1000000;
+    if (type == 0 && MRAND (100) >= hitrate)
+    {
+        damage = damage2 = 0;
+        dmg_lv = ATK_FLEE;
+    }
+    else
+    {
+        dmg_lv = ATK_DEF;
+    }
+    // スキル修正3(武器研究)
+    if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0)
+    {
+        damage += skill * 2;
+        damage2 += skill * 2;
+    }
+    //Advanced Katar Research by zanetheinsane
+    if (sd->weapontype1 == 0x10 || sd->weapontype2 == 0x10)
+    {
+        if ((skill = pc_checkskill (sd, ASC_KATAR)) > 0)
+        {
+            damage += (damage * ((skill * 2) + 10)) / 100;
+        }
+    }
+
+//スキルによるダメージ補正ここまで
+
+//カードによるダメージ追加処理ここから
+    cardfix = 100;
+    if (!sd->state.arrow_atk)
+    {                           //弓矢以外
+        if (!battle_config.left_cardfix_to_right)
+        {                       //左手カード補正設定無し
+            cardfix = cardfix * (100 + sd->addrace[t_race]) / 100;  // 種族によるダメージ修正
+            cardfix = cardfix * (100 + sd->addele[t_ele]) / 100;    // 属性によるダメージ修正
+            cardfix = cardfix * (100 + sd->addsize[t_size]) / 100;  // サイズによるダメージ修正
+        }
+        else
+        {
+            cardfix = cardfix * (100 + sd->addrace[t_race] + sd->addrace_[t_race]) / 100;   // 種族によるダメージ修正(左手による追加あり)
+            cardfix = cardfix * (100 + sd->addele[t_ele] + sd->addele_[t_ele]) / 100;   // 属性によるダメージ修正(左手による追加あり)
+            cardfix = cardfix * (100 + sd->addsize[t_size] + sd->addsize_[t_size]) / 100;   // サイズによるダメージ修正(左手による追加あり)
+        }
+    }
+    else
+    {                           //弓矢
+        cardfix = cardfix * (100 + sd->addrace[t_race] + sd->arrow_addrace[t_race]) / 100;  // 種族によるダメージ修正(弓矢による追加あり)
+        cardfix = cardfix * (100 + sd->addele[t_ele] + sd->arrow_addele[t_ele]) / 100;  // 属性によるダメージ修正(弓矢による追加あり)
+        cardfix = cardfix * (100 + sd->addsize[t_size] + sd->arrow_addsize[t_size]) / 100;  // サイズによるダメージ修正(弓矢による追加あり)
+    }
+    if (t_mode & 0x20)
+    {                           //ボス
+        if (!sd->state.arrow_atk)
+        {                       //弓矢攻撃以外なら
+            if (!battle_config.left_cardfix_to_right)   //左手カード補正設定無し
+                cardfix = cardfix * (100 + sd->addrace[10]) / 100;  //ボスモンスターに追加ダメージ
+            else                //左手カード補正設定あり
+                cardfix = cardfix * (100 + sd->addrace[10] + sd->addrace_[10]) / 100;   //ボスモンスターに追加ダメージ(左手による追加あり)
+        }
+        else                    //弓矢攻撃
+            cardfix = cardfix * (100 + sd->addrace[10] + sd->arrow_addrace[10]) / 100;  //ボスモンスターに追加ダメージ(弓矢による追加あり)
+    }
+    else
+    {                           //ボスじゃない
+        if (!sd->state.arrow_atk)
+        {                       //弓矢攻撃以外
+            if (!battle_config.left_cardfix_to_right)   //左手カード補正設定無し
+                cardfix = cardfix * (100 + sd->addrace[11]) / 100;  //ボス以外モンスターに追加ダメージ
+            else                //左手カード補正設定あり
+                cardfix = cardfix * (100 + sd->addrace[11] + sd->addrace_[11]) / 100;   //ボス以外モンスターに追加ダメージ(左手による追加あり)
+        }
+        else
+            cardfix = cardfix * (100 + sd->addrace[11] + sd->arrow_addrace[11]) / 100;  //ボス以外モンスターに追加ダメージ(弓矢による追加あり)
+    }
+    //特定Class用補正処理(少女の日記→ボンゴン用?)
+    t_class = battle_get_class (target);
+    for (i = 0; i < sd->add_damage_class_count; i++)
+    {
+        if (sd->add_damage_classid[i] == t_class)
+        {
+            cardfix = cardfix * (100 + sd->add_damage_classrate[i]) / 100;
+            break;
+        }
+    }
+    if (skill_num != CR_GRANDCROSS || !battle_config.gx_cardfix)
+        damage = damage * cardfix / 100;    //カード補正によるダメージ増加
+//カードによるダメージ増加処理ここまで
+
+//カードによるダメージ追加処理(左手)ここから
+    cardfix = 100;
+    if (!battle_config.left_cardfix_to_right)
+    {                           //左手カード補正設定無し
+        cardfix = cardfix * (100 + sd->addrace_[t_race]) / 100; // 種族によるダメージ修正左手
+        cardfix = cardfix * (100 + sd->addele_[t_ele]) / 100;   // 属 性によるダメージ修正左手
+        cardfix = cardfix * (100 + sd->addsize_[t_size]) / 100; // サイズによるダメージ修正左手
+        if (t_mode & 0x20)      //ボス
+            cardfix = cardfix * (100 + sd->addrace_[10]) / 100; //ボスモンスターに追加ダメージ左手
+        else
+            cardfix = cardfix * (100 + sd->addrace_[11]) / 100; //ボス以外モンスターに追加ダメージ左手
+    }
+    //特定Class用補正処理左手(少女の日記→ボンゴン用?)
+    for (i = 0; i < sd->add_damage_class_count_; i++)
+    {
+        if (sd->add_damage_classid_[i] == t_class)
+        {
+            cardfix = cardfix * (100 + sd->add_damage_classrate_[i]) / 100;
+            break;
+        }
+    }
+    if (skill_num != CR_GRANDCROSS)
+        damage2 = damage2 * cardfix / 100;  //カード補正による左手ダメージ増加
+//カードによるダメージ増加処理(左手)ここまで
+
+// -- moonsoul (cardfix for magic damage portion of ASC_BREAKER)
+    if (skill_num == ASC_BREAKER)
+        damage3 = damage3 * cardfix / 100;
+
+//カードによるダメージ減衰処理ここから
+    if (tsd)
+    {                           //対象がPCの場合
+        cardfix = 100;
+        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // 種族によるダメージ耐性
+        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // 属性によるダメージ耐性
+        if (battle_get_mode (src) & 0x20)
+            cardfix = cardfix * (100 - tsd->subrace[10]) / 100; //ボスからの攻撃はダメージ減少
+        else
+            cardfix = cardfix * (100 - tsd->subrace[11]) / 100; //ボス以外からの攻撃はダメージ減少
+        //特定Class用補正処理左手(少女の日記→ボンゴン用?)
+        for (i = 0; i < tsd->add_def_class_count; i++)
+        {
+            if (tsd->add_def_classid[i] == sd->status.pc_class)
+            {
+                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
+                break;
+            }
+        }
+        if (flag & BF_LONG)
+            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;    //遠距離攻撃はダメージ減少(ホルンCとか)
+        if (flag & BF_SHORT)
+            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;    //近距離攻撃はダメージ減少(該当無し?)
+        damage = damage * cardfix / 100;    //カード補正によるダメージ減少
+        damage2 = damage2 * cardfix / 100;  //カード補正による左手ダメージ減少
+    }
+//カードによるダメージ減衰処理ここまで
+
+//対象にステータス異常がある場合のダメージ減算処理ここから
+    if (t_sc_data)
+    {
+        cardfix = 100;
+        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)   //ディフェンダー状態で遠距離攻撃
+            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;  //ディフェンダーによる減衰
+        if (cardfix != 100)
+        {
+            damage = damage * cardfix / 100;    //ディフェンダー補正によるダメージ減少
+            damage2 = damage2 * cardfix / 100;  //ディフェンダー補正による左手ダメージ減少
+        }
+        if (t_sc_data[SC_ASSUMPTIO].timer != -1)
+        {                       //アスムプティオ
+            if (!map[target->m].flag.pvp)
+            {
+                damage = damage / 3;
+                damage2 = damage2 / 3;
+            }
+            else
+            {
+                damage = damage / 2;
+                damage2 = damage2 / 2;
+            }
+        }
+    }
+//対象にステータス異常がある場合のダメージ減算処理ここまで
+
+    if (damage < 0)
+        damage = 0;
+    if (damage2 < 0)
+        damage2 = 0;
+
+    // 属 性の適用
+    damage = battle_attr_fix (damage, s_ele, battle_get_element (target));
+    damage2 = battle_attr_fix (damage2, s_ele_, battle_get_element (target));
+
+    // 星のかけら、気球の適用
+    damage += sd->star;
+    damage2 += sd->star_;
+    damage += sd->spiritball * 3;
+    damage2 += sd->spiritball * 3;
+
+    if (sc_data && sc_data[SC_AURABLADE].timer != -1)
+    {                           /* オーラブレード 必中 */
+        damage += sc_data[SC_AURABLADE].val1 * 10;
+        damage2 += sc_data[SC_AURABLADE].val1 * 10;
+    }
+    if (skill_num == PA_PRESSURE)
+    {                           /* プレッシャー 必中? */
+        damage = 700 + 100 * skill_lv;
+        damage2 = 700 + 100 * skill_lv;
+    }
+
+    // >二刀流の左右ダメージ計算誰かやってくれぇぇぇぇえええ!
+    // >map_session_data に左手ダメージ(atk,atk2)追加して
+    // >pc_calcstatus()でやるべきかな?
+    // map_session_data に左手武器(atk,atk2,ele,star,atkmods)追加して
+    // pc_calcstatus()でデータを入力しています
+
+    //左手のみ武器装備
+    if (sd->weapontype1 == 0 && sd->weapontype2 > 0)
+    {
+        damage = damage2;
+        damage2 = 0;
+    }
+    // 右手、左手修練の適用
+    if (sd->status.weapon > 16)
+    {                           // 二刀流か?
+        int  dmg = damage, dmg2 = damage2;
+        // 右手修練(60% 〜 100%) 右手全般
+        skill = pc_checkskill (sd, AS_RIGHT);
+        damage = damage * (50 + (skill * 10)) / 100;
+        if (dmg > 0 && damage < 1)
+            damage = 1;
+        // 左手修練(40% 〜 80%) 左手全般
+        skill = pc_checkskill (sd, AS_LEFT);
+        damage2 = damage2 * (30 + (skill * 10)) / 100;
+        if (dmg2 > 0 && damage2 < 1)
+            damage2 = 1;
+    }
+    else                        //二刀流でなければ左手ダメージは0
+        damage2 = 0;
+
+    // 右手,短剣のみ
+    if (da == 1)
+    {                           //ダブルアタックが発動しているか
+        div_ = 2;
+        damage += damage;
+        type = 0x08;
+    }
+
+    if (sd->status.weapon == 16)
+    {
+        // カタール追撃ダメージ
+        skill = pc_checkskill (sd, TF_DOUBLE);
+        damage2 = damage * (1 + (skill * 2)) / 100;
+        if (damage > 0 && damage2 < 1)
+            damage2 = 1;
+    }
+
+    // インベナム修正
+    if (skill_num == TF_POISON)
+    {
+        damage =
+            battle_attr_fix (damage + 15 * skill_lv, s_ele,
+                             battle_get_element (target));
+    }
+    if (skill_num == MC_CARTREVOLUTION)
+    {
+        damage = battle_attr_fix (damage, 0, battle_get_element (target));
+    }
+
+    // 完全回避の判定
+    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL && div_ < 255
+        && MRAND (1000) < battle_get_flee2 (target))
+    {
+        damage = damage2 = 0;
+        type = 0x0b;
+        dmg_lv = ATK_LUCKY;
+    }
+
+    // 対象が完全回避をする設定がONなら
+    if (battle_config.enemy_perfect_flee)
+    {
+        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL && div_ < 255
+            && MRAND (1000) < battle_get_flee2 (target))
+        {
+            damage = damage2 = 0;
+            type = 0x0b;
+            dmg_lv = ATK_LUCKY;
+        }
+    }
+
+    //MobのModeに頑強フラグが立っているときの処理
+    if (t_mode & 0x40)
+    {
+        if (damage > 0)
+            damage = 1;
+        if (damage2 > 0)
+            damage2 = 1;
+    }
+
+    //bNoWeaponDamage(設定アイテム無し?)でグランドクロスじゃない場合はダメージが0
+    if (tsd && tsd->special_state.no_weapon_damage
+        && skill_num != CR_GRANDCROSS)
+        damage = damage2 = 0;
+
+    if (skill_num != CR_GRANDCROSS && (damage > 0 || damage2 > 0))
+    {
+        if (damage2 < 1)        // ダメージ最終修正
+            damage =
+                battle_calc_damage (src, target, damage, div_, skill_num,
+                                    skill_lv, flag);
+        else if (damage < 1)    // 右手がミス?
+            damage2 =
+                battle_calc_damage (src, target, damage2, div_, skill_num,
+                                    skill_lv, flag);
+        else
+        {                       // 両 手/カタールの場合はちょっと計算ややこしい
+            int  d1 = damage + damage2, d2 = damage2;
+            damage =
+                battle_calc_damage (src, target, damage + damage2, div_,
+                                    skill_num, skill_lv, flag);
+            damage2 = (d2 * 100 / d1) * damage / 100;
+            if (damage > 1 && damage2 < 1)
+                damage2 = 1;
+            damage -= damage2;
+        }
+    }
+
+    /*              For executioner card [Valaris]              */
+    if (src->type == BL_PC && sd->random_attack_increase_add > 0
+        && sd->random_attack_increase_per > 0 && skill_num == 0)
+    {
+        if (MRAND (100) < sd->random_attack_increase_per)
+        {
+            if (damage > 0)
+                damage *= sd->random_attack_increase_add / 100;
+            if (damage2 > 0)
+                damage2 *= sd->random_attack_increase_add / 100;
+        }
+    }
+    /*                  End addition                    */
+
+// -- moonsoul (final combination of phys, mag damage for ASC_BREAKER)
+    if (skill_num == ASC_BREAKER)
+    {
+        damage += damage3;
+        damage2 += damage3;
+    }
+
+    wd.damage = damage;
+    wd.damage2 = damage2;
+    wd.type = type;
+    wd.div_ = div_;
+    wd.amotion = battle_get_amotion (src);
+    if (skill_num == KN_AUTOCOUNTER)
+        wd.amotion >>= 1;
+    wd.dmotion = battle_get_dmotion (target);
+    wd.blewcount = blewcount;
+    wd.flag = flag;
+    wd.dmg_lv = dmg_lv;
+
+    return wd;
+}
+
+/*==========================================
+ * 武器ダメージ計算
+ *------------------------------------------
+ */
+struct Damage battle_calc_weapon_attack (struct block_list *src,
+                                         struct block_list *target,
+                                         int skill_num, int skill_lv,
+                                         int wflag)
+{
+    struct Damage wd;
+
+    //return前の処理があるので情報出力部のみ変更
+    if (src == NULL || target == NULL)
+    {
+        nullpo_info (NLP_MARK);
+        memset (&wd, 0, sizeof (wd));
+        return wd;
+    }
+
+    else if (src->type == BL_PC)
+        wd = battle_calc_pc_weapon_attack (src, target, skill_num, skill_lv, wflag);    // weapon breaking [Valaris]
+    else if (src->type == BL_MOB)
+        wd = battle_calc_mob_weapon_attack (src, target, skill_num, skill_lv,
+                                            wflag);
+    else
+        memset (&wd, 0, sizeof (wd));
+
+    if (battle_config.equipment_breaking && src->type == BL_PC
+        && (wd.damage > 0 || wd.damage2 > 0))
+    {
+        struct map_session_data *sd = (struct map_session_data *) src;
+        if (sd->status.weapon && sd->status.weapon != 11)
+        {
+            int  breakrate = 1;
+            if (target->type == BL_PC && sd->sc_data[SC_MELTDOWN].timer != -1)
+            {
+                breakrate += 100 * sd->sc_data[SC_MELTDOWN].val1;
+                if (MRAND (10000) <
+                    breakrate * battle_config.equipment_break_rate / 100
+                    || breakrate >= 10000)
+                    pc_breakweapon ((struct map_session_data *) target);
+            }
+            if (sd->sc_data[SC_OVERTHRUST].timer != -1)
+                breakrate += 20 * sd->sc_data[SC_OVERTHRUST].val1;
+            if (wd.type == 0x0a)
+                breakrate *= 2;
+            if (MRAND (10000) <
+                breakrate * battle_config.equipment_break_rate / 100
+                || breakrate >= 10000)
+            {
+                pc_breakweapon (sd);
+                memset (&wd, 0, sizeof (wd));
+            }
+        }
+    }
+
+    if (battle_config.equipment_breaking && target->type == BL_PC
+        && (wd.damage > 0 || wd.damage2 > 0))
+    {
+        int  breakrate = 1;
+        if (src->type == BL_PC
+            && ((struct map_session_data *) src)->
+            sc_data[SC_MELTDOWN].timer != -1)
+            breakrate +=
+                70 *
+                ((struct map_session_data *) src)->sc_data[SC_MELTDOWN].val1;
+        if (wd.type == 0x0a)
+            breakrate *= 2;
+        if (MRAND (10000) <
+            breakrate * battle_config.equipment_break_rate / 100
+            || breakrate >= 10000)
+        {
+            pc_breakarmor ((struct map_session_data *) target);
+        }
+    }
+
+    return wd;
+}
+
+/*==========================================
+ * 魔法ダメージ計算
+ *------------------------------------------
+ */
+struct Damage battle_calc_magic_attack (struct block_list *bl,
+                                        struct block_list *target,
+                                        int skill_num, int skill_lv, int flag)
+{
+    int  mdef1 = battle_get_mdef (target);
+    int  mdef2 = battle_get_mdef2 (target);
+    int  matk1, matk2, damage = 0, div_ = 1, blewcount =
+        skill_get_blewcount (skill_num, skill_lv), rdamage = 0;
+    struct Damage md;
+    int  aflag;
+    int  normalmagic_flag = 1;
+    int  ele = 0, race = 7, t_ele = 0, t_race = 7, t_mode =
+        0, cardfix, t_class, i;
+    struct map_session_data *sd = NULL, *tsd = NULL;
+    struct mob_data *tmd = NULL;
+
+    //return前の処理があるので情報出力部のみ変更
+    if (bl == NULL || target == NULL)
+    {
+        nullpo_info (NLP_MARK);
+        memset (&md, 0, sizeof (md));
+        return md;
+    }
+
+    matk1 = battle_get_matk1 (bl);
+    matk2 = battle_get_matk2 (bl);
+    ele = skill_get_pl (skill_num);
+    race = battle_get_race (bl);
+    t_ele = battle_get_elem_type (target);
+    t_race = battle_get_race (target);
+    t_mode = battle_get_mode (target);
+
+#define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); }
+
+    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
+    {
+        sd->state.attack_type = BF_MAGIC;
+        if (sd->matk_rate != 100)
+            MATK_FIX (sd->matk_rate, 100);
+        sd->state.arrow_atk = 0;
+    }
+    if (target->type == BL_PC)
+        tsd = (struct map_session_data *) target;
+    else if (target->type == BL_MOB)
+        tmd = (struct mob_data *) target;
+
+    aflag = BF_MAGIC | BF_LONG | BF_SKILL;
+
+    if (skill_num > 0)
+    {
+        switch (skill_num)
+        {                       // 基本ダメージ計算(スキルごとに処理)
+                // ヒールor聖体
+            case AL_HEAL:
+            case PR_BENEDICTIO:
+                damage = skill_calc_heal (bl, skill_lv) / 2;
+                normalmagic_flag = 0;
+                break;
+            case PR_ASPERSIO:  /* アスペルシオ */
+                damage = 40;    //固定ダメージ
+                normalmagic_flag = 0;
+                break;
+            case PR_SANCTUARY: // サンクチュアリ
+                damage = (skill_lv > 6) ? 388 : skill_lv * 50;
+                normalmagic_flag = 0;
+                blewcount |= 0x10000;
+                break;
+            case ALL_RESURRECTION:
+            case PR_TURNUNDEAD:    // 攻撃リザレクションとターンアンデッド
+                if (target->type != BL_PC
+                    && battle_check_undead (t_race, t_ele))
+                {
+                    int  hp, mhp, thres;
+                    hp = battle_get_hp (target);
+                    mhp = battle_get_max_hp (target);
+                    thres = (skill_lv * 20) + battle_get_luk (bl) +
+                        battle_get_int (bl) + battle_get_lv (bl) +
+                        ((200 - hp * 200 / mhp));
+                    if (thres > 700)
+                        thres = 700;
+//              if(battle_config.battle_log)
+//                  printf("ターンアンデッド! 確率%d ‰(千分率)\n", thres);
+                    if (MRAND (1000) < thres && !(t_mode & 0x20))   // 成功
+                        damage = hp;
+                    else        // 失敗
+                        damage =
+                            battle_get_lv (bl) + battle_get_int (bl) +
+                            skill_lv * 10;
+                }
+                normalmagic_flag = 0;
+                break;
+
+            case MG_NAPALMBEAT:    // ナパームビート(分散計算込み)
+                MATK_FIX (70 + skill_lv * 10, 100);
+                if (flag > 0)
+                {
+                    MATK_FIX (1, flag);
+                }
+                else
+                {
+                    if (battle_config.error_log)
+                        printf
+                            ("battle_calc_magic_attack(): napam enemy count=0 !\n");
+                }
+                break;
+            case MG_FIREBALL:  // ファイヤーボール
+            {
+                const int drate[] = { 100, 90, 70 };
+                if (flag > 2)
+                    matk1 = matk2 = 0;
+                else
+                    MATK_FIX ((95 + skill_lv * 5) * drate[flag], 10000);
+            }
+                break;
+            case MG_FIREWALL:  // ファイヤーウォール
+/*
+			if( (t_ele!=3 && !battle_check_undead(t_race,t_ele)) || target->type==BL_PC ) //PCは火属性でも飛ぶ?そもそもダメージ受ける?
+				blewcount |= 0x10000;
+			else
+				blewcount = 0;
+*/
+                if ((t_ele == 3 || battle_check_undead (t_race, t_ele))
+                    && target->type != BL_PC)
+                    blewcount = 0;
+                else
+                    blewcount |= 0x10000;
+                MATK_FIX (1, 2);
+                break;
+            case MG_THUNDERSTORM:  // サンダーストーム
+                MATK_FIX (80, 100);
+                break;
+            case MG_FROSTDIVER:    // フロストダイバ
+                MATK_FIX (100 + skill_lv * 10, 100);
+                break;
+            case WZ_FROSTNOVA: // フロストダイバ
+                MATK_FIX (((100 + skill_lv * 10) * (2 / 3)), 100);
+                break;
+            case WZ_FIREPILLAR:    // ファイヤーピラー
+                if (mdef1 < 1000000)
+                    mdef1 = mdef2 = 0;  // MDEF無視
+                MATK_FIX (1, 5);
+                matk1 += 50;
+                matk2 += 50;
+                break;
+            case WZ_SIGHTRASHER:
+                MATK_FIX (100 + skill_lv * 20, 100);
+                break;
+            case WZ_METEOR:
+            case WZ_JUPITEL:   // ユピテルサンダー
+                break;
+            case WZ_VERMILION: // ロードオブバーミリオン
+                MATK_FIX (skill_lv * 20 + 80, 100);
+                break;
+            case WZ_WATERBALL: // ウォーターボール
+                matk1 += skill_lv * 30;
+                matk2 += skill_lv * 30;
+                break;
+            case WZ_STORMGUST: // ストームガスト
+                MATK_FIX (skill_lv * 40 + 100, 100);
+                blewcount |= 0x10000;
+                break;
+            case AL_HOLYLIGHT: // ホーリーライト
+                MATK_FIX (125, 100);
+                break;
+            case AL_RUWACH:
+                MATK_FIX (145, 100);
+                break;
+            case HW_NAPALMVULCAN:  // ナパームビート(分散計算込み)
+                MATK_FIX (70 + skill_lv * 10, 100);
+                if (flag > 0)
+                {
+                    MATK_FIX (1, flag);
+                }
+                else
+                {
+                    if (battle_config.error_log)
+                        printf
+                            ("battle_calc_magic_attack(): napalmvulcan enemy count=0 !\n");
+                }
+                break;
+        }
+    }
+
+    if (normalmagic_flag)
+    {                           // 一般魔法ダメージ計算
+        int  imdef_flag = 0;
+        if (matk1 > matk2)
+            damage = matk2 + MRAND ((matk1 - matk2 + 1));
+        else
+            damage = matk2;
+        if (sd)
+        {
+            if (sd->ignore_mdef_ele & (1 << t_ele)
+                || sd->ignore_mdef_race & (1 << t_race))
+                imdef_flag = 1;
+            if (t_mode & 0x20)
+            {
+                if (sd->ignore_mdef_race & (1 << 10))
+                    imdef_flag = 1;
+            }
+            else
+            {
+                if (sd->ignore_mdef_race & (1 << 11))
+                    imdef_flag = 1;
+            }
+        }
+        if (!imdef_flag)
+        {
+            if (battle_config.magic_defense_type)
+            {
+                damage =
+                    damage - (mdef1 * battle_config.magic_defense_type) -
+                    mdef2;
+            }
+            else
+            {
+                damage = (damage * (100 - mdef1)) / 100 - mdef2;
+            }
+        }
+
+        if (damage < 1)
+            damage = 1;
+    }
+
+    if (sd)
+    {
+        cardfix = 100;
+        cardfix = cardfix * (100 + sd->magic_addrace[t_race]) / 100;
+        cardfix = cardfix * (100 + sd->magic_addele[t_ele]) / 100;
+        if (t_mode & 0x20)
+            cardfix = cardfix * (100 + sd->magic_addrace[10]) / 100;
+        else
+            cardfix = cardfix * (100 + sd->magic_addrace[11]) / 100;
+        t_class = battle_get_class (target);
+        for (i = 0; i < sd->add_magic_damage_class_count; i++)
+        {
+            if (sd->add_magic_damage_classid[i] == t_class)
+            {
+                cardfix =
+                    cardfix * (100 + sd->add_magic_damage_classrate[i]) / 100;
+                break;
+            }
+        }
+        damage = damage * cardfix / 100;
+    }
+
+    if (tsd)
+    {
+        int  s_class = battle_get_class (bl);
+        cardfix = 100;
+        cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // 属 性によるダメージ耐性
+        cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // 種族によるダメージ耐性
+        cardfix = cardfix * (100 - tsd->magic_subrace[race]) / 100;
+        if (battle_get_mode (bl) & 0x20)
+            cardfix = cardfix * (100 - tsd->magic_subrace[10]) / 100;
+        else
+            cardfix = cardfix * (100 - tsd->magic_subrace[11]) / 100;
+        for (i = 0; i < tsd->add_mdef_class_count; i++)
+        {
+            if (tsd->add_mdef_classid[i] == s_class)
+            {
+                cardfix = cardfix * (100 - tsd->add_mdef_classrate[i]) / 100;
+                break;
+            }
+        }
+        cardfix = cardfix * (100 - tsd->magic_def_rate) / 100;
+        damage = damage * cardfix / 100;
+    }
+    if (damage < 0)
+        damage = 0;
+
+    damage = battle_attr_fix (damage, ele, battle_get_element (target));    // 属 性修正
+
+    if (skill_num == CR_GRANDCROSS)
+    {                           // グランドクロス
+        struct Damage wd;
+        wd = battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
+                                        flag);
+        damage = (damage + wd.damage) * (100 + 40 * skill_lv) / 100;
+        if (battle_config.gx_dupele)
+            damage = battle_attr_fix (damage, ele, battle_get_element (target));    //属性2回かかる
+        if (bl == target)
+            damage = damage / 2;    //反動は半分
+    }
+
+    div_ = skill_get_num (skill_num, skill_lv);
+
+    if (div_ > 1 && skill_num != WZ_VERMILION)
+        damage *= div_;
+
+//  if(mdef1 >= 1000000 && damage > 0)
+    if (t_mode & 0x40 && damage > 0)
+        damage = 1;
+
+    if (tsd && tsd->special_state.no_magic_damage)
+    {
+        if (battle_config.gtb_pvp_only != 0)
+        {                       // [MouseJstr]
+            if ((map[target->m].flag.pvp || map[target->m].flag.gvg)
+                && target->type == BL_PC)
+                damage = (damage * (100 - battle_config.gtb_pvp_only)) / 100;
+        }
+        else
+            damage = 0;         // 黄 金蟲カード(魔法ダメージ0)
+    }
+
+    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // 最終修正
+
+    /* magic_damage_return by [AppleGirl] and [Valaris]     */
+    if (target->type == BL_PC && tsd && tsd->magic_damage_return > 0)
+    {
+        rdamage += damage * tsd->magic_damage_return / 100;
+        if (rdamage < 1)
+            rdamage = 1;
+        clif_damage (target, bl, gettick (), 0, 0, rdamage, 0, 0, 0);
+        battle_damage (target, bl, rdamage, 0);
+    }
+    /*          end magic_damage_return         */
+
+    md.damage = damage;
+    md.div_ = div_;
+    md.amotion = battle_get_amotion (bl);
+    md.dmotion = battle_get_dmotion (target);
+    md.damage2 = 0;
+    md.type = 0;
+    md.blewcount = blewcount;
+    md.flag = aflag;
+
+    return md;
+}
+
+/*==========================================
+ * その他ダメージ計算
+ *------------------------------------------
+ */
+struct Damage battle_calc_misc_attack (struct block_list *bl,
+                                       struct block_list *target,
+                                       int skill_num, int skill_lv, int flag)
+{
+    int  int_ = battle_get_int (bl);
+//  int luk=battle_get_luk(bl);
+    int  dex = battle_get_dex (bl);
+    int  skill, ele, race, cardfix;
+    struct map_session_data *sd = NULL, *tsd = NULL;
+    int  damage = 0, div_ = 1, blewcount =
+        skill_get_blewcount (skill_num, skill_lv);
+    struct Damage md;
+    int  damagefix = 1;
+
+    int  aflag = BF_MISC | BF_LONG | BF_SKILL;
+
+    //return前の処理があるので情報出力部のみ変更
+    if (bl == NULL || target == NULL)
+    {
+        nullpo_info (NLP_MARK);
+        memset (&md, 0, sizeof (md));
+        return md;
+    }
+
+    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
+    {
+        sd->state.attack_type = BF_MISC;
+        sd->state.arrow_atk = 0;
+    }
+
+    if (target->type == BL_PC)
+        tsd = (struct map_session_data *) target;
+
+    switch (skill_num)
+    {
+
+        case HT_LANDMINE:      // ランドマイン
+            damage = skill_lv * (dex + 75) * (100 + int_) / 100;
+            break;
+
+        case HT_BLASTMINE:     // ブラストマイン
+            damage = skill_lv * (dex / 2 + 50) * (100 + int_) / 100;
+            break;
+
+        case HT_CLAYMORETRAP:  // クレイモアートラップ
+            damage = skill_lv * (dex / 2 + 75) * (100 + int_) / 100;
+            break;
+
+        case HT_BLITZBEAT:     // ブリッツビート
+            if (sd == NULL || (skill = pc_checkskill (sd, HT_STEELCROW)) <= 0)
+                skill = 0;
+            damage = (dex / 10 + int_ / 2 + skill * 3 + 40) * 2;
+            if (flag > 1)
+                damage /= flag;
+            break;
+
+        case TF_THROWSTONE:    // 石投げ
+            damage = 30;
+            damagefix = 0;
+            break;
+
+        case BA_DISSONANCE:    // 不協和音
+            damage =
+                (skill_lv) * 20 + pc_checkskill (sd, BA_MUSICALLESSON) * 3;
+            break;
+
+        case NPC_SELFDESTRUCTION:  // 自爆
+            damage = battle_get_hp (bl) - (bl == target ? 1 : 0);
+            damagefix = 0;
+            break;
+
+        case NPC_SMOKING:      // タバコを吸う
+            damage = 3;
+            damagefix = 0;
+            break;
+
+        case NPC_DARKBREATH:
+        {
+            struct status_change *sc_data = battle_get_sc_data (target);
+            int  hitrate =
+                battle_get_hit (bl) - battle_get_flee (target) + 80;
+            hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
+            if (sc_data
+                && (sc_data[SC_SLEEP].timer != -1
+                    || sc_data[SC_STAN].timer != -1
+                    || sc_data[SC_FREEZE].timer != -1
+                    || (sc_data[SC_STONE].timer != -1
+                        && sc_data[SC_STONE].val2 == 0)))
+                hitrate = 1000000;
+            if (MRAND (100) < hitrate)
+            {
+                damage = 500 + (skill_lv - 1) * 1000 + MRAND (1000);
+                if (damage > 9999)
+                    damage = 9999;
+            }
+        }
+            break;
+        case SN_FALCONASSAULT: /* ファルコンアサルト */
+            skill = pc_checkskill (sd, HT_BLITZBEAT);
+            damage =
+                (100 + 50 * skill_lv +
+                 (dex / 10 + int_ / 2 + skill * 3 + 40) * 2);
+            break;
+    }
+
+    ele = skill_get_pl (skill_num);
+    race = battle_get_race (bl);
+
+    if (damagefix)
+    {
+        if (damage < 1 && skill_num != NPC_DARKBREATH)
+            damage = 1;
+
+        if (tsd)
+        {
+            cardfix = 100;
+            cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // 属性によるダメージ耐性
+            cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // 種族によるダメージ耐性
+            cardfix = cardfix * (100 - tsd->misc_def_rate) / 100;
+            damage = damage * cardfix / 100;
+        }
+        if (damage < 0)
+            damage = 0;
+        damage = battle_attr_fix (damage, ele, battle_get_element (target));    // 属性修正
+    }
+
+    div_ = skill_get_num (skill_num, skill_lv);
+    if (div_ > 1)
+        damage *= div_;
+
+    if (damage > 0
+        && (damage < div_
+            || (battle_get_def (target) >= 1000000
+                && battle_get_mdef (target) >= 1000000)))
+    {
+        damage = div_;
+    }
+
+    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // 最終修正
+
+    md.damage = damage;
+    md.div_ = div_;
+    md.amotion = battle_get_amotion (bl);
+    md.dmotion = battle_get_dmotion (target);
+    md.damage2 = 0;
+    md.type = 0;
+    md.blewcount = blewcount;
+    md.flag = aflag;
+    return md;
+
+}
+
+/*==========================================
+ * ダメージ計算一括処理用
+ *------------------------------------------
+ */
+struct Damage battle_calc_attack (int attack_type,
+                                  struct block_list *bl,
+                                  struct block_list *target, int skill_num,
+                                  int skill_lv, int flag)
+{
+    struct Damage d;
+    memset (&d, 0, sizeof (d));
+
+    switch (attack_type)
+    {
+        case BF_WEAPON:
+            return battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
+                                              flag);
+        case BF_MAGIC:
+            return battle_calc_magic_attack (bl, target, skill_num, skill_lv,
+                                             flag);
+        case BF_MISC:
+            return battle_calc_misc_attack (bl, target, skill_num, skill_lv,
+                                            flag);
+        default:
+            if (battle_config.error_log)
+                printf ("battle_calc_attack: unknwon attack type ! %d\n",
+                        attack_type);
+            break;
+    }
+    return d;
+}
+
+/*==========================================
+ * 通常攻撃処理まとめ
+ *------------------------------------------
+ */
+int battle_weapon_attack (struct block_list *src, struct block_list *target,
+                          unsigned int tick, int flag)
+{
+    struct map_session_data *sd = NULL;
+    struct status_change *sc_data = battle_get_sc_data (src), *t_sc_data =
+        battle_get_sc_data (target);
+    short *opt1;
+    int  race = 7, ele = 0;
+    int  damage, rdamage = 0;
+    struct Damage wd;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, target);
+
+    if (src->type == BL_PC)
+        sd = (struct map_session_data *) src;
+
+    if (src->prev == NULL || target->prev == NULL)
+        return 0;
+    if (src->type == BL_PC && pc_isdead (sd))
+        return 0;
+    if (target->type == BL_PC
+        && pc_isdead ((struct map_session_data *) target))
+        return 0;
+
+    opt1 = battle_get_opt1 (src);
+    if (opt1 && *opt1 > 0)
+    {
+        battle_stopattack (src);
+        return 0;
+    }
+    if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+    {
+        battle_stopattack (src);
+        return 0;
+    }
+
+    race = battle_get_race (target);
+    ele = battle_get_elem_type (target);
+    if (battle_check_target (src, target, BCT_ENEMY) > 0 &&
+        battle_check_range (src, target, 0))
+    {
+        // 攻撃対象となりうるので攻撃
+        if (sd && sd->status.weapon == 11)
+        {
+            if (sd->equip_index[10] >= 0)
+            {
+                if (battle_config.arrow_decrement)
+                    pc_delitem (sd, sd->equip_index[10], 1, 0);
+            }
+            else
+            {
+                clif_arrow_fail (sd, 0);
+                return 0;
+            }
+        }
+        if (flag & 0x8000)
+        {
+            if (sd && battle_config.pc_attack_direction_change)
+                sd->dir = sd->head_dir =
+                    map_calc_dir (src, target->x, target->y);
+            else if (src->type == BL_MOB
+                     && battle_config.monster_attack_direction_change)
+                ((struct mob_data *) src)->dir =
+                    map_calc_dir (src, target->x, target->y);
+            wd = battle_calc_weapon_attack (src, target, KN_AUTOCOUNTER,
+                                            flag & 0xff, 0);
+        }
+        else
+            wd = battle_calc_weapon_attack (src, target, 0, 0, 0);
+
+        // significantly increase injuries for hasted characters
+        if (wd.damage > 0 && (t_sc_data[SC_HASTE].timer != -1))
+        {
+            wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4;
+        }
+
+        if (wd.damage > 0
+            && t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC)
+        {
+            int  reduction = t_sc_data[SC_PHYS_SHIELD].val1;
+            if (reduction > wd.damage)
+                reduction = wd.damage;
+
+            wd.damage -= reduction;
+            MAP_LOG_PC (((struct map_session_data *) target),
+                        "MAGIC-ABSORB-DMG %d", reduction);
+        }
+
+        if ((damage = wd.damage + wd.damage2) > 0 && src != target)
+        {
+            if (wd.flag & BF_SHORT)
+            {
+                if (target->type == BL_PC)
+                {
+                    struct map_session_data *tsd =
+                        (struct map_session_data *) target;
+                    if (tsd && tsd->short_weapon_damage_return > 0)
+                    {
+                        rdamage +=
+                            damage * tsd->short_weapon_damage_return / 100;
+                        if (rdamage < 1)
+                            rdamage = 1;
+                    }
+                }
+                if (t_sc_data && t_sc_data[SC_REFLECTSHIELD].timer != -1)
+                {
+                    rdamage +=
+                        damage * t_sc_data[SC_REFLECTSHIELD].val2 / 100;
+                    if (rdamage < 1)
+                        rdamage = 1;
+                }
+            }
+            else if (wd.flag & BF_LONG)
+            {
+                if (target->type == BL_PC)
+                {
+                    struct map_session_data *tsd =
+                        (struct map_session_data *) target;
+                    if (tsd && tsd->long_weapon_damage_return > 0)
+                    {
+                        rdamage +=
+                            damage * tsd->long_weapon_damage_return / 100;
+                        if (rdamage < 1)
+                            rdamage = 1;
+                    }
+                }
+            }
+
+            if (rdamage > 0)
+                clif_damage (src, src, tick, wd.amotion, 0, rdamage, 1, 4, 0);
+        }
+
+        if (wd.div_ == 255 && sd)
+        {                       //三段掌
+            int  delay =
+                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
+            int  skilllv;
+            if (wd.damage + wd.damage2 < battle_get_hp (target))
+            {
+                if ((skilllv = pc_checkskill (sd, MO_CHAINCOMBO)) > 0)
+                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
+
+                skill_status_change_start (src, SC_COMBO, MO_TRIPLEATTACK,
+                                           skilllv, 0, 0, delay, 0);
+            }
+            sd->attackabletime = sd->canmove_tick = tick + delay;
+            clif_combo_delay (src, delay);
+            clif_skill_damage (src, target, tick, wd.amotion, wd.dmotion,
+                               wd.damage, 3, MO_TRIPLEATTACK,
+                               pc_checkskill (sd, MO_TRIPLEATTACK), -1);
+        }
+        else
+        {
+            clif_damage (src, target, tick, wd.amotion, wd.dmotion,
+                         wd.damage, wd.div_, wd.type, wd.damage2);
+            //二刀流左手とカタール追撃のミス表示(無理やり〜)
+            if (sd && sd->status.weapon >= 16 && wd.damage2 == 0)
+                clif_damage (src, target, tick + 10, wd.amotion, wd.dmotion,
+                             0, 1, 0, 0);
+        }
+        if (sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0))
+            skill_castend_damage_id (src, target, 0, -1, tick, 0);
+        map_freeblock_lock ();
+
+        if (src->type == BL_PC)
+        {
+            int  weapon_index = sd->equip_index[9];
+            int  weapon = 0;
+            if (sd->inventory_data[weapon_index]
+                && sd->status.inventory[weapon_index].equip & 0x2)
+                weapon = sd->inventory_data[weapon_index]->nameid;
+
+            MAP_LOG ("PC%d %d:%d,%d WPNDMG %s%d %d FOR %d WPN %d",
+                     sd->status.char_id, src->m, src->x, src->y,
+                     (target->type == BL_PC) ? "PC" : "MOB",
+                     (target->type ==
+                      BL_PC) ? ((struct map_session_data *) target)->
+                     status.char_id : target->id,
+                     (target->type ==
+                      BL_PC) ? 0 : ((struct mob_data *) target)->mob_class,
+                     wd.damage + wd.damage2, weapon);
+        }
+
+        if (target->type == BL_PC)
+        {
+            struct map_session_data *sd2 = (struct map_session_data *) target;
+            MAP_LOG ("PC%d %d:%d,%d WPNINJURY %s%d %d FOR %d",
+                     sd2->status.char_id, target->m, target->x, target->y,
+                     (src->type == BL_PC) ? "PC" : "MOB",
+                     (src->type ==
+                      BL_PC) ? ((struct map_session_data *) src)->
+                     status.char_id : src->id,
+                     (src->type ==
+                      BL_PC) ? 0 : ((struct mob_data *) src)->mob_class,
+                     wd.damage + wd.damage2);
+        }
+
+        battle_damage (src, target, (wd.damage + wd.damage2), 0);
+        if (target->prev != NULL &&
+            (target->type != BL_PC
+             || (target->type == BL_PC
+                 && !pc_isdead ((struct map_session_data *) target))))
+        {
+            if (wd.damage > 0 || wd.damage2 > 0)
+            {
+                skill_additional_effect (src, target, 0, 0, BF_WEAPON, tick);
+                if (sd)
+                {
+                    if (sd->weapon_coma_ele[ele] > 0
+                        && MRAND (10000) < sd->weapon_coma_ele[ele])
+                        battle_damage (src, target,
+                                       battle_get_max_hp (target), 1);
+                    if (sd->weapon_coma_race[race] > 0
+                        && MRAND (10000) < sd->weapon_coma_race[race])
+                        battle_damage (src, target,
+                                       battle_get_max_hp (target), 1);
+                    if (battle_get_mode (target) & 0x20)
+                    {
+                        if (sd->weapon_coma_race[10] > 0
+                            && MRAND (10000) < sd->weapon_coma_race[10])
+                            battle_damage (src, target,
+                                           battle_get_max_hp (target), 1);
+                    }
+                    else
+                    {
+                        if (sd->weapon_coma_race[11] > 0
+                            && MRAND (10000) < sd->weapon_coma_race[11])
+                            battle_damage (src, target,
+                                           battle_get_max_hp (target), 1);
+                    }
+                }
+            }
+        }
+        if (sc_data && sc_data[SC_AUTOSPELL].timer != -1
+            && MRAND (100) < sc_data[SC_AUTOSPELL].val4)
+        {
+            int  skilllv = sc_data[SC_AUTOSPELL].val3, i, f = 0;
+            i = MRAND (100);
+            if (i >= 50)
+                skilllv -= 2;
+            else if (i >= 15)
+                skilllv--;
+            if (skilllv < 1)
+                skilllv = 1;
+            if (sd)
+            {
+                int  sp = skill_get_sp (sc_data[SC_AUTOSPELL].val2,
+                                        skilllv) * 2 / 3;
+                if (sd->status.sp >= sp)
+                {
+                    if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
+                        || i == 32)
+                        f = skill_castend_pos2 (src, target->x, target->y,
+                                                sc_data[SC_AUTOSPELL].val2,
+                                                skilllv, tick, flag);
+                    else
+                    {
+                        switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
+                        {
+                            case 0:
+                            case 2:
+                                f = skill_castend_damage_id (src, target,
+                                                             sc_data
+                                                             [SC_AUTOSPELL].val2,
+                                                             skilllv, tick,
+                                                             flag);
+                                break;
+                            case 1:    /* 支援系 */
+                                if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
+                                     || (sc_data[SC_AUTOSPELL].val2 ==
+                                         ALL_RESURRECTION
+                                         && target->type != BL_PC))
+                                    && battle_check_undead (race, ele))
+                                    f = skill_castend_damage_id (src, target,
+                                                                 sc_data
+                                                                 [SC_AUTOSPELL].val2,
+                                                                 skilllv,
+                                                                 tick, flag);
+                                else
+                                    f = skill_castend_nodamage_id (src,
+                                                                   target,
+                                                                   sc_data
+                                                                   [SC_AUTOSPELL].val2,
+                                                                   skilllv,
+                                                                   tick,
+                                                                   flag);
+                                break;
+                        }
+                    }
+                    if (!f)
+                        pc_heal (sd, 0, -sp);
+                }
+            }
+            else
+            {
+                if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
+                    || i == 32)
+                    skill_castend_pos2 (src, target->x, target->y,
+                                        sc_data[SC_AUTOSPELL].val2, skilllv,
+                                        tick, flag);
+                else
+                {
+                    switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
+                    {
+                        case 0:
+                        case 2:
+                            skill_castend_damage_id (src, target,
+                                                     sc_data
+                                                     [SC_AUTOSPELL].val2,
+                                                     skilllv, tick, flag);
+                            break;
+                        case 1:    /* 支援系 */
+                            if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
+                                 || (sc_data[SC_AUTOSPELL].val2 ==
+                                     ALL_RESURRECTION
+                                     && target->type != BL_PC))
+                                && battle_check_undead (race, ele))
+                                skill_castend_damage_id (src, target,
+                                                         sc_data
+                                                         [SC_AUTOSPELL].val2,
+                                                         skilllv, tick, flag);
+                            else
+                                skill_castend_nodamage_id (src, target,
+                                                           sc_data
+                                                           [SC_AUTOSPELL].val2,
+                                                           skilllv, tick,
+                                                           flag);
+                            break;
+                    }
+                }
+            }
+        }
+        if (sd)
+        {
+            if (sd->autospell_id > 0 && sd->autospell_lv > 0
+                && MRAND (100) < sd->autospell_rate)
+            {
+                int  skilllv = sd->autospell_lv, i, f = 0, sp;
+                i = MRAND (100);
+                if (i >= 50)
+                    skilllv -= 2;
+                else if (i >= 15)
+                    skilllv--;
+                if (skilllv < 1)
+                    skilllv = 1;
+                sp = skill_get_sp (sd->autospell_id, skilllv) * 2 / 3;
+                if (sd->status.sp >= sp)
+                {
+                    if ((i = skill_get_inf (sd->autospell_id) == 2)
+                        || i == 32)
+                        f = skill_castend_pos2 (src, target->x, target->y,
+                                                sd->autospell_id, skilllv,
+                                                tick, flag);
+                    else
+                    {
+                        switch (skill_get_nk (sd->autospell_id))
+                        {
+                            case 0:
+                            case 2:
+                                f = skill_castend_damage_id (src, target,
+                                                             sd->autospell_id,
+                                                             skilllv, tick,
+                                                             flag);
+                                break;
+                            case 1:    /* 支援系 */
+                                if ((sd->autospell_id == AL_HEAL
+                                     || (sd->autospell_id == ALL_RESURRECTION
+                                         && target->type != BL_PC))
+                                    && battle_check_undead (race, ele))
+                                    f = skill_castend_damage_id (src, target,
+                                                                 sd->autospell_id,
+                                                                 skilllv,
+                                                                 tick, flag);
+                                else
+                                    f = skill_castend_nodamage_id (src,
+                                                                   target,
+                                                                   sd->autospell_id,
+                                                                   skilllv,
+                                                                   tick,
+                                                                   flag);
+                                break;
+                        }
+                    }
+                    if (!f)
+                        pc_heal (sd, 0, -sp);
+                }
+            }
+            if (wd.flag & BF_WEAPON && src != target
+                && (wd.damage > 0 || wd.damage2 > 0))
+            {
+                int  hp = 0, sp = 0;
+                if (sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0
+                    && MRAND (100) < sd->hp_drain_rate)
+                {
+                    hp += (wd.damage * sd->hp_drain_per) / 100;
+                    if (sd->hp_drain_rate > 0 && hp < 1)
+                        hp = 1;
+                    else if (sd->hp_drain_rate < 0 && hp > -1)
+                        hp = -1;
+                }
+                if (sd->hp_drain_rate_ && sd->hp_drain_per_ > 0
+                    && wd.damage2 > 0 && MRAND (100) < sd->hp_drain_rate_)
+                {
+                    hp += (wd.damage2 * sd->hp_drain_per_) / 100;
+                    if (sd->hp_drain_rate_ > 0 && hp < 1)
+                        hp = 1;
+                    else if (sd->hp_drain_rate_ < 0 && hp > -1)
+                        hp = -1;
+                }
+                if (sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0
+                    && MRAND (100) < sd->sp_drain_rate)
+                {
+                    sp += (wd.damage * sd->sp_drain_per) / 100;
+                    if (sd->sp_drain_rate > 0 && sp < 1)
+                        sp = 1;
+                    else if (sd->sp_drain_rate < 0 && sp > -1)
+                        sp = -1;
+                }
+                if (sd->sp_drain_rate_ && sd->sp_drain_per_ > 0
+                    && wd.damage2 > 0 && MRAND (100) < sd->sp_drain_rate_)
+                {
+                    sp += (wd.damage2 * sd->sp_drain_per_) / 100;
+                    if (sd->sp_drain_rate_ > 0 && sp < 1)
+                        sp = 1;
+                    else if (sd->sp_drain_rate_ < 0 && sp > -1)
+                        sp = -1;
+                }
+                if (hp || sp)
+                    pc_heal (sd, hp, sp);
+            }
+        }
+
+        if (rdamage > 0)
+            battle_damage (target, src, rdamage, 0);
+        if (t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1
+            && t_sc_data[SC_AUTOCOUNTER].val4 > 0)
+        {
+            if (t_sc_data[SC_AUTOCOUNTER].val3 == src->id)
+                battle_weapon_attack (target, src, tick,
+                                      0x8000 |
+                                      t_sc_data[SC_AUTOCOUNTER].val1);
+            skill_status_change_end (target, SC_AUTOCOUNTER, -1);
+        }
+        if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1)
+        {
+            int  lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
+            skill_status_change_end (target, SC_BLADESTOP_WAIT, -1);
+            skill_status_change_start (src, SC_BLADESTOP, lv, 1, (int) src,
+                                       (int) target,
+                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
+            skill_status_change_start (target, SC_BLADESTOP, lv, 2,
+                                       (int) target, (int) src,
+                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
+        }
+        if (t_sc_data && t_sc_data[SC_SPLASHER].timer != -1)    //殴ったので対象のベナムスプラッシャー状態を解除
+            skill_status_change_end (target, SC_SPLASHER, -1);
+
+        map_freeblock_unlock ();
+    }
+    return wd.dmg_lv;
+}
+
+int battle_check_undead (int race, int element)
+{
+    if (battle_config.undead_detect_type == 0)
+    {
+        if (element == 9)
+            return 1;
+    }
+    else if (battle_config.undead_detect_type == 1)
+    {
+        if (race == 1)
+            return 1;
+    }
+    else
+    {
+        if (element == 9 || race == 1)
+            return 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 敵味方判定(1=肯定,0=否定,-1=エラー)
+ * flag&0xf0000 = 0x00000:敵じゃないか判定(ret:1=敵ではない)
+ *				= 0x10000:パーティー判定(ret:1=パーティーメンバ)
+ *				= 0x20000:全て(ret:1=敵味方両方)
+ *				= 0x40000:敵か判定(ret:1=敵)
+ *				= 0x50000:パーティーじゃないか判定(ret:1=パーティでない)
+ *------------------------------------------
+ */
+int battle_check_target (struct block_list *src, struct block_list *target,
+                         int flag)
+{
+    int  s_p, s_g, t_p, t_g;
+    struct block_list *ss = src;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, target);
+
+    if (flag & 0x40000)
+    {                           // 反転フラグ
+        int  ret = battle_check_target (src, target, flag & 0x30000);
+        if (ret != -1)
+            return !ret;
+        return -1;
+    }
+
+    if (flag & 0x20000)
+    {
+        if (target->type == BL_MOB || target->type == BL_PC)
+            return 1;
+        else
+            return -1;
+    }
+
+    if (src->type == BL_SKILL && target->type == BL_SKILL)  // 対象がスキルユニットなら無条件肯定
+        return -1;
+
+    if (target->type == BL_PC
+        && ((struct map_session_data *) target)->invincible_timer != -1)
+        return -1;
+
+    if (target->type == BL_SKILL)
+    {
+        switch (((struct skill_unit *) target)->group->unit_id)
+        {
+            case 0x8d:
+            case 0x8f:
+            case 0x98:
+                return 0;
+                break;
+        }
+    }
+
+    // スキルユニットの場合、親を求める
+    if (src->type == BL_SKILL)
+    {
+        int  inf2 =
+            skill_get_inf2 (((struct skill_unit *) src)->group->skill_id);
+        if ((ss =
+             map_id2bl (((struct skill_unit *) src)->group->src_id)) == NULL)
+            return -1;
+        if (ss->prev == NULL)
+            return -1;
+        if (inf2 & 0x80 && (map[src->m].flag.pvp || pc_iskiller ((struct map_session_data *) src, (struct map_session_data *) target)) &&   // [MouseJstr]
+            !(target->type == BL_PC
+              && pc_isinvisible ((struct map_session_data *) target)))
+            return 0;
+        if (ss == target)
+        {
+            if (inf2 & 0x100)
+                return 0;
+            if (inf2 & 0x200)
+                return -1;
+        }
+    }
+    // Mobでmaster_idがあってspecial_mob_aiなら、召喚主を求める
+    if (src->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) src;
+        if (md && md->master_id > 0)
+        {
+            if (md->master_id == target->id)    // 主なら肯定
+                return 1;
+            if (md->state.special_mob_ai)
+            {
+                if (target->type == BL_MOB)
+                {               //special_mob_aiで対象がMob
+                    struct mob_data *tmd = (struct mob_data *) target;
+                    if (tmd)
+                    {
+                        if (tmd->master_id != md->master_id)    //召喚主が一緒でなければ否定
+                            return 0;
+                        else
+                        {       //召喚主が一緒なので肯定したいけど自爆は否定
+                            if (md->state.special_mob_ai > 2)
+                                return 0;
+                            else
+                                return 1;
+                        }
+                    }
+                }
+            }
+            if ((ss = map_id2bl (md->master_id)) == NULL)
+                return -1;
+        }
+    }
+
+    if (src == target || ss == target)  // 同じなら肯定
+        return 1;
+
+    if (target->type == BL_PC
+        && pc_isinvisible ((struct map_session_data *) target))
+        return -1;
+
+    if (src->prev == NULL ||    // 死んでるならエラー
+        (src->type == BL_PC && pc_isdead ((struct map_session_data *) src)))
+        return -1;
+
+    if ((ss->type == BL_PC && target->type == BL_MOB) ||
+        (ss->type == BL_MOB && target->type == BL_PC))
+        return 0;               // PCvsMOBなら否定
+
+    s_p = battle_get_party_id (ss);
+    s_g = battle_get_guild_id (ss);
+
+    t_p = battle_get_party_id (target);
+    t_g = battle_get_guild_id (target);
+
+    if (flag & 0x10000)
+    {
+        if (s_p && t_p && s_p == t_p)   // 同じパーティなら肯定(味方)
+            return 1;
+        else                    // パーティ検索なら同じパーティじゃない時点で否定
+            return 0;
+    }
+
+    if (ss->type == BL_MOB && s_g > 0 && t_g > 0 && s_g == t_g) // 同じギルド/mobクラスなら肯定(味方)
+        return 1;
+
+//printf("ss:%d src:%d target:%d flag:0x%x %d %d ",ss->id,src->id,target->id,flag,src->type,target->type);
+//printf("p:%d %d g:%d %d\n",s_p,t_p,s_g,t_g);
+
+    if (ss->type == BL_PC && target->type == BL_PC)
+    {                           // 両方PVPモードなら否定(敵)
+        struct skill_unit *su = NULL;
+        if (src->type == BL_SKILL)
+            su = (struct skill_unit *) src;
+        if (map[ss->m].flag.pvp
+            || pc_iskiller ((struct map_session_data *) ss,
+                            (struct map_session_data *) target))
+        {                       // [MouseJstr]
+            if (su && su->group->target_flag == BCT_NOENEMY)
+                return 1;
+            else if (battle_config.pk_mode
+                     && (((struct map_session_data *) ss)->status.pc_class == 0
+                         || ((struct map_session_data *) target)->
+                         status.pc_class == 0))
+                return 1;       // prevent novice engagement in pk_mode [Valaris]
+            else if (map[ss->m].flag.pvp_noparty && s_p > 0 && t_p > 0
+                     && s_p == t_p)
+                return 1;
+            else if (map[ss->m].flag.pvp_noguild && s_g > 0 && t_g > 0
+                     && s_g == t_g)
+                return 1;
+            return 0;
+        }
+        if (map[src->m].flag.gvg)
+        {
+            struct guild *g = NULL;
+            if (su && su->group->target_flag == BCT_NOENEMY)
+                return 1;
+            if (s_g > 0 && s_g == t_g)
+                return 1;
+            if (map[src->m].flag.gvg_noparty && s_p > 0 && t_p > 0
+                && s_p == t_p)
+                return 1;
+            if ((g = guild_search (s_g)))
+            {
+                int  i;
+                for (i = 0; i < MAX_GUILDALLIANCE; i++)
+                {
+                    if (g->alliance[i].guild_id > 0
+                        && g->alliance[i].guild_id == t_g)
+                    {
+                        if (g->alliance[i].opposition)
+                            return 0;   //敵対ギルドなら無条件に敵
+                        else
+                            return 1;   //同盟ギルドなら無条件に味方
+                    }
+                }
+            }
+            return 0;
+        }
+    }
+
+    return 1;                   // 該当しないので無関係人物(まあ敵じゃないので味方)
+}
+
+/*==========================================
+ * 射程判定
+ *------------------------------------------
+ */
+int battle_check_range (struct block_list *src, struct block_list *bl,
+                        int range)
+{
+
+    int  dx, dy;
+    struct walkpath_data wpd;
+    int  arange;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, bl);
+
+    dx = abs (bl->x - src->x);
+    dy = abs (bl->y - src->y);
+    arange = ((dx > dy) ? dx : dy);
+
+    if (src->m != bl->m)        // 違うマップ
+        return 0;
+
+    if (range > 0 && range < arange)    // 遠すぎる
+        return 0;
+
+    if (arange < 2)             // 同じマスか隣接
+        return 1;
+
+//  if(bl->type == BL_SKILL && ((struct skill_unit *)bl)->group->unit_id == 0x8d)
+//      return 1;
+
+    // 障害物判定
+    wpd.path_len = 0;
+    wpd.path_pos = 0;
+    wpd.path_half = 0;
+    if (path_search (&wpd, src->m, src->x, src->y, bl->x, bl->y, 0x10001) !=
+        -1)
+        return 1;
+
+    dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
+    dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
+    return (path_search (&wpd, src->m, src->x + dx, src->y + dy,
+                         bl->x - dx, bl->y - dy, 0x10001) != -1) ? 1 : 0;
+}
+
+/*==========================================
+ * Return numerical value of a switch configuration (modified by [Yor])
+ * on/off, english, fran軋is, deutsch, espal
+ *------------------------------------------
+ */
+int battle_config_switch (const char *str)
+{
+    if (strcasecmp (str, "on") == 0 || strcasecmp (str, "yes") == 0
+        || strcasecmp (str, "oui") == 0 || strcasecmp (str, "ja") == 0
+        || strcasecmp (str, "si") == 0)
+        return 1;
+    if (strcasecmp (str, "off") == 0 || strcasecmp (str, "no") == 0
+        || strcasecmp (str, "non") == 0 || strcasecmp (str, "nein") == 0)
+        return 0;
+    return atoi (str);
+}
+
+/*==========================================
+ * 設定ファイルを読み込む
+ *------------------------------------------
+ */
+int battle_config_read (const char *cfgName)
+{
+    int  i;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+    static int count = 0;
+
+    if ((count++) == 0)
+    {
+        battle_config.warp_point_debug = 0;
+        battle_config.enemy_critical = 0;
+        battle_config.enemy_critical_rate = 100;
+        battle_config.enemy_str = 1;
+        battle_config.enemy_perfect_flee = 0;
+        battle_config.cast_rate = 100;
+        battle_config.delay_rate = 100;
+        battle_config.delay_dependon_dex = 0;
+        battle_config.sdelay_attack_enable = 0;
+        battle_config.left_cardfix_to_right = 0;
+        battle_config.pc_skill_add_range = 0;
+        battle_config.skill_out_range_consume = 1;
+        battle_config.mob_skill_add_range = 0;
+        battle_config.pc_damage_delay = 1;
+        battle_config.pc_damage_delay_rate = 100;
+        battle_config.defnotenemy = 1;
+        battle_config.random_monster_checklv = 1;
+        battle_config.attr_recover = 1;
+        battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
+        battle_config.item_auto_get = 0;
+        battle_config.drop_pickup_safety_zone = 20;
+        battle_config.item_first_get_time = 3000;
+        battle_config.item_second_get_time = 1000;
+        battle_config.item_third_get_time = 1000;
+        battle_config.mvp_item_first_get_time = 10000;
+        battle_config.mvp_item_second_get_time = 10000;
+        battle_config.mvp_item_third_get_time = 2000;
+
+        battle_config.drop_rate0item = 0;
+        battle_config.base_exp_rate = 100;
+        battle_config.job_exp_rate = 100;
+        battle_config.pvp_exp = 1;
+        battle_config.gtb_pvp_only = 0;
+        battle_config.death_penalty_type = 0;
+        battle_config.death_penalty_base = 0;
+        battle_config.death_penalty_job = 0;
+        battle_config.zeny_penalty = 0;
+        battle_config.restart_hp_rate = 0;
+        battle_config.restart_sp_rate = 0;
+        battle_config.mvp_item_rate = 100;
+        battle_config.mvp_exp_rate = 100;
+        battle_config.mvp_hp_rate = 100;
+        battle_config.monster_hp_rate = 100;
+        battle_config.monster_max_aspd = 199;
+        battle_config.atc_gmonly = 0;
+        battle_config.gm_allskill = 0;
+        battle_config.gm_allequip = 0;
+        battle_config.gm_skilluncond = 0;
+        battle_config.guild_max_castles = 0;
+        battle_config.skillfree = 0;
+        battle_config.skillup_limit = 0;
+        battle_config.wp_rate = 100;
+        battle_config.pp_rate = 100;
+        battle_config.monster_active_enable = 1;
+        battle_config.monster_damage_delay_rate = 100;
+        battle_config.monster_loot_type = 0;
+        battle_config.mob_skill_use = 1;
+        battle_config.mob_count_rate = 100;
+        battle_config.quest_skill_learn = 0;
+        battle_config.quest_skill_reset = 1;
+        battle_config.basic_skill_check = 1;
+        battle_config.guild_emperium_check = 1;
+        battle_config.guild_exp_limit = 50;
+        battle_config.pc_invincible_time = 5000;
+        battle_config.skill_min_damage = 0;
+        battle_config.finger_offensive_type = 0;
+        battle_config.heal_exp = 0;
+        battle_config.resurrection_exp = 0;
+        battle_config.shop_exp = 0;
+        battle_config.combo_delay_rate = 100;
+        battle_config.item_check = 1;
+        battle_config.wedding_modifydisplay = 0;
+        battle_config.natural_healhp_interval = 6000;
+        battle_config.natural_healsp_interval = 8000;
+        battle_config.natural_heal_skill_interval = 10000;
+        battle_config.natural_heal_weight_rate = 50;
+        battle_config.itemheal_regeneration_factor = 1;
+        battle_config.item_name_override_grffile = 1;
+        battle_config.arrow_decrement = 1;
+        battle_config.max_aspd = 199;
+        battle_config.max_hp = 32500;
+        battle_config.max_sp = 32500;
+        battle_config.max_lv = 99;  // [MouseJstr]
+        battle_config.max_parameter = 99;
+        battle_config.max_cart_weight = 8000;
+        battle_config.pc_skill_log = 0;
+        battle_config.mob_skill_log = 0;
+        battle_config.battle_log = 0;
+        battle_config.save_log = 0;
+        battle_config.error_log = 1;
+        battle_config.etc_log = 1;
+        battle_config.save_clothcolor = 0;
+        battle_config.undead_detect_type = 0;
+        battle_config.pc_auto_counter_type = 1;
+        battle_config.monster_auto_counter_type = 1;
+        battle_config.agi_penaly_type = 0;
+        battle_config.agi_penaly_count = 3;
+        battle_config.agi_penaly_num = 0;
+        battle_config.agi_penaly_count_lv = ATK_FLEE;
+        battle_config.vit_penaly_type = 0;
+        battle_config.vit_penaly_count = 3;
+        battle_config.vit_penaly_num = 0;
+        battle_config.vit_penaly_count_lv = ATK_DEF;
+        battle_config.player_defense_type = 0;
+        battle_config.monster_defense_type = 0;
+        battle_config.magic_defense_type = 0;
+        battle_config.pc_skill_reiteration = 0;
+        battle_config.monster_skill_reiteration = 0;
+        battle_config.pc_skill_nofootset = 0;
+        battle_config.monster_skill_nofootset = 0;
+        battle_config.pc_cloak_check_type = 0;
+        battle_config.monster_cloak_check_type = 0;
+        battle_config.gvg_short_damage_rate = 100;
+        battle_config.gvg_long_damage_rate = 100;
+        battle_config.gvg_magic_damage_rate = 100;
+        battle_config.gvg_misc_damage_rate = 100;
+        battle_config.gvg_eliminate_time = 7000;
+        battle_config.mob_changetarget_byskill = 0;
+        battle_config.pc_attack_direction_change = 1;
+        battle_config.monster_attack_direction_change = 1;
+        battle_config.pc_undead_nofreeze = 0;
+        battle_config.pc_land_skill_limit = 1;
+        battle_config.monster_land_skill_limit = 1;
+        battle_config.party_skill_penaly = 1;
+        battle_config.monster_class_change_full_recover = 0;
+        battle_config.produce_item_name_input = 1;
+        battle_config.produce_potion_name_input = 1;
+        battle_config.making_arrow_name_input = 1;
+        battle_config.holywater_name_input = 1;
+        battle_config.display_delay_skill_fail = 1;
+        battle_config.chat_warpportal = 0;
+        battle_config.mob_warpportal = 0;
+        battle_config.dead_branch_active = 0;
+        battle_config.show_steal_in_same_party = 0;
+        battle_config.enable_upper_class = 0;
+        battle_config.pc_attack_attr_none = 0;
+        battle_config.mob_attack_attr_none = 1;
+        battle_config.mob_ghostring_fix = 0;
+        battle_config.gx_allhit = 0;
+        battle_config.gx_cardfix = 0;
+        battle_config.gx_dupele = 1;
+        battle_config.gx_disptype = 1;
+        battle_config.player_skill_partner_check = 1;
+        battle_config.hide_GM_session = 0;
+        battle_config.unit_movement_type = 0;
+        battle_config.invite_request_check = 1;
+        battle_config.skill_removetrap_type = 0;
+        battle_config.disp_experience = 0;
+        battle_config.item_rate_common = 100;
+        battle_config.item_rate_equip = 100;
+        battle_config.item_rate_card = 100;
+        battle_config.item_rate_heal = 100; // Added by Valaris
+        battle_config.item_rate_use = 100;  // End
+        battle_config.item_drop_common_min = 1; // Added by TyrNemesis^
+        battle_config.item_drop_common_max = 10000;
+        battle_config.item_drop_equip_min = 1;
+        battle_config.item_drop_equip_max = 10000;
+        battle_config.item_drop_card_min = 1;
+        battle_config.item_drop_card_max = 10000;
+        battle_config.item_drop_mvp_min = 1;
+        battle_config.item_drop_mvp_max = 10000;    // End Addition
+        battle_config.item_drop_heal_min = 1;   // Added by Valaris
+        battle_config.item_drop_heal_max = 10000;
+        battle_config.item_drop_use_min = 1;
+        battle_config.item_drop_use_max = 10000;    // End
+        battle_config.prevent_logout = 1;   // Added by RoVeRT
+        battle_config.maximum_level = 255;  // Added by Valaris
+        battle_config.drops_by_luk = 0; // [Valaris]
+        battle_config.equipment_breaking = 0;   // [Valaris]
+        battle_config.equipment_break_rate = 100;   // [Valaris]
+        battle_config.pk_mode = 0;  // [Valaris]
+        battle_config.multi_level_up = 0;   // [Valaris]
+        battle_config.backstab_bow_penalty = 0; // Akaru
+        battle_config.night_at_start = 0;   // added by [Yor]
+        battle_config.day_duration = 2 * 60 * 60 * 1000;    // added by [Yor] (2 hours)
+        battle_config.night_duration = 30 * 60 * 1000;  // added by [Yor] (30 minutes)
+        battle_config.show_mob_hp = 0;  // [Valaris]
+        battle_config.hack_info_GM_level = 60;  // added by [Yor] (default: 60, GM level)
+        battle_config.any_warp_GM_min_level = 20;   // added by [Yor]
+        battle_config.packet_ver_flag = 63; // added by [Yor]
+        battle_config.min_hair_style = 0;
+        battle_config.max_hair_style = 20;
+        battle_config.min_hair_color = 0;
+        battle_config.max_hair_color = 9;
+        battle_config.min_cloth_color = 0;
+        battle_config.max_cloth_color = 4;
+
+        battle_config.castrate_dex_scale = 150;
+
+        battle_config.area_size = 14;
+
+        battle_config.chat_lame_penalty = 2;
+        battle_config.chat_spam_threshold = 10;
+        battle_config.chat_spam_flood = 10;
+        battle_config.chat_spam_ban = 1;
+        battle_config.chat_spam_warn = 8;
+        battle_config.chat_maxline = 255;
+
+        battle_config.packet_spam_threshold = 2;
+        battle_config.packet_spam_flood = 30;
+        battle_config.packet_spam_kick = 1;
+
+        battle_config.mask_ip_gms = 1;
+
+        battle_config.mob_splash_radius = -1;
+    }
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        printf ("file not found: %s\n", cfgName);
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        const struct
+        {
+            char str[128];
+            int *val;
+        } data[] =
+        {
+            {
+            "warp_point_debug", &battle_config.warp_point_debug},
+            {
+            "enemy_critical", &battle_config.enemy_critical},
+            {
+            "enemy_critical_rate", &battle_config.enemy_critical_rate},
+            {
+            "enemy_str", &battle_config.enemy_str},
+            {
+            "enemy_perfect_flee", &battle_config.enemy_perfect_flee},
+            {
+            "casting_rate", &battle_config.cast_rate},
+            {
+            "delay_rate", &battle_config.delay_rate},
+            {
+            "delay_dependon_dex", &battle_config.delay_dependon_dex},
+            {
+            "skill_delay_attack_enable",
+                    &battle_config.sdelay_attack_enable},
+            {
+            "left_cardfix_to_right", &battle_config.left_cardfix_to_right},
+            {
+            "player_skill_add_range", &battle_config.pc_skill_add_range},
+            {
+            "skill_out_range_consume",
+                    &battle_config.skill_out_range_consume},
+            {
+            "monster_skill_add_range", &battle_config.mob_skill_add_range},
+            {
+            "player_damage_delay", &battle_config.pc_damage_delay},
+            {
+            "player_damage_delay_rate",
+                    &battle_config.pc_damage_delay_rate},
+            {
+            "defunit_not_enemy", &battle_config.defnotenemy},
+            {
+            "random_monster_checklv",
+                    &battle_config.random_monster_checklv},
+            {
+            "attribute_recover", &battle_config.attr_recover},
+            {
+            "flooritem_lifetime", &battle_config.flooritem_lifetime},
+            {
+            "item_auto_get", &battle_config.item_auto_get},
+            {
+            "drop_pickup_safety_zone",
+                    &battle_config.drop_pickup_safety_zone},
+            {
+            "item_first_get_time", &battle_config.item_first_get_time},
+            {
+            "item_second_get_time", &battle_config.item_second_get_time},
+            {
+            "item_third_get_time", &battle_config.item_third_get_time},
+            {
+            "mvp_item_first_get_time",
+                    &battle_config.mvp_item_first_get_time},
+            {
+            "mvp_item_second_get_time",
+                    &battle_config.mvp_item_second_get_time},
+            {
+            "mvp_item_third_get_time",
+                    &battle_config.mvp_item_third_get_time},
+            {
+            "item_rate", &battle_config.item_rate},
+            {
+            "drop_rate0item", &battle_config.drop_rate0item},
+            {
+            "base_exp_rate", &battle_config.base_exp_rate},
+            {
+            "job_exp_rate", &battle_config.job_exp_rate},
+            {
+            "pvp_exp", &battle_config.pvp_exp},
+            {
+            "gtb_pvp_only", &battle_config.gtb_pvp_only},
+            {
+            "guild_max_castles", &battle_config.guild_max_castles},
+            {
+            "death_penalty_type", &battle_config.death_penalty_type},
+            {
+            "death_penalty_base", &battle_config.death_penalty_base},
+            {
+            "death_penalty_job", &battle_config.death_penalty_job},
+            {
+            "zeny_penalty", &battle_config.zeny_penalty},
+            {
+            "restart_hp_rate", &battle_config.restart_hp_rate},
+            {
+            "restart_sp_rate", &battle_config.restart_sp_rate},
+            {
+            "mvp_hp_rate", &battle_config.mvp_hp_rate},
+            {
+            "mvp_item_rate", &battle_config.mvp_item_rate},
+            {
+            "mvp_exp_rate", &battle_config.mvp_exp_rate},
+            {
+            "monster_hp_rate", &battle_config.monster_hp_rate},
+            {
+            "monster_max_aspd", &battle_config.monster_max_aspd},
+            {
+            "atcommand_gm_only", &battle_config.atc_gmonly},
+            {
+            "atcommand_spawn_quantity_limit",
+                    &battle_config.atc_spawn_quantity_limit},
+            {
+            "gm_all_skill", &battle_config.gm_allskill},
+            {
+            "gm_all_skill_add_abra", &battle_config.gm_allskill_addabra},
+            {
+            "gm_all_equipment", &battle_config.gm_allequip},
+            {
+            "gm_skill_unconditional", &battle_config.gm_skilluncond},
+            {
+            "player_skillfree", &battle_config.skillfree},
+            {
+            "player_skillup_limit", &battle_config.skillup_limit},
+            {
+            "weapon_produce_rate", &battle_config.wp_rate},
+            {
+            "potion_produce_rate", &battle_config.pp_rate},
+            {
+            "monster_active_enable", &battle_config.monster_active_enable},
+            {
+            "monster_damage_delay_rate",
+                    &battle_config.monster_damage_delay_rate},
+            {
+            "monster_loot_type", &battle_config.monster_loot_type},
+            {
+            "mob_skill_use", &battle_config.mob_skill_use},
+            {
+            "mob_count_rate", &battle_config.mob_count_rate},
+            {
+            "quest_skill_learn", &battle_config.quest_skill_learn},
+            {
+            "quest_skill_reset", &battle_config.quest_skill_reset},
+            {
+            "basic_skill_check", &battle_config.basic_skill_check},
+            {
+            "guild_emperium_check", &battle_config.guild_emperium_check},
+            {
+            "guild_exp_limit", &battle_config.guild_exp_limit},
+            {
+            "player_invincible_time", &battle_config.pc_invincible_time},
+            {
+            "skill_min_damage", &battle_config.skill_min_damage},
+            {
+            "finger_offensive_type", &battle_config.finger_offensive_type},
+            {
+            "heal_exp", &battle_config.heal_exp},
+            {
+            "resurrection_exp", &battle_config.resurrection_exp},
+            {
+            "shop_exp", &battle_config.shop_exp},
+            {
+            "combo_delay_rate", &battle_config.combo_delay_rate},
+            {
+            "item_check", &battle_config.item_check},
+            {
+            "wedding_modifydisplay", &battle_config.wedding_modifydisplay},
+            {
+            "natural_healhp_interval",
+                    &battle_config.natural_healhp_interval},
+            {
+            "natural_healsp_interval",
+                    &battle_config.natural_healsp_interval},
+            {
+            "natural_heal_skill_interval",
+                    &battle_config.natural_heal_skill_interval},
+            {
+            "natural_heal_weight_rate",
+                    &battle_config.natural_heal_weight_rate},
+            {
+            "itemheal_regeneration_factor",
+                    &battle_config.itemheal_regeneration_factor},
+            {
+            "item_name_override_grffile",
+                    &battle_config.item_name_override_grffile},
+            {
+            "arrow_decrement", &battle_config.arrow_decrement},
+            {
+            "max_aspd", &battle_config.max_aspd},
+            {
+            "max_hp", &battle_config.max_hp},
+            {
+            "max_sp", &battle_config.max_sp},
+            {
+            "max_lv", &battle_config.max_lv},
+            {
+            "max_parameter", &battle_config.max_parameter},
+            {
+            "max_cart_weight", &battle_config.max_cart_weight},
+            {
+            "player_skill_log", &battle_config.pc_skill_log},
+            {
+            "monster_skill_log", &battle_config.mob_skill_log},
+            {
+            "battle_log", &battle_config.battle_log},
+            {
+            "save_log", &battle_config.save_log},
+            {
+            "error_log", &battle_config.error_log},
+            {
+            "etc_log", &battle_config.etc_log},
+            {
+            "save_clothcolor", &battle_config.save_clothcolor},
+            {
+            "undead_detect_type", &battle_config.undead_detect_type},
+            {
+            "player_auto_counter_type",
+                    &battle_config.pc_auto_counter_type},
+            {
+            "monster_auto_counter_type",
+                    &battle_config.monster_auto_counter_type},
+            {
+            "agi_penaly_type", &battle_config.agi_penaly_type},
+            {
+            "agi_penaly_count", &battle_config.agi_penaly_count},
+            {
+            "agi_penaly_num", &battle_config.agi_penaly_num},
+            {
+            "agi_penaly_count_lv", &battle_config.agi_penaly_count_lv},
+            {
+            "vit_penaly_type", &battle_config.vit_penaly_type},
+            {
+            "vit_penaly_count", &battle_config.vit_penaly_count},
+            {
+            "vit_penaly_num", &battle_config.vit_penaly_num},
+            {
+            "vit_penaly_count_lv", &battle_config.vit_penaly_count_lv},
+            {
+            "player_defense_type", &battle_config.player_defense_type},
+            {
+            "monster_defense_type", &battle_config.monster_defense_type},
+            {
+            "magic_defense_type", &battle_config.magic_defense_type},
+            {
+            "player_skill_reiteration",
+                    &battle_config.pc_skill_reiteration},
+            {
+            "monster_skill_reiteration",
+                    &battle_config.monster_skill_reiteration},
+            {
+            "player_skill_nofootset", &battle_config.pc_skill_nofootset},
+            {
+            "monster_skill_nofootset",
+                    &battle_config.monster_skill_nofootset},
+            {
+            "player_cloak_check_type", &battle_config.pc_cloak_check_type},
+            {
+            "monster_cloak_check_type",
+                    &battle_config.monster_cloak_check_type},
+            {
+            "gvg_short_attack_damage_rate",
+                    &battle_config.gvg_short_damage_rate},
+            {
+            "gvg_long_attack_damage_rate",
+                    &battle_config.gvg_long_damage_rate},
+            {
+            "gvg_magic_attack_damage_rate",
+                    &battle_config.gvg_magic_damage_rate},
+            {
+            "gvg_misc_attack_damage_rate",
+                    &battle_config.gvg_misc_damage_rate},
+            {
+            "gvg_eliminate_time", &battle_config.gvg_eliminate_time},
+            {
+            "mob_changetarget_byskill",
+                    &battle_config.mob_changetarget_byskill},
+            {
+            "player_attack_direction_change",
+                    &battle_config.pc_attack_direction_change},
+            {
+            "monster_attack_direction_change",
+                    &battle_config.monster_attack_direction_change},
+            {
+            "player_land_skill_limit", &battle_config.pc_land_skill_limit},
+            {
+            "monster_land_skill_limit",
+                    &battle_config.monster_land_skill_limit},
+            {
+            "party_skill_penaly", &battle_config.party_skill_penaly},
+            {
+            "monster_class_change_full_recover",
+                    &battle_config.monster_class_change_full_recover},
+            {
+            "produce_item_name_input",
+                    &battle_config.produce_item_name_input},
+            {
+            "produce_potion_name_input",
+                    &battle_config.produce_potion_name_input},
+            {
+            "making_arrow_name_input",
+                    &battle_config.making_arrow_name_input},
+            {
+            "holywater_name_input", &battle_config.holywater_name_input},
+            {
+            "display_delay_skill_fail",
+                    &battle_config.display_delay_skill_fail},
+            {
+            "chat_warpportal", &battle_config.chat_warpportal},
+            {
+            "mob_warpportal", &battle_config.mob_warpportal},
+            {
+            "dead_branch_active", &battle_config.dead_branch_active},
+            {
+            "show_steal_in_same_party",
+                    &battle_config.show_steal_in_same_party},
+            {
+            "enable_upper_class", &battle_config.enable_upper_class},
+            {
+            "mob_attack_attr_none", &battle_config.mob_attack_attr_none},
+            {
+            "mob_ghostring_fix", &battle_config.mob_ghostring_fix},
+            {
+            "pc_attack_attr_none", &battle_config.pc_attack_attr_none},
+            {
+            "gx_allhit", &battle_config.gx_allhit},
+            {
+            "gx_cardfix", &battle_config.gx_cardfix},
+            {
+            "gx_dupele", &battle_config.gx_dupele},
+            {
+            "gx_disptype", &battle_config.gx_disptype},
+            {
+            "player_skill_partner_check",
+                    &battle_config.player_skill_partner_check},
+            {
+            "hide_GM_session", &battle_config.hide_GM_session},
+            {
+            "unit_movement_type", &battle_config.unit_movement_type},
+            {
+            "invite_request_check", &battle_config.invite_request_check},
+            {
+            "skill_removetrap_type", &battle_config.skill_removetrap_type},
+            {
+            "disp_experience", &battle_config.disp_experience},
+            {
+            "castle_defense_rate", &battle_config.castle_defense_rate},
+            {
+            "riding_weight", &battle_config.riding_weight},
+            {
+            "item_rate_common", &battle_config.item_rate_common},   // Added by RoVeRT
+            {
+            "item_rate_equip", &battle_config.item_rate_equip},
+            {
+            "item_rate_card", &battle_config.item_rate_card},   // End Addition
+            {
+            "item_rate_heal", &battle_config.item_rate_heal},   // Added by Valaris
+            {
+            "item_rate_use", &battle_config.item_rate_use}, // End
+            {
+            "item_drop_common_min", &battle_config.item_drop_common_min},   // Added by TyrNemesis^
+            {
+            "item_drop_common_max", &battle_config.item_drop_common_max},
+            {
+            "item_drop_equip_min", &battle_config.item_drop_equip_min},
+            {
+            "item_drop_equip_max", &battle_config.item_drop_equip_max},
+            {
+            "item_drop_card_min", &battle_config.item_drop_card_min},
+            {
+            "item_drop_card_max", &battle_config.item_drop_card_max},
+            {
+            "item_drop_mvp_min", &battle_config.item_drop_mvp_min},
+            {
+            "item_drop_mvp_max", &battle_config.item_drop_mvp_max}, // End Addition
+            {
+            "prevent_logout", &battle_config.prevent_logout},   // Added by RoVeRT
+            {
+            "alchemist_summon_reward", &battle_config.alchemist_summon_reward}, // [Valaris]
+            {
+            "maximum_level", &battle_config.maximum_level}, // [Valaris]
+            {
+            "drops_by_luk", &battle_config.drops_by_luk},   // [Valaris]
+            {
+            "monsters_ignore_gm", &battle_config.monsters_ignore_gm},   // [Valaris]
+            {
+            "equipment_breaking", &battle_config.equipment_breaking},   // [Valaris]
+            {
+            "equipment_break_rate", &battle_config.equipment_break_rate},   // [Valaris]
+            {
+            "pk_mode", &battle_config.pk_mode}, // [Valaris]
+            {
+            "multi_level_up", &battle_config.multi_level_up},   // [Valaris]
+            {
+            "backstab_bow_penalty", &battle_config.backstab_bow_penalty},
+            {
+            "night_at_start", &battle_config.night_at_start},   // added by [Yor]
+            {
+            "day_duration", &battle_config.day_duration},   // added by [Yor]
+            {
+            "night_duration", &battle_config.night_duration},   // added by [Yor]
+            {
+            "show_mob_hp", &battle_config.show_mob_hp}, // [Valaris]
+            {
+            "hack_info_GM_level", &battle_config.hack_info_GM_level},   // added by [Yor]
+            {
+            "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level}, // added by [Yor]
+            {
+            "packet_ver_flag", &battle_config.packet_ver_flag}, // added by [Yor]
+            {
+            "min_hair_style", &battle_config.min_hair_style},   // added by [MouseJstr]
+            {
+            "max_hair_style", &battle_config.max_hair_style},   // added by [MouseJstr]
+            {
+            "min_hair_color", &battle_config.min_hair_color},   // added by [MouseJstr]
+            {
+            "max_hair_color", &battle_config.max_hair_color},   // added by [MouseJstr]
+            {
+            "min_cloth_color", &battle_config.min_cloth_color}, // added by [MouseJstr]
+            {
+            "max_cloth_color", &battle_config.max_cloth_color}, // added by [MouseJstr]
+            {
+            "castrate_dex_scale", &battle_config.castrate_dex_scale},   // added by [MouseJstr]
+            {
+            "area_size", &battle_config.area_size}, // added by [MouseJstr]
+            {
+            "muting_players", &battle_config.muting_players},   // added by [Apple]
+            {
+            "chat_lame_penalty", &battle_config.chat_lame_penalty},
+            {
+            "chat_spam_threshold", &battle_config.chat_spam_threshold},
+            {
+            "chat_spam_flood", &battle_config.chat_spam_flood},
+            {
+            "chat_spam_ban", &battle_config.chat_spam_ban},
+            {
+            "chat_spam_warn", &battle_config.chat_spam_warn},
+            {
+            "chat_maxline", &battle_config.chat_maxline},
+            {
+            "packet_spam_threshold", &battle_config.packet_spam_threshold},
+            {
+            "packet_spam_flood", &battle_config.packet_spam_flood},
+            {
+            "packet_spam_kick", &battle_config.packet_spam_kick},
+            {
+            "mask_ip_gms", &battle_config.mask_ip_gms},
+            {
+            "mob_splash_radius", &battle_config.mob_splash_radius},
+        };
+
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (sscanf (line, "%[^:]:%s", w1, w2) != 2)
+            continue;
+        for (i = 0; i < sizeof (data) / (sizeof (data[0])); i++)
+            if (strcasecmp (w1, data[i].str) == 0)
+                *data[i].val = battle_config_switch (w2);
+
+        if (strcasecmp (w1, "import") == 0)
+            battle_config_read (w2);
+    }
+    fclose_ (fp);
+
+    if (--count == 0)
+    {
+        if (battle_config.flooritem_lifetime < 1000)
+            battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
+        if (battle_config.restart_hp_rate < 0)
+            battle_config.restart_hp_rate = 0;
+        else if (battle_config.restart_hp_rate > 100)
+            battle_config.restart_hp_rate = 100;
+        if (battle_config.restart_sp_rate < 0)
+            battle_config.restart_sp_rate = 0;
+        else if (battle_config.restart_sp_rate > 100)
+            battle_config.restart_sp_rate = 100;
+        if (battle_config.natural_healhp_interval < NATURAL_HEAL_INTERVAL)
+            battle_config.natural_healhp_interval = NATURAL_HEAL_INTERVAL;
+        if (battle_config.natural_healsp_interval < NATURAL_HEAL_INTERVAL)
+            battle_config.natural_healsp_interval = NATURAL_HEAL_INTERVAL;
+        if (battle_config.natural_heal_skill_interval < NATURAL_HEAL_INTERVAL)
+            battle_config.natural_heal_skill_interval = NATURAL_HEAL_INTERVAL;
+        if (battle_config.natural_heal_weight_rate < 50)
+            battle_config.natural_heal_weight_rate = 50;
+        if (battle_config.natural_heal_weight_rate > 101)
+            battle_config.natural_heal_weight_rate = 101;
+        battle_config.monster_max_aspd =
+            2000 - battle_config.monster_max_aspd * 10;
+        if (battle_config.monster_max_aspd < 10)
+            battle_config.monster_max_aspd = 10;
+        if (battle_config.monster_max_aspd > 1000)
+            battle_config.monster_max_aspd = 1000;
+        battle_config.max_aspd = 2000 - battle_config.max_aspd * 10;
+        if (battle_config.max_aspd < 10)
+            battle_config.max_aspd = 10;
+        if (battle_config.max_aspd > 1000)
+            battle_config.max_aspd = 1000;
+        if (battle_config.max_hp > 1000000)
+            battle_config.max_hp = 1000000;
+        if (battle_config.max_hp < 100)
+            battle_config.max_hp = 100;
+        if (battle_config.max_sp > 1000000)
+            battle_config.max_sp = 1000000;
+        if (battle_config.max_sp < 100)
+            battle_config.max_sp = 100;
+        if (battle_config.max_parameter < 10)
+            battle_config.max_parameter = 10;
+        if (battle_config.max_parameter > 10000)
+            battle_config.max_parameter = 10000;
+        if (battle_config.max_cart_weight > 1000000)
+            battle_config.max_cart_weight = 1000000;
+        if (battle_config.max_cart_weight < 100)
+            battle_config.max_cart_weight = 100;
+        battle_config.max_cart_weight *= 10;
+
+        if (battle_config.agi_penaly_count < 2)
+            battle_config.agi_penaly_count = 2;
+        if (battle_config.vit_penaly_count < 2)
+            battle_config.vit_penaly_count = 2;
+
+        if (battle_config.guild_exp_limit > 99)
+            battle_config.guild_exp_limit = 99;
+        if (battle_config.guild_exp_limit < 0)
+            battle_config.guild_exp_limit = 0;
+
+        if (battle_config.castle_defense_rate < 0)
+            battle_config.castle_defense_rate = 0;
+        if (battle_config.castle_defense_rate > 100)
+            battle_config.castle_defense_rate = 100;
+        if (battle_config.item_drop_common_min < 1) // Added by TyrNemesis^
+            battle_config.item_drop_common_min = 1;
+        if (battle_config.item_drop_common_max > 10000)
+            battle_config.item_drop_common_max = 10000;
+        if (battle_config.item_drop_equip_min < 1)
+            battle_config.item_drop_equip_min = 1;
+        if (battle_config.item_drop_equip_max > 10000)
+            battle_config.item_drop_equip_max = 10000;
+        if (battle_config.item_drop_card_min < 1)
+            battle_config.item_drop_card_min = 1;
+        if (battle_config.item_drop_card_max > 10000)
+            battle_config.item_drop_card_max = 10000;
+        if (battle_config.item_drop_mvp_min < 1)
+            battle_config.item_drop_mvp_min = 1;
+        if (battle_config.item_drop_mvp_max > 10000)
+            battle_config.item_drop_mvp_max = 10000;    // End Addition
+
+        if (battle_config.night_at_start < 0)   // added by [Yor]
+            battle_config.night_at_start = 0;
+        else if (battle_config.night_at_start > 1)  // added by [Yor]
+            battle_config.night_at_start = 1;
+        if (battle_config.day_duration < 0) // added by [Yor]
+            battle_config.day_duration = 0;
+        if (battle_config.night_duration < 0)   // added by [Yor]
+            battle_config.night_duration = 0;
+
+        if (battle_config.hack_info_GM_level < 0)   // added by [Yor]
+            battle_config.hack_info_GM_level = 0;
+        else if (battle_config.hack_info_GM_level > 100)
+            battle_config.hack_info_GM_level = 100;
+
+        if (battle_config.any_warp_GM_min_level < 0)    // added by [Yor]
+            battle_config.any_warp_GM_min_level = 0;
+        else if (battle_config.any_warp_GM_min_level > 100)
+            battle_config.any_warp_GM_min_level = 100;
+
+        if (battle_config.chat_spam_ban < 0)
+            battle_config.chat_spam_ban = 0;
+        else if (battle_config.chat_spam_ban > 32767)
+            battle_config.chat_spam_ban = 32767;
+
+        if (battle_config.chat_spam_flood < 0)
+            battle_config.chat_spam_flood = 0;
+        else if (battle_config.chat_spam_flood > 32767)
+            battle_config.chat_spam_flood = 32767;
+
+        if (battle_config.chat_spam_warn < 0)
+            battle_config.chat_spam_warn = 0;
+        else if (battle_config.chat_spam_warn > 32767)
+            battle_config.chat_spam_warn = 32767;
+
+        if (battle_config.chat_spam_threshold < 0)
+            battle_config.chat_spam_threshold = 0;
+        else if (battle_config.chat_spam_threshold > 32767)
+            battle_config.chat_spam_threshold = 32767;
+
+        if (battle_config.chat_maxline < 1)
+            battle_config.chat_maxline = 1;
+        else if (battle_config.chat_maxline > 512)
+            battle_config.chat_maxline = 512;
+
+        if (battle_config.packet_spam_threshold < 0)
+            battle_config.packet_spam_threshold = 0;
+        else if (battle_config.packet_spam_threshold > 32767)
+            battle_config.packet_spam_threshold = 32767;
+
+        if (battle_config.packet_spam_flood < 0)
+            battle_config.packet_spam_flood = 0;
+        else if (battle_config.packet_spam_flood > 32767)
+            battle_config.packet_spam_flood = 32767;
+
+        if (battle_config.packet_spam_kick < 0)
+            battle_config.packet_spam_kick = 0;
+        else if (battle_config.packet_spam_kick > 1)
+            battle_config.packet_spam_kick = 1;
+
+        if (battle_config.mask_ip_gms < 0)
+            battle_config.mask_ip_gms = 0;
+        else if (battle_config.mask_ip_gms > 1)
+            battle_config.mask_ip_gms = 1;
+
+        // at least 1 client must be accepted
+        if ((battle_config.packet_ver_flag & 63) == 0)  // added by [Yor]
+            battle_config.packet_ver_flag = 63; // accept all clients
+
+    }
+
+    return 0;
+}
diff --git a/src/map/battle.h b/src/map/battle.h
deleted file mode 100644
index 66ca3d4..0000000
--- a/src/map/battle.h
+++ /dev/null
@@ -1,357 +0,0 @@
-// $Id: battle.h,v 1.6 2004/09/29 21:08:17 Akitasha Exp $
-#ifndef _BATTLE_H_
-#define _BATTLE_H_
-
-// ダメージ
-struct Damage
-{
-    int  damage, damage2;
-    int  type, div_;
-    int  amotion, dmotion;
-    int  blewcount;
-    int  flag;
-    int  dmg_lv;                //囲まれ減算計算用 0:スキル攻撃 ATK_LUCKY,ATK_FLEE,ATK_DEF
-};
-
-// 属性表(読み込みはpc.c、battle_attr_fixで使用)
-extern int attr_fix_table[4][10][10];
-
-struct map_session_data;
-struct mob_data;
-struct block_list;
-
-// ダメージ計算
-
-struct Damage battle_calc_attack (int attack_type,
-                                  struct block_list *bl,
-                                  struct block_list *target, int skill_num,
-                                  int skill_lv, int flag);
-struct Damage battle_calc_weapon_attack (struct block_list *bl,
-                                         struct block_list *target,
-                                         int skill_num, int skill_lv,
-                                         int flag);
-struct Damage battle_calc_magic_attack (struct block_list *bl,
-                                        struct block_list *target,
-                                        int skill_num, int skill_lv,
-                                        int flag);
-struct Damage battle_calc_misc_attack (struct block_list *bl,
-                                       struct block_list *target,
-                                       int skill_num, int skill_lv, int flag);
-
-// 属性修正計算
-int  battle_attr_fix (int damage, int atk_elem, int def_elem);
-
-// ダメージ最終計算
-int  battle_calc_damage (struct block_list *src, struct block_list *bl,
-                         int damage, int div_, int skill_num, int skill_lv,
-                         int flag);
-enum
-{                               // 最終計算のフラグ
-    BF_WEAPON = 0x0001,
-    BF_MAGIC = 0x0002,
-    BF_MISC = 0x0004,
-    BF_SHORT = 0x0010,
-    BF_LONG = 0x0040,
-    BF_SKILL = 0x0100,
-    BF_NORMAL = 0x0200,
-    BF_WEAPONMASK = 0x000f,
-    BF_RANGEMASK = 0x00f0,
-    BF_SKILLMASK = 0x0f00,
-};
-
-// 実際にHPを増減
-int  battle_delay_damage (unsigned int tick, struct block_list *src,
-                          struct block_list *target, int damage, int flag);
-int  battle_damage (struct block_list *bl, struct block_list *target,
-                    int damage, int flag);
-int  battle_heal (struct block_list *bl, struct block_list *target, int hp,
-                  int sp, int flag);
-
-// 攻撃や移動を止める
-int  battle_stopattack (struct block_list *bl);
-int  battle_stopwalking (struct block_list *bl, int type);
-
-// 通常攻撃処理まとめ
-int  battle_weapon_attack (struct block_list *bl, struct block_list *target,
-                           unsigned int tick, int flag);
-
-// 各種パラメータを得る
-int  battle_counttargeted (struct block_list *bl, struct block_list *src,
-                           int target_lv);
-int  battle_is_unarmed (struct block_list *bl);
-int  battle_get_class (struct block_list *bl);
-int  battle_get_dir (struct block_list *bl);
-int  battle_get_lv (struct block_list *bl);
-int  battle_get_range (struct block_list *bl);
-int  battle_get_hp (struct block_list *bl);
-int  battle_get_max_hp (struct block_list *bl);
-int  battle_get_str (struct block_list *bl);
-int  battle_get_agi (struct block_list *bl);
-int  battle_get_vit (struct block_list *bl);
-int  battle_get_int (struct block_list *bl);
-int  battle_get_dex (struct block_list *bl);
-int  battle_get_luk (struct block_list *bl);
-int  battle_get_hit (struct block_list *bl);
-int  battle_get_flee (struct block_list *bl);
-int  battle_get_def (struct block_list *bl);
-int  battle_get_mdef (struct block_list *bl);
-int  battle_get_flee2 (struct block_list *bl);
-int  battle_get_def2 (struct block_list *bl);
-int  battle_get_mdef2 (struct block_list *bl);
-int  battle_get_baseatk (struct block_list *bl);
-int  battle_get_atk (struct block_list *bl);
-int  battle_get_atk2 (struct block_list *bl);
-int  battle_get_speed (struct block_list *bl);
-int  battle_get_adelay (struct block_list *bl);
-int  battle_get_amotion (struct block_list *bl);
-int  battle_get_dmotion (struct block_list *bl);
-int  battle_get_element (struct block_list *bl);
-int  battle_get_attack_element (struct block_list *bl);
-int  battle_get_attack_element2 (struct block_list *bl);    //左手武器属性取得
-#define battle_get_elem_type(bl)	(battle_get_element(bl)%10)
-#define battle_get_elem_level(bl)	(battle_get_element(bl)/10/2)
-int  battle_get_party_id (struct block_list *bl);
-int  battle_get_guild_id (struct block_list *bl);
-int  battle_get_race (struct block_list *bl);
-int  battle_get_size (struct block_list *bl);
-int  battle_get_mode (struct block_list *bl);
-int  battle_get_mexp (struct block_list *bl);
-int  battle_get_stat (int stat_id /* SP_VIT or similar */ ,
-                      struct block_list *bl);
-
-struct status_change *battle_get_sc_data (struct block_list *bl);
-short *battle_get_sc_count (struct block_list *bl);
-short *battle_get_opt1 (struct block_list *bl);
-short *battle_get_opt2 (struct block_list *bl);
-short *battle_get_opt3 (struct block_list *bl);
-short *battle_get_option (struct block_list *bl);
-
-enum
-{
-    BCT_NOENEMY = 0x00000,
-    BCT_PARTY = 0x10000,
-    BCT_ENEMY = 0x40000,
-    BCT_NOPARTY = 0x50000,
-    BCT_ALL = 0x20000,
-    BCT_NOONE = 0x60000,
-};
-
-int  battle_check_undead (int race, int element);
-int  battle_check_target (struct block_list *src, struct block_list *target,
-                          int flag);
-int  battle_check_range (struct block_list *src, struct block_list *bl,
-                         int range);
-
-// 設定
-
-int  battle_config_switch (const char *str);    // [Valaris]
-
-extern struct Battle_Config
-{
-    int  warp_point_debug;
-    int  enemy_critical;
-    int  enemy_critical_rate;
-    int  enemy_str;
-    int  enemy_perfect_flee;
-    int  cast_rate, delay_rate, delay_dependon_dex;
-    int  sdelay_attack_enable;
-    int  left_cardfix_to_right;
-    int  pc_skill_add_range;
-    int  skill_out_range_consume;
-    int  mob_skill_add_range;
-    int  pc_damage_delay;
-    int  pc_damage_delay_rate;
-    int  defnotenemy;
-    int  random_monster_checklv;
-    int  attr_recover;
-    int  flooritem_lifetime;
-    int  item_auto_get;
-    int  item_first_get_time;
-    int  item_second_get_time;
-    int  item_third_get_time;
-    int  mvp_item_first_get_time;
-    int  mvp_item_second_get_time;
-    int  mvp_item_third_get_time;
-    int  item_rate, base_exp_rate, job_exp_rate;    // removed item rate, depreciated
-    int  drop_rate0item;
-    int  death_penalty_type;
-    int  death_penalty_base, death_penalty_job;
-    int  pvp_exp;               // [MouseJstr]
-    int  gtb_pvp_only;          // [MouseJstr]
-    int  zeny_penalty;
-    int  restart_hp_rate;
-    int  restart_sp_rate;
-    int  mvp_item_rate, mvp_exp_rate;
-    int  mvp_hp_rate;
-    int  monster_hp_rate;
-    int  monster_max_aspd;
-    int  atc_gmonly;
-    int  atc_spawn_quantity_limit;
-    int  gm_allskill;
-    int  gm_allskill_addabra;
-    int  gm_allequip;
-    int  gm_skilluncond;
-    int  skillfree;
-    int  skillup_limit;
-    int  wp_rate;
-    int  pp_rate;
-    int  monster_active_enable;
-    int  monster_damage_delay_rate;
-    int  monster_loot_type;
-    int  mob_skill_use;
-    int  mob_count_rate;
-    int  quest_skill_learn;
-    int  quest_skill_reset;
-    int  basic_skill_check;
-    int  guild_emperium_check;
-    int  guild_exp_limit;
-    int  guild_max_castles;
-    int  pc_invincible_time;
-    int  skill_min_damage;
-    int  finger_offensive_type;
-    int  heal_exp;
-    int  resurrection_exp;
-    int  shop_exp;
-    int  combo_delay_rate;
-    int  item_check;
-    int  wedding_modifydisplay;
-    int  natural_healhp_interval;
-    int  natural_healsp_interval;
-    int  natural_heal_skill_interval;
-    int  natural_heal_weight_rate;
-    int  item_name_override_grffile;
-    int  arrow_decrement;
-    int  max_aspd;
-    int  max_hp;
-    int  max_sp;
-    int  max_lv;
-    int  max_parameter;
-    int  max_cart_weight;
-    int  pc_skill_log;
-    int  mob_skill_log;
-    int  battle_log;
-    int  save_log;
-    int  error_log;
-    int  etc_log;
-    int  save_clothcolor;
-    int  undead_detect_type;
-    int  pc_auto_counter_type;
-    int  monster_auto_counter_type;
-    int  agi_penaly_type;
-    int  agi_penaly_count;
-    int  agi_penaly_num;
-    int  vit_penaly_type;
-    int  vit_penaly_count;
-    int  vit_penaly_num;
-    int  player_defense_type;
-    int  monster_defense_type;
-    int  magic_defense_type;
-    int  pc_skill_reiteration;
-    int  monster_skill_reiteration;
-    int  pc_skill_nofootset;
-    int  monster_skill_nofootset;
-    int  pc_cloak_check_type;
-    int  monster_cloak_check_type;
-    int  gvg_short_damage_rate;
-    int  gvg_long_damage_rate;
-    int  gvg_magic_damage_rate;
-    int  gvg_misc_damage_rate;
-    int  gvg_eliminate_time;
-    int  mob_changetarget_byskill;
-    int  pc_attack_direction_change;
-    int  monster_attack_direction_change;
-    int  pc_undead_nofreeze;
-    int  pc_land_skill_limit;
-    int  monster_land_skill_limit;
-    int  party_skill_penaly;
-    int  monster_class_change_full_recover;
-    int  produce_item_name_input;
-    int  produce_potion_name_input;
-    int  making_arrow_name_input;
-    int  holywater_name_input;
-    int  display_delay_skill_fail;
-    int  chat_warpportal;
-    int  mob_warpportal;
-    int  dead_branch_active;
-    int  show_steal_in_same_party;
-    int  enable_upper_class;
-    int  mob_attack_attr_none;
-    int  mob_ghostring_fix;
-    int  pc_attack_attr_none;
-    int  item_rate_common, item_rate_card, item_rate_equip, item_rate_heal, item_rate_use;  // Added by RoVeRT, Additional Heal and Usable item rate by Val
-    int  item_drop_common_min, item_drop_common_max;    // Added by TyrNemesis^
-    int  item_drop_card_min, item_drop_card_max;
-    int  item_drop_equip_min, item_drop_equip_max;
-    int  item_drop_mvp_min, item_drop_mvp_max;  // End Addition
-    int  item_drop_heal_min, item_drop_heal_max;    // Added by Valatris
-    int  item_drop_use_min, item_drop_use_max;  //End
-
-    int  prevent_logout;        // Added by RoVeRT
-
-    int  alchemist_summon_reward;   // [Valaris]
-    int  maximum_level;
-    int  drops_by_luk;
-    int  monsters_ignore_gm;
-    int  equipment_breaking;
-    int  equipment_break_rate;
-    int  multi_level_up;
-    int  pk_mode;
-    int  show_mob_hp;           // end additions [Valaris]
-
-    int  agi_penaly_count_lv;
-    int  vit_penaly_count_lv;
-
-    int  gx_allhit;
-    int  gx_cardfix;
-    int  gx_dupele;
-    int  gx_disptype;
-    int  player_skill_partner_check;
-    int  hide_GM_session;
-    int  unit_movement_type;
-    int  invite_request_check;
-    int  skill_removetrap_type;
-    int  disp_experience;
-    int  castle_defense_rate;
-    int  riding_weight;
-    int  backstab_bow_penalty;
-
-    int  night_at_start;        // added by [Yor]
-    int  day_duration;          // added by [Yor]
-    int  night_duration;        // added by [Yor]
-    int  hack_info_GM_level;    // added by [Yor]
-    int  any_warp_GM_min_level; // added by [Yor]
-    int  packet_ver_flag;       // added by [Yor]
-    int  muting_players;        // added by [Apple]
-
-    int  min_hair_style;        // added by [MouseJstr]
-    int  max_hair_style;        // added by [MouseJstr]
-    int  min_hair_color;        // added by [MouseJstr]
-    int  max_hair_color;        // added by [MouseJstr]
-    int  min_cloth_color;       // added by [MouseJstr]
-    int  max_cloth_color;       // added by [MouseJstr]
-
-    int  castrate_dex_scale;    // added by [MouseJstr]
-    int  area_size;             // added by [MouseJstr]
-
-    int  chat_lame_penalty;
-    int  chat_spam_threshold;
-    int  chat_spam_flood;
-    int  chat_spam_ban;
-    int  chat_spam_warn;
-    int  chat_maxline;
-
-    int  packet_spam_threshold;
-    int  packet_spam_flood;
-    int  packet_spam_kick;
-
-    int  mask_ip_gms;
-
-    int  drop_pickup_safety_zone;   // [Fate] Max. distance to an object dropped by a kill by self in which dropsteal protection works
-    int  itemheal_regeneration_factor;  // [Fate] itemheal speed factor
-
-    int  mob_splash_radius;
-} battle_config;
-
-int  battle_config_read (const char *cfgName);
-
-#endif
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
new file mode 100644
index 0000000..5f2a22f
--- /dev/null
+++ b/src/map/battle.hpp
@@ -0,0 +1,357 @@
+// $Id: battle.h,v 1.6 2004/09/29 21:08:17 Akitasha Exp $
+#ifndef BATTLE_HPP
+#define BATTLE_HPP
+
+// ダメージ
+struct Damage
+{
+    int  damage, damage2;
+    int  type, div_;
+    int  amotion, dmotion;
+    int  blewcount;
+    int  flag;
+    int  dmg_lv;                //囲まれ減算計算用 0:スキル攻撃 ATK_LUCKY,ATK_FLEE,ATK_DEF
+};
+
+// 属性表(読み込みはpc.c、battle_attr_fixで使用)
+extern int attr_fix_table[4][10][10];
+
+struct map_session_data;
+struct mob_data;
+struct block_list;
+
+// ダメージ計算
+
+struct Damage battle_calc_attack (int attack_type,
+                                  struct block_list *bl,
+                                  struct block_list *target, int skill_num,
+                                  int skill_lv, int flag);
+struct Damage battle_calc_weapon_attack (struct block_list *bl,
+                                         struct block_list *target,
+                                         int skill_num, int skill_lv,
+                                         int flag);
+struct Damage battle_calc_magic_attack (struct block_list *bl,
+                                        struct block_list *target,
+                                        int skill_num, int skill_lv,
+                                        int flag);
+struct Damage battle_calc_misc_attack (struct block_list *bl,
+                                       struct block_list *target,
+                                       int skill_num, int skill_lv, int flag);
+
+// 属性修正計算
+int  battle_attr_fix (int damage, int atk_elem, int def_elem);
+
+// ダメージ最終計算
+int  battle_calc_damage (struct block_list *src, struct block_list *bl,
+                         int damage, int div_, int skill_num, int skill_lv,
+                         int flag);
+enum
+{                               // 最終計算のフラグ
+    BF_WEAPON = 0x0001,
+    BF_MAGIC = 0x0002,
+    BF_MISC = 0x0004,
+    BF_SHORT = 0x0010,
+    BF_LONG = 0x0040,
+    BF_SKILL = 0x0100,
+    BF_NORMAL = 0x0200,
+    BF_WEAPONMASK = 0x000f,
+    BF_RANGEMASK = 0x00f0,
+    BF_SKILLMASK = 0x0f00,
+};
+
+// 実際にHPを増減
+int  battle_delay_damage (unsigned int tick, struct block_list *src,
+                          struct block_list *target, int damage, int flag);
+int  battle_damage (struct block_list *bl, struct block_list *target,
+                    int damage, int flag);
+int  battle_heal (struct block_list *bl, struct block_list *target, int hp,
+                  int sp, int flag);
+
+// 攻撃や移動を止める
+int  battle_stopattack (struct block_list *bl);
+int  battle_stopwalking (struct block_list *bl, int type);
+
+// 通常攻撃処理まとめ
+int  battle_weapon_attack (struct block_list *bl, struct block_list *target,
+                           unsigned int tick, int flag);
+
+// 各種パラメータを得る
+int  battle_counttargeted (struct block_list *bl, struct block_list *src,
+                           int target_lv);
+int  battle_is_unarmed (struct block_list *bl);
+int  battle_get_class (struct block_list *bl);
+int  battle_get_dir (struct block_list *bl);
+int  battle_get_lv (struct block_list *bl);
+int  battle_get_range (struct block_list *bl);
+int  battle_get_hp (struct block_list *bl);
+int  battle_get_max_hp (struct block_list *bl);
+int  battle_get_str (struct block_list *bl);
+int  battle_get_agi (struct block_list *bl);
+int  battle_get_vit (struct block_list *bl);
+int  battle_get_int (struct block_list *bl);
+int  battle_get_dex (struct block_list *bl);
+int  battle_get_luk (struct block_list *bl);
+int  battle_get_hit (struct block_list *bl);
+int  battle_get_flee (struct block_list *bl);
+int  battle_get_def (struct block_list *bl);
+int  battle_get_mdef (struct block_list *bl);
+int  battle_get_flee2 (struct block_list *bl);
+int  battle_get_def2 (struct block_list *bl);
+int  battle_get_mdef2 (struct block_list *bl);
+int  battle_get_baseatk (struct block_list *bl);
+int  battle_get_atk (struct block_list *bl);
+int  battle_get_atk2 (struct block_list *bl);
+int  battle_get_speed (struct block_list *bl);
+int  battle_get_adelay (struct block_list *bl);
+int  battle_get_amotion (struct block_list *bl);
+int  battle_get_dmotion (struct block_list *bl);
+int  battle_get_element (struct block_list *bl);
+int  battle_get_attack_element (struct block_list *bl);
+int  battle_get_attack_element2 (struct block_list *bl);    //左手武器属性取得
+#define battle_get_elem_type(bl)	(battle_get_element(bl)%10)
+#define battle_get_elem_level(bl)	(battle_get_element(bl)/10/2)
+int  battle_get_party_id (struct block_list *bl);
+int  battle_get_guild_id (struct block_list *bl);
+int  battle_get_race (struct block_list *bl);
+int  battle_get_size (struct block_list *bl);
+int  battle_get_mode (struct block_list *bl);
+int  battle_get_mexp (struct block_list *bl);
+int  battle_get_stat (int stat_id /* SP_VIT or similar */ ,
+                      struct block_list *bl);
+
+struct status_change *battle_get_sc_data (struct block_list *bl);
+short *battle_get_sc_count (struct block_list *bl);
+short *battle_get_opt1 (struct block_list *bl);
+short *battle_get_opt2 (struct block_list *bl);
+short *battle_get_opt3 (struct block_list *bl);
+short *battle_get_option (struct block_list *bl);
+
+enum
+{
+    BCT_NOENEMY = 0x00000,
+    BCT_PARTY = 0x10000,
+    BCT_ENEMY = 0x40000,
+    BCT_NOPARTY = 0x50000,
+    BCT_ALL = 0x20000,
+    BCT_NOONE = 0x60000,
+};
+
+int  battle_check_undead (int race, int element);
+int  battle_check_target (struct block_list *src, struct block_list *target,
+                          int flag);
+int  battle_check_range (struct block_list *src, struct block_list *bl,
+                         int range);
+
+// 設定
+
+int  battle_config_switch (const char *str);    // [Valaris]
+
+extern struct Battle_Config
+{
+    int  warp_point_debug;
+    int  enemy_critical;
+    int  enemy_critical_rate;
+    int  enemy_str;
+    int  enemy_perfect_flee;
+    int  cast_rate, delay_rate, delay_dependon_dex;
+    int  sdelay_attack_enable;
+    int  left_cardfix_to_right;
+    int  pc_skill_add_range;
+    int  skill_out_range_consume;
+    int  mob_skill_add_range;
+    int  pc_damage_delay;
+    int  pc_damage_delay_rate;
+    int  defnotenemy;
+    int  random_monster_checklv;
+    int  attr_recover;
+    int  flooritem_lifetime;
+    int  item_auto_get;
+    int  item_first_get_time;
+    int  item_second_get_time;
+    int  item_third_get_time;
+    int  mvp_item_first_get_time;
+    int  mvp_item_second_get_time;
+    int  mvp_item_third_get_time;
+    int  item_rate, base_exp_rate, job_exp_rate;    // removed item rate, depreciated
+    int  drop_rate0item;
+    int  death_penalty_type;
+    int  death_penalty_base, death_penalty_job;
+    int  pvp_exp;               // [MouseJstr]
+    int  gtb_pvp_only;          // [MouseJstr]
+    int  zeny_penalty;
+    int  restart_hp_rate;
+    int  restart_sp_rate;
+    int  mvp_item_rate, mvp_exp_rate;
+    int  mvp_hp_rate;
+    int  monster_hp_rate;
+    int  monster_max_aspd;
+    int  atc_gmonly;
+    int  atc_spawn_quantity_limit;
+    int  gm_allskill;
+    int  gm_allskill_addabra;
+    int  gm_allequip;
+    int  gm_skilluncond;
+    int  skillfree;
+    int  skillup_limit;
+    int  wp_rate;
+    int  pp_rate;
+    int  monster_active_enable;
+    int  monster_damage_delay_rate;
+    int  monster_loot_type;
+    int  mob_skill_use;
+    int  mob_count_rate;
+    int  quest_skill_learn;
+    int  quest_skill_reset;
+    int  basic_skill_check;
+    int  guild_emperium_check;
+    int  guild_exp_limit;
+    int  guild_max_castles;
+    int  pc_invincible_time;
+    int  skill_min_damage;
+    int  finger_offensive_type;
+    int  heal_exp;
+    int  resurrection_exp;
+    int  shop_exp;
+    int  combo_delay_rate;
+    int  item_check;
+    int  wedding_modifydisplay;
+    int  natural_healhp_interval;
+    int  natural_healsp_interval;
+    int  natural_heal_skill_interval;
+    int  natural_heal_weight_rate;
+    int  item_name_override_grffile;
+    int  arrow_decrement;
+    int  max_aspd;
+    int  max_hp;
+    int  max_sp;
+    int  max_lv;
+    int  max_parameter;
+    int  max_cart_weight;
+    int  pc_skill_log;
+    int  mob_skill_log;
+    int  battle_log;
+    int  save_log;
+    int  error_log;
+    int  etc_log;
+    int  save_clothcolor;
+    int  undead_detect_type;
+    int  pc_auto_counter_type;
+    int  monster_auto_counter_type;
+    int  agi_penaly_type;
+    int  agi_penaly_count;
+    int  agi_penaly_num;
+    int  vit_penaly_type;
+    int  vit_penaly_count;
+    int  vit_penaly_num;
+    int  player_defense_type;
+    int  monster_defense_type;
+    int  magic_defense_type;
+    int  pc_skill_reiteration;
+    int  monster_skill_reiteration;
+    int  pc_skill_nofootset;
+    int  monster_skill_nofootset;
+    int  pc_cloak_check_type;
+    int  monster_cloak_check_type;
+    int  gvg_short_damage_rate;
+    int  gvg_long_damage_rate;
+    int  gvg_magic_damage_rate;
+    int  gvg_misc_damage_rate;
+    int  gvg_eliminate_time;
+    int  mob_changetarget_byskill;
+    int  pc_attack_direction_change;
+    int  monster_attack_direction_change;
+    int  pc_undead_nofreeze;
+    int  pc_land_skill_limit;
+    int  monster_land_skill_limit;
+    int  party_skill_penaly;
+    int  monster_class_change_full_recover;
+    int  produce_item_name_input;
+    int  produce_potion_name_input;
+    int  making_arrow_name_input;
+    int  holywater_name_input;
+    int  display_delay_skill_fail;
+    int  chat_warpportal;
+    int  mob_warpportal;
+    int  dead_branch_active;
+    int  show_steal_in_same_party;
+    int  enable_upper_class;
+    int  mob_attack_attr_none;
+    int  mob_ghostring_fix;
+    int  pc_attack_attr_none;
+    int  item_rate_common, item_rate_card, item_rate_equip, item_rate_heal, item_rate_use;  // Added by RoVeRT, Additional Heal and Usable item rate by Val
+    int  item_drop_common_min, item_drop_common_max;    // Added by TyrNemesis^
+    int  item_drop_card_min, item_drop_card_max;
+    int  item_drop_equip_min, item_drop_equip_max;
+    int  item_drop_mvp_min, item_drop_mvp_max;  // End Addition
+    int  item_drop_heal_min, item_drop_heal_max;    // Added by Valatris
+    int  item_drop_use_min, item_drop_use_max;  //End
+
+    int  prevent_logout;        // Added by RoVeRT
+
+    int  alchemist_summon_reward;   // [Valaris]
+    int  maximum_level;
+    int  drops_by_luk;
+    int  monsters_ignore_gm;
+    int  equipment_breaking;
+    int  equipment_break_rate;
+    int  multi_level_up;
+    int  pk_mode;
+    int  show_mob_hp;           // end additions [Valaris]
+
+    int  agi_penaly_count_lv;
+    int  vit_penaly_count_lv;
+
+    int  gx_allhit;
+    int  gx_cardfix;
+    int  gx_dupele;
+    int  gx_disptype;
+    int  player_skill_partner_check;
+    int  hide_GM_session;
+    int  unit_movement_type;
+    int  invite_request_check;
+    int  skill_removetrap_type;
+    int  disp_experience;
+    int  castle_defense_rate;
+    int  riding_weight;
+    int  backstab_bow_penalty;
+
+    int  night_at_start;        // added by [Yor]
+    int  day_duration;          // added by [Yor]
+    int  night_duration;        // added by [Yor]
+    int  hack_info_GM_level;    // added by [Yor]
+    int  any_warp_GM_min_level; // added by [Yor]
+    int  packet_ver_flag;       // added by [Yor]
+    int  muting_players;        // added by [Apple]
+
+    int  min_hair_style;        // added by [MouseJstr]
+    int  max_hair_style;        // added by [MouseJstr]
+    int  min_hair_color;        // added by [MouseJstr]
+    int  max_hair_color;        // added by [MouseJstr]
+    int  min_cloth_color;       // added by [MouseJstr]
+    int  max_cloth_color;       // added by [MouseJstr]
+
+    int  castrate_dex_scale;    // added by [MouseJstr]
+    int  area_size;             // added by [MouseJstr]
+
+    int  chat_lame_penalty;
+    int  chat_spam_threshold;
+    int  chat_spam_flood;
+    int  chat_spam_ban;
+    int  chat_spam_warn;
+    int  chat_maxline;
+
+    int  packet_spam_threshold;
+    int  packet_spam_flood;
+    int  packet_spam_kick;
+
+    int  mask_ip_gms;
+
+    int  drop_pickup_safety_zone;   // [Fate] Max. distance to an object dropped by a kill by self in which dropsteal protection works
+    int  itemheal_regeneration_factor;  // [Fate] itemheal speed factor
+
+    int  mob_splash_radius;
+} battle_config;
+
+int  battle_config_read (const char *cfgName);
+
+#endif
diff --git a/src/map/chat.c b/src/map/chat.c
deleted file mode 100644
index ccb75df..0000000
--- a/src/map/chat.c
+++ /dev/null
@@ -1,395 +0,0 @@
-// $Id: chat.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/db.h"
-#include "../common/nullpo.h"
-#include "map.h"
-#include "clif.h"
-#include "pc.h"
-#include "chat.h"
-#include "npc.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-int  chat_triggerevent (struct chat_data *cd);
-
-/*==========================================
- * チャットルーム作成
- *------------------------------------------
- */
-int chat_createchat (struct map_session_data *sd, int limit, int pub,
-                     char *pass, char *title, int titlelen)
-{
-    struct chat_data *cd;
-
-    nullpo_retr (0, sd);
-
-    CREATE(cd, struct chat_data, 1);
-
-    cd->limit = limit;
-    cd->pub = pub;
-    cd->users = 1;
-    memcpy (cd->pass, pass, 8);
-    if (titlelen >= sizeof (cd->title) - 1)
-        titlelen = sizeof (cd->title) - 1;
-    memcpy (cd->title, title, titlelen);
-    cd->title[titlelen] = 0;
-
-    cd->owner = (struct block_list **) (&cd->usersd[0]);
-    cd->usersd[0] = sd;
-    cd->bl.m = sd->bl.m;
-    cd->bl.x = sd->bl.x;
-    cd->bl.y = sd->bl.y;
-    cd->bl.type = BL_CHAT;
-
-    cd->bl.id = map_addobject (&cd->bl);
-    if (cd->bl.id == 0)
-    {
-        clif_createchat (sd, 1);
-        free (cd);
-        return 0;
-    }
-    pc_setchatid (sd, cd->bl.id);
-
-    clif_createchat (sd, 0);
-    clif_dispchat (cd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 既存チャットルームに参加
- *------------------------------------------
- */
-int chat_joinchat (struct map_session_data *sd, int chatid, char *pass)
-{
-    struct chat_data *cd;
-
-    nullpo_retr (0, sd);
-
-    cd = (struct chat_data *) map_id2bl (chatid);
-    if (cd == NULL)
-        return 1;
-
-    if (cd->bl.m != sd->bl.m || cd->limit <= cd->users)
-    {
-        clif_joinchatfail (sd, 0);
-        return 0;
-    }
-    if (cd->pub == 0 && strncmp (pass, cd->pass, 8))
-    {
-        clif_joinchatfail (sd, 1);
-        return 0;
-    }
-
-    cd->usersd[cd->users] = sd;
-    cd->users++;
-
-    pc_setchatid (sd, cd->bl.id);
-
-    clif_joinchatok (sd, cd);   // 新たに参加した人には全員のリスト
-    clif_addchat (cd, sd);      // 既に中に居た人には追加した人の報告
-    clif_dispchat (cd, 0);      // 周囲の人には人数変化報告
-
-    chat_triggerevent (cd);     // イベント
-
-    return 0;
-}
-
-/*==========================================
- * チャットルームから抜ける
- *------------------------------------------
- */
-int chat_leavechat (struct map_session_data *sd)
-{
-    struct chat_data *cd;
-    int  i, leavechar;
-
-    nullpo_retr (1, sd);
-
-    cd = (struct chat_data *) map_id2bl (sd->chatID);
-    if (cd == NULL)
-        return 1;
-
-    for (i = 0, leavechar = -1; i < cd->users; i++)
-    {
-        if (cd->usersd[i] == sd)
-        {
-            leavechar = i;
-            break;
-        }
-    }
-    if (leavechar < 0)          // そのchatに所属していないらしい (バグ時のみ)
-        return -1;
-
-    if (leavechar == 0 && cd->users > 1 && (*cd->owner)->type == BL_PC)
-    {
-        // 所有者だった&他に人が居る&PCのチャット
-        clif_changechatowner (cd, cd->usersd[1]);
-        clif_clearchat (cd, 0);
-    }
-
-    // 抜けるPCにも送るのでusersを減らす前に実行
-    clif_leavechat (cd, sd);
-
-    cd->users--;
-    pc_setchatid (sd, 0);
-
-    if (cd->users == 0 && (*cd->owner)->type == BL_PC)
-    {
-        // 全員居なくなった&PCのチャットなので消す
-        clif_clearchat (cd, 0);
-        map_delobject (cd->bl.id, BL_CHAT); // freeまでしてくれる
-    }
-    else
-    {
-        for (i = leavechar; i < cd->users; i++)
-            cd->usersd[i] = cd->usersd[i + 1];
-        if (leavechar == 0 && (*cd->owner)->type == BL_PC)
-        {
-            // PCのチャットなので所有者が抜けたので位置変更
-            cd->bl.x = cd->usersd[0]->bl.x;
-            cd->bl.y = cd->usersd[0]->bl.y;
-        }
-        clif_dispchat (cd, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * チャットルームの持ち主を譲る
- *------------------------------------------
- */
-int chat_changechatowner (struct map_session_data *sd, char *nextownername)
-{
-    struct chat_data *cd;
-    struct map_session_data *tmp_sd;
-    int  i, nextowner;
-
-    nullpo_retr (1, sd);
-
-    cd = (struct chat_data *) map_id2bl (sd->chatID);
-    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
-        return 1;
-
-    for (i = 1, nextowner = -1; i < cd->users; i++)
-    {
-        if (strcmp (cd->usersd[i]->status.name, nextownername) == 0)
-        {
-            nextowner = i;
-            break;
-        }
-    }
-    if (nextowner < 0)          // そんな人は居ない
-        return -1;
-
-    clif_changechatowner (cd, cd->usersd[nextowner]);
-    // 一旦消す
-    clif_clearchat (cd, 0);
-
-    // userlistの順番変更 (0が所有者なので)
-    if ((tmp_sd = cd->usersd[0]) == NULL)
-        return 1;               //ありえるのかな?
-    cd->usersd[0] = cd->usersd[nextowner];
-    cd->usersd[nextowner] = tmp_sd;
-
-    // 新しい所有者の位置へ変更
-    cd->bl.x = cd->usersd[0]->bl.x;
-    cd->bl.y = cd->usersd[0]->bl.y;
-
-    // 再度表示
-    clif_dispchat (cd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * チャットの状態(タイトル等)を変更
- *------------------------------------------
- */
-int chat_changechatstatus (struct map_session_data *sd, int limit, int pub,
-                           char *pass, char *title, int titlelen)
-{
-    struct chat_data *cd;
-
-    nullpo_retr (1, sd);
-
-    cd = (struct chat_data *) map_id2bl (sd->chatID);
-    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
-        return 1;
-
-    cd->limit = limit;
-    cd->pub = pub;
-    memcpy (cd->pass, pass, 8);
-    if (titlelen >= sizeof (cd->title) - 1)
-        titlelen = sizeof (cd->title) - 1;
-    memcpy (cd->title, title, titlelen);
-    cd->title[titlelen] = 0;
-
-    clif_changechatstatus (cd);
-    clif_dispchat (cd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * チャットルームから蹴り出す
- *------------------------------------------
- */
-int chat_kickchat (struct map_session_data *sd, char *kickusername)
-{
-    struct chat_data *cd;
-    int  i, kickuser;
-
-    nullpo_retr (1, sd);
-
-    cd = (struct chat_data *) map_id2bl (sd->chatID);
-    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
-        return 1;
-
-    for (i = 0, kickuser = -1; i < cd->users; i++)
-    {
-        if (strcmp (cd->usersd[i]->status.name, kickusername) == 0)
-        {
-            kickuser = i;
-            break;
-        }
-    }
-    if (kickuser < 0)           // そんな人は居ない
-        return -1;
-
-    chat_leavechat (cd->usersd[kickuser]);
-
-    return 0;
-}
-
-/*==========================================
- * npcチャットルーム作成
- *------------------------------------------
- */
-int chat_createnpcchat (struct npc_data *nd, int limit, int pub, int trigger,
-                        char *title, int titlelen, const char *ev)
-{
-    struct chat_data *cd;
-
-    nullpo_retr (1, nd);
-
-    CREATE (cd, struct chat_data, 1);
-
-    cd->limit = cd->trigger = limit;
-    if (trigger > 0)
-        cd->trigger = trigger;
-    cd->pub = pub;
-    cd->users = 0;
-    memcpy (cd->pass, "", 8);
-    if (titlelen >= sizeof (cd->title) - 1)
-        titlelen = sizeof (cd->title) - 1;
-    memcpy (cd->title, title, titlelen);
-    cd->title[titlelen] = 0;
-
-    cd->bl.m = nd->bl.m;
-    cd->bl.x = nd->bl.x;
-    cd->bl.y = nd->bl.y;
-    cd->bl.type = BL_CHAT;
-    cd->owner_ = (struct block_list *) nd;
-    cd->owner = &cd->owner_;
-    memcpy (cd->npc_event, ev, sizeof (cd->npc_event));
-
-    cd->bl.id = map_addobject (&cd->bl);
-    if (cd->bl.id == 0)
-    {
-        free (cd);
-        return 0;
-    }
-    nd->chat_id = cd->bl.id;
-
-    clif_dispchat (cd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * npcチャットルーム削除
- *------------------------------------------
- */
-int chat_deletenpcchat (struct npc_data *nd)
-{
-    struct chat_data *cd;
-
-    nullpo_retr (0, nd);
-    nullpo_retr (0, cd = (struct chat_data *) map_id2bl (nd->chat_id));
-
-    chat_npckickall (cd);
-    clif_clearchat (cd, 0);
-    map_delobject (cd->bl.id, BL_CHAT); // freeまでしてくれる
-    nd->chat_id = 0;
-
-    return 0;
-}
-
-/*==========================================
- * 規定人数以上でイベントが定義されてるなら実行
- *------------------------------------------
- */
-int chat_triggerevent (struct chat_data *cd)
-{
-    nullpo_retr (0, cd);
-
-    if (cd->users >= cd->trigger && cd->npc_event[0])
-        npc_event_do (cd->npc_event);
-    return 0;
-}
-
-/*==========================================
- * イベントの有効化
- *------------------------------------------
- */
-int chat_enableevent (struct chat_data *cd)
-{
-    nullpo_retr (0, cd);
-
-    cd->trigger &= 0x7f;
-    chat_triggerevent (cd);
-    return 0;
-}
-
-/*==========================================
- * イベントの無効化
- *------------------------------------------
- */
-int chat_disableevent (struct chat_data *cd)
-{
-    nullpo_retr (0, cd);
-
-    cd->trigger |= 0x80;
-    return 0;
-}
-
-/*==========================================
- * チャットルームから全員蹴り出す
- *------------------------------------------
- */
-int chat_npckickall (struct chat_data *cd)
-{
-    nullpo_retr (0, cd);
-
-    while (cd->users > 0)
-    {
-        chat_leavechat (cd->usersd[cd->users - 1]);
-    }
-    return 0;
-}
-
-/*==========================================
- * 終了
- *------------------------------------------
- */
-int do_final_chat (void)
-{
-    return 0;
-}
diff --git a/src/map/chat.cpp b/src/map/chat.cpp
new file mode 100644
index 0000000..0615b41
--- /dev/null
+++ b/src/map/chat.cpp
@@ -0,0 +1,395 @@
+// $Id: chat.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/db.hpp"
+#include "../common/nullpo.hpp"
+#include "map.hpp"
+#include "clif.hpp"
+#include "pc.hpp"
+#include "chat.hpp"
+#include "npc.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+int  chat_triggerevent (struct chat_data *cd);
+
+/*==========================================
+ * チャットルーム作成
+ *------------------------------------------
+ */
+int chat_createchat (struct map_session_data *sd, int limit, int pub,
+                     char *pass, char *title, int titlelen)
+{
+    struct chat_data *cd;
+
+    nullpo_retr (0, sd);
+
+    CREATE(cd, struct chat_data, 1);
+
+    cd->limit = limit;
+    cd->pub = pub;
+    cd->users = 1;
+    memcpy (cd->pass, pass, 8);
+    if (titlelen >= sizeof (cd->title) - 1)
+        titlelen = sizeof (cd->title) - 1;
+    memcpy (cd->title, title, titlelen);
+    cd->title[titlelen] = 0;
+
+    cd->owner = (struct block_list **) (&cd->usersd[0]);
+    cd->usersd[0] = sd;
+    cd->bl.m = sd->bl.m;
+    cd->bl.x = sd->bl.x;
+    cd->bl.y = sd->bl.y;
+    cd->bl.type = BL_CHAT;
+
+    cd->bl.id = map_addobject (&cd->bl);
+    if (cd->bl.id == 0)
+    {
+        clif_createchat (sd, 1);
+        free (cd);
+        return 0;
+    }
+    pc_setchatid (sd, cd->bl.id);
+
+    clif_createchat (sd, 0);
+    clif_dispchat (cd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 既存チャットルームに参加
+ *------------------------------------------
+ */
+int chat_joinchat (struct map_session_data *sd, int chatid, char *pass)
+{
+    struct chat_data *cd;
+
+    nullpo_retr (0, sd);
+
+    cd = (struct chat_data *) map_id2bl (chatid);
+    if (cd == NULL)
+        return 1;
+
+    if (cd->bl.m != sd->bl.m || cd->limit <= cd->users)
+    {
+        clif_joinchatfail (sd, 0);
+        return 0;
+    }
+    if (cd->pub == 0 && strncmp (pass, cd->pass, 8))
+    {
+        clif_joinchatfail (sd, 1);
+        return 0;
+    }
+
+    cd->usersd[cd->users] = sd;
+    cd->users++;
+
+    pc_setchatid (sd, cd->bl.id);
+
+    clif_joinchatok (sd, cd);   // 新たに参加した人には全員のリスト
+    clif_addchat (cd, sd);      // 既に中に居た人には追加した人の報告
+    clif_dispchat (cd, 0);      // 周囲の人には人数変化報告
+
+    chat_triggerevent (cd);     // イベント
+
+    return 0;
+}
+
+/*==========================================
+ * チャットルームから抜ける
+ *------------------------------------------
+ */
+int chat_leavechat (struct map_session_data *sd)
+{
+    struct chat_data *cd;
+    int  i, leavechar;
+
+    nullpo_retr (1, sd);
+
+    cd = (struct chat_data *) map_id2bl (sd->chatID);
+    if (cd == NULL)
+        return 1;
+
+    for (i = 0, leavechar = -1; i < cd->users; i++)
+    {
+        if (cd->usersd[i] == sd)
+        {
+            leavechar = i;
+            break;
+        }
+    }
+    if (leavechar < 0)          // そのchatに所属していないらしい (バグ時のみ)
+        return -1;
+
+    if (leavechar == 0 && cd->users > 1 && (*cd->owner)->type == BL_PC)
+    {
+        // 所有者だった&他に人が居る&PCのチャット
+        clif_changechatowner (cd, cd->usersd[1]);
+        clif_clearchat (cd, 0);
+    }
+
+    // 抜けるPCにも送るのでusersを減らす前に実行
+    clif_leavechat (cd, sd);
+
+    cd->users--;
+    pc_setchatid (sd, 0);
+
+    if (cd->users == 0 && (*cd->owner)->type == BL_PC)
+    {
+        // 全員居なくなった&PCのチャットなので消す
+        clif_clearchat (cd, 0);
+        map_delobject (cd->bl.id, BL_CHAT); // freeまでしてくれる
+    }
+    else
+    {
+        for (i = leavechar; i < cd->users; i++)
+            cd->usersd[i] = cd->usersd[i + 1];
+        if (leavechar == 0 && (*cd->owner)->type == BL_PC)
+        {
+            // PCのチャットなので所有者が抜けたので位置変更
+            cd->bl.x = cd->usersd[0]->bl.x;
+            cd->bl.y = cd->usersd[0]->bl.y;
+        }
+        clif_dispchat (cd, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * チャットルームの持ち主を譲る
+ *------------------------------------------
+ */
+int chat_changechatowner (struct map_session_data *sd, char *nextownername)
+{
+    struct chat_data *cd;
+    struct map_session_data *tmp_sd;
+    int  i, nextowner;
+
+    nullpo_retr (1, sd);
+
+    cd = (struct chat_data *) map_id2bl (sd->chatID);
+    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
+        return 1;
+
+    for (i = 1, nextowner = -1; i < cd->users; i++)
+    {
+        if (strcmp (cd->usersd[i]->status.name, nextownername) == 0)
+        {
+            nextowner = i;
+            break;
+        }
+    }
+    if (nextowner < 0)          // そんな人は居ない
+        return -1;
+
+    clif_changechatowner (cd, cd->usersd[nextowner]);
+    // 一旦消す
+    clif_clearchat (cd, 0);
+
+    // userlistの順番変更 (0が所有者なので)
+    if ((tmp_sd = cd->usersd[0]) == NULL)
+        return 1;               //ありえるのかな?
+    cd->usersd[0] = cd->usersd[nextowner];
+    cd->usersd[nextowner] = tmp_sd;
+
+    // 新しい所有者の位置へ変更
+    cd->bl.x = cd->usersd[0]->bl.x;
+    cd->bl.y = cd->usersd[0]->bl.y;
+
+    // 再度表示
+    clif_dispchat (cd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * チャットの状態(タイトル等)を変更
+ *------------------------------------------
+ */
+int chat_changechatstatus (struct map_session_data *sd, int limit, int pub,
+                           char *pass, char *title, int titlelen)
+{
+    struct chat_data *cd;
+
+    nullpo_retr (1, sd);
+
+    cd = (struct chat_data *) map_id2bl (sd->chatID);
+    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
+        return 1;
+
+    cd->limit = limit;
+    cd->pub = pub;
+    memcpy (cd->pass, pass, 8);
+    if (titlelen >= sizeof (cd->title) - 1)
+        titlelen = sizeof (cd->title) - 1;
+    memcpy (cd->title, title, titlelen);
+    cd->title[titlelen] = 0;
+
+    clif_changechatstatus (cd);
+    clif_dispchat (cd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * チャットルームから蹴り出す
+ *------------------------------------------
+ */
+int chat_kickchat (struct map_session_data *sd, char *kickusername)
+{
+    struct chat_data *cd;
+    int  i, kickuser;
+
+    nullpo_retr (1, sd);
+
+    cd = (struct chat_data *) map_id2bl (sd->chatID);
+    if (cd == NULL || (struct block_list *) sd != (*cd->owner))
+        return 1;
+
+    for (i = 0, kickuser = -1; i < cd->users; i++)
+    {
+        if (strcmp (cd->usersd[i]->status.name, kickusername) == 0)
+        {
+            kickuser = i;
+            break;
+        }
+    }
+    if (kickuser < 0)           // そんな人は居ない
+        return -1;
+
+    chat_leavechat (cd->usersd[kickuser]);
+
+    return 0;
+}
+
+/*==========================================
+ * npcチャットルーム作成
+ *------------------------------------------
+ */
+int chat_createnpcchat (struct npc_data *nd, int limit, int pub, int trigger,
+                        char *title, int titlelen, const char *ev)
+{
+    struct chat_data *cd;
+
+    nullpo_retr (1, nd);
+
+    CREATE (cd, struct chat_data, 1);
+
+    cd->limit = cd->trigger = limit;
+    if (trigger > 0)
+        cd->trigger = trigger;
+    cd->pub = pub;
+    cd->users = 0;
+    memcpy (cd->pass, "", 8);
+    if (titlelen >= sizeof (cd->title) - 1)
+        titlelen = sizeof (cd->title) - 1;
+    memcpy (cd->title, title, titlelen);
+    cd->title[titlelen] = 0;
+
+    cd->bl.m = nd->bl.m;
+    cd->bl.x = nd->bl.x;
+    cd->bl.y = nd->bl.y;
+    cd->bl.type = BL_CHAT;
+    cd->owner_ = (struct block_list *) nd;
+    cd->owner = &cd->owner_;
+    memcpy (cd->npc_event, ev, sizeof (cd->npc_event));
+
+    cd->bl.id = map_addobject (&cd->bl);
+    if (cd->bl.id == 0)
+    {
+        free (cd);
+        return 0;
+    }
+    nd->chat_id = cd->bl.id;
+
+    clif_dispchat (cd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * npcチャットルーム削除
+ *------------------------------------------
+ */
+int chat_deletenpcchat (struct npc_data *nd)
+{
+    struct chat_data *cd;
+
+    nullpo_retr (0, nd);
+    nullpo_retr (0, cd = (struct chat_data *) map_id2bl (nd->chat_id));
+
+    chat_npckickall (cd);
+    clif_clearchat (cd, 0);
+    map_delobject (cd->bl.id, BL_CHAT); // freeまでしてくれる
+    nd->chat_id = 0;
+
+    return 0;
+}
+
+/*==========================================
+ * 規定人数以上でイベントが定義されてるなら実行
+ *------------------------------------------
+ */
+int chat_triggerevent (struct chat_data *cd)
+{
+    nullpo_retr (0, cd);
+
+    if (cd->users >= cd->trigger && cd->npc_event[0])
+        npc_event_do (cd->npc_event);
+    return 0;
+}
+
+/*==========================================
+ * イベントの有効化
+ *------------------------------------------
+ */
+int chat_enableevent (struct chat_data *cd)
+{
+    nullpo_retr (0, cd);
+
+    cd->trigger &= 0x7f;
+    chat_triggerevent (cd);
+    return 0;
+}
+
+/*==========================================
+ * イベントの無効化
+ *------------------------------------------
+ */
+int chat_disableevent (struct chat_data *cd)
+{
+    nullpo_retr (0, cd);
+
+    cd->trigger |= 0x80;
+    return 0;
+}
+
+/*==========================================
+ * チャットルームから全員蹴り出す
+ *------------------------------------------
+ */
+int chat_npckickall (struct chat_data *cd)
+{
+    nullpo_retr (0, cd);
+
+    while (cd->users > 0)
+    {
+        chat_leavechat (cd->usersd[cd->users - 1]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+int do_final_chat (void)
+{
+    return 0;
+}
diff --git a/src/map/chat.h b/src/map/chat.h
deleted file mode 100644
index 7f61f54..0000000
--- a/src/map/chat.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// $Id: chat.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _CHAT_H_
-#define _CHAT_H_
-
-#include "map.h"
-
-int  chat_createchat (struct map_session_data *, int, int, char *, char *,
-                      int);
-int  chat_joinchat (struct map_session_data *, int, char *);
-int  chat_leavechat (struct map_session_data *);
-int  chat_changechatowner (struct map_session_data *, char *);
-int  chat_changechatstatus (struct map_session_data *, int, int, char *,
-                            char *, int);
-int  chat_kickchat (struct map_session_data *, char *);
-
-int  chat_createnpcchat (struct npc_data *nd, int limit, int pub, int trigger,
-                         char *title, int titlelen, const char *ev);
-int  chat_deletenpcchat (struct npc_data *nd);
-int  chat_enableevent (struct chat_data *cd);
-int  chat_disableevent (struct chat_data *cd);
-int  chat_npckickall (struct chat_data *cd);
-
-int  do_final_chat (void);
-
-#endif
diff --git a/src/map/chat.hpp b/src/map/chat.hpp
new file mode 100644
index 0000000..3a9ccb6
--- /dev/null
+++ b/src/map/chat.hpp
@@ -0,0 +1,25 @@
+// $Id: chat.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef CHAT_HPP
+#define CHAT_HPP
+
+#include "map.hpp"
+
+int  chat_createchat (struct map_session_data *, int, int, char *, char *,
+                      int);
+int  chat_joinchat (struct map_session_data *, int, char *);
+int  chat_leavechat (struct map_session_data *);
+int  chat_changechatowner (struct map_session_data *, char *);
+int  chat_changechatstatus (struct map_session_data *, int, int, char *,
+                            char *, int);
+int  chat_kickchat (struct map_session_data *, char *);
+
+int  chat_createnpcchat (struct npc_data *nd, int limit, int pub, int trigger,
+                         char *title, int titlelen, const char *ev);
+int  chat_deletenpcchat (struct npc_data *nd);
+int  chat_enableevent (struct chat_data *cd);
+int  chat_disableevent (struct chat_data *cd);
+int  chat_npckickall (struct chat_data *cd);
+
+int  do_final_chat (void);
+
+#endif
diff --git a/src/map/chrif.c b/src/map/chrif.c
deleted file mode 100644
index 5e2cd4c..0000000
--- a/src/map/chrif.c
+++ /dev/null
@@ -1,1307 +0,0 @@
-// $Id: chrif.c,v 1.6 2004/09/25 11:39:17 MouseJstr Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef LCCWIN32
-#include <winsock.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include <sys/types.h>
-#include <time.h>
-
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "map.h"
-#include "battle.h"
-#include "chrif.h"
-#include "clif.h"
-#include "intif.h"
-#include "npc.h"
-#include "pc.h"
-#include "../common/nullpo.h"
-#include "itemdb.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-static const int packet_len_table[0x20] = {
-    60, 3, 10, 27, 22, -1, 6, -1,   // 2af8-2aff
-    6, -1, 18, 7, -1, 49, 44, 0,    // 2b00-2b07
-    6, 30, -1, 10, 86, 7, 44, 34,   // 2b08-2b0f
-    -1, -1, 10, 6, 11, -1, 0, 0,    // 2b10-2b17
-};
-
-int  char_fd;
-int  srvinfo;
-static char char_ip_str[16];
-static int char_ip;
-static int char_port = 6121;
-static char userid[24], passwd[24];
-static int chrif_state;
-
-// 設定ファイル読み込み関係
-/*==========================================
- *
- *------------------------------------------
- */
-void chrif_setuserid (char *id)
-{
-    strncpy (userid, id, sizeof(userid)-1);
-    userid[sizeof(userid)-1] = '\0';
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void chrif_setpasswd (char *pwd)
-{
-    strncpy (passwd, pwd, sizeof(passwd)-1);
-    passwd[sizeof(passwd)-1] = '\0';
-}
-
-char *chrif_getpasswd (void)
-{
-    return passwd;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void chrif_setip (char *ip)
-{
-    strncpy (char_ip_str, ip, sizeof(char_ip_str)-1);
-    char_ip_str[sizeof(char_ip_str)-1] = '\0';
-    char_ip = inet_addr (char_ip_str);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void chrif_setport (int port)
-{
-    char_port = port;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_isconnect (void)
-{
-    return chrif_state == 2;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_save (struct map_session_data *sd)
-{
-    nullpo_retr (-1, sd);
-
-    if (char_fd < 0)
-        return -1;
-
-    pc_makesavestatus (sd);
-
-    WFIFOW (char_fd, 0) = 0x2b01;
-    WFIFOW (char_fd, 2) = sizeof (sd->status) + 12;
-    WFIFOL (char_fd, 4) = sd->bl.id;
-    WFIFOL (char_fd, 8) = sd->char_id;
-    memcpy (WFIFOP (char_fd, 12), &sd->status, sizeof (sd->status));
-    WFIFOSET (char_fd, WFIFOW (char_fd, 2));
-
-    //For data sync
-    if (sd->state.storage_flag == 1)
-        storage_storage_save (sd->status.account_id, 0);
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storagesave (sd->status.account_id, sd->status.guild_id,
-                                   0);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_connect (int fd)
-{
-    WFIFOW (fd, 0) = 0x2af8;
-    memcpy (WFIFOP (fd, 2), userid, 24);
-    memcpy (WFIFOP (fd, 26), passwd, 24);
-    WFIFOL (fd, 50) = 0;
-    WFIFOL (fd, 54) = clif_getip ();
-    WFIFOW (fd, 58) = clif_getport ();  // [Valaris] thanks to fov
-    WFIFOSET (fd, 60);
-
-    return 0;
-}
-
-/*==========================================
- * マップ送信
- *------------------------------------------
- */
-int chrif_sendmap (int fd)
-{
-    int  i;
-
-    WFIFOW (fd, 0) = 0x2afa;
-    for (i = 0; i < map_num; i++)
-        if (map[i].alias[0] != '\0')    // [MouseJstr] map aliasing
-            memcpy (WFIFOP (fd, 4 + i * 16), map[i].alias, 16);
-        else
-            memcpy (WFIFOP (fd, 4 + i * 16), map[i].name, 16);
-    WFIFOW (fd, 2) = 4 + i * 16;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- * マップ受信
- *------------------------------------------
- */
-int chrif_recvmap (int fd)
-{
-    int  i, j, ip, port;
-    unsigned char *p = (unsigned char *) &ip;
-
-    if (chrif_state < 2)        // まだ準備中
-        return -1;
-
-    ip = RFIFOL (fd, 4);
-    port = RFIFOW (fd, 8);
-    for (i = 10, j = 0; i < RFIFOW (fd, 2); i += 16, j++)
-    {
-        map_setipport (RFIFOP (fd, i), ip, port);
-//      if (battle_config.etc_log)
-//          printf("recv map %d %s\n", j, RFIFOP(fd,i));
-    }
-    if (battle_config.etc_log)
-        printf ("recv map on %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2],
-                p[3], port, j);
-
-    return 0;
-}
-
-/*==========================================
- * マップ鯖間移動のためのデータ準備要求
- *------------------------------------------
- */
-int chrif_changemapserver (struct map_session_data *sd, char *name, int x,
-                           int y, int ip, short port)
-{
-    int  i, s_ip;
-
-    nullpo_retr (-1, sd);
-
-    s_ip = 0;
-    for (i = 0; i < fd_max; i++)
-        if (session[i] && session[i]->session_data == sd)
-        {
-            s_ip = session[i]->client_addr.sin_addr.s_addr;
-            break;
-        }
-
-    WFIFOW (char_fd, 0) = 0x2b05;
-    WFIFOL (char_fd, 2) = sd->bl.id;
-    WFIFOL (char_fd, 6) = sd->login_id1;
-    WFIFOL (char_fd, 10) = sd->login_id2;
-    WFIFOL (char_fd, 14) = sd->status.char_id;
-    memcpy (WFIFOP (char_fd, 18), name, 16);
-    WFIFOW (char_fd, 34) = x;
-    WFIFOW (char_fd, 36) = y;
-    WFIFOL (char_fd, 38) = ip;
-    WFIFOL (char_fd, 42) = port;
-    WFIFOB (char_fd, 44) = sd->status.sex;
-    WFIFOL (char_fd, 45) = s_ip;
-    WFIFOSET (char_fd, 49);
-
-    return 0;
-}
-
-/*==========================================
- * マップ鯖間移動ack
- *------------------------------------------
- */
-int chrif_changemapserverack (int fd)
-{
-    struct map_session_data *sd = map_id2sd (RFIFOL (fd, 2));
-
-    if (sd == NULL || sd->status.char_id != RFIFOL (fd, 14))
-        return -1;
-
-    if (RFIFOL (fd, 6) == 1)
-    {
-        if (battle_config.error_log)
-            printf ("map server change failed.\n");
-        pc_authfail (sd->fd);
-        return 0;
-    }
-    clif_changemapserver (sd, RFIFOP (fd, 18), RFIFOW (fd, 34),
-                          RFIFOW (fd, 36), RFIFOL (fd, 38), RFIFOW (fd, 42));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_connectack (int fd)
-{
-    if (RFIFOB (fd, 2))
-    {
-        printf ("Connected to char-server failed %d.\n", RFIFOB (fd, 2));
-        exit (1);
-    }
-    printf ("Connected to char-server (connection #%d).\n", fd);
-    chrif_state = 1;
-
-    chrif_sendmap (fd);
-
-    printf ("chrif: OnCharIfInit event done. (%d events)\n",
-            npc_event_doall ("OnCharIfInit"));
-    printf ("chrif: OnInterIfInit event done. (%d events)\n",
-            npc_event_doall ("OnInterIfInit"));
-
-    // <Agit> Run Event [AgitInit]
-//  printf("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit"));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_sendmapack (int fd)
-{
-    if (RFIFOB (fd, 2))
-    {
-        printf ("chrif : send map list to char server failed %d\n",
-                RFIFOB (fd, 2));
-        exit (1);
-    }
-
-    memcpy (wisp_server_name, RFIFOP (fd, 3), 24);
-
-    chrif_state = 2;
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_authreq (struct map_session_data *sd)
-{
-    int  i;
-
-    nullpo_retr (-1, sd);
-
-    if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
-        return -1;
-
-    for (i = 0; i < fd_max; i++)
-        if (session[i] && session[i]->session_data == sd)
-        {
-            WFIFOW (char_fd, 0) = 0x2afc;
-            WFIFOL (char_fd, 2) = sd->bl.id;
-            WFIFOL (char_fd, 6) = sd->char_id;
-            WFIFOL (char_fd, 10) = sd->login_id1;
-            WFIFOL (char_fd, 14) = sd->login_id2;
-            WFIFOL (char_fd, 18) = session[i]->client_addr.sin_addr.s_addr;
-            WFIFOSET (char_fd, 22);
-            break;
-        }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int chrif_charselectreq (struct map_session_data *sd)
-{
-    int  i, s_ip;
-
-    nullpo_retr (-1, sd);
-
-    if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
-        return -1;
-
-    s_ip = 0;
-    for (i = 0; i < fd_max; i++)
-        if (session[i] && session[i]->session_data == sd)
-        {
-            s_ip = session[i]->client_addr.sin_addr.s_addr;
-            break;
-        }
-
-    WFIFOW (char_fd, 0) = 0x2b02;
-    WFIFOL (char_fd, 2) = sd->bl.id;
-    WFIFOL (char_fd, 6) = sd->login_id1;
-    WFIFOL (char_fd, 10) = sd->login_id2;
-    WFIFOL (char_fd, 14) = s_ip;
-    WFIFOSET (char_fd, 18);
-
-    return 0;
-}
-
-/*==========================================
- * キャラ名問い合わせ
- *------------------------------------------
- */
-int chrif_searchcharid (int char_id)
-{
-    if (!char_id)
-        return -1;
-
-    WFIFOW (char_fd, 0) = 0x2b08;
-    WFIFOL (char_fd, 2) = char_id;
-    WFIFOSET (char_fd, 6);
-
-    return 0;
-}
-
-/*==========================================
- * GMに変化要求
- *------------------------------------------
- */
-int chrif_changegm (int id, const char *pass, int len)
-{
-    if (battle_config.etc_log)
-        printf ("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
-
-    WFIFOW (char_fd, 0) = 0x2b0a;
-    WFIFOW (char_fd, 2) = len + 8;
-    WFIFOL (char_fd, 4) = id;
-    memcpy (WFIFOP (char_fd, 8), pass, len);
-    WFIFOSET (char_fd, len + 8);
-
-    return 0;
-}
-
-/*==========================================
- * Change Email
- *------------------------------------------
- */
-int chrif_changeemail (int id, const char *actual_email,
-                       const char *new_email)
-{
-    if (battle_config.etc_log)
-        printf
-            ("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n",
-             id, actual_email, new_email);
-
-    WFIFOW (char_fd, 0) = 0x2b0c;
-    WFIFOL (char_fd, 2) = id;
-    memcpy (WFIFOP (char_fd, 6), actual_email, 40);
-    memcpy (WFIFOP (char_fd, 46), new_email, 40);
-    WFIFOSET (char_fd, 86);
-
-    return 0;
-}
-
-/*==========================================
- * Send message to char-server with a character name to do some operations (by Yor)
- * Used to ask Char-server about a character name to have the account number to modify account file in login-server.
- * type of operation:
- *   1: block
- *   2: ban
- *   3: unblock
- *   4: unban
- *   5: changesex
- *------------------------------------------
- */
-int chrif_char_ask_name (int id, char *character_name, short operation_type,
-                         int year, int month, int day, int hour, int minute,
-                         int second)
-{
-    WFIFOW (char_fd, 0) = 0x2b0e;
-    WFIFOL (char_fd, 2) = id;   // account_id of who ask (for answer) -1 if nobody
-    memcpy (WFIFOP (char_fd, 6), character_name, 24);
-    WFIFOW (char_fd, 30) = operation_type;  // type of operation
-    if (operation_type == 2)
-    {
-        WFIFOW (char_fd, 32) = year;
-        WFIFOW (char_fd, 34) = month;
-        WFIFOW (char_fd, 36) = day;
-        WFIFOW (char_fd, 38) = hour;
-        WFIFOW (char_fd, 40) = minute;
-        WFIFOW (char_fd, 42) = second;
-    }
-    printf ("chrif : sended 0x2b0e\n");
-    WFIFOSET (char_fd, 44);
-
-    return 0;
-}
-
-/*==========================================
- * Answer after a request about a character name to do some operations (by Yor)
- * Used to answer of chrif_char_ask_name.
- * type of operation:
- *   1: block
- *   2: ban
- *   3: unblock
- *   4: unban
- *   5: changesex
- * type of answer:
- *   0: login-server resquest done
- *   1: player not found
- *   2: gm level too low
- *   3: login-server offline
- *------------------------------------------
- */
-int chrif_char_ask_name_answer (int fd)
-{
-    int  acc;
-    struct map_session_data *sd;
-    char output[256];
-    char player_name[24];
-
-    acc = RFIFOL (fd, 2);       // account_id of who has asked (-1 if nobody)
-    memcpy (player_name, RFIFOP (fd, 6), sizeof (player_name));
-    player_name[sizeof (player_name) - 1] = '\0';
-
-    sd = map_id2sd (acc);
-    if (acc >= 0 && sd != NULL)
-    {
-        if (RFIFOW (fd, 32) == 1)   // player not found
-            sprintf (output, "The player '%s' doesn't exist.", player_name);
-        else
-        {
-            switch (RFIFOW (fd, 30))
-            {
-                case 1:        // block
-                    switch (RFIFOW (fd, 32))
-                    {
-                        case 0:    // login-server resquest done
-                            sprintf (output,
-                                     "Login-server has been asked to block the player '%s'.",
-                                     player_name);
-                            break;
-                            //case 1: // player not found
-                        case 2:    // gm level too low
-                            sprintf (output,
-                                     "Your GM level don't authorise you to block the player '%s'.",
-                                     player_name);
-                            break;
-                        case 3:    // login-server offline
-                            sprintf (output,
-                                     "Login-server is offline. Impossible to block the the player '%s'.",
-                                     player_name);
-                            break;
-                    }
-                    break;
-                case 2:        // ban
-                    switch (RFIFOW (fd, 32))
-                    {
-                        case 0:    // login-server resquest done
-                            sprintf (output,
-                                     "Login-server has been asked to ban the player '%s'.",
-                                     player_name);
-                            break;
-                            //case 1: // player not found
-                        case 2:    // gm level too low
-                            sprintf (output,
-                                     "Your GM level don't authorise you to ban the player '%s'.",
-                                     player_name);
-                            break;
-                        case 3:    // login-server offline
-                            sprintf (output,
-                                     "Login-server is offline. Impossible to ban the the player '%s'.",
-                                     player_name);
-                            break;
-                    }
-                    break;
-                case 3:        // unblock
-                    switch (RFIFOW (fd, 32))
-                    {
-                        case 0:    // login-server resquest done
-                            sprintf (output,
-                                     "Login-server has been asked to unblock the player '%s'.",
-                                     player_name);
-                            break;
-                            //case 1: // player not found
-                        case 2:    // gm level too low
-                            sprintf (output,
-                                     "Your GM level don't authorise you to unblock the player '%s'.",
-                                     player_name);
-                            break;
-                        case 3:    // login-server offline
-                            sprintf (output,
-                                     "Login-server is offline. Impossible to unblock the the player '%s'.",
-                                     player_name);
-                            break;
-                    }
-                    break;
-                case 4:        // unban
-                    switch (RFIFOW (fd, 32))
-                    {
-                        case 0:    // login-server resquest done
-                            sprintf (output,
-                                     "Login-server has been asked to unban the player '%s'.",
-                                     player_name);
-                            break;
-                            //case 1: // player not found
-                        case 2:    // gm level too low
-                            sprintf (output,
-                                     "Your GM level don't authorise you to unban the player '%s'.",
-                                     player_name);
-                            break;
-                        case 3:    // login-server offline
-                            sprintf (output,
-                                     "Login-server is offline. Impossible to unban the the player '%s'.",
-                                     player_name);
-                            break;
-                    }
-                    break;
-                case 5:        // changesex
-                    switch (RFIFOW (fd, 32))
-                    {
-                        case 0:    // login-server resquest done
-                            sprintf (output,
-                                     "Login-server has been asked to change the sex of the player '%s'.",
-                                     player_name);
-                            break;
-                            //case 1: // player not found
-                        case 2:    // gm level too low
-                            sprintf (output,
-                                     "Your GM level don't authorise you to change the sex of the player '%s'.",
-                                     player_name);
-                            break;
-                        case 3:    // login-server offline
-                            sprintf (output,
-                                     "Login-server is offline. Impossible to change the sex of the the player '%s'.",
-                                     player_name);
-                            break;
-                    }
-                    break;
-            }
-        }
-        if (output[0] != '\0')
-        {
-            output[sizeof (output) - 1] = '\0';
-            clif_displaymessage (sd->fd, output);
-        }
-    }
-    else
-        printf ("chrif_char_ask_name_answer failed - player not online.\n");
-
-    return 0;
-}
-
-/*==========================================
- * End of GM change (@GM) (modified by Yor)
- *------------------------------------------
- */
-int chrif_changedgm (int fd)
-{
-    int  acc, level;
-    struct map_session_data *sd = NULL;
-
-    acc = RFIFOL (fd, 2);
-    level = RFIFOL (fd, 6);
-
-    sd = map_id2sd (acc);
-
-    if (battle_config.etc_log)
-        printf ("chrif_changedgm: account: %d, GM level 0 -> %d.\n", acc,
-                level);
-    if (sd != NULL)
-    {
-        if (level > 0)
-            clif_displaymessage (sd->fd, "GM modification success.");
-        else
-            clif_displaymessage (sd->fd, "Failure of GM modification.");
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 性別変化終了 (modified by Yor)
- *------------------------------------------
- */
-int chrif_changedsex (int fd)
-{
-    int  acc, sex, i;
-    struct map_session_data *sd;
-    struct pc_base_job s_class;
-
-    acc = RFIFOL (fd, 2);
-    sex = RFIFOL (fd, 6);
-    if (battle_config.etc_log)
-        printf ("chrif_changedsex %d.\n", acc);
-    sd = map_id2sd (acc);
-    if (acc > 0)
-    {
-        if (sd != NULL && sd->status.sex != sex)
-        {
-            s_class = pc_calc_base_job (sd->status.pc_class);
-            if (sd->status.sex == 0)
-            {
-                sd->status.sex = 1;
-                sd->sex = 1;
-            }
-            else if (sd->status.sex == 1)
-            {
-                sd->status.sex = 0;
-                sd->sex = 0;
-            }
-            // to avoid any problem with equipment and invalid sex, equipment is unequiped.
-            for (i = 0; i < MAX_INVENTORY; i++)
-            {
-                if (sd->status.inventory[i].nameid
-                    && sd->status.inventory[i].equip)
-                    pc_unequipitem ((struct map_session_data *) sd, i, 0);
-            }
-            // reset skill of some job
-            if (s_class.job == 19 || s_class.job == 4020
-                || s_class.job == 4042 || s_class.job == 20
-                || s_class.job == 4021 || s_class.job == 4043)
-            {
-
-                clif_updatestatus (sd, SP_SKILLPOINT);
-                // change job if necessary
-                if (s_class.job == 20 || s_class.job == 4021
-                    || s_class.job == 4043)
-                    sd->status.pc_class -= 1;
-                else if (s_class.job == 19 || s_class.job == 4020
-                         || s_class.job == 4042)
-                    sd->status.pc_class += 1;
-            }
-            // save character
-            chrif_save (sd);
-            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
-            // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
-            clif_displaymessage (sd->fd,
-                                 "Your sex has been changed (need disconexion by the server)...");
-            clif_setwaitclose (sd->fd); // forced to disconnect for the change
-        }
-    }
-    else
-    {
-        if (sd != NULL)
-        {
-            printf ("chrif_changedsex failed.\n");
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * アカウント変数保存要求
- *------------------------------------------
- */
-int chrif_saveaccountreg2 (struct map_session_data *sd)
-{
-    int  p, j;
-    nullpo_retr (-1, sd);
-
-    p = 8;
-    for (j = 0; j < sd->status.account_reg2_num; j++)
-    {
-        struct global_reg *reg = &sd->status.account_reg2[j];
-        if (reg->str[0] && reg->value != 0)
-        {
-            memcpy (WFIFOP (char_fd, p), reg->str, 32);
-            WFIFOL (char_fd, p + 32) = reg->value;
-            p += 36;
-        }
-    }
-    WFIFOW (char_fd, 0) = 0x2b10;
-    WFIFOW (char_fd, 2) = p;
-    WFIFOL (char_fd, 4) = sd->bl.id;
-    WFIFOSET (char_fd, p);
-
-    return 0;
-}
-
-/*==========================================
- * アカウント変数通知
- *------------------------------------------
- */
-int chrif_accountreg2 (int fd)
-{
-    int  j, p;
-    struct map_session_data *sd;
-
-    if ((sd = map_id2sd (RFIFOL (fd, 4))) == NULL)
-        return 1;
-
-    for (p = 8, j = 0; p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
-         p += 36, j++)
-    {
-        memcpy (sd->status.account_reg2[j].str, RFIFOP (fd, p), 32);
-        sd->status.account_reg2[j].value = RFIFOL (fd, p + 32);
-    }
-    sd->status.account_reg2_num = j;
-//  printf("chrif: accountreg2\n");
-
-    return 0;
-}
-
-/*==========================================
- * Divorce request from char server
- * triggered on account deletion or as an
- * ack from a map-server divorce request
- *------------------------------------------
- */
-int chrif_divorce (int char_id, int partner_id)
-{
-    struct map_session_data *sd = NULL;
-
-    if (!char_id || !partner_id)
-        return 0;
-
-    sd = map_nick2sd (map_charid2nick (char_id));
-    if (sd && sd->status.partner_id == partner_id)
-    {
-        sd->status.partner_id = 0;
-
-        if (sd->npc_flags.divorce)
-        {
-            sd->npc_flags.divorce = 0;
-            map_scriptcont (sd, sd->npc_id);
-        }
-    }
-
-    nullpo_retr (0, sd = map_nick2sd (map_charid2nick (partner_id)));
-    if (sd->status.partner_id == char_id)
-        sd->status.partner_id = 0;
-
-    return 0;
-}
-
-/*==========================================
- * Tell character server someone is divorced
- * Needed to divorce when partner is not connected to map server
- *-------------------------------------
- */
-int chrif_send_divorce (int char_id)
-{
-    if (char_fd < 0)
-        return -1;
-
-    WFIFOW (char_fd, 0) = 0x2b16;
-    WFIFOL (char_fd, 2) = char_id;
-    WFIFOSET (char_fd, 6);
-    return 0;
-}
-
-/*==========================================
- * Disconnection of a player (account has been deleted in login-server) by [Yor]
- *------------------------------------------
- */
-int chrif_accountdeletion (int fd)
-{
-    int  acc;
-    struct map_session_data *sd;
-
-    acc = RFIFOL (fd, 2);
-    if (battle_config.etc_log)
-        printf ("chrif_accountdeletion %d.\n", acc);
-    sd = map_id2sd (acc);
-    if (acc > 0)
-    {
-        if (sd != NULL)
-        {
-            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
-            clif_displaymessage (sd->fd,
-                                 "Your account has been deleted (disconnection)...");
-            clif_setwaitclose (sd->fd); // forced to disconnect for the change
-        }
-    }
-    else
-    {
-        if (sd != NULL)
-            printf ("chrif_accountdeletion failed - player not online.\n");
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
- *------------------------------------------
- */
-int chrif_accountban (int fd)
-{
-    int  acc;
-    struct map_session_data *sd;
-
-    acc = RFIFOL (fd, 2);
-    if (battle_config.etc_log)
-        printf ("chrif_accountban %d.\n", acc);
-    sd = map_id2sd (acc);
-    if (acc > 0)
-    {
-        if (sd != NULL)
-        {
-            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
-            if (RFIFOB (fd, 6) == 0)
-            {                   // 0: change of statut, 1: ban
-                switch (RFIFOL (fd, 7))
-                {               // status or final date of a banishment
-                    case 1:    // 0 = Unregistered ID
-                        clif_displaymessage (sd->fd,
-                                             "Your account has 'Unregistered'.");
-                        break;
-                    case 2:    // 1 = Incorrect Password
-                        clif_displaymessage (sd->fd,
-                                             "Your account has an 'Incorrect Password'...");
-                        break;
-                    case 3:    // 2 = This ID is expired
-                        clif_displaymessage (sd->fd,
-                                             "Your account has expired.");
-                        break;
-                    case 4:    // 3 = Rejected from Server
-                        clif_displaymessage (sd->fd,
-                                             "Your account has been rejected from server.");
-                        break;
-                    case 5:    // 4 = You have been blocked by the GM Team
-                        clif_displaymessage (sd->fd,
-                                             "Your account has been blocked by the GM Team.");
-                        break;
-                    case 6:    // 5 = Your Game's EXE file is not the latest version
-                        clif_displaymessage (sd->fd,
-                                             "Your Game's EXE file is not the latest version.");
-                        break;
-                    case 7:    // 6 = Your are Prohibited to log in until %s
-                        clif_displaymessage (sd->fd,
-                                             "Your account has been prohibited to log in.");
-                        break;
-                    case 8:    // 7 = Server is jammed due to over populated
-                        clif_displaymessage (sd->fd,
-                                             "Server is jammed due to over populated.");
-                        break;
-                    case 9:    // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
-                        clif_displaymessage (sd->fd,
-                                             "Your account has not more authorised.");
-                        break;
-                    case 100:  // 99 = This ID has been totally erased
-                        clif_displaymessage (sd->fd,
-                                             "Your account has been totally erased.");
-                        break;
-                    default:
-                        clif_displaymessage (sd->fd,
-                                             "Your account has not more authorised.");
-                        break;
-                }
-            }
-            else if (RFIFOB (fd, 6) == 1)
-            {                   // 0: change of statut, 1: ban
-                time_t timestamp;
-                char tmpstr[2048];
-                timestamp = (time_t) RFIFOL (fd, 7);    // status or final date of a banishment
-                strcpy (tmpstr, "Your account has been banished until ");
-                strftime (tmpstr + strlen (tmpstr), 24, "%d-%m-%Y %H:%M:%S",
-                          gmtime (&timestamp));
-                clif_displaymessage (sd->fd, tmpstr);
-            }
-            clif_setwaitclose (sd->fd); // forced to disconnect for the change
-        }
-    }
-    else
-    {
-        if (sd != NULL)
-            printf ("chrif_accountban failed - player not online.\n");
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Receiving GM accounts and their levels from char-server by [Yor]
- *------------------------------------------
- */
-int chrif_recvgmaccounts (int fd)
-{
-    printf ("From login-server: receiving of %d GM accounts information.\n",
-            pc_read_gm_account (fd));
-
-    return 0;
-}
-
-/*==========================================
- * Request to reload GM accounts and their levels: send to char-server by [Yor]
- *------------------------------------------
- */
-int chrif_reloadGMdb (void)
-{
-
-    WFIFOW (char_fd, 0) = 0x2af7;
-    WFIFOSET (char_fd, 2);
-
-    return 0;
-}
-
-/*==========================================
- * Send rates and motd to char server [Wizputer]
- *------------------------------------------
- */
-int chrif_ragsrvinfo (int base_rate, int job_rate, int drop_rate)
-{
-    char buf[256];
-    FILE *fp;
-    int  i;
-
-    WFIFOW (char_fd, 0) = 0x2b16;
-    WFIFOW (char_fd, 2) = base_rate;
-    WFIFOW (char_fd, 4) = job_rate;
-    WFIFOW (char_fd, 6) = drop_rate;
-
-    if ((fp = fopen_ (motd_txt, "r")) != NULL)
-    {
-        if (fgets (buf, 250, fp) != NULL)
-        {
-            for (i = 0; buf[i]; i++)
-            {
-                if (buf[i] == '\r' || buf[i] == '\n')
-                {
-                    buf[i] = 0;
-                    break;
-                }
-            }
-            WFIFOW (char_fd, 8) = sizeof (buf) + 10;
-            memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
-        }
-        fclose_ (fp);
-    }
-    else
-    {
-        WFIFOW (char_fd, 8) = sizeof (buf) + 10;
-        memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
-    }
-    WFIFOSET (char_fd, WFIFOW (char_fd, 8));
-
-    return 0;
-}
-
-/*=========================================
- * Tell char-server charcter disconnected [Wizputer]
- *-----------------------------------------
- */
-
-int chrif_char_offline (struct map_session_data *sd)
-{
-    if (char_fd < 0)
-        return -1;
-
-    WFIFOW (char_fd, 0) = 0x2b17;
-    WFIFOL (char_fd, 2) = sd->status.char_id;
-    WFIFOSET (char_fd, 6);
-
-    return 0;
-}
-
-/*========================================
- * Map item IDs
- *----------------------------------------
- */
-
-static void ladmin_itemfrob_fix_item (int source, int dest, struct item *item)
-{
-    if (item && item->nameid == source)
-    {
-        item->nameid = dest;
-        item->equip = 0;
-    }
-}
-
-static int ladmin_itemfrob_c2 (struct block_list *bl, int source_id,
-                               int dest_id)
-{
-#define IFIX(v) if (v == source_id) {v = dest_id; }
-#define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item)
-
-    if (!bl)
-        return 0;
-
-    switch (bl->type)
-    {
-        case BL_PC:
-        {
-            struct map_session_data *pc = (struct map_session_data *) bl;
-            struct storage *stor = account2storage2 (pc->status.account_id);
-            int  j;
-
-            for (j = 0; j < MAX_INVENTORY; j++)
-                IFIX (pc->status.inventory[j].nameid);
-            for (j = 0; j < MAX_CART; j++)
-                IFIX (pc->status.cart[j].nameid);
-            IFIX (pc->status.weapon);
-            IFIX (pc->status.shield);
-            IFIX (pc->status.head_top);
-            IFIX (pc->status.head_mid);
-            IFIX (pc->status.head_bottom);
-
-            if (stor)
-                for (j = 0; j < stor->storage_amount; j++)
-                    FIX (stor->storage_[j]);
-
-            for (j = 0; j < MAX_INVENTORY; j++)
-            {
-                struct item_data *item = pc->inventory_data[j];
-                if (item && item->nameid == source_id)
-                {
-                    item->nameid = dest_id;
-                    if (item->equip)
-                        pc_unequipitem (pc, j, 0);
-                    item->nameid = dest_id;
-                }
-            }
-
-            break;
-        }
-
-        case BL_MOB:
-        {
-            struct mob_data *mob = (struct mob_data *) bl;
-            int  i;
-            for (i = 0; i < mob->lootitem_count; i++)
-                FIX (mob->lootitem[i]);
-            break;
-        }
-
-        case BL_ITEM:
-        {
-            struct flooritem_data *item = (struct flooritem_data *) bl;
-            FIX (item->item_data);
-            break;
-        }
-    }
-#undef FIX
-#undef IFIX
-
-    return 0;
-}
-
-int ladmin_itemfrob_c (struct block_list *bl, va_list va_args)
-{
-    int  source_id = va_arg (va_args, int);
-    int  dest_id = va_arg (va_args, int);
-    return ladmin_itemfrob_c2 (bl, source_id, dest_id);
-}
-
-void ladmin_itemfrob (int fd)
-{
-    int  source_id = RFIFOL (fd, 2);
-    int  dest_id = RFIFOL (fd, 6);
-    struct block_list *bl = (struct block_list *) map_get_first_session ();
-
-    // flooritems
-    map_foreachobject (ladmin_itemfrob_c, 0 /* any object */ , source_id,
-                       dest_id);
-
-    // player characters (and, hopefully, mobs)
-    while (bl->next)
-    {
-        ladmin_itemfrob_c2 (bl, source_id, dest_id);
-        bl = bl->next;
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void chrif_parse (int fd)
-{
-    int  packet_len, cmd;
-
-    // only char-server can have an access to here.
-    // so, if it isn't the char-server, we disconnect the session (fd != char_fd).
-    if (fd != char_fd || session[fd]->eof)
-    {
-        if (fd == char_fd)
-        {
-            printf
-                ("Map-server can't connect to char-server (connection #%d).\n",
-                 fd);
-            char_fd = -1;
-        }
-        close (fd);
-        delete_session (fd);
-        return;
-    }
-
-    while (RFIFOREST (fd) >= 2)
-    {
-        cmd = RFIFOW (fd, 0);
-        if (cmd < 0x2af8
-            || cmd >=
-            0x2af8 +
-            (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
-            || packet_len_table[cmd - 0x2af8] == 0)
-        {
-
-            int  r = intif_parse (fd);  // intifに渡す
-
-            if (r == 1)
-                continue;       // intifで処理した
-            if (r == 2)
-                return;       // intifで処理したが、データが足りない
-
-            session[fd]->eof = 1;
-            return;
-        }
-        packet_len = packet_len_table[cmd - 0x2af8];
-        if (packet_len == -1)
-        {
-            if (RFIFOREST (fd) < 4)
-                return;
-            packet_len = RFIFOW (fd, 2);
-        }
-        if (RFIFOREST (fd) < packet_len)
-            return;
-
-        switch (cmd)
-        {
-            case 0x2af9:
-                chrif_connectack (fd);
-                break;
-            case 0x2afa:
-                ladmin_itemfrob (fd);
-                break;
-            case 0x2afb:
-                chrif_sendmapack (fd);
-                break;
-            case 0x2afd:
-                pc_authok (RFIFOL (fd, 4), RFIFOL (fd, 8),
-                           (time_t) RFIFOL (fd, 12), RFIFOW (fd, 16),
-                           (struct mmo_charstatus *) RFIFOP (fd, 18));
-                break;
-            case 0x2afe:
-                pc_authfail (RFIFOL (fd, 2));
-                break;
-            case 0x2b00:
-                map_setusers (RFIFOL (fd, 2));
-                break;
-            case 0x2b03:
-                clif_charselectok (RFIFOL (fd, 2));
-                break;
-            case 0x2b04:
-                chrif_recvmap (fd);
-                break;
-            case 0x2b06:
-                chrif_changemapserverack (fd);
-                break;
-            case 0x2b09:
-                map_addchariddb (RFIFOL (fd, 2), RFIFOP (fd, 6));
-                break;
-            case 0x2b0b:
-                chrif_changedgm (fd);
-                break;
-            case 0x2b0d:
-                chrif_changedsex (fd);
-                break;
-            case 0x2b0f:
-                chrif_char_ask_name_answer (fd);
-                break;
-            case 0x2b11:
-                chrif_accountreg2 (fd);
-                break;
-            case 0x2b12:
-                chrif_divorce (RFIFOL (fd, 2), RFIFOL (fd, 6));
-                break;
-            case 0x2b13:
-                chrif_accountdeletion (fd);
-                break;
-            case 0x2b14:
-                chrif_accountban (fd);
-                break;
-            case 0x2b15:
-                chrif_recvgmaccounts (fd);
-                break;
-
-            default:
-                if (battle_config.error_log)
-                    printf ("chrif_parse : unknown packet %d %d\n", fd,
-                            RFIFOW (fd, 0));
-                session[fd]->eof = 1;
-                return;
-        }
-        RFIFOSKIP (fd, packet_len);
-    }
-}
-
-/*==========================================
- * timer関数
- * 今このmap鯖に繋がっているクライアント人数をchar鯖へ送る
- *------------------------------------------
- */
-void send_users_tochar (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  users = 0, i;
-    struct map_session_data *sd;
-
-    if (char_fd <= 0 || session[char_fd] == NULL)
-        return;
-
-    WFIFOW (char_fd, 0) = 0x2aff;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth &&
-            !((battle_config.hide_GM_session
-               || sd->state.shroud_active
-               || (sd->status.option & OPTION_HIDE)) && pc_isGM (sd)))
-        {
-            WFIFOL (char_fd, 6 + 4 * users) = sd->status.char_id;
-            users++;
-        }
-    }
-    WFIFOW (char_fd, 2) = 6 + 4 * users;
-    WFIFOW (char_fd, 4) = users;
-    WFIFOSET (char_fd, 6 + 4 * users);
-}
-
-/*==========================================
- * timer関数
- * char鯖との接続を確認し、もし切れていたら再度接続する
- *------------------------------------------
- */
-void check_connect_char_server (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    if (char_fd <= 0 || session[char_fd] == NULL)
-    {
-        printf ("Attempt to connect to char-server...\n");
-        chrif_state = 0;
-        if ((char_fd = make_connection (char_ip, char_port)) < 0)
-            return;
-        session[char_fd]->func_parse = chrif_parse;
-        realloc_fifo (char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
-        chrif_connect (char_fd);
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int do_init_chrif (void)
-{
-//    add_timer_func_list (check_connect_char_server, "check_connect_char_server");
-//    add_timer_func_list (send_users_tochar, "send_users_tochar");
-    add_timer_interval (gettick () + 1000, check_connect_char_server, 0, 0,
-                        10 * 1000);
-    add_timer_interval (gettick () + 1000, send_users_tochar, 0, 0, 5 * 1000);
-
-    return 0;
-}
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
new file mode 100644
index 0000000..0223e67
--- /dev/null
+++ b/src/map/chrif.cpp
@@ -0,0 +1,1307 @@
+// $Id: chrif.c,v 1.6 2004/09/25 11:39:17 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef LCCWIN32
+#include <winsock.h>
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <sys/types.h>
+#include <time.h>
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "map.hpp"
+#include "battle.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "../common/nullpo.hpp"
+#include "itemdb.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+static const int packet_len_table[0x20] = {
+    60, 3, 10, 27, 22, -1, 6, -1,   // 2af8-2aff
+    6, -1, 18, 7, -1, 49, 44, 0,    // 2b00-2b07
+    6, 30, -1, 10, 86, 7, 44, 34,   // 2b08-2b0f
+    -1, -1, 10, 6, 11, -1, 0, 0,    // 2b10-2b17
+};
+
+int  char_fd;
+int  srvinfo;
+static char char_ip_str[16];
+static int char_ip;
+static int char_port = 6121;
+static char userid[24], passwd[24];
+static int chrif_state;
+
+// 設定ファイル読み込み関係
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setuserid (char *id)
+{
+    strncpy (userid, id, sizeof(userid)-1);
+    userid[sizeof(userid)-1] = '\0';
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setpasswd (char *pwd)
+{
+    strncpy (passwd, pwd, sizeof(passwd)-1);
+    passwd[sizeof(passwd)-1] = '\0';
+}
+
+char *chrif_getpasswd (void)
+{
+    return passwd;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setip (char *ip)
+{
+    strncpy (char_ip_str, ip, sizeof(char_ip_str)-1);
+    char_ip_str[sizeof(char_ip_str)-1] = '\0';
+    char_ip = inet_addr (char_ip_str);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_setport (int port)
+{
+    char_port = port;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_isconnect (void)
+{
+    return chrif_state == 2;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_save (struct map_session_data *sd)
+{
+    nullpo_retr (-1, sd);
+
+    if (char_fd < 0)
+        return -1;
+
+    pc_makesavestatus (sd);
+
+    WFIFOW (char_fd, 0) = 0x2b01;
+    WFIFOW (char_fd, 2) = sizeof (sd->status) + 12;
+    WFIFOL (char_fd, 4) = sd->bl.id;
+    WFIFOL (char_fd, 8) = sd->char_id;
+    memcpy (WFIFOP (char_fd, 12), &sd->status, sizeof (sd->status));
+    WFIFOSET (char_fd, WFIFOW (char_fd, 2));
+
+    //For data sync
+    if (sd->state.storage_flag == 1)
+        storage_storage_save (sd->status.account_id, 0);
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storagesave (sd->status.account_id, sd->status.guild_id,
+                                   0);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_connect (int fd)
+{
+    WFIFOW (fd, 0) = 0x2af8;
+    memcpy (WFIFOP (fd, 2), userid, 24);
+    memcpy (WFIFOP (fd, 26), passwd, 24);
+    WFIFOL (fd, 50) = 0;
+    WFIFOL (fd, 54) = clif_getip ();
+    WFIFOW (fd, 58) = clif_getport ();  // [Valaris] thanks to fov
+    WFIFOSET (fd, 60);
+
+    return 0;
+}
+
+/*==========================================
+ * マップ送信
+ *------------------------------------------
+ */
+int chrif_sendmap (int fd)
+{
+    int  i;
+
+    WFIFOW (fd, 0) = 0x2afa;
+    for (i = 0; i < map_num; i++)
+        if (map[i].alias[0] != '\0')    // [MouseJstr] map aliasing
+            memcpy (WFIFOP (fd, 4 + i * 16), map[i].alias, 16);
+        else
+            memcpy (WFIFOP (fd, 4 + i * 16), map[i].name, 16);
+    WFIFOW (fd, 2) = 4 + i * 16;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ * マップ受信
+ *------------------------------------------
+ */
+int chrif_recvmap (int fd)
+{
+    int  i, j, ip, port;
+    unsigned char *p = (unsigned char *) &ip;
+
+    if (chrif_state < 2)        // まだ準備中
+        return -1;
+
+    ip = RFIFOL (fd, 4);
+    port = RFIFOW (fd, 8);
+    for (i = 10, j = 0; i < RFIFOW (fd, 2); i += 16, j++)
+    {
+        map_setipport (RFIFOP (fd, i), ip, port);
+//      if (battle_config.etc_log)
+//          printf("recv map %d %s\n", j, RFIFOP(fd,i));
+    }
+    if (battle_config.etc_log)
+        printf ("recv map on %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2],
+                p[3], port, j);
+
+    return 0;
+}
+
+/*==========================================
+ * マップ鯖間移動のためのデータ準備要求
+ *------------------------------------------
+ */
+int chrif_changemapserver (struct map_session_data *sd, char *name, int x,
+                           int y, int ip, short port)
+{
+    int  i, s_ip;
+
+    nullpo_retr (-1, sd);
+
+    s_ip = 0;
+    for (i = 0; i < fd_max; i++)
+        if (session[i] && session[i]->session_data == sd)
+        {
+            s_ip = session[i]->client_addr.sin_addr.s_addr;
+            break;
+        }
+
+    WFIFOW (char_fd, 0) = 0x2b05;
+    WFIFOL (char_fd, 2) = sd->bl.id;
+    WFIFOL (char_fd, 6) = sd->login_id1;
+    WFIFOL (char_fd, 10) = sd->login_id2;
+    WFIFOL (char_fd, 14) = sd->status.char_id;
+    memcpy (WFIFOP (char_fd, 18), name, 16);
+    WFIFOW (char_fd, 34) = x;
+    WFIFOW (char_fd, 36) = y;
+    WFIFOL (char_fd, 38) = ip;
+    WFIFOL (char_fd, 42) = port;
+    WFIFOB (char_fd, 44) = sd->status.sex;
+    WFIFOL (char_fd, 45) = s_ip;
+    WFIFOSET (char_fd, 49);
+
+    return 0;
+}
+
+/*==========================================
+ * マップ鯖間移動ack
+ *------------------------------------------
+ */
+int chrif_changemapserverack (int fd)
+{
+    struct map_session_data *sd = map_id2sd (RFIFOL (fd, 2));
+
+    if (sd == NULL || sd->status.char_id != RFIFOL (fd, 14))
+        return -1;
+
+    if (RFIFOL (fd, 6) == 1)
+    {
+        if (battle_config.error_log)
+            printf ("map server change failed.\n");
+        pc_authfail (sd->fd);
+        return 0;
+    }
+    clif_changemapserver (sd, RFIFOP (fd, 18), RFIFOW (fd, 34),
+                          RFIFOW (fd, 36), RFIFOL (fd, 38), RFIFOW (fd, 42));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_connectack (int fd)
+{
+    if (RFIFOB (fd, 2))
+    {
+        printf ("Connected to char-server failed %d.\n", RFIFOB (fd, 2));
+        exit (1);
+    }
+    printf ("Connected to char-server (connection #%d).\n", fd);
+    chrif_state = 1;
+
+    chrif_sendmap (fd);
+
+    printf ("chrif: OnCharIfInit event done. (%d events)\n",
+            npc_event_doall ("OnCharIfInit"));
+    printf ("chrif: OnInterIfInit event done. (%d events)\n",
+            npc_event_doall ("OnInterIfInit"));
+
+    // <Agit> Run Event [AgitInit]
+//  printf("NPC_Event:[OnAgitInit] do (%d) events (Agit Initialize).\n", npc_event_doall("OnAgitInit"));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_sendmapack (int fd)
+{
+    if (RFIFOB (fd, 2))
+    {
+        printf ("chrif : send map list to char server failed %d\n",
+                RFIFOB (fd, 2));
+        exit (1);
+    }
+
+    memcpy (wisp_server_name, RFIFOP (fd, 3), 24);
+
+    chrif_state = 2;
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_authreq (struct map_session_data *sd)
+{
+    int  i;
+
+    nullpo_retr (-1, sd);
+
+    if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+        return -1;
+
+    for (i = 0; i < fd_max; i++)
+        if (session[i] && session[i]->session_data == sd)
+        {
+            WFIFOW (char_fd, 0) = 0x2afc;
+            WFIFOL (char_fd, 2) = sd->bl.id;
+            WFIFOL (char_fd, 6) = sd->char_id;
+            WFIFOL (char_fd, 10) = sd->login_id1;
+            WFIFOL (char_fd, 14) = sd->login_id2;
+            WFIFOL (char_fd, 18) = session[i]->client_addr.sin_addr.s_addr;
+            WFIFOSET (char_fd, 22);
+            break;
+        }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int chrif_charselectreq (struct map_session_data *sd)
+{
+    int  i, s_ip;
+
+    nullpo_retr (-1, sd);
+
+    if (!sd || !char_fd || !sd->bl.id || !sd->login_id1)
+        return -1;
+
+    s_ip = 0;
+    for (i = 0; i < fd_max; i++)
+        if (session[i] && session[i]->session_data == sd)
+        {
+            s_ip = session[i]->client_addr.sin_addr.s_addr;
+            break;
+        }
+
+    WFIFOW (char_fd, 0) = 0x2b02;
+    WFIFOL (char_fd, 2) = sd->bl.id;
+    WFIFOL (char_fd, 6) = sd->login_id1;
+    WFIFOL (char_fd, 10) = sd->login_id2;
+    WFIFOL (char_fd, 14) = s_ip;
+    WFIFOSET (char_fd, 18);
+
+    return 0;
+}
+
+/*==========================================
+ * キャラ名問い合わせ
+ *------------------------------------------
+ */
+int chrif_searchcharid (int char_id)
+{
+    if (!char_id)
+        return -1;
+
+    WFIFOW (char_fd, 0) = 0x2b08;
+    WFIFOL (char_fd, 2) = char_id;
+    WFIFOSET (char_fd, 6);
+
+    return 0;
+}
+
+/*==========================================
+ * GMに変化要求
+ *------------------------------------------
+ */
+int chrif_changegm (int id, const char *pass, int len)
+{
+    if (battle_config.etc_log)
+        printf ("chrif_changegm: account: %d, password: '%s'.\n", id, pass);
+
+    WFIFOW (char_fd, 0) = 0x2b0a;
+    WFIFOW (char_fd, 2) = len + 8;
+    WFIFOL (char_fd, 4) = id;
+    memcpy (WFIFOP (char_fd, 8), pass, len);
+    WFIFOSET (char_fd, len + 8);
+
+    return 0;
+}
+
+/*==========================================
+ * Change Email
+ *------------------------------------------
+ */
+int chrif_changeemail (int id, const char *actual_email,
+                       const char *new_email)
+{
+    if (battle_config.etc_log)
+        printf
+            ("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n",
+             id, actual_email, new_email);
+
+    WFIFOW (char_fd, 0) = 0x2b0c;
+    WFIFOL (char_fd, 2) = id;
+    memcpy (WFIFOP (char_fd, 6), actual_email, 40);
+    memcpy (WFIFOP (char_fd, 46), new_email, 40);
+    WFIFOSET (char_fd, 86);
+
+    return 0;
+}
+
+/*==========================================
+ * Send message to char-server with a character name to do some operations (by Yor)
+ * Used to ask Char-server about a character name to have the account number to modify account file in login-server.
+ * type of operation:
+ *   1: block
+ *   2: ban
+ *   3: unblock
+ *   4: unban
+ *   5: changesex
+ *------------------------------------------
+ */
+int chrif_char_ask_name (int id, char *character_name, short operation_type,
+                         int year, int month, int day, int hour, int minute,
+                         int second)
+{
+    WFIFOW (char_fd, 0) = 0x2b0e;
+    WFIFOL (char_fd, 2) = id;   // account_id of who ask (for answer) -1 if nobody
+    memcpy (WFIFOP (char_fd, 6), character_name, 24);
+    WFIFOW (char_fd, 30) = operation_type;  // type of operation
+    if (operation_type == 2)
+    {
+        WFIFOW (char_fd, 32) = year;
+        WFIFOW (char_fd, 34) = month;
+        WFIFOW (char_fd, 36) = day;
+        WFIFOW (char_fd, 38) = hour;
+        WFIFOW (char_fd, 40) = minute;
+        WFIFOW (char_fd, 42) = second;
+    }
+    printf ("chrif : sended 0x2b0e\n");
+    WFIFOSET (char_fd, 44);
+
+    return 0;
+}
+
+/*==========================================
+ * Answer after a request about a character name to do some operations (by Yor)
+ * Used to answer of chrif_char_ask_name.
+ * type of operation:
+ *   1: block
+ *   2: ban
+ *   3: unblock
+ *   4: unban
+ *   5: changesex
+ * type of answer:
+ *   0: login-server resquest done
+ *   1: player not found
+ *   2: gm level too low
+ *   3: login-server offline
+ *------------------------------------------
+ */
+int chrif_char_ask_name_answer (int fd)
+{
+    int  acc;
+    struct map_session_data *sd;
+    char output[256];
+    char player_name[24];
+
+    acc = RFIFOL (fd, 2);       // account_id of who has asked (-1 if nobody)
+    memcpy (player_name, RFIFOP (fd, 6), sizeof (player_name));
+    player_name[sizeof (player_name) - 1] = '\0';
+
+    sd = map_id2sd (acc);
+    if (acc >= 0 && sd != NULL)
+    {
+        if (RFIFOW (fd, 32) == 1)   // player not found
+            sprintf (output, "The player '%s' doesn't exist.", player_name);
+        else
+        {
+            switch (RFIFOW (fd, 30))
+            {
+                case 1:        // block
+                    switch (RFIFOW (fd, 32))
+                    {
+                        case 0:    // login-server resquest done
+                            sprintf (output,
+                                     "Login-server has been asked to block the player '%s'.",
+                                     player_name);
+                            break;
+                            //case 1: // player not found
+                        case 2:    // gm level too low
+                            sprintf (output,
+                                     "Your GM level don't authorise you to block the player '%s'.",
+                                     player_name);
+                            break;
+                        case 3:    // login-server offline
+                            sprintf (output,
+                                     "Login-server is offline. Impossible to block the the player '%s'.",
+                                     player_name);
+                            break;
+                    }
+                    break;
+                case 2:        // ban
+                    switch (RFIFOW (fd, 32))
+                    {
+                        case 0:    // login-server resquest done
+                            sprintf (output,
+                                     "Login-server has been asked to ban the player '%s'.",
+                                     player_name);
+                            break;
+                            //case 1: // player not found
+                        case 2:    // gm level too low
+                            sprintf (output,
+                                     "Your GM level don't authorise you to ban the player '%s'.",
+                                     player_name);
+                            break;
+                        case 3:    // login-server offline
+                            sprintf (output,
+                                     "Login-server is offline. Impossible to ban the the player '%s'.",
+                                     player_name);
+                            break;
+                    }
+                    break;
+                case 3:        // unblock
+                    switch (RFIFOW (fd, 32))
+                    {
+                        case 0:    // login-server resquest done
+                            sprintf (output,
+                                     "Login-server has been asked to unblock the player '%s'.",
+                                     player_name);
+                            break;
+                            //case 1: // player not found
+                        case 2:    // gm level too low
+                            sprintf (output,
+                                     "Your GM level don't authorise you to unblock the player '%s'.",
+                                     player_name);
+                            break;
+                        case 3:    // login-server offline
+                            sprintf (output,
+                                     "Login-server is offline. Impossible to unblock the the player '%s'.",
+                                     player_name);
+                            break;
+                    }
+                    break;
+                case 4:        // unban
+                    switch (RFIFOW (fd, 32))
+                    {
+                        case 0:    // login-server resquest done
+                            sprintf (output,
+                                     "Login-server has been asked to unban the player '%s'.",
+                                     player_name);
+                            break;
+                            //case 1: // player not found
+                        case 2:    // gm level too low
+                            sprintf (output,
+                                     "Your GM level don't authorise you to unban the player '%s'.",
+                                     player_name);
+                            break;
+                        case 3:    // login-server offline
+                            sprintf (output,
+                                     "Login-server is offline. Impossible to unban the the player '%s'.",
+                                     player_name);
+                            break;
+                    }
+                    break;
+                case 5:        // changesex
+                    switch (RFIFOW (fd, 32))
+                    {
+                        case 0:    // login-server resquest done
+                            sprintf (output,
+                                     "Login-server has been asked to change the sex of the player '%s'.",
+                                     player_name);
+                            break;
+                            //case 1: // player not found
+                        case 2:    // gm level too low
+                            sprintf (output,
+                                     "Your GM level don't authorise you to change the sex of the player '%s'.",
+                                     player_name);
+                            break;
+                        case 3:    // login-server offline
+                            sprintf (output,
+                                     "Login-server is offline. Impossible to change the sex of the the player '%s'.",
+                                     player_name);
+                            break;
+                    }
+                    break;
+            }
+        }
+        if (output[0] != '\0')
+        {
+            output[sizeof (output) - 1] = '\0';
+            clif_displaymessage (sd->fd, output);
+        }
+    }
+    else
+        printf ("chrif_char_ask_name_answer failed - player not online.\n");
+
+    return 0;
+}
+
+/*==========================================
+ * End of GM change (@GM) (modified by Yor)
+ *------------------------------------------
+ */
+int chrif_changedgm (int fd)
+{
+    int  acc, level;
+    struct map_session_data *sd = NULL;
+
+    acc = RFIFOL (fd, 2);
+    level = RFIFOL (fd, 6);
+
+    sd = map_id2sd (acc);
+
+    if (battle_config.etc_log)
+        printf ("chrif_changedgm: account: %d, GM level 0 -> %d.\n", acc,
+                level);
+    if (sd != NULL)
+    {
+        if (level > 0)
+            clif_displaymessage (sd->fd, "GM modification success.");
+        else
+            clif_displaymessage (sd->fd, "Failure of GM modification.");
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 性別変化終了 (modified by Yor)
+ *------------------------------------------
+ */
+int chrif_changedsex (int fd)
+{
+    int  acc, sex, i;
+    struct map_session_data *sd;
+    struct pc_base_job s_class;
+
+    acc = RFIFOL (fd, 2);
+    sex = RFIFOL (fd, 6);
+    if (battle_config.etc_log)
+        printf ("chrif_changedsex %d.\n", acc);
+    sd = map_id2sd (acc);
+    if (acc > 0)
+    {
+        if (sd != NULL && sd->status.sex != sex)
+        {
+            s_class = pc_calc_base_job (sd->status.pc_class);
+            if (sd->status.sex == 0)
+            {
+                sd->status.sex = 1;
+                sd->sex = 1;
+            }
+            else if (sd->status.sex == 1)
+            {
+                sd->status.sex = 0;
+                sd->sex = 0;
+            }
+            // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+            for (i = 0; i < MAX_INVENTORY; i++)
+            {
+                if (sd->status.inventory[i].nameid
+                    && sd->status.inventory[i].equip)
+                    pc_unequipitem ((struct map_session_data *) sd, i, 0);
+            }
+            // reset skill of some job
+            if (s_class.job == 19 || s_class.job == 4020
+                || s_class.job == 4042 || s_class.job == 20
+                || s_class.job == 4021 || s_class.job == 4043)
+            {
+
+                clif_updatestatus (sd, SP_SKILLPOINT);
+                // change job if necessary
+                if (s_class.job == 20 || s_class.job == 4021
+                    || s_class.job == 4043)
+                    sd->status.pc_class -= 1;
+                else if (s_class.job == 19 || s_class.job == 4020
+                         || s_class.job == 4042)
+                    sd->status.pc_class += 1;
+            }
+            // save character
+            chrif_save (sd);
+            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
+            // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
+            clif_displaymessage (sd->fd,
+                                 "Your sex has been changed (need disconexion by the server)...");
+            clif_setwaitclose (sd->fd); // forced to disconnect for the change
+        }
+    }
+    else
+    {
+        if (sd != NULL)
+        {
+            printf ("chrif_changedsex failed.\n");
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * アカウント変数保存要求
+ *------------------------------------------
+ */
+int chrif_saveaccountreg2 (struct map_session_data *sd)
+{
+    int  p, j;
+    nullpo_retr (-1, sd);
+
+    p = 8;
+    for (j = 0; j < sd->status.account_reg2_num; j++)
+    {
+        struct global_reg *reg = &sd->status.account_reg2[j];
+        if (reg->str[0] && reg->value != 0)
+        {
+            memcpy (WFIFOP (char_fd, p), reg->str, 32);
+            WFIFOL (char_fd, p + 32) = reg->value;
+            p += 36;
+        }
+    }
+    WFIFOW (char_fd, 0) = 0x2b10;
+    WFIFOW (char_fd, 2) = p;
+    WFIFOL (char_fd, 4) = sd->bl.id;
+    WFIFOSET (char_fd, p);
+
+    return 0;
+}
+
+/*==========================================
+ * アカウント変数通知
+ *------------------------------------------
+ */
+int chrif_accountreg2 (int fd)
+{
+    int  j, p;
+    struct map_session_data *sd;
+
+    if ((sd = map_id2sd (RFIFOL (fd, 4))) == NULL)
+        return 1;
+
+    for (p = 8, j = 0; p < RFIFOW (fd, 2) && j < ACCOUNT_REG2_NUM;
+         p += 36, j++)
+    {
+        memcpy (sd->status.account_reg2[j].str, RFIFOP (fd, p), 32);
+        sd->status.account_reg2[j].value = RFIFOL (fd, p + 32);
+    }
+    sd->status.account_reg2_num = j;
+//  printf("chrif: accountreg2\n");
+
+    return 0;
+}
+
+/*==========================================
+ * Divorce request from char server
+ * triggered on account deletion or as an
+ * ack from a map-server divorce request
+ *------------------------------------------
+ */
+int chrif_divorce (int char_id, int partner_id)
+{
+    struct map_session_data *sd = NULL;
+
+    if (!char_id || !partner_id)
+        return 0;
+
+    sd = map_nick2sd (map_charid2nick (char_id));
+    if (sd && sd->status.partner_id == partner_id)
+    {
+        sd->status.partner_id = 0;
+
+        if (sd->npc_flags.divorce)
+        {
+            sd->npc_flags.divorce = 0;
+            map_scriptcont (sd, sd->npc_id);
+        }
+    }
+
+    nullpo_retr (0, sd = map_nick2sd (map_charid2nick (partner_id)));
+    if (sd->status.partner_id == char_id)
+        sd->status.partner_id = 0;
+
+    return 0;
+}
+
+/*==========================================
+ * Tell character server someone is divorced
+ * Needed to divorce when partner is not connected to map server
+ *-------------------------------------
+ */
+int chrif_send_divorce (int char_id)
+{
+    if (char_fd < 0)
+        return -1;
+
+    WFIFOW (char_fd, 0) = 0x2b16;
+    WFIFOL (char_fd, 2) = char_id;
+    WFIFOSET (char_fd, 6);
+    return 0;
+}
+
+/*==========================================
+ * Disconnection of a player (account has been deleted in login-server) by [Yor]
+ *------------------------------------------
+ */
+int chrif_accountdeletion (int fd)
+{
+    int  acc;
+    struct map_session_data *sd;
+
+    acc = RFIFOL (fd, 2);
+    if (battle_config.etc_log)
+        printf ("chrif_accountdeletion %d.\n", acc);
+    sd = map_id2sd (acc);
+    if (acc > 0)
+    {
+        if (sd != NULL)
+        {
+            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
+            clif_displaymessage (sd->fd,
+                                 "Your account has been deleted (disconnection)...");
+            clif_setwaitclose (sd->fd); // forced to disconnect for the change
+        }
+    }
+    else
+    {
+        if (sd != NULL)
+            printf ("chrif_accountdeletion failed - player not online.\n");
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
+ *------------------------------------------
+ */
+int chrif_accountban (int fd)
+{
+    int  acc;
+    struct map_session_data *sd;
+
+    acc = RFIFOL (fd, 2);
+    if (battle_config.etc_log)
+        printf ("chrif_accountban %d.\n", acc);
+    sd = map_id2sd (acc);
+    if (acc > 0)
+    {
+        if (sd != NULL)
+        {
+            sd->login_id1++;    // change identify, because if player come back in char within the 5 seconds, he can change its characters
+            if (RFIFOB (fd, 6) == 0)
+            {                   // 0: change of statut, 1: ban
+                switch (RFIFOL (fd, 7))
+                {               // status or final date of a banishment
+                    case 1:    // 0 = Unregistered ID
+                        clif_displaymessage (sd->fd,
+                                             "Your account has 'Unregistered'.");
+                        break;
+                    case 2:    // 1 = Incorrect Password
+                        clif_displaymessage (sd->fd,
+                                             "Your account has an 'Incorrect Password'...");
+                        break;
+                    case 3:    // 2 = This ID is expired
+                        clif_displaymessage (sd->fd,
+                                             "Your account has expired.");
+                        break;
+                    case 4:    // 3 = Rejected from Server
+                        clif_displaymessage (sd->fd,
+                                             "Your account has been rejected from server.");
+                        break;
+                    case 5:    // 4 = You have been blocked by the GM Team
+                        clif_displaymessage (sd->fd,
+                                             "Your account has been blocked by the GM Team.");
+                        break;
+                    case 6:    // 5 = Your Game's EXE file is not the latest version
+                        clif_displaymessage (sd->fd,
+                                             "Your Game's EXE file is not the latest version.");
+                        break;
+                    case 7:    // 6 = Your are Prohibited to log in until %s
+                        clif_displaymessage (sd->fd,
+                                             "Your account has been prohibited to log in.");
+                        break;
+                    case 8:    // 7 = Server is jammed due to over populated
+                        clif_displaymessage (sd->fd,
+                                             "Server is jammed due to over populated.");
+                        break;
+                    case 9:    // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
+                        clif_displaymessage (sd->fd,
+                                             "Your account has not more authorised.");
+                        break;
+                    case 100:  // 99 = This ID has been totally erased
+                        clif_displaymessage (sd->fd,
+                                             "Your account has been totally erased.");
+                        break;
+                    default:
+                        clif_displaymessage (sd->fd,
+                                             "Your account has not more authorised.");
+                        break;
+                }
+            }
+            else if (RFIFOB (fd, 6) == 1)
+            {                   // 0: change of statut, 1: ban
+                time_t timestamp;
+                char tmpstr[2048];
+                timestamp = (time_t) RFIFOL (fd, 7);    // status or final date of a banishment
+                strcpy (tmpstr, "Your account has been banished until ");
+                strftime (tmpstr + strlen (tmpstr), 24, "%d-%m-%Y %H:%M:%S",
+                          gmtime (&timestamp));
+                clif_displaymessage (sd->fd, tmpstr);
+            }
+            clif_setwaitclose (sd->fd); // forced to disconnect for the change
+        }
+    }
+    else
+    {
+        if (sd != NULL)
+            printf ("chrif_accountban failed - player not online.\n");
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Receiving GM accounts and their levels from char-server by [Yor]
+ *------------------------------------------
+ */
+int chrif_recvgmaccounts (int fd)
+{
+    printf ("From login-server: receiving of %d GM accounts information.\n",
+            pc_read_gm_account (fd));
+
+    return 0;
+}
+
+/*==========================================
+ * Request to reload GM accounts and their levels: send to char-server by [Yor]
+ *------------------------------------------
+ */
+int chrif_reloadGMdb (void)
+{
+
+    WFIFOW (char_fd, 0) = 0x2af7;
+    WFIFOSET (char_fd, 2);
+
+    return 0;
+}
+
+/*==========================================
+ * Send rates and motd to char server [Wizputer]
+ *------------------------------------------
+ */
+int chrif_ragsrvinfo (int base_rate, int job_rate, int drop_rate)
+{
+    char buf[256];
+    FILE *fp;
+    int  i;
+
+    WFIFOW (char_fd, 0) = 0x2b16;
+    WFIFOW (char_fd, 2) = base_rate;
+    WFIFOW (char_fd, 4) = job_rate;
+    WFIFOW (char_fd, 6) = drop_rate;
+
+    if ((fp = fopen_ (motd_txt, "r")) != NULL)
+    {
+        if (fgets (buf, 250, fp) != NULL)
+        {
+            for (i = 0; buf[i]; i++)
+            {
+                if (buf[i] == '\r' || buf[i] == '\n')
+                {
+                    buf[i] = 0;
+                    break;
+                }
+            }
+            WFIFOW (char_fd, 8) = sizeof (buf) + 10;
+            memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
+        }
+        fclose_ (fp);
+    }
+    else
+    {
+        WFIFOW (char_fd, 8) = sizeof (buf) + 10;
+        memcpy (WFIFOP (char_fd, 10), buf, sizeof (buf));
+    }
+    WFIFOSET (char_fd, WFIFOW (char_fd, 8));
+
+    return 0;
+}
+
+/*=========================================
+ * Tell char-server charcter disconnected [Wizputer]
+ *-----------------------------------------
+ */
+
+int chrif_char_offline (struct map_session_data *sd)
+{
+    if (char_fd < 0)
+        return -1;
+
+    WFIFOW (char_fd, 0) = 0x2b17;
+    WFIFOL (char_fd, 2) = sd->status.char_id;
+    WFIFOSET (char_fd, 6);
+
+    return 0;
+}
+
+/*========================================
+ * Map item IDs
+ *----------------------------------------
+ */
+
+static void ladmin_itemfrob_fix_item (int source, int dest, struct item *item)
+{
+    if (item && item->nameid == source)
+    {
+        item->nameid = dest;
+        item->equip = 0;
+    }
+}
+
+static int ladmin_itemfrob_c2 (struct block_list *bl, int source_id,
+                               int dest_id)
+{
+#define IFIX(v) if (v == source_id) {v = dest_id; }
+#define FIX(item) ladmin_itemfrob_fix_item(source_id, dest_id, &item)
+
+    if (!bl)
+        return 0;
+
+    switch (bl->type)
+    {
+        case BL_PC:
+        {
+            struct map_session_data *pc = (struct map_session_data *) bl;
+            struct storage *stor = account2storage2 (pc->status.account_id);
+            int  j;
+
+            for (j = 0; j < MAX_INVENTORY; j++)
+                IFIX (pc->status.inventory[j].nameid);
+            for (j = 0; j < MAX_CART; j++)
+                IFIX (pc->status.cart[j].nameid);
+            IFIX (pc->status.weapon);
+            IFIX (pc->status.shield);
+            IFIX (pc->status.head_top);
+            IFIX (pc->status.head_mid);
+            IFIX (pc->status.head_bottom);
+
+            if (stor)
+                for (j = 0; j < stor->storage_amount; j++)
+                    FIX (stor->storage_[j]);
+
+            for (j = 0; j < MAX_INVENTORY; j++)
+            {
+                struct item_data *item = pc->inventory_data[j];
+                if (item && item->nameid == source_id)
+                {
+                    item->nameid = dest_id;
+                    if (item->equip)
+                        pc_unequipitem (pc, j, 0);
+                    item->nameid = dest_id;
+                }
+            }
+
+            break;
+        }
+
+        case BL_MOB:
+        {
+            struct mob_data *mob = (struct mob_data *) bl;
+            int  i;
+            for (i = 0; i < mob->lootitem_count; i++)
+                FIX (mob->lootitem[i]);
+            break;
+        }
+
+        case BL_ITEM:
+        {
+            struct flooritem_data *item = (struct flooritem_data *) bl;
+            FIX (item->item_data);
+            break;
+        }
+    }
+#undef FIX
+#undef IFIX
+
+    return 0;
+}
+
+int ladmin_itemfrob_c (struct block_list *bl, va_list va_args)
+{
+    int  source_id = va_arg (va_args, int);
+    int  dest_id = va_arg (va_args, int);
+    return ladmin_itemfrob_c2 (bl, source_id, dest_id);
+}
+
+void ladmin_itemfrob (int fd)
+{
+    int  source_id = RFIFOL (fd, 2);
+    int  dest_id = RFIFOL (fd, 6);
+    struct block_list *bl = (struct block_list *) map_get_first_session ();
+
+    // flooritems
+    map_foreachobject (ladmin_itemfrob_c, 0 /* any object */ , source_id,
+                       dest_id);
+
+    // player characters (and, hopefully, mobs)
+    while (bl->next)
+    {
+        ladmin_itemfrob_c2 (bl, source_id, dest_id);
+        bl = bl->next;
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void chrif_parse (int fd)
+{
+    int  packet_len, cmd;
+
+    // only char-server can have an access to here.
+    // so, if it isn't the char-server, we disconnect the session (fd != char_fd).
+    if (fd != char_fd || session[fd]->eof)
+    {
+        if (fd == char_fd)
+        {
+            printf
+                ("Map-server can't connect to char-server (connection #%d).\n",
+                 fd);
+            char_fd = -1;
+        }
+        close (fd);
+        delete_session (fd);
+        return;
+    }
+
+    while (RFIFOREST (fd) >= 2)
+    {
+        cmd = RFIFOW (fd, 0);
+        if (cmd < 0x2af8
+            || cmd >=
+            0x2af8 +
+            (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
+            || packet_len_table[cmd - 0x2af8] == 0)
+        {
+
+            int  r = intif_parse (fd);  // intifに渡す
+
+            if (r == 1)
+                continue;       // intifで処理した
+            if (r == 2)
+                return;       // intifで処理したが、データが足りない
+
+            session[fd]->eof = 1;
+            return;
+        }
+        packet_len = packet_len_table[cmd - 0x2af8];
+        if (packet_len == -1)
+        {
+            if (RFIFOREST (fd) < 4)
+                return;
+            packet_len = RFIFOW (fd, 2);
+        }
+        if (RFIFOREST (fd) < packet_len)
+            return;
+
+        switch (cmd)
+        {
+            case 0x2af9:
+                chrif_connectack (fd);
+                break;
+            case 0x2afa:
+                ladmin_itemfrob (fd);
+                break;
+            case 0x2afb:
+                chrif_sendmapack (fd);
+                break;
+            case 0x2afd:
+                pc_authok (RFIFOL (fd, 4), RFIFOL (fd, 8),
+                           (time_t) RFIFOL (fd, 12), RFIFOW (fd, 16),
+                           (struct mmo_charstatus *) RFIFOP (fd, 18));
+                break;
+            case 0x2afe:
+                pc_authfail (RFIFOL (fd, 2));
+                break;
+            case 0x2b00:
+                map_setusers (RFIFOL (fd, 2));
+                break;
+            case 0x2b03:
+                clif_charselectok (RFIFOL (fd, 2));
+                break;
+            case 0x2b04:
+                chrif_recvmap (fd);
+                break;
+            case 0x2b06:
+                chrif_changemapserverack (fd);
+                break;
+            case 0x2b09:
+                map_addchariddb (RFIFOL (fd, 2), RFIFOP (fd, 6));
+                break;
+            case 0x2b0b:
+                chrif_changedgm (fd);
+                break;
+            case 0x2b0d:
+                chrif_changedsex (fd);
+                break;
+            case 0x2b0f:
+                chrif_char_ask_name_answer (fd);
+                break;
+            case 0x2b11:
+                chrif_accountreg2 (fd);
+                break;
+            case 0x2b12:
+                chrif_divorce (RFIFOL (fd, 2), RFIFOL (fd, 6));
+                break;
+            case 0x2b13:
+                chrif_accountdeletion (fd);
+                break;
+            case 0x2b14:
+                chrif_accountban (fd);
+                break;
+            case 0x2b15:
+                chrif_recvgmaccounts (fd);
+                break;
+
+            default:
+                if (battle_config.error_log)
+                    printf ("chrif_parse : unknown packet %d %d\n", fd,
+                            RFIFOW (fd, 0));
+                session[fd]->eof = 1;
+                return;
+        }
+        RFIFOSKIP (fd, packet_len);
+    }
+}
+
+/*==========================================
+ * timer関数
+ * 今このmap鯖に繋がっているクライアント人数をchar鯖へ送る
+ *------------------------------------------
+ */
+void send_users_tochar (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  users = 0, i;
+    struct map_session_data *sd;
+
+    if (char_fd <= 0 || session[char_fd] == NULL)
+        return;
+
+    WFIFOW (char_fd, 0) = 0x2aff;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth &&
+            !((battle_config.hide_GM_session
+               || sd->state.shroud_active
+               || (sd->status.option & OPTION_HIDE)) && pc_isGM (sd)))
+        {
+            WFIFOL (char_fd, 6 + 4 * users) = sd->status.char_id;
+            users++;
+        }
+    }
+    WFIFOW (char_fd, 2) = 6 + 4 * users;
+    WFIFOW (char_fd, 4) = users;
+    WFIFOSET (char_fd, 6 + 4 * users);
+}
+
+/*==========================================
+ * timer関数
+ * char鯖との接続を確認し、もし切れていたら再度接続する
+ *------------------------------------------
+ */
+void check_connect_char_server (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    if (char_fd <= 0 || session[char_fd] == NULL)
+    {
+        printf ("Attempt to connect to char-server...\n");
+        chrif_state = 0;
+        if ((char_fd = make_connection (char_ip, char_port)) < 0)
+            return;
+        session[char_fd]->func_parse = chrif_parse;
+        realloc_fifo (char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+
+        chrif_connect (char_fd);
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int do_init_chrif (void)
+{
+//    add_timer_func_list (check_connect_char_server, "check_connect_char_server");
+//    add_timer_func_list (send_users_tochar, "send_users_tochar");
+    add_timer_interval (gettick () + 1000, check_connect_char_server, 0, 0,
+                        10 * 1000);
+    add_timer_interval (gettick () + 1000, send_users_tochar, 0, 0, 5 * 1000);
+
+    return 0;
+}
diff --git a/src/map/chrif.h b/src/map/chrif.h
deleted file mode 100644
index e891be7..0000000
--- a/src/map/chrif.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// $Id: chrif.h,v 1.3 2004/09/25 11:39:17 MouseJstr Exp $
-#ifndef _CHRIF_H_
-#define _CHRIF_H_
-
-void chrif_setuserid (char *);
-void chrif_setpasswd (char *);
-char *chrif_getpasswd (void);
-
-void chrif_setip (char *);
-void chrif_setport (int);
-
-int  chrif_isconnect (void);
-
-int  chrif_authreq (struct map_session_data *);
-int  chrif_save (struct map_session_data *);
-int  chrif_charselectreq (struct map_session_data *);
-
-int  chrif_changemapserver (struct map_session_data *sd, char *name, int x,
-                            int y, int ip, short port);
-
-int  chrif_searchcharid (int char_id);
-int  chrif_changegm (int id, const char *pass, int len);
-int  chrif_changeemail (int id, const char *actual_email,
-                        const char *new_email);
-int  chrif_char_ask_name (int id, char *character_name, short operation_type,
-                          int year, int month, int day, int hour, int minute,
-                          int second);
-int  chrif_saveaccountreg2 (struct map_session_data *sd);
-int  chrif_reloadGMdb (void);
-int  chrif_ragsrvinfo (int base_rate, int job_rate, int drop_rate);
-int  chrif_char_offline (struct map_session_data *sd);
-int  chrif_send_divorce (int char_id);
-
-int  do_init_chrif (void);
-
-#endif
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
new file mode 100644
index 0000000..5b0341e
--- /dev/null
+++ b/src/map/chrif.hpp
@@ -0,0 +1,36 @@
+// $Id: chrif.h,v 1.3 2004/09/25 11:39:17 MouseJstr Exp $
+#ifndef CHRIF_HPP
+#define CHRIF_HPP
+
+void chrif_setuserid (char *);
+void chrif_setpasswd (char *);
+char *chrif_getpasswd (void);
+
+void chrif_setip (char *);
+void chrif_setport (int);
+
+int  chrif_isconnect (void);
+
+int  chrif_authreq (struct map_session_data *);
+int  chrif_save (struct map_session_data *);
+int  chrif_charselectreq (struct map_session_data *);
+
+int  chrif_changemapserver (struct map_session_data *sd, char *name, int x,
+                            int y, int ip, short port);
+
+int  chrif_searchcharid (int char_id);
+int  chrif_changegm (int id, const char *pass, int len);
+int  chrif_changeemail (int id, const char *actual_email,
+                        const char *new_email);
+int  chrif_char_ask_name (int id, char *character_name, short operation_type,
+                          int year, int month, int day, int hour, int minute,
+                          int second);
+int  chrif_saveaccountreg2 (struct map_session_data *sd);
+int  chrif_reloadGMdb (void);
+int  chrif_ragsrvinfo (int base_rate, int job_rate, int drop_rate);
+int  chrif_char_offline (struct map_session_data *sd);
+int  chrif_send_divorce (int char_id);
+
+int  do_init_chrif (void);
+
+#endif
diff --git a/src/map/clif.c b/src/map/clif.c
deleted file mode 100644
index 30348fe..0000000
--- a/src/map/clif.c
+++ /dev/null
@@ -1,10332 +0,0 @@
-// $Id: clif.c 164 2004-10-01 16:46:58Z $
-
-#define DUMP_UNKNOWN_PACKET	1
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#ifdef LCCWIN32
-#include <winsock.h>
-#else
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include <time.h>
-
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/version.h"
-#include "../common/nullpo.h"
-#include "../common/md5calc.h"
-#include "../common/mt_rand.h"
-
-#include "atcommand.h"
-#include "battle.h"
-#include "chat.h"
-#include "chrif.h"
-#include "clif.h"
-#include "guild.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "magic.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "storage.h"
-#include "tmw.h"
-#include "trade.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define STATE_BLIND 0x10
-#define EMOTE_IGNORED 0x0e
-
-static const int packet_len_table[0x220] = {
-    10, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-//#0x0040
-    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, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3, 108, 3, 2,
-    3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
-//#0x0080
-    7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, // 0x8b unknown... size 2 or 23?
-    7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
-    23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
-    8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
-//#0x00C0
-    7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
-    3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
-    30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
-    3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
-
-//#0x0100
-    2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
-    10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
-    6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
-    6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
-//#0x0140
-    22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
-    110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
-    -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14, 186, 182,
-    14, 30, 10, 3, -1, 6, 106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
-//#0x0180
-    6, 3, 106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
-    90, 86, 24, 6, 30, 102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6,
-    3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
-    11, 7, -1, 67, 12, 18, 114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
-//#0x01C0,   Set 0x1d5=-1
-    2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 30, 6, 28,
-    8, 14, 10, 35, 6, -1, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
-    30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
-    -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
-//#0x200
-    26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 19, 10, -1, 24, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-// local define
-enum
-{
-    ALL_CLIENT,
-    ALL_SAMEMAP,
-    AREA,
-    AREA_WOS,
-    AREA_WOC,
-    AREA_WOSC,
-    AREA_CHAT_WOC,
-    CHAT,
-    CHAT_WOS,
-    PARTY,
-    PARTY_WOS,
-    PARTY_SAMEMAP,
-    PARTY_SAMEMAP_WOS,
-    PARTY_AREA,
-    PARTY_AREA_WOS,
-    GUILD,
-    GUILD_WOS,
-    GUILD_SAMEMAP,              // [Valaris]
-    GUILD_SAMEMAP_WOS,
-    GUILD_AREA,
-    GUILD_AREA_WOS,             // end additions [Valaris]
-    SELF
-};
-
-#define WBUFPOS(p,pos,x,y) { unsigned char *__p = (p); __p+=(pos); __p[0] = (x)>>2; __p[1] = ((x)<<6) | (((y)>>4)&0x3f); __p[2] = (y)<<4; }
-#define WBUFPOS2(p,pos,x0,y0,x1,y1) { unsigned char *__p = (p); __p+=(pos); __p[0] = (x0)>>2; __p[1] = ((x0)<<6) | (((y0)>>4)&0x3f); __p[2] = ((y0)<<4) | (((x1)>>6)&0x0f); __p[3]=((x1)<<2) | (((y1)>>8)&0x03); __p[4]=(y1); }
-
-#define WFIFOPOS(fd,pos,x,y) { WBUFPOS (WFIFOP(fd,pos),0,x,y); }
-#define WFIFOPOS2(fd,pos,x0,y0,x1,y1) { WBUFPOS2(WFIFOP(fd,pos),0,x0,y0,x1,y1); }
-
-static char map_ip_str[16];
-static in_addr_t map_ip;
-static int map_port = 5121;
-int  map_fd;
-char talkie_mes[80];
-
-/*==========================================
- * map鯖のip設定
- *------------------------------------------
- */
-void clif_setip (char *ip)
-{
-    memcpy (map_ip_str, ip, 16);
-    map_ip = inet_addr (map_ip_str);
-}
-
-/*==========================================
- * map鯖のport設定
- *------------------------------------------
- */
-void clif_setport (int port)
-{
-    map_port = port;
-}
-
-/*==========================================
- * map鯖のip読み出し
- *------------------------------------------
- */
-in_addr_t clif_getip (void)
-{
-    return map_ip;
-}
-
-/*==========================================
- * map鯖のport読み出し
- *------------------------------------------
- */
-int clif_getport (void)
-{
-    return map_port;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_countusers (void)
-{
-    int  users = 0, i;
-    struct map_session_data *sd;
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd
-            && sd->state.auth && !(battle_config.hide_GM_session
-                                   && pc_isGM (sd)))
-            users++;
-    }
-    return users;
-}
-
-/*==========================================
- * 全てのclientに対してfunc()実行
- *------------------------------------------
- */
-int clif_foreachclient (int (*func) (struct map_session_data *, va_list), ...)
-{
-    int  i;
-    va_list ap;
-    struct map_session_data *sd;
-
-    va_start (ap, func);
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd
-            && sd->state.auth)
-            func (sd, ap);
-    }
-    va_end (ap);
-    return 0;
-}
-
-static int is_deaf (struct block_list *bl)
-{
-    struct map_session_data *sd = (struct map_session_data *) bl;
-    if (!bl || bl->type != BL_PC)
-        return 0;
-    return sd->special_state.deaf;
-}
-
-static void clif_emotion_towards (struct block_list *bl,
-                                  struct block_list *target, int type);
-
-static char *clif_validate_chat (struct map_session_data *sd, int type,
-                                 char **message, size_t *message_len);
-
-/*==========================================
- * clif_sendでAREA*指定時用
- *------------------------------------------
- */
-int clif_send_sub (struct block_list *bl, va_list ap)
-{
-    unsigned char *buf;
-    int  len;
-    struct block_list *src_bl;
-    int  type;
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = (struct map_session_data *) bl);
-
-    buf = va_arg (ap, unsigned char *);
-    len = va_arg (ap, int);
-    nullpo_retr (0, src_bl = va_arg (ap, struct block_list *));
-    type = va_arg (ap, int);
-
-    switch (type)
-    {
-        case AREA_WOS:
-            if (bl && bl == src_bl)
-                return 0;
-            break;
-
-        case AREA_CHAT_WOC:
-            if (is_deaf (bl)
-                && !(bl->type == BL_PC
-                     && pc_isGM ((struct map_session_data *) src_bl)))
-            {
-                clif_emotion_towards (src_bl, bl, EMOTE_IGNORED);
-                return 0;
-            }
-            /* fall through... */
-        case AREA_WOC:
-            if ((sd && sd->chatID) || (bl && bl == src_bl))
-                return 0;
-
-            break;
-        case AREA_WOSC:
-            if ((sd) && sd->chatID
-                && sd->chatID == ((struct map_session_data *) src_bl)->chatID)
-                return 0;
-            break;
-    }
-
-    if (session[sd->fd] != NULL)
-    {
-        if (WFIFOP (sd->fd, 0) == buf)
-        {
-            printf ("WARNING: Invalid use of clif_send function\n");
-            printf
-                ("         Packet x%4x use a WFIFO of a player instead of to use a buffer.\n",
-                 WBUFW (buf, 0));
-            printf ("         Please correct your code.\n");
-            // don't send to not move the pointer of the packet for next sessions in the loop
-        }
-        else
-        {
-            if (packet_len_table[RBUFW (buf, 0)])
-            {                   // packet must exist
-                memcpy (WFIFOP (sd->fd, 0), buf, len);
-                WFIFOSET (sd->fd, len);
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_send (unsigned char *buf, int len, struct block_list *bl, int type)
-{
-    int  i;
-    struct map_session_data *sd;
-    struct chat_data *cd;
-    struct party *p = NULL;
-    struct guild *g = NULL;
-    int  x0 = 0, x1 = 0, y0 = 0, y1 = 0;
-
-    if (type != ALL_CLIENT)
-    {
-        nullpo_retr (0, bl);
-
-        if (bl->type == BL_PC)
-        {
-            struct map_session_data *sd = (struct map_session_data *) bl;
-            if (sd->status.option & OPTION_INVISIBILITY)
-            {
-                // Obscure hidden GMs
-
-                switch (type)
-                {
-                    case AREA:
-                    case AREA_WOC:
-                        type = SELF;
-                        break;
-
-                    case AREA_WOS:
-                    case AREA_WOSC:
-                        return 1;
-
-                    default:
-                        break;
-                }
-            }
-        }
-    }
-
-    switch (type)
-    {
-        case ALL_CLIENT:       // 全クライアントに送信
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
-                    && sd->state.auth)
-                {
-                    if (packet_len_table[RBUFW (buf, 0)])
-                    {           // packet must exist
-                        memcpy (WFIFOP (i, 0), buf, len);
-                        WFIFOSET (i, len);
-                    }
-                }
-            }
-            break;
-        case ALL_SAMEMAP:      // 同じマップの全クライアントに送信
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
-                    && sd->state.auth && sd->bl.m == bl->m)
-                {
-                    if (packet_len_table[RBUFW (buf, 0)])
-                    {           // packet must exist
-                        memcpy (WFIFOP (i, 0), buf, len);
-                        WFIFOSET (i, len);
-                    }
-                }
-            }
-            break;
-        case AREA:
-        case AREA_WOS:
-        case AREA_WOC:
-        case AREA_WOSC:
-            map_foreachinarea (clif_send_sub, bl->m, bl->x - AREA_SIZE,
-                               bl->y - AREA_SIZE, bl->x + AREA_SIZE,
-                               bl->y + AREA_SIZE, BL_PC, buf, len, bl, type);
-            break;
-        case AREA_CHAT_WOC:
-            map_foreachinarea (clif_send_sub, bl->m, bl->x - (AREA_SIZE),
-                               bl->y - (AREA_SIZE),
-                               bl->x + (AREA_SIZE),
-                               bl->y + (AREA_SIZE), BL_PC, buf, len, bl,
-                               AREA_CHAT_WOC);
-            break;
-        case CHAT:
-        case CHAT_WOS:
-            cd = (struct chat_data *) bl;
-            if (bl->type == BL_PC)
-            {
-                sd = (struct map_session_data *) bl;
-                cd = (struct chat_data *) map_id2bl (sd->chatID);
-            }
-            else if (bl->type != BL_CHAT)
-                break;
-            if (cd == NULL)
-                break;
-            for (i = 0; i < cd->users; i++)
-            {
-                if (type == CHAT_WOS
-                    && cd->usersd[i] == (struct map_session_data *) bl)
-                    continue;
-                if (packet_len_table[RBUFW (buf, 0)])
-                {               // packet must exist
-                    memcpy (WFIFOP (cd->usersd[i]->fd, 0), buf, len);
-                    WFIFOSET (cd->usersd[i]->fd, len);
-                }
-            }
-            break;
-
-        case PARTY_AREA:       // 同じ画面内の全パーティーメンバに送信
-        case PARTY_AREA_WOS:   // 自分以外の同じ画面内の全パーティーメンバに送信
-            x0 = bl->x - AREA_SIZE;
-            y0 = bl->y - AREA_SIZE;
-            x1 = bl->x + AREA_SIZE;
-            y1 = bl->y + AREA_SIZE;
-        case PARTY:            // 全パーティーメンバに送信
-        case PARTY_WOS:        // 自分以外の全パーティーメンバに送信
-        case PARTY_SAMEMAP:    // 同じマップの全パーティーメンバに送信
-        case PARTY_SAMEMAP_WOS:    // 自分以外の同じマップの全パーティーメンバに送信
-            if (bl->type == BL_PC)
-            {
-                sd = (struct map_session_data *) bl;
-                if (sd->partyspy > 0)
-                {
-                    p = party_search (sd->partyspy);
-                }
-                else
-                {
-                    if (sd->status.party_id > 0)
-                        p = party_search (sd->status.party_id);
-                }
-            }
-            if (p)
-            {
-                for (i = 0; i < MAX_PARTY; i++)
-                {
-                    if ((sd = p->member[i].sd) != NULL)
-                    {
-                        if (sd->bl.id == bl->id && (type == PARTY_WOS ||
-                                                    type == PARTY_SAMEMAP_WOS
-                                                    || type ==
-                                                    PARTY_AREA_WOS))
-                            continue;
-                        if (type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m)    // マップチェック
-                            continue;
-                        if ((type == PARTY_AREA || type == PARTY_AREA_WOS) &&
-                            (sd->bl.x < x0 || sd->bl.y < y0 ||
-                             sd->bl.x > x1 || sd->bl.y > y1))
-                            continue;
-                        if (packet_len_table[RBUFW (buf, 0)])
-                        {       // packet must exist
-                            memcpy (WFIFOP (sd->fd, 0), buf, len);
-                            WFIFOSET (sd->fd, len);
-                        }
-                    }
-                }
-                for (i = 0; i < fd_max; i++)
-                {
-                    if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
-                        && sd->state.auth)
-                    {
-                        if (sd->partyspy == p->party_id)
-                        {
-                            if (packet_len_table[RBUFW (buf, 0)])
-                            {   // packet must exist
-                                memcpy (WFIFOP (sd->fd, 0), buf, len);
-                                WFIFOSET (sd->fd, len);
-                            }
-                        }
-                    }
-                }
-            }
-            break;
-        case SELF:
-            sd = (struct map_session_data *) bl;
-            if (packet_len_table[RBUFW (buf, 0)])
-            {                   // packet must exist
-                memcpy (WFIFOP (sd->fd, 0), buf, len);
-                WFIFOSET (sd->fd, len);
-            }
-            break;
-
-/* New definitions for guilds [Valaris]	*/
-
-        case GUILD_AREA:
-        case GUILD_AREA_WOS:
-            x0 = bl->x - AREA_SIZE;
-            y0 = bl->y - AREA_SIZE;
-            x1 = bl->x + AREA_SIZE;
-            y1 = bl->y + AREA_SIZE;
-        case GUILD:
-        case GUILD_WOS:
-            if (bl && bl->type == BL_PC)
-            {                   // guildspy [Syrus22]
-                sd = (struct map_session_data *) bl;
-                if (sd->guildspy > 0)
-                {
-                    g = guild_search (sd->guildspy);
-                }
-                else
-                {
-                    if (sd->status.guild_id > 0)
-                        g = guild_search (sd->status.guild_id);
-                }
-            }
-            if (g)
-            {
-                for (i = 0; i < g->max_member; i++)
-                {
-                    if ((sd = g->member[i].sd) != NULL)
-                    {
-                        if (type == GUILD_WOS && sd->bl.id == bl->id)
-                            continue;
-                        if (packet_len_table[RBUFW (buf, 0)])
-                        {       // packet must exist
-                            memcpy (WFIFOP (sd->fd, 0), buf, len);
-                            WFIFOSET (sd->fd, len);
-                        }
-                    }
-                }
-                for (i = 0; i < fd_max; i++)
-                {
-                    if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
-                        && sd->state.auth)
-                    {
-                        if (sd->guildspy == g->guild_id)
-                        {
-                            if (packet_len_table[RBUFW (buf, 0)])
-                            {   // packet must exist
-                                memcpy (WFIFOP (sd->fd, 0), buf, len);
-                                WFIFOSET (sd->fd, len);
-                            }
-                        }
-                    }
-                }
-            }
-            break;
-        case GUILD_SAMEMAP:
-        case GUILD_SAMEMAP_WOS:
-            if (bl->type == BL_PC)
-            {
-                sd = (struct map_session_data *) bl;
-                if (sd->status.guild_id > 0)
-                    g = guild_search (sd->status.guild_id);
-            }
-            if (g)
-            {
-                for (i = 0; i < g->max_member; i++)
-                {
-                    if ((sd = g->member[i].sd) != NULL)
-                    {
-                        if (sd->bl.id == bl->id && (type == GUILD_WOS ||
-                                                    type == GUILD_SAMEMAP_WOS
-                                                    || type ==
-                                                    GUILD_AREA_WOS))
-                            continue;
-                        if (type != GUILD && type != GUILD_WOS && bl->m != sd->bl.m)    // マップチェック
-                            continue;
-                        if ((type == GUILD_AREA || type == GUILD_AREA_WOS) &&
-                            (sd->bl.x < x0 || sd->bl.y < y0 ||
-                             sd->bl.x > x1 || sd->bl.y > y1))
-                            continue;
-                        if (packet_len_table[RBUFW (buf, 0)])
-                        {       // packet must exist
-                            memcpy (WFIFOP (sd->fd, 0), buf, len);
-                            WFIFOSET (sd->fd, len);
-                        }
-                    }
-                }
-            }
-            break;
-
-        default:
-            if (battle_config.error_log)
-                printf ("clif_send まだ作ってないよー\n");
-            return -1;
-    }
-
-    return 0;
-}
-
-//
-// パケット作って送信
-//
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_authok (struct map_session_data *sd)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    if (!sd)
-        return 0;
-
-    if (!sd->fd)
-        return 0;
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x73;
-    WFIFOL (fd, 2) = gettick ();
-    WFIFOPOS (fd, 6, sd->bl.x, sd->bl.y);
-    WFIFOB (fd, 9) = 5;
-    WFIFOB (fd, 10) = 5;
-    WFIFOSET (fd, packet_len_table[0x73]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_authfail_fd (int fd, int type)
-{
-    if (!fd || !session[fd])
-        return 0;
-
-    WFIFOW (fd, 0) = 0x81;
-    WFIFOL (fd, 2) = type;
-    WFIFOSET (fd, packet_len_table[0x81]);
-
-    clif_setwaitclose (fd);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_charselectok (int id)
-{
-    struct map_session_data *sd;
-    int  fd;
-
-    if ((sd = map_id2sd (id)) == NULL)
-        return 1;
-
-    if (!sd->fd)
-        return 1;
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xb3;
-    WFIFOB (fd, 2) = 1;
-    WFIFOSET (fd, packet_len_table[0xb3]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_set009e (struct flooritem_data *fitem, char *buf)
-{
-    int  view;
-
-    nullpo_retr (0, fitem);
-
-    //009e <ID>.l <name ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w
-    WBUFW (buf, 0) = 0x9e;
-    WBUFL (buf, 2) = fitem->bl.id;
-    if ((view = itemdb_viewid (fitem->item_data.nameid)) > 0)
-        WBUFW (buf, 6) = view;
-    else
-        WBUFW (buf, 6) = fitem->item_data.nameid;
-    WBUFB (buf, 8) = fitem->item_data.identify;
-    WBUFW (buf, 9) = fitem->bl.x;
-    WBUFW (buf, 11) = fitem->bl.y;
-    WBUFB (buf, 13) = fitem->subx;
-    WBUFB (buf, 14) = fitem->suby;
-    WBUFW (buf, 15) = fitem->item_data.amount;
-
-    return packet_len_table[0x9e];
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_dropflooritem (struct flooritem_data *fitem)
-{
-    char buf[64];
-
-    nullpo_retr (0, fitem);
-
-    if (fitem->item_data.nameid <= 0)
-        return 0;
-    clif_set009e (fitem, buf);
-    clif_send (buf, packet_len_table[0x9e], &fitem->bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_clearflooritem (struct flooritem_data *fitem, int fd)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, fitem);
-
-    WBUFW (buf, 0) = 0xa1;
-    WBUFL (buf, 2) = fitem->bl.id;
-
-    if (fd == 0)
-    {
-        clif_send (buf, packet_len_table[0xa1], &fitem->bl, AREA);
-    }
-    else
-    {
-        memcpy (WFIFOP (fd, 0), buf, 6);
-        WFIFOSET (fd, packet_len_table[0xa1]);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_clearchar (struct block_list *bl, int type)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x80;
-    WBUFL (buf, 2) = bl->id;
-    if (type == 9)
-    {
-        WBUFB (buf, 6) = 0;
-        clif_send (buf, packet_len_table[0x80], bl, AREA);
-    }
-    else
-    {
-        WBUFB (buf, 6) = type;
-        clif_send (buf, packet_len_table[0x80], bl,
-                   type == 1 ? AREA : AREA_WOS);
-    }
-
-    return 0;
-}
-
-static void clif_clearchar_delay_sub (timer_id tid, tick_t tick, custom_id_t id,
-                                     custom_data_t data)
-{
-    struct block_list *bl = (struct block_list *) id;
-
-    clif_clearchar (bl, data);
-    map_freeblock (bl);
-}
-
-int clif_clearchar_delay (unsigned int tick, struct block_list *bl, int type)
-{
-    struct block_list *tmpbl;
-    CREATE (tmpbl, struct block_list, 1);
-
-    memcpy (tmpbl, bl, sizeof (struct block_list));
-    add_timer (tick, clif_clearchar_delay_sub, (custom_id_t) tmpbl, type);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_clearchar_id (int id, int type, int fd)
-{
-    unsigned char buf[16];
-
-    WBUFW (buf, 0) = 0x80;
-    WBUFL (buf, 2) = id;
-    WBUFB (buf, 6) = type;
-    memcpy (WFIFOP (fd, 0), buf, 7);
-    WFIFOSET (fd, packet_len_table[0x80]);
-
-    return 0;
-}
-
-/*
-static int current_weapon(struct map_session_data *sd)
-{
-        if (sd->attack_spell_override)
-                return sd->attack_spell_look_override;
-        else {
-                return sd->status.weapon;
-        }
-}
-*/
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_set0078 (struct map_session_data *sd, unsigned char *buf)
-{
-    int  level = 0;
-
-    nullpo_retr (0, sd);
-
-    if (sd->disguise > 23 && sd->disguise < 4001)
-    {                           // mob disguises [Valaris]
-        WBUFW (buf, 0) = 0x78;
-        WBUFL (buf, 2) = sd->bl.id;
-        WBUFW (buf, 6) = battle_get_speed (&sd->bl);
-        WBUFW (buf, 8) = sd->opt1;
-        WBUFW (buf, 10) = sd->opt2;
-        WBUFW (buf, 12) = sd->status.option;
-        WBUFW (buf, 14) = sd->disguise;
-        WBUFW (buf, 42) = 0;
-        WBUFB (buf, 44) = 0;
-        WBUFPOS (buf, 46, sd->bl.x, sd->bl.y);
-        WBUFB (buf, 48) |= sd->dir & 0x0f;
-        WBUFB (buf, 49) = 5;
-        WBUFB (buf, 50) = 5;
-        WBUFB (buf, 51) = 0;
-        WBUFW (buf, 52) =
-            ((level =
-              battle_get_lv (&sd->bl)) >
-             battle_config.max_lv) ? battle_config.max_lv : level;
-
-        return packet_len_table[0x78];
-    }
-
-    WBUFW (buf, 0) = 0x1d8;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFW (buf, 6) = sd->speed;
-    WBUFW (buf, 8) = sd->opt1;
-    WBUFW (buf, 10) = sd->opt2;
-    WBUFW (buf, 12) = sd->status.option;
-    WBUFW (buf, 14) = sd->view_class;
-    WBUFW (buf, 16) = sd->status.hair;
-    if (sd->attack_spell_override)
-        WBUFB (buf, 18) = sd->attack_spell_look_override;
-    else
-    {
-        if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]]
-            && sd->view_class != 22)
-        {
-            if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
-                WBUFW (buf, 18) =
-                    sd->inventory_data[sd->equip_index[9]]->view_id;
-            else
-                WBUFW (buf, 18) =
-                    sd->status.inventory[sd->equip_index[9]].nameid;
-        }
-        else
-            WBUFW (buf, 18) = 0;
-    }
-    if (sd->equip_index[8] >= 0 && sd->equip_index[8] != sd->equip_index[9]
-        && sd->inventory_data[sd->equip_index[8]] && sd->view_class != 22)
-    {
-        if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
-            WBUFW (buf, 20) = sd->inventory_data[sd->equip_index[8]]->view_id;
-        else
-            WBUFW (buf, 20) = sd->status.inventory[sd->equip_index[8]].nameid;
-    }
-    else
-        WBUFW (buf, 20) = 0;
-    WBUFW (buf, 22) = sd->status.head_bottom;
-    WBUFW (buf, 24) = sd->status.head_top;
-    WBUFW (buf, 26) = sd->status.head_mid;
-    WBUFW (buf, 28) = sd->status.hair_color;
-    WBUFW (buf, 30) = sd->status.clothes_color;
-    WBUFW (buf, 32) = sd->head_dir;
-    WBUFL (buf, 34) = sd->status.guild_id;
-    WBUFW (buf, 38) = sd->guild_emblem_id;
-    WBUFW (buf, 40) = sd->status.manner;
-    WBUFW (buf, 42) = sd->opt3;
-    WBUFB (buf, 44) = sd->status.karma;
-    WBUFB (buf, 45) = sd->sex;
-    WBUFPOS (buf, 46, sd->bl.x, sd->bl.y);
-    WBUFB (buf, 48) |= sd->dir & 0x0f;
-    WBUFW (buf, 49) = (pc_isGM (sd) == 60 || pc_isGM (sd) == 99) ? 0x80 : 0;
-    WBUFB (buf, 51) = sd->state.dead_sit;
-    WBUFW (buf, 52) = 0;
-
-    return packet_len_table[0x1d8];
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_set007b (struct map_session_data *sd, unsigned char *buf)
-{
-    int  level = 0;
-    nullpo_retr (0, sd);
-
-    if (sd->disguise > 23 && sd->disguise < 4001)
-    {                           // mob disguises [Valaris]
-        WBUFW (buf, 0) = 0x7b;
-        WBUFL (buf, 2) = sd->bl.id;
-        WBUFW (buf, 6) = battle_get_speed (&sd->bl);
-        WBUFW (buf, 8) = sd->opt1;
-        WBUFW (buf, 10) = sd->opt2;
-        WBUFW (buf, 12) = sd->status.option;
-        WBUFW (buf, 14) = sd->disguise;
-        WBUFL (buf, 22) = gettick ();
-        WBUFW (buf, 46) = 0;
-        WBUFB (buf, 48) = 0;
-        WBUFPOS2 (buf, 50, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
-        WBUFB (buf, 55) = 0;
-        WBUFB (buf, 56) = 5;
-        WBUFB (buf, 57) = 5;
-        WBUFW (buf, 58) =
-            ((level =
-              battle_get_lv (&sd->bl)) >
-             battle_config.max_lv) ? battle_config.max_lv : level;
-
-        return packet_len_table[0x7b];
-    }
-
-    WBUFW (buf, 0) = 0x1da;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFW (buf, 6) = sd->speed;
-    WBUFW (buf, 8) = sd->opt1;
-    WBUFW (buf, 10) = sd->opt2;
-    WBUFW (buf, 12) = sd->status.option;
-    WBUFW (buf, 14) = sd->view_class;
-    WBUFW (buf, 16) = sd->status.hair;
-    if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]]
-        && sd->view_class != 22)
-    {
-        if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
-            WBUFW (buf, 18) = sd->inventory_data[sd->equip_index[9]]->view_id;
-        else
-            WBUFW (buf, 18) = sd->status.inventory[sd->equip_index[9]].nameid;
-    }
-    else
-        WBUFW (buf, 18) = 0;
-    if (sd->equip_index[8] >= 0 && sd->equip_index[8] != sd->equip_index[9]
-        && sd->inventory_data[sd->equip_index[8]] && sd->view_class != 22)
-    {
-        if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
-            WBUFW (buf, 20) = sd->inventory_data[sd->equip_index[8]]->view_id;
-        else
-            WBUFW (buf, 20) = sd->status.inventory[sd->equip_index[8]].nameid;
-    }
-    else
-        WBUFW (buf, 20) = 0;
-    WBUFW (buf, 22) = sd->status.head_bottom;
-    WBUFL (buf, 24) = gettick ();
-    WBUFW (buf, 28) = sd->status.head_top;
-    WBUFW (buf, 30) = sd->status.head_mid;
-    WBUFW (buf, 32) = sd->status.hair_color;
-    WBUFW (buf, 34) = sd->status.clothes_color;
-    WBUFW (buf, 36) = sd->head_dir;
-    WBUFL (buf, 38) = sd->status.guild_id;
-    WBUFW (buf, 42) = sd->guild_emblem_id;
-    WBUFW (buf, 44) = sd->status.manner;
-    WBUFW (buf, 46) = sd->opt3;
-    WBUFB (buf, 48) = sd->status.karma;
-    WBUFB (buf, 49) = sd->sex;
-    WBUFPOS2 (buf, 50, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
-    WBUFW (buf, 55) = pc_isGM (sd) == 60 ? 0x80 : 0;
-    WBUFB (buf, 57) = 5;
-    WBUFW (buf, 58) = 0;
-
-    return packet_len_table[0x1da];
-}
-
-/*==========================================
- * クラスチェンジ typeはMobの場合は1で他は0?
- *------------------------------------------
- */
-int clif_npc_class_change (struct block_list *bl, int npc_class, int type)
-{
-    char buf[16];
-
-    nullpo_retr (0, bl);
-
-    if (npc_class >= MAX_PC_CLASS)
-    {
-        WBUFW (buf, 0) = 0x1b0;
-        WBUFL (buf, 2) = bl->id;
-        WBUFB (buf, 6) = type;
-        WBUFL (buf, 7) = npc_class;
-
-        clif_send (buf, packet_len_table[0x1b0], bl, AREA);
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_mob_class_change (struct mob_data *md, int class_)
-{
-    char buf[16];
-    int  view = mob_get_viewclass (class_);
-
-    nullpo_retr (0, md);
-
-    if (view >= MAX_PC_CLASS)
-    {
-        WBUFW (buf, 0) = 0x1b0;
-        WBUFL (buf, 2) = md->bl.id;
-        WBUFB (buf, 6) = 1;
-        WBUFL (buf, 7) = view;
-
-        clif_send (buf, packet_len_table[0x1b0], &md->bl, AREA);
-    }
-    return 0;
-}
-
-// mob equipment [Valaris]
-
-int clif_mob_equip (struct mob_data *md, int nameid)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, md);
-
-    memset (buf, 0, packet_len_table[0x1a4]);
-
-    WBUFW (buf, 0) = 0x1a4;
-    WBUFB (buf, 2) = 3;
-    WBUFL (buf, 3) = md->bl.id;
-    WBUFL (buf, 7) = nameid;
-
-    clif_send (buf, packet_len_table[0x1a4], &md->bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * MOB表示1
- *------------------------------------------
- */
-static int clif_mob0078 (struct mob_data *md, unsigned char *buf)
-{
-    int  level;
-
-    memset (buf, 0, packet_len_table[0x78]);
-
-    nullpo_retr (0, md);
-
-    WBUFW (buf, 0) = 0x78;
-    WBUFL (buf, 2) = md->bl.id;
-    WBUFW (buf, 6) = battle_get_speed (&md->bl);
-    WBUFW (buf, 8) = md->opt1;
-    WBUFW (buf, 10) = md->opt2;
-    WBUFW (buf, 12) = md->option;
-    WBUFW (buf, 14) = mob_get_viewclass (md->mob_class);
-    if ((mob_get_viewclass (md->mob_class) <= 23)
-        || (mob_get_viewclass (md->mob_class) == 812)
-        || (mob_get_viewclass (md->mob_class) >= 4001))
-    {
-        WBUFW (buf, 12) |= mob_db[md->mob_class].option;
-        WBUFW (buf, 16) = mob_get_hair (md->mob_class);
-        WBUFW (buf, 18) = mob_get_weapon (md->mob_class);
-        WBUFW (buf, 20) = mob_get_head_buttom (md->mob_class);
-        WBUFW (buf, 22) = mob_get_shield (md->mob_class);
-        WBUFW (buf, 24) = mob_get_head_top (md->mob_class);
-        WBUFW (buf, 26) = mob_get_head_mid (md->mob_class);
-        WBUFW (buf, 28) = mob_get_hair_color (md->mob_class);
-        WBUFW (buf, 30) = mob_get_clothes_color (md->mob_class);    //Add for player monster dye - Valaris
-        WBUFB (buf, 45) = mob_get_sex (md->mob_class);
-    }
-
-    if (md->mob_class >= 1285 && md->mob_class <= 1287)
-    {                           // Added guardian emblems [Valaris]
-        struct guild *g;
-        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
-        if (gc && gc->guild_id > 0)
-        {
-            g = guild_search (gc->guild_id);
-            if (g)
-            {
-                WBUFL (buf, 26) = gc->guild_id;
-                WBUFL (buf, 22) = g->emblem_id;
-            }
-        }
-    }                           // End addition
-
-    WBUFPOS (buf, 46, md->bl.x, md->bl.y);
-    WBUFB (buf, 48) |= md->dir & 0x0f;
-    WBUFB (buf, 49) = 5;
-    WBUFB (buf, 50) = 5;
-    WBUFW (buf, 52) =
-        ((level =
-          battle_get_lv (&md->bl)) >
-         battle_config.max_lv) ? battle_config.max_lv : level;
-
-    return packet_len_table[0x78];
-}
-
-/*==========================================
- * MOB表示2
- *------------------------------------------
- */
-static int clif_mob007b (struct mob_data *md, unsigned char *buf)
-{
-    int  level;
-
-    memset (buf, 0, packet_len_table[0x7b]);
-
-    nullpo_retr (0, md);
-
-    WBUFW (buf, 0) = 0x7b;
-    WBUFL (buf, 2) = md->bl.id;
-    WBUFW (buf, 6) = battle_get_speed (&md->bl);
-    WBUFW (buf, 8) = md->opt1;
-    WBUFW (buf, 10) = md->opt2;
-    WBUFW (buf, 12) = md->option;
-    WBUFW (buf, 14) = mob_get_viewclass (md->mob_class);
-    if ((mob_get_viewclass (md->mob_class) < 24)
-        || (mob_get_viewclass (md->mob_class) > 4000))
-    {
-        WBUFW (buf, 12) |= mob_db[md->mob_class].option;
-        WBUFW (buf, 16) = mob_get_hair (md->mob_class);
-        WBUFW (buf, 18) = mob_get_weapon (md->mob_class);
-        WBUFW (buf, 20) = mob_get_head_buttom (md->mob_class);
-        WBUFL (buf, 22) = gettick ();
-        WBUFW (buf, 26) = mob_get_shield (md->mob_class);
-        WBUFW (buf, 28) = mob_get_head_top (md->mob_class);
-        WBUFW (buf, 30) = mob_get_head_mid (md->mob_class);
-        WBUFW (buf, 32) = mob_get_hair_color (md->mob_class);
-        WBUFW (buf, 34) = mob_get_clothes_color (md->mob_class);    //Add for player monster dye - Valaris
-        WBUFB (buf, 49) = mob_get_sex (md->mob_class);
-    }
-    else
-        WBUFL (buf, 22) = gettick ();
-
-    if (md->mob_class >= 1285 && md->mob_class <= 1287)
-    {                           // Added guardian emblems [Valaris]
-        struct guild *g;
-        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
-        if (gc && gc->guild_id > 0)
-        {
-            g = guild_search (gc->guild_id);
-            if (g)
-            {
-                WBUFL (buf, 28) = gc->guild_id;
-                WBUFL (buf, 24) = g->emblem_id;
-            }
-        }
-    }                           // End addition
-
-    WBUFPOS2 (buf, 50, md->bl.x, md->bl.y, md->to_x, md->to_y);
-    WBUFB (buf, 56) = 5;
-    WBUFB (buf, 57) = 5;
-    WBUFW (buf, 58) =
-        ((level =
-          battle_get_lv (&md->bl)) >
-         battle_config.max_lv) ? battle_config.max_lv : level;
-
-    return packet_len_table[0x7b];
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_npc0078 (struct npc_data *nd, unsigned char *buf)
-{
-    struct guild *g;
-
-    nullpo_retr (0, nd);
-
-    memset (buf, 0, packet_len_table[0x78]);
-
-    WBUFW (buf, 0) = 0x78;
-    WBUFL (buf, 2) = nd->bl.id;
-    WBUFW (buf, 6) = nd->speed;
-    WBUFW (buf, 14) = nd->npc_class;
-    if ((nd->npc_class == 722) && (nd->u.scr.guild_id > 0)
-        && ((g = guild_search (nd->u.scr.guild_id)) != NULL))
-    {
-        WBUFL (buf, 22) = g->emblem_id;
-        WBUFL (buf, 26) = g->guild_id;
-    }
-    WBUFPOS (buf, 46, nd->bl.x, nd->bl.y);
-    WBUFB (buf, 48) |= nd->dir & 0x0f;
-    WBUFB (buf, 49) = 5;
-    WBUFB (buf, 50) = 5;
-
-    return packet_len_table[0x78];
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_set01e1 (struct map_session_data *sd, unsigned char *buf)
-{
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x1e1;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFW (buf, 6) = sd->spiritball;
-
-    return packet_len_table[0x1e1];
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int clif_set0192 (int fd, int m, int x, int y, int type)
-{
-    WFIFOW (fd, 0) = 0x192;
-    WFIFOW (fd, 2) = x;
-    WFIFOW (fd, 4) = y;
-    WFIFOW (fd, 6) = type;
-    memcpy (WFIFOP (fd, 8), map[m].name, 16);
-    WFIFOSET (fd, packet_len_table[0x192]);
-
-    return 0;
-}
-
-/* These indices are derived from equip_pos in pc.c and some guesswork */
-static int equip_points[LOOK_LAST + 1] = {
-    -1,                         /* 0: base */
-    -1,                         /* 1: hair */
-    9,                          /* 2: weapon */
-    4,                          /* 3: head botom -- leg armour */
-    6,                          /* 4: head top -- hat */
-    5,                          /* 5: head mid -- torso armour */
-    -1,                         /* 6: hair colour */
-    -1,                         /* 6: clothes colour */
-    8,                          /* 6: shield */
-    2,                          /* 9: shoes */
-    3,                          /* gloves */
-    1,                          /* cape */
-    7,                          /* misc1 */
-    0,                          /* misc2 */
-};
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_spawnpc (struct map_session_data *sd)
-{
-    unsigned char buf[128];
-
-    nullpo_retr (0, sd);
-
-    if (sd->disguise > 23 && sd->disguise < 4001)
-    {                           // mob disguises [Valaris]
-        clif_clearchar (&sd->bl, 9);
-
-        memset (buf, 0, packet_len_table[0x119]);
-
-        WBUFW (buf, 0) = 0x119;
-        WBUFL (buf, 2) = sd->bl.id;
-        WBUFW (buf, 6) = 0;
-        WBUFW (buf, 8) = 0;
-        WBUFW (buf, 10) = 0x40;
-        WBUFB (buf, 12) = 0;
-
-        clif_send (buf, packet_len_table[0x119], &sd->bl, SELF);
-
-        memset (buf, 0, packet_len_table[0x7c]);
-
-        WBUFW (buf, 0) = 0x7c;
-        WBUFL (buf, 2) = sd->bl.id;
-        WBUFW (buf, 6) = sd->speed;
-        WBUFW (buf, 8) = sd->opt1;
-        WBUFW (buf, 10) = sd->opt2;
-        WBUFW (buf, 12) = sd->status.option;
-        WBUFW (buf, 20) = sd->disguise;
-        WBUFPOS (buf, 36, sd->bl.x, sd->bl.y);
-        clif_send (buf, packet_len_table[0x7c], &sd->bl, AREA);
-    }
-
-    clif_set0078 (sd, buf);
-
-    WBUFW (buf, 0) = 0x1d9;
-    WBUFW (buf, 51) = 0;
-    clif_send (buf, packet_len_table[0x1d9], &sd->bl, AREA_WOS);
-
-    if (sd->spiritball > 0)
-        clif_spiritball (sd);
-
-    if (sd->status.guild_id > 0)
-    {                           // force display of guild emblem [Valaris]
-        struct guild *g = guild_search (sd->status.guild_id);
-        if (g)
-            clif_guild_emblem (sd, g);
-    }                           // end addition [Valaris]
-
-    if (sd->status.pc_class == 13 || sd->status.pc_class == 21
-        || sd->status.pc_class == 4014 || sd->status.pc_class == 4022)
-        pc_setoption (sd, sd->status.option | 0x0020);  // [Valaris]
-
-    if ((pc_isriding (sd) && pc_checkskill (sd, KN_RIDING) > 0)
-        && (sd->status.pc_class == 7 || sd->status.pc_class == 14
-            || sd->status.pc_class == 4008 || sd->status.pc_class == 4015))
-        pc_setriding (sd);      // update peco riders for people upgrading athena [Valaris]
-
-    if (map[sd->bl.m].flag.snow)
-        clif_specialeffect (&sd->bl, 162, 1);
-    if (map[sd->bl.m].flag.fog)
-        clif_specialeffect (&sd->bl, 233, 1);
-    if (map[sd->bl.m].flag.sakura)
-        clif_specialeffect (&sd->bl, 163, 1);
-    if (map[sd->bl.m].flag.leaves)
-        clif_specialeffect (&sd->bl, 333, 1);
-    if (map[sd->bl.m].flag.rain)
-        clif_specialeffect (&sd->bl, 161, 1);
-
-//        clif_changelook_accessories(&sd->bl, NULL);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_spawnnpc (struct npc_data *nd)
-{
-    unsigned char buf[64];
-    int  len;
-
-    nullpo_retr (0, nd);
-
-    if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS)
-        return 0;
-
-    memset (buf, 0, packet_len_table[0x7c]);
-
-    WBUFW (buf, 0) = 0x7c;
-    WBUFL (buf, 2) = nd->bl.id;
-    WBUFW (buf, 6) = nd->speed;
-    WBUFW (buf, 20) = nd->npc_class;
-    WBUFPOS (buf, 36, nd->bl.x, nd->bl.y);
-
-    clif_send (buf, packet_len_table[0x7c], &nd->bl, AREA);
-
-    len = clif_npc0078 (nd, buf);
-    clif_send (buf, len, &nd->bl, AREA);
-
-    return 0;
-}
-
-int
-clif_spawn_fake_npc_for_player (struct map_session_data *sd, int fake_npc_id)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    if (!fd)
-        return 0;
-
-    WFIFOW (fd, 0) = 0x7c;
-    WFIFOL (fd, 2) = fake_npc_id;
-    WFIFOW (fd, 6) = 0;
-    WFIFOW (fd, 8) = 0;
-    WFIFOW (fd, 10) = 0;
-    WFIFOW (fd, 12) = 0;
-    WFIFOW (fd, 20) = 127;
-    WFIFOPOS (fd, 36, sd->bl.x, sd->bl.y);
-    WFIFOSET (fd, packet_len_table[0x7c]);
-
-    WFIFOW (fd, 0) = 0x78;
-    WFIFOL (fd, 2) = fake_npc_id;
-    WFIFOW (fd, 6) = 0;
-    WFIFOW (fd, 8) = 0;
-    WFIFOW (fd, 10) = 0;
-    WFIFOW (fd, 12) = 0;
-    WFIFOW (fd, 14) = 127;      // identifies as NPC
-    WFIFOW (fd, 20) = 127;
-    WFIFOPOS (fd, 46, sd->bl.x, sd->bl.y);
-    WFIFOPOS (fd, 36, sd->bl.x, sd->bl.y);
-    WFIFOB (fd, 49) = 5;
-    WFIFOB (fd, 50) = 5;
-    WFIFOSET (fd, packet_len_table[0x78]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_spawnmob (struct mob_data *md)
-{
-    unsigned char buf[64];
-    int  len;
-
-    nullpo_retr (0, md);
-
-    if (mob_get_viewclass (md->mob_class) > 23)
-    {
-        memset (buf, 0, packet_len_table[0x7c]);
-
-        WBUFW (buf, 0) = 0x7c;
-        WBUFL (buf, 2) = md->bl.id;
-        WBUFW (buf, 6) = md->stats[MOB_SPEED];
-        WBUFW (buf, 8) = md->opt1;
-        WBUFW (buf, 10) = md->opt2;
-        WBUFW (buf, 12) = md->option;
-        WBUFW (buf, 20) = mob_get_viewclass (md->mob_class);
-        WBUFPOS (buf, 36, md->bl.x, md->bl.y);
-        clif_send (buf, packet_len_table[0x7c], &md->bl, AREA);
-    }
-
-    len = clif_mob0078 (md, buf);
-    clif_send (buf, len, &md->bl, AREA);
-
-    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
-        clif_mob_equip (md, mob_get_equip (md->mob_class));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_servertick (struct map_session_data *sd)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x7f;
-    WFIFOL (fd, 2) = sd->server_tick;
-    WFIFOSET (fd, packet_len_table[0x7f]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_walkok (struct map_session_data *sd)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x87;
-    WFIFOL (fd, 2) = gettick ();;
-    WFIFOPOS2 (fd, 6, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
-    WFIFOB (fd, 11) = 0;
-    WFIFOSET (fd, packet_len_table[0x87]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_movechar (struct map_session_data *sd)
-{
-    int  fd;
-    int  len;
-    unsigned char buf[256];
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    len = clif_set007b (sd, buf);
-
-    if (sd->disguise > 23 && sd->disguise < 4001)
-    {
-        clif_send (buf, len, &sd->bl, AREA);
-        return 0;
-    }
-    else
-        clif_send (buf, len, &sd->bl, AREA_WOS);
-
-    if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0)
-        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
-                         sd->status.clothes_color);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_quitsave (int fd, struct map_session_data *sd)
-{
-    map_quit (sd);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static void clif_waitclose (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    if (session[id])
-        session[id]->eof = 1;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_setwaitclose (int fd)
-{
-    add_timer (gettick () + 5000, clif_waitclose, fd, 0);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_changemap (struct map_session_data *sd, char *mapname, int x, int y)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x91;
-    memcpy (WFIFOP (fd, 2), mapname, 16);
-    WFIFOW (fd, 18) = x;
-    WFIFOW (fd, 20) = y;
-    WFIFOSET (fd, packet_len_table[0x91]);
-
-    if (sd->disguise > 23 && sd->disguise < 4001)   // mob disguises [Valaris]
-        clif_spawnpc (sd);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_changemapserver (struct map_session_data *sd, char *mapname, int x,
-                          int y, int ip, int port)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x92;
-    memcpy (WFIFOP (fd, 2), mapname, 16);
-    WFIFOW (fd, 18) = x;
-    WFIFOW (fd, 20) = y;
-    WFIFOL (fd, 22) = ip;
-    WFIFOW (fd, 26) = port;
-    WFIFOSET (fd, packet_len_table[0x92]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_fixpos (struct block_list *bl)
-{
-    char buf[16];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x88;
-    WBUFL (buf, 2) = bl->id;
-    WBUFW (buf, 6) = bl->x;
-    WBUFW (buf, 8) = bl->y;
-
-    clif_send (buf, packet_len_table[0x88], bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_npcbuysell (struct map_session_data *sd, int id)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xc4;
-    WFIFOL (fd, 2) = id;
-    WFIFOSET (fd, packet_len_table[0xc4]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_buylist (struct map_session_data *sd, struct npc_data *nd)
-{
-    struct item_data *id;
-    int  fd, i, val;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, nd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xc6;
-    for (i = 0; nd->u.shop_item[i].nameid > 0; i++)
-    {
-        id = itemdb_search (nd->u.shop_item[i].nameid);
-        val = nd->u.shop_item[i].value;
-        WFIFOL (fd, 4 + i * 11) = val;
-        if (!id->flag.value_notdc)
-            val = pc_modifybuyvalue (sd, val);
-        WFIFOL (fd, 8 + i * 11) = val;
-        WFIFOB (fd, 12 + i * 11) = id->type;
-        if (id->view_id > 0)
-            WFIFOW (fd, 13 + i * 11) = id->view_id;
-        else
-            WFIFOW (fd, 13 + i * 11) = nd->u.shop_item[i].nameid;
-    }
-    WFIFOW (fd, 2) = i * 11 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_selllist (struct map_session_data *sd)
-{
-    int  fd, i, c = 0, val;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xc7;
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i])
-        {
-            val = sd->inventory_data[i]->value_sell;
-            if (val < 0)
-                continue;
-            WFIFOW (fd, 4 + c * 10) = i + 2;
-            WFIFOL (fd, 6 + c * 10) = val;
-            if (!sd->inventory_data[i]->flag.value_notoc)
-                val = pc_modifysellvalue (sd, val);
-            WFIFOL (fd, 10 + c * 10) = val;
-            c++;
-        }
-    }
-    WFIFOW (fd, 2) = c * 10 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptmes (struct map_session_data *sd, int npcid, char *mes)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xb4;
-    WFIFOW (fd, 2) = strlen (mes) + 9;
-    WFIFOL (fd, 4) = npcid;
-    strcpy (WFIFOP (fd, 8), mes);
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptnext (struct map_session_data *sd, int npcid)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xb5;
-    WFIFOL (fd, 2) = npcid;
-    WFIFOSET (fd, packet_len_table[0xb5]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptclose (struct map_session_data *sd, int npcid)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xb6;
-    WFIFOL (fd, 2) = npcid;
-    WFIFOSET (fd, packet_len_table[0xb6]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptmenu (struct map_session_data *sd, int npcid, char *mes)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xb7;
-    WFIFOW (fd, 2) = strlen (mes) + 8;
-    WFIFOL (fd, 4) = npcid;
-    strcpy (WFIFOP (fd, 8), mes);
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptinput (struct map_session_data *sd, int npcid)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x142;
-    WFIFOL (fd, 2) = npcid;
-    WFIFOSET (fd, packet_len_table[0x142]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_scriptinputstr (struct map_session_data *sd, int npcid)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1d4;
-    WFIFOL (fd, 2) = npcid;
-    WFIFOSET (fd, packet_len_table[0x1d4]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_viewpoint (struct map_session_data *sd, int npc_id, int type, int x,
-                    int y, int id, int color)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x144;
-    WFIFOL (fd, 2) = npc_id;
-    WFIFOL (fd, 6) = type;
-    WFIFOL (fd, 10) = x;
-    WFIFOL (fd, 14) = y;
-    WFIFOB (fd, 18) = id;
-    WFIFOL (fd, 19) = color;
-    WFIFOSET (fd, packet_len_table[0x144]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_cutin (struct map_session_data *sd, char *image, int type)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1b3;
-    memcpy (WFIFOP (fd, 2), image, 64);
-    WFIFOB (fd, 66) = type;
-    WFIFOSET (fd, packet_len_table[0x1b3]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_additem (struct map_session_data *sd, int n, int amount, int fail)
-{
-    int  fd, j;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    if (fail)
-    {
-        WBUFW (buf, 0) = 0xa0;
-        WBUFW (buf, 2) = n + 2;
-        WBUFW (buf, 4) = amount;
-        WBUFW (buf, 6) = 0;
-        WBUFB (buf, 8) = 0;
-        WBUFB (buf, 9) = 0;
-        WBUFB (buf, 10) = 0;
-        WBUFW (buf, 11) = 0;
-        WBUFW (buf, 13) = 0;
-        WBUFW (buf, 15) = 0;
-        WBUFW (buf, 17) = 0;
-        WBUFW (buf, 19) = 0;
-        WBUFB (buf, 21) = 0;
-        WBUFB (buf, 22) = fail;
-    }
-    else
-    {
-        if (n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <= 0
-            || sd->inventory_data[n] == NULL)
-            return 1;
-
-        WBUFW (buf, 0) = 0xa0;
-        WBUFW (buf, 2) = n + 2;
-        WBUFW (buf, 4) = amount;
-        if (sd->inventory_data[n]->view_id > 0)
-            WBUFW (buf, 6) = sd->inventory_data[n]->view_id;
-        else
-            WBUFW (buf, 6) = sd->status.inventory[n].nameid;
-        WBUFB (buf, 8) = sd->status.inventory[n].identify;
-        if (sd->status.inventory[n].broken == 1)
-            WBUFB (buf, 9) = 1; // is weapon broken [Valaris]
-        else
-            WBUFB (buf, 9) = sd->status.inventory[n].attribute;
-        WBUFB (buf, 10) = sd->status.inventory[n].refine;
-        if (sd->status.inventory[n].card[0] == 0x00ff
-            || sd->status.inventory[n].card[0] == 0x00fe
-            || sd->status.inventory[n].card[0] == (short) 0xff00)
-        {
-            WBUFW (buf, 11) = sd->status.inventory[n].card[0];
-            WBUFW (buf, 13) = sd->status.inventory[n].card[1];
-            WBUFW (buf, 15) = sd->status.inventory[n].card[2];
-            WBUFW (buf, 17) = sd->status.inventory[n].card[3];
-        }
-        else
-        {
-            if (sd->status.inventory[n].card[0] > 0
-                && (j = itemdb_viewid (sd->status.inventory[n].card[0])) > 0)
-                WBUFW (buf, 11) = j;
-            else
-                WBUFW (buf, 11) = sd->status.inventory[n].card[0];
-            if (sd->status.inventory[n].card[1] > 0
-                && (j = itemdb_viewid (sd->status.inventory[n].card[1])) > 0)
-                WBUFW (buf, 13) = j;
-            else
-                WBUFW (buf, 13) = sd->status.inventory[n].card[1];
-            if (sd->status.inventory[n].card[2] > 0
-                && (j = itemdb_viewid (sd->status.inventory[n].card[2])) > 0)
-                WBUFW (buf, 15) = j;
-            else
-                WBUFW (buf, 15) = sd->status.inventory[n].card[2];
-            if (sd->status.inventory[n].card[3] > 0
-                && (j = itemdb_viewid (sd->status.inventory[n].card[3])) > 0)
-                WBUFW (buf, 17) = j;
-            else
-                WBUFW (buf, 17) = sd->status.inventory[n].card[3];
-        }
-        WBUFW (buf, 19) = pc_equippoint (sd, n);
-        WBUFB (buf, 21) =
-            (sd->inventory_data[n]->type ==
-             7) ? 4 : sd->inventory_data[n]->type;
-        WBUFB (buf, 22) = fail;
-    }
-
-    WFIFOSET (fd, packet_len_table[0xa0]);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_delitem (struct map_session_data *sd, int n, int amount)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xaf;
-    WFIFOW (fd, 2) = n + 2;
-    WFIFOW (fd, 4) = amount;
-
-    WFIFOSET (fd, packet_len_table[0xaf]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_itemlist (struct map_session_data *sd)
-{
-    int  i, n, fd, arrow = -1;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    WBUFW (buf, 0) = 0x1ee;
-    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid <= 0
-            || sd->inventory_data[i] == NULL
-            || itemdb_isequip2 (sd->inventory_data[i]))
-            continue;
-        WBUFW (buf, n * 18 + 4) = i + 2;
-        if (sd->inventory_data[i]->view_id > 0)
-            WBUFW (buf, n * 18 + 6) = sd->inventory_data[i]->view_id;
-        else
-            WBUFW (buf, n * 18 + 6) = sd->status.inventory[i].nameid;
-        WBUFB (buf, n * 18 + 8) = sd->inventory_data[i]->type;
-        WBUFB (buf, n * 18 + 9) = sd->status.inventory[i].identify;
-        WBUFW (buf, n * 18 + 10) = sd->status.inventory[i].amount;
-        if (sd->inventory_data[i]->equip == 0x8000)
-        {
-            WBUFW (buf, n * 18 + 12) = 0x8000;
-            if (sd->status.inventory[i].equip)
-                arrow = i;      // ついでに矢装備チェック
-        }
-        else
-            WBUFW (buf, n * 18 + 12) = 0;
-        WBUFW (buf, n * 18 + 14) = sd->status.inventory[i].card[0];
-        WBUFW (buf, n * 18 + 16) = sd->status.inventory[i].card[1];
-        WBUFW (buf, n * 18 + 18) = sd->status.inventory[i].card[2];
-        WBUFW (buf, n * 18 + 20) = sd->status.inventory[i].card[3];
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 18;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    if (arrow >= 0)
-        clif_arrowequip (sd, arrow);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_equiplist (struct map_session_data *sd)
-{
-    int  i, j, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    WBUFW (buf, 0) = 0xa4;
-    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid <= 0
-            || sd->inventory_data[i] == NULL
-            || !itemdb_isequip2 (sd->inventory_data[i]))
-            continue;
-        WBUFW (buf, n * 20 + 4) = i + 2;
-        if (sd->inventory_data[i]->view_id > 0)
-            WBUFW (buf, n * 20 + 6) = sd->inventory_data[i]->view_id;
-        else
-            WBUFW (buf, n * 20 + 6) = sd->status.inventory[i].nameid;
-        WBUFB (buf, n * 20 + 8) =
-            (sd->inventory_data[i]->type ==
-             7) ? 4 : sd->inventory_data[i]->type;
-        WBUFB (buf, n * 20 + 9) = sd->status.inventory[i].identify;
-        WBUFW (buf, n * 20 + 10) = pc_equippoint (sd, i);
-        WBUFW (buf, n * 20 + 12) = sd->status.inventory[i].equip;
-        if (sd->status.inventory[i].broken == 1)
-            WBUFB (buf, n * 20 + 14) = 1;   // is weapon broken [Valaris]
-        else
-            WBUFB (buf, n * 20 + 14) = sd->status.inventory[i].attribute;
-        WBUFB (buf, n * 20 + 15) = sd->status.inventory[i].refine;
-        if (sd->status.inventory[i].card[0] == 0x00ff
-            || sd->status.inventory[i].card[0] == 0x00fe
-            || sd->status.inventory[i].card[0] == (short) 0xff00)
-        {
-            WBUFW (buf, n * 20 + 16) = sd->status.inventory[i].card[0];
-            WBUFW (buf, n * 20 + 18) = sd->status.inventory[i].card[1];
-            WBUFW (buf, n * 20 + 20) = sd->status.inventory[i].card[2];
-            WBUFW (buf, n * 20 + 22) = sd->status.inventory[i].card[3];
-        }
-        else
-        {
-            if (sd->status.inventory[i].card[0] > 0
-                && (j = itemdb_viewid (sd->status.inventory[i].card[0])) > 0)
-                WBUFW (buf, n * 20 + 16) = j;
-            else
-                WBUFW (buf, n * 20 + 16) = sd->status.inventory[i].card[0];
-            if (sd->status.inventory[i].card[1] > 0
-                && (j = itemdb_viewid (sd->status.inventory[i].card[1])) > 0)
-                WBUFW (buf, n * 20 + 18) = j;
-            else
-                WBUFW (buf, n * 20 + 18) = sd->status.inventory[i].card[1];
-            if (sd->status.inventory[i].card[2] > 0
-                && (j = itemdb_viewid (sd->status.inventory[i].card[2])) > 0)
-                WBUFW (buf, n * 20 + 20) = j;
-            else
-                WBUFW (buf, n * 20 + 20) = sd->status.inventory[i].card[2];
-            if (sd->status.inventory[i].card[3] > 0
-                && (j = itemdb_viewid (sd->status.inventory[i].card[3])) > 0)
-                WBUFW (buf, n * 20 + 22) = j;
-            else
-                WBUFW (buf, n * 20 + 22) = sd->status.inventory[i].card[3];
-        }
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 20;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * カプラさんに預けてある消耗品&収集品リスト
- *------------------------------------------
- */
-int clif_storageitemlist (struct map_session_data *sd, struct storage *stor)
-{
-    struct item_data *id;
-    int  i, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    WBUFW (buf, 0) = 0x1f0;
-    for (i = 0, n = 0; i < MAX_STORAGE; i++)
-    {
-        if (stor->storage_[i].nameid <= 0)
-            continue;
-        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
-        if (itemdb_isequip2 (id))
-            continue;
-
-        WBUFW (buf, n * 18 + 4) = i + 1;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 18 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 18 + 6) = stor->storage_[i].nameid;
-        WBUFB (buf, n * 18 + 8) = id->type;;
-        WBUFB (buf, n * 18 + 9) = stor->storage_[i].identify;
-        WBUFW (buf, n * 18 + 10) = stor->storage_[i].amount;
-        WBUFW (buf, n * 18 + 12) = 0;
-        WBUFW (buf, n * 18 + 14) = stor->storage_[i].card[0];
-        WBUFW (buf, n * 18 + 16) = stor->storage_[i].card[1];
-        WBUFW (buf, n * 18 + 18) = stor->storage_[i].card[2];
-        WBUFW (buf, n * 18 + 20) = stor->storage_[i].card[3];
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 18;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * カプラさんに預けてある装備リスト
- *------------------------------------------
- */
-int clif_storageequiplist (struct map_session_data *sd, struct storage *stor)
-{
-    struct item_data *id;
-    int  i, j, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    WBUFW (buf, 0) = 0xa6;
-    for (i = 0, n = 0; i < MAX_STORAGE; i++)
-    {
-        if (stor->storage_[i].nameid <= 0)
-            continue;
-        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
-        if (!itemdb_isequip2 (id))
-            continue;
-        WBUFW (buf, n * 20 + 4) = i + 1;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 20 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 20 + 6) = stor->storage_[i].nameid;
-        WBUFB (buf, n * 20 + 8) = id->type;
-        WBUFB (buf, n * 20 + 9) = stor->storage_[i].identify;
-        WBUFW (buf, n * 20 + 10) = id->equip;
-        WBUFW (buf, n * 20 + 12) = stor->storage_[i].equip;
-        if (stor->storage_[i].broken == 1)
-            WBUFB (buf, n * 20 + 14) = 1;   //is weapon broken [Valaris]
-        else
-            WBUFB (buf, n * 20 + 14) = stor->storage_[i].attribute;
-        WBUFB (buf, n * 20 + 15) = stor->storage_[i].refine;
-        if (stor->storage_[i].card[0] == 0x00ff
-            || stor->storage_[i].card[0] == 0x00fe
-            || stor->storage_[i].card[0] == (short) 0xff00)
-        {
-            WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
-            WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
-            WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
-            WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
-        }
-        else
-        {
-            if (stor->storage_[i].card[0] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[0])) > 0)
-                WBUFW (buf, n * 20 + 16) = j;
-            else
-                WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
-            if (stor->storage_[i].card[1] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[1])) > 0)
-                WBUFW (buf, n * 20 + 18) = j;
-            else
-                WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
-            if (stor->storage_[i].card[2] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[2])) > 0)
-                WBUFW (buf, n * 20 + 20) = j;
-            else
-                WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
-            if (stor->storage_[i].card[3] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[3])) > 0)
-                WBUFW (buf, n * 20 + 22) = j;
-            else
-                WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
-        }
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 20;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_guildstorageitemlist (struct map_session_data *sd,
-                               struct guild_storage *stor)
-{
-    struct item_data *id;
-    int  i, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-
-    WBUFW (buf, 0) = 0x1f0;
-    for (i = 0, n = 0; i < MAX_GUILD_STORAGE; i++)
-    {
-        if (stor->storage_[i].nameid <= 0)
-            continue;
-        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
-        if (itemdb_isequip2 (id))
-            continue;
-
-        WBUFW (buf, n * 18 + 4) = i + 1;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 18 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 18 + 6) = stor->storage_[i].nameid;
-        WBUFB (buf, n * 18 + 8) = id->type;;
-        WBUFB (buf, n * 18 + 9) = stor->storage_[i].identify;
-        WBUFW (buf, n * 18 + 10) = stor->storage_[i].amount;
-        WBUFW (buf, n * 18 + 12) = 0;
-        WBUFW (buf, n * 18 + 14) = stor->storage_[i].card[0];
-        WBUFW (buf, n * 18 + 16) = stor->storage_[i].card[1];
-        WBUFW (buf, n * 18 + 18) = stor->storage_[i].card[2];
-        WBUFW (buf, n * 18 + 20) = stor->storage_[i].card[3];
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 18;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_guildstorageequiplist (struct map_session_data *sd,
-                                struct guild_storage *stor)
-{
-    struct item_data *id;
-    int  i, j, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-
-    WBUFW (buf, 0) = 0xa6;
-    for (i = 0, n = 0; i < MAX_GUILD_STORAGE; i++)
-    {
-        if (stor->storage_[i].nameid <= 0)
-            continue;
-        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
-        if (!itemdb_isequip2 (id))
-            continue;
-        WBUFW (buf, n * 20 + 4) = i + 1;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 20 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 20 + 6) = stor->storage_[i].nameid;
-        WBUFB (buf, n * 20 + 8) = id->type;
-        WBUFB (buf, n * 20 + 9) = stor->storage_[i].identify;
-        WBUFW (buf, n * 20 + 10) = id->equip;
-        WBUFW (buf, n * 20 + 12) = stor->storage_[i].equip;
-        if (stor->storage_[i].broken == 1)
-            WBUFB (buf, n * 20 + 14) = 1;   // is weapon broken [Valaris]
-        else
-            WBUFB (buf, n * 20 + 14) = stor->storage_[i].attribute;
-        WBUFB (buf, n * 20 + 15) = stor->storage_[i].refine;
-        if (stor->storage_[i].card[0] == 0x00ff
-            || stor->storage_[i].card[0] == 0x00fe
-            || stor->storage_[i].card[0] == (short) 0xff00)
-        {
-            WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
-            WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
-            WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
-            WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
-        }
-        else
-        {
-            if (stor->storage_[i].card[0] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[0])) > 0)
-                WBUFW (buf, n * 20 + 16) = j;
-            else
-                WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
-            if (stor->storage_[i].card[1] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[1])) > 0)
-                WBUFW (buf, n * 20 + 18) = j;
-            else
-                WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
-            if (stor->storage_[i].card[2] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[2])) > 0)
-                WBUFW (buf, n * 20 + 20) = j;
-            else
-                WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
-            if (stor->storage_[i].card[3] > 0
-                && (j = itemdb_viewid (stor->storage_[i].card[3])) > 0)
-                WBUFW (buf, n * 20 + 22) = j;
-            else
-                WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
-        }
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 20;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * ステータスを送りつける
- * 表示専用数字はこの中で計算して送る
- *------------------------------------------
- */
-int clif_updatestatus (struct map_session_data *sd, int type)
-{
-    int  fd, len = 8;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0xb0;
-    WFIFOW (fd, 2) = type;
-    switch (type)
-    {
-            // 00b0
-        case SP_WEIGHT:
-            pc_checkweighticon (sd);
-            WFIFOW (fd, 0) = 0xb0;
-            WFIFOW (fd, 2) = type;
-            WFIFOL (fd, 4) = sd->weight;
-            break;
-        case SP_MAXWEIGHT:
-            WFIFOL (fd, 4) = sd->max_weight;
-            break;
-        case SP_SPEED:
-            WFIFOL (fd, 4) = sd->speed;
-            break;
-        case SP_BASELEVEL:
-            WFIFOL (fd, 4) = sd->status.base_level;
-            break;
-        case SP_JOBLEVEL:
-            WFIFOL (fd, 4) = 0;
-            break;
-        case SP_MANNER:
-            WFIFOL (fd, 4) = sd->status.manner;
-            clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
-            break;
-        case SP_STATUSPOINT:
-            WFIFOL (fd, 4) = sd->status.status_point;
-            break;
-        case SP_SKILLPOINT:
-            WFIFOL (fd, 4) = sd->status.skill_point;
-            break;
-        case SP_HIT:
-            WFIFOL (fd, 4) = sd->hit;
-            break;
-        case SP_FLEE1:
-            WFIFOL (fd, 4) = sd->flee;
-            break;
-        case SP_FLEE2:
-            WFIFOL (fd, 4) = sd->flee2 / 10;
-            break;
-        case SP_MAXHP:
-            WFIFOL (fd, 4) = sd->status.max_hp;
-            break;
-        case SP_MAXSP:
-            WFIFOL (fd, 4) = sd->status.max_sp;
-            break;
-        case SP_HP:
-            WFIFOL (fd, 4) = sd->status.hp;
-            break;
-        case SP_SP:
-            WFIFOL (fd, 4) = sd->status.sp;
-            break;
-        case SP_ASPD:
-            WFIFOL (fd, 4) = sd->aspd;
-            break;
-        case SP_ATK1:
-            WFIFOL (fd, 4) = sd->base_atk + sd->watk;
-            break;
-        case SP_DEF1:
-            WFIFOL (fd, 4) = sd->def;
-            break;
-        case SP_MDEF1:
-            WFIFOL (fd, 4) = sd->mdef;
-            break;
-        case SP_ATK2:
-            WFIFOL (fd, 4) = sd->watk2;
-            break;
-        case SP_DEF2:
-            WFIFOL (fd, 4) = sd->def2;
-            break;
-        case SP_MDEF2:
-            WFIFOL (fd, 4) = sd->mdef2;
-            break;
-        case SP_CRITICAL:
-            WFIFOL (fd, 4) = sd->critical / 10;
-            break;
-        case SP_MATK1:
-            WFIFOL (fd, 4) = sd->matk1;
-            break;
-        case SP_MATK2:
-            WFIFOL (fd, 4) = sd->matk2;
-            break;
-
-        case SP_ZENY:
-            trade_verifyzeny (sd);
-            WFIFOW (fd, 0) = 0xb1;
-            if (sd->status.zeny < 0)
-                sd->status.zeny = 0;
-            WFIFOL (fd, 4) = sd->status.zeny;
-            break;
-        case SP_BASEEXP:
-            WFIFOW (fd, 0) = 0xb1;
-            WFIFOL (fd, 4) = sd->status.base_exp;
-            break;
-        case SP_JOBEXP:
-            WFIFOW (fd, 0) = 0xb1;
-            WFIFOL (fd, 4) = sd->status.job_exp;
-            break;
-        case SP_NEXTBASEEXP:
-            WFIFOW (fd, 0) = 0xb1;
-            WFIFOL (fd, 4) = pc_nextbaseexp (sd);
-            break;
-        case SP_NEXTJOBEXP:
-            WFIFOW (fd, 0) = 0xb1;
-            WFIFOL (fd, 4) = pc_nextjobexp (sd);
-            break;
-
-            // 00be 終了
-        case SP_USTR:
-        case SP_UAGI:
-        case SP_UVIT:
-        case SP_UINT:
-        case SP_UDEX:
-        case SP_ULUK:
-            WFIFOW (fd, 0) = 0xbe;
-            WFIFOB (fd, 4) =
-                pc_need_status_point (sd, type - SP_USTR + SP_STR);
-            len = 5;
-            break;
-
-            // 013a 終了
-        case SP_ATTACKRANGE:
-            WFIFOW (fd, 0) = 0x13a;
-            WFIFOW (fd, 2) = (sd->attack_spell_override)
-                ? sd->attack_spell_range : sd->attackrange;
-            len = 4;
-            break;
-
-            // 0141 終了
-        case SP_STR:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.str;
-            WFIFOL (fd, 10) = sd->paramb[0] + sd->parame[0];
-            len = 14;
-            break;
-        case SP_AGI:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.agi;
-            WFIFOL (fd, 10) = sd->paramb[1] + sd->parame[1];
-            len = 14;
-            break;
-        case SP_VIT:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.vit;
-            WFIFOL (fd, 10) = sd->paramb[2] + sd->parame[2];
-            len = 14;
-            break;
-        case SP_INT:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.int_;
-            WFIFOL (fd, 10) = sd->paramb[3] + sd->parame[3];
-            len = 14;
-            break;
-        case SP_DEX:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.dex;
-            WFIFOL (fd, 10) = sd->paramb[4] + sd->parame[4];
-            len = 14;
-            break;
-        case SP_LUK:
-            WFIFOW (fd, 0) = 0x141;
-            WFIFOL (fd, 2) = type;
-            WFIFOL (fd, 6) = sd->status.luk;
-            WFIFOL (fd, 10) = sd->paramb[5] + sd->parame[5];
-            len = 14;
-            break;
-
-        case SP_CARTINFO:
-            WFIFOW (fd, 0) = 0x121;
-            WFIFOW (fd, 2) = sd->cart_num;
-            WFIFOW (fd, 4) = sd->cart_max_num;
-            WFIFOL (fd, 6) = sd->cart_weight;
-            WFIFOL (fd, 10) = sd->cart_max_weight;
-            len = 14;
-            break;
-
-        case SP_GM:
-            WFIFOL (fd, 4) = pc_isGM (sd);
-            break;
-
-        default:
-            if (battle_config.error_log)
-                printf ("clif_updatestatus : make %d routine\n", type);
-            return 1;
-    }
-    WFIFOSET (fd, len);
-
-    return 0;
-}
-
-int clif_changestatus (struct block_list *bl, int type, int val)
-{
-    unsigned char buf[12];
-    struct map_session_data *sd = NULL;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-        sd = (struct map_session_data *) bl;
-
-//printf("clif_changestatus id:%d type:%d val:%d\n",bl->id,type,val);
-    if (sd)
-    {
-        WBUFW (buf, 0) = 0x1ab;
-        WBUFL (buf, 2) = bl->id;
-        WBUFW (buf, 6) = type;
-        switch (type)
-        {
-            case SP_MANNER:
-                WBUFL (buf, 8) = val;
-                break;
-            default:
-                if (battle_config.error_log)
-                    printf ("clif_changestatus : make %d routine\n", type);
-                return 1;
-        }
-        clif_send (buf, packet_len_table[0x1ab], bl, AREA_WOS);
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_changelook (struct block_list *bl, int type, int val)
-{
-    return clif_changelook_towards (bl, type, val, NULL);
-}
-
-int clif_changelook_towards (struct block_list *bl, int type, int val,
-                             struct map_session_data *dstsd)
-{
-    unsigned char rbuf[32];
-    unsigned char *buf = dstsd ? WFIFOP (dstsd->fd, 0) : rbuf;  // pick target buffer or general-purpose one
-    struct map_session_data *sd = NULL;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-        sd = (struct map_session_data *) bl;
-
-    if (sd && sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris]
-        return 0;
-
-    if (sd && sd->status.option & OPTION_INVISIBILITY)
-        return 0;
-
-    if (sd
-        && (type == LOOK_WEAPON || type == LOOK_SHIELD || type >= LOOK_SHOES))
-    {
-        WBUFW (buf, 0) = 0x1d7;
-        WBUFL (buf, 2) = bl->id;
-        if (type >= LOOK_SHOES)
-        {
-            int  equip_point = equip_points[type];
-
-            WBUFB (buf, 6) = type;
-            if (sd->equip_index[equip_point] >= 0
-                && sd->inventory_data[sd->equip_index[equip_point]])
-            {
-                if (sd->
-                    inventory_data[sd->equip_index[equip_point]]->view_id > 0)
-                    WBUFW (buf, 7) =
-                        sd->inventory_data[sd->
-                                           equip_index[equip_point]]->view_id;
-                else
-                    WBUFW (buf, 7) =
-                        sd->status.inventory[sd->
-                                             equip_index[equip_point]].nameid;
-            }
-            else
-                WBUFW (buf, 7) = 0;
-            WBUFW (buf, 9) = 0;
-        }
-        else
-        {
-            WBUFB (buf, 6) = 2;
-            if (sd->attack_spell_override)
-                WBUFW (buf, 7) = sd->attack_spell_look_override;
-            else
-            {
-                if (sd->equip_index[9] >= 0
-                    && sd->inventory_data[sd->equip_index[9]]
-                    && sd->view_class != 22)
-                {
-                    if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
-                        WBUFW (buf, 7) =
-                            sd->inventory_data[sd->equip_index[9]]->view_id;
-                    else
-                        WBUFW (buf, 7) =
-                            sd->status.inventory[sd->equip_index[9]].nameid;
-                }
-                else
-                    WBUFW (buf, 7) = 0;
-            }
-            if (sd->equip_index[8] >= 0
-                && sd->equip_index[8] != sd->equip_index[9]
-                && sd->inventory_data[sd->equip_index[8]]
-                && sd->view_class != 22)
-            {
-                if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
-                    WBUFW (buf, 9) =
-                        sd->inventory_data[sd->equip_index[8]]->view_id;
-                else
-                    WBUFW (buf, 9) =
-                        sd->status.inventory[sd->equip_index[8]].nameid;
-            }
-            else
-                WBUFW (buf, 9) = 0;
-        }
-        if (dstsd)
-            WFIFOSET (dstsd->fd, packet_len_table[0x1d7]);
-        else
-            clif_send (buf, packet_len_table[0x1d7], bl, AREA);
-    }
-    else
-    {
-        WBUFW (buf, 0) = 0x1d7;
-        WBUFL (buf, 2) = bl->id;
-        WBUFB (buf, 6) = type;
-        WBUFW (buf, 7) = val;
-        WBUFW (buf, 9) = 0;
-        if (dstsd)
-            WFIFOSET (dstsd->fd, packet_len_table[0x1d7]);
-        else
-            clif_send (buf, packet_len_table[0x1d7], bl, AREA);
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_initialstatus (struct map_session_data *sd)
-{
-    int  fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-
-    WBUFW (buf, 0) = 0xbd;
-    WBUFW (buf, 2) = sd->status.status_point;
-    WBUFB (buf, 4) = (sd->status.str > 255) ? 255 : sd->status.str;
-    WBUFB (buf, 5) = pc_need_status_point (sd, SP_STR);
-    WBUFB (buf, 6) = (sd->status.agi > 255) ? 255 : sd->status.agi;
-    WBUFB (buf, 7) = pc_need_status_point (sd, SP_AGI);
-    WBUFB (buf, 8) = (sd->status.vit > 255) ? 255 : sd->status.vit;
-    WBUFB (buf, 9) = pc_need_status_point (sd, SP_VIT);
-    WBUFB (buf, 10) = (sd->status.int_ > 255) ? 255 : sd->status.int_;
-    WBUFB (buf, 11) = pc_need_status_point (sd, SP_INT);
-    WBUFB (buf, 12) = (sd->status.dex > 255) ? 255 : sd->status.dex;
-    WBUFB (buf, 13) = pc_need_status_point (sd, SP_DEX);
-    WBUFB (buf, 14) = (sd->status.luk > 255) ? 255 : sd->status.luk;
-    WBUFB (buf, 15) = pc_need_status_point (sd, SP_LUK);
-
-    WBUFW (buf, 16) = sd->base_atk + sd->watk;
-    WBUFW (buf, 18) = sd->watk2;    //atk bonus
-    WBUFW (buf, 20) = sd->matk1;
-    WBUFW (buf, 22) = sd->matk2;
-    WBUFW (buf, 24) = sd->def;  // def
-    WBUFW (buf, 26) = sd->def2;
-    WBUFW (buf, 28) = sd->mdef; // mdef
-    WBUFW (buf, 30) = sd->mdef2;
-    WBUFW (buf, 32) = sd->hit;
-    WBUFW (buf, 34) = sd->flee;
-    WBUFW (buf, 36) = sd->flee2 / 10;
-    WBUFW (buf, 38) = sd->critical / 10;
-    WBUFW (buf, 40) = sd->status.karma;
-    WBUFW (buf, 42) = sd->status.manner;
-
-    WFIFOSET (fd, packet_len_table[0xbd]);
-
-    clif_updatestatus (sd, SP_STR);
-    clif_updatestatus (sd, SP_AGI);
-    clif_updatestatus (sd, SP_VIT);
-    clif_updatestatus (sd, SP_INT);
-    clif_updatestatus (sd, SP_DEX);
-    clif_updatestatus (sd, SP_LUK);
-
-    clif_updatestatus (sd, SP_ATTACKRANGE);
-    clif_updatestatus (sd, SP_ASPD);
-
-    return 0;
-}
-
-/*==========================================
- *矢装備
- *------------------------------------------
- */
-int clif_arrowequip (struct map_session_data *sd, int val)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    if (sd->attacktarget && sd->attacktarget > 0)   // [Valaris]
-        sd->attacktarget = 0;
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x013c;
-    WFIFOW (fd, 2) = val + 2;   //矢のアイテムID
-
-    WFIFOSET (fd, packet_len_table[0x013c]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_arrow_fail (struct map_session_data *sd, int type)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x013b;
-    WFIFOW (fd, 2) = type;
-
-    WFIFOSET (fd, packet_len_table[0x013b]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_statusupack (struct map_session_data *sd, int type, int ok, int val)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xbc;
-    WFIFOW (fd, 2) = type;
-    WFIFOB (fd, 4) = ok;
-    WFIFOB (fd, 5) = val;
-    WFIFOSET (fd, packet_len_table[0xbc]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_equipitemack (struct map_session_data *sd, int n, int pos, int ok)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xaa;
-    WFIFOW (fd, 2) = n + 2;
-    WFIFOW (fd, 4) = pos;
-    WFIFOB (fd, 6) = ok;
-    WFIFOSET (fd, packet_len_table[0xaa]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_unequipitemack (struct map_session_data *sd, int n, int pos, int ok)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xac;
-    WFIFOW (fd, 2) = n + 2;
-    WFIFOW (fd, 4) = pos;
-    WFIFOB (fd, 6) = ok;
-    WFIFOSET (fd, packet_len_table[0xac]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_misceffect (struct block_list *bl, int type)
-{
-    char buf[32];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x19b;
-    WBUFL (buf, 2) = bl->id;
-    WBUFL (buf, 6) = type;
-
-    clif_send (buf, packet_len_table[0x19b], bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * 表示オプション変更
- *------------------------------------------
- */
-int clif_changeoption (struct block_list *bl)
-{
-    char buf[32];
-    short option;
-    struct status_change *sc_data;
-    static const int omask[] = { 0x10, 0x20 };
-    static const int scnum[] = { SC_FALCON, SC_RIDING };
-    int  i;
-
-    nullpo_retr (0, bl);
-
-    option = *battle_get_option (bl);
-    sc_data = battle_get_sc_data (bl);
-
-    WBUFW (buf, 0) = 0x119;
-    WBUFL (buf, 2) = bl->id;
-    WBUFW (buf, 6) = *battle_get_opt1 (bl);
-    WBUFW (buf, 8) = *battle_get_opt2 (bl);
-    WBUFW (buf, 10) = option;
-    WBUFB (buf, 12) = 0;        // ??
-
-    if (bl->type == BL_PC)
-    {                           // disguises [Valaris]
-        struct map_session_data *sd = ((struct map_session_data *) bl);
-        if (sd && sd->disguise > 23 && sd->disguise < 4001)
-        {
-            clif_send (buf, packet_len_table[0x119], bl, AREA_WOS);
-            clif_spawnpc (sd);
-        }
-        else
-            clif_send (buf, packet_len_table[0x119], bl, AREA);
-    }
-    else
-        clif_send (buf, packet_len_table[0x119], bl, AREA);
-
-    // アイコンの表示
-    for (i = 0; i < sizeof (omask) / sizeof (omask[0]); i++)
-    {
-        if (option & omask[i])
-        {
-            if (sc_data[scnum[i]].timer == -1)
-                skill_status_change_start (bl, scnum[i], 0, 0, 0, 0, 0, 0);
-        }
-        else
-        {
-            skill_status_change_end (bl, scnum[i], -1);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_useitemack (struct map_session_data *sd, int index, int amount,
-                     int ok)
-{
-    nullpo_retr (0, sd);
-
-    if (!ok)
-    {
-        int  fd = sd->fd;
-        WFIFOW (fd, 0) = 0xa8;
-        WFIFOW (fd, 2) = index + 2;
-        WFIFOW (fd, 4) = amount;
-        WFIFOB (fd, 6) = ok;
-        WFIFOSET (fd, packet_len_table[0xa8]);
-    }
-    else
-    {
-        char buf[32];
-
-        WBUFW (buf, 0) = 0x1c8;
-        WBUFW (buf, 2) = index + 2;
-        if (sd->inventory_data[index]
-            && sd->inventory_data[index]->view_id > 0)
-            WBUFW (buf, 4) = sd->inventory_data[index]->view_id;
-        else
-            WBUFW (buf, 4) = sd->status.inventory[index].nameid;
-        WBUFL (buf, 6) = sd->bl.id;
-        WBUFW (buf, 10) = amount;
-        WBUFB (buf, 12) = ok;
-        clif_send (buf, packet_len_table[0x1c8], &sd->bl, SELF);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_createchat (struct map_session_data *sd, int fail)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xd6;
-    WFIFOB (fd, 2) = fail;
-    WFIFOSET (fd, packet_len_table[0xd6]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_dispchat (struct chat_data *cd, int fd)
-{
-    char buf[128];              // 最大title(60バイト)+17
-
-    if (cd == NULL || *cd->owner == NULL)
-        return 1;
-
-    WBUFW (buf, 0) = 0xd7;
-    WBUFW (buf, 2) = strlen (cd->title) + 17;
-    WBUFL (buf, 4) = (*cd->owner)->id;
-    WBUFL (buf, 8) = cd->bl.id;
-    WBUFW (buf, 12) = cd->limit;
-    WBUFW (buf, 14) = cd->users;
-    WBUFB (buf, 16) = cd->pub;
-    strcpy (WBUFP (buf, 17), cd->title);
-    if (fd)
-    {
-        memcpy (WFIFOP (fd, 0), buf, WBUFW (buf, 2));
-        WFIFOSET (fd, WBUFW (buf, 2));
-    }
-    else
-    {
-        clif_send (buf, WBUFW (buf, 2), *cd->owner, AREA_WOSC);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * chatの状態変更成功
- * 外部の人用と命令コード(d7->df)が違うだけ
- *------------------------------------------
- */
-int clif_changechatstatus (struct chat_data *cd)
-{
-    char buf[128];              // 最大title(60バイト)+17
-
-    if (cd == NULL || cd->usersd[0] == NULL)
-        return 1;
-
-    WBUFW (buf, 0) = 0xdf;
-    WBUFW (buf, 2) = strlen (cd->title) + 17;
-    WBUFL (buf, 4) = cd->usersd[0]->bl.id;
-    WBUFL (buf, 8) = cd->bl.id;
-    WBUFW (buf, 12) = cd->limit;
-    WBUFW (buf, 14) = cd->users;
-    WBUFB (buf, 16) = cd->pub;
-    strcpy (WBUFP (buf, 17), cd->title);
-    clif_send (buf, WBUFW (buf, 2), &cd->usersd[0]->bl, CHAT);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_clearchat (struct chat_data *cd, int fd)
-{
-    char buf[32];
-
-    nullpo_retr (0, cd);
-
-    WBUFW (buf, 0) = 0xd8;
-    WBUFL (buf, 2) = cd->bl.id;
-    if (fd)
-    {
-        memcpy (WFIFOP (fd, 0), buf, packet_len_table[0xd8]);
-        WFIFOSET (fd, packet_len_table[0xd8]);
-    }
-    else
-    {
-        clif_send (buf, packet_len_table[0xd8], *cd->owner, AREA_WOSC);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_joinchatfail (struct map_session_data *sd, int fail)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0xda;
-    WFIFOB (fd, 2) = fail;
-    WFIFOSET (fd, packet_len_table[0xda]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_joinchatok (struct map_session_data *sd, struct chat_data *cd)
-{
-    int  fd;
-    int  i;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, cd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xdb;
-    WFIFOW (fd, 2) = 8 + (28 * cd->users);
-    WFIFOL (fd, 4) = cd->bl.id;
-    for (i = 0; i < cd->users; i++)
-    {
-        WFIFOL (fd, 8 + i * 28) = (i != 0) || ((*cd->owner)->type == BL_NPC);
-        memcpy (WFIFOP (fd, 8 + i * 28 + 4), cd->usersd[i]->status.name, 24);
-    }
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_addchat (struct chat_data *cd, struct map_session_data *sd)
-{
-    char buf[32];
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, cd);
-
-    WBUFW (buf, 0) = 0x0dc;
-    WBUFW (buf, 2) = cd->users;
-    memcpy (WBUFP (buf, 4), sd->status.name, 24);
-    clif_send (buf, packet_len_table[0xdc], &sd->bl, CHAT_WOS);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_changechatowner (struct chat_data *cd, struct map_session_data *sd)
-{
-    char buf[64];
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, cd);
-
-    WBUFW (buf, 0) = 0xe1;
-    WBUFL (buf, 2) = 1;
-    memcpy (WBUFP (buf, 6), cd->usersd[0]->status.name, 24);
-    WBUFW (buf, 30) = 0xe1;
-    WBUFL (buf, 32) = 0;
-    memcpy (WBUFP (buf, 36), sd->status.name, 24);
-
-    clif_send (buf, packet_len_table[0xe1] * 2, &sd->bl, CHAT);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_leavechat (struct chat_data *cd, struct map_session_data *sd)
-{
-    char buf[32];
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, cd);
-
-    WBUFW (buf, 0) = 0xdd;
-    WBUFW (buf, 2) = cd->users - 1;
-    memcpy (WBUFP (buf, 4), sd->status.name, 24);
-    WBUFB (buf, 28) = 0;
-
-    clif_send (buf, packet_len_table[0xdd], &sd->bl, CHAT);
-
-    return 0;
-}
-
-/*==========================================
- * 取り引き要請受け
- *------------------------------------------
- */
-int clif_traderequest (struct map_session_data *sd, char *name)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xe5;
-    strcpy (WFIFOP (fd, 2), name);
-    WFIFOSET (fd, packet_len_table[0xe5]);
-
-    return 0;
-}
-
-/*==========================================
- * 取り引き要求応答
- *------------------------------------------
- */
-int clif_tradestart (struct map_session_data *sd, int type)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xe7;
-    WFIFOB (fd, 2) = type;
-    WFIFOSET (fd, packet_len_table[0xe7]);
-
-    return 0;
-}
-
-/*==========================================
- * 相手方からのアイテム追加
- *------------------------------------------
- */
-int clif_tradeadditem (struct map_session_data *sd,
-                       struct map_session_data *tsd, int index, int amount)
-{
-    int  fd, j;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, tsd);
-
-    fd = tsd->fd;
-    WFIFOW (fd, 0) = 0xe9;
-    WFIFOL (fd, 2) = amount;
-    if (index == 0)
-    {
-        WFIFOW (fd, 6) = 0;     // type id
-        WFIFOB (fd, 8) = 0;     //identify flag
-        WFIFOB (fd, 9) = 0;     // attribute
-        WFIFOB (fd, 10) = 0;    //refine
-        WFIFOW (fd, 11) = 0;    //card (4w)
-        WFIFOW (fd, 13) = 0;    //card (4w)
-        WFIFOW (fd, 15) = 0;    //card (4w)
-        WFIFOW (fd, 17) = 0;    //card (4w)
-    }
-    else
-    {
-        index -= 2;
-        if (sd->inventory_data[index]
-            && sd->inventory_data[index]->view_id > 0)
-            WFIFOW (fd, 6) = sd->inventory_data[index]->view_id;
-        else
-            WFIFOW (fd, 6) = sd->status.inventory[index].nameid;    // type id
-        WFIFOB (fd, 8) = sd->status.inventory[index].identify;  //identify flag
-        if (sd->status.inventory[index].broken == 1)
-            WFIFOB (fd, 9) = 1; // is broke weapon [Valaris]
-        else
-            WFIFOB (fd, 9) = sd->status.inventory[index].attribute; // attribute
-        WFIFOB (fd, 10) = sd->status.inventory[index].refine;   //refine
-        if (sd->status.inventory[index].card[0] == 0x00ff
-            || sd->status.inventory[index].card[0] == 0x00fe
-            || sd->status.inventory[index].card[0] == (short) 0xff00)
-        {
-            WFIFOW (fd, 11) = sd->status.inventory[index].card[0];  //card (4w)
-            WFIFOW (fd, 13) = sd->status.inventory[index].card[1];  //card (4w)
-            WFIFOW (fd, 15) = sd->status.inventory[index].card[2];  //card (4w)
-            WFIFOW (fd, 17) = sd->status.inventory[index].card[3];  //card (4w)
-        }
-        else
-        {
-            if (sd->status.inventory[index].card[0] > 0
-                && (j =
-                    itemdb_viewid (sd->status.inventory[index].card[0])) > 0)
-                WFIFOW (fd, 11) = j;
-            else
-                WFIFOW (fd, 11) = sd->status.inventory[index].card[0];
-            if (sd->status.inventory[index].card[1] > 0
-                && (j =
-                    itemdb_viewid (sd->status.inventory[index].card[1])) > 0)
-                WFIFOW (fd, 13) = j;
-            else
-                WFIFOW (fd, 13) = sd->status.inventory[index].card[1];
-            if (sd->status.inventory[index].card[2] > 0
-                && (j =
-                    itemdb_viewid (sd->status.inventory[index].card[2])) > 0)
-                WFIFOW (fd, 15) = j;
-            else
-                WFIFOW (fd, 15) = sd->status.inventory[index].card[2];
-            if (sd->status.inventory[index].card[3] > 0
-                && (j =
-                    itemdb_viewid (sd->status.inventory[index].card[3])) > 0)
-                WFIFOW (fd, 17) = j;
-            else
-                WFIFOW (fd, 17) = sd->status.inventory[index].card[3];
-        }
-    }
-    WFIFOSET (fd, packet_len_table[0xe9]);
-
-    return 0;
-}
-
-/*==========================================
- * アイテム追加成功/失敗
- *------------------------------------------
- */
-int clif_tradeitemok (struct map_session_data *sd, int index, int amount,
-                      int fail)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1b1;
-    //WFIFOW(fd,0)=0xea;
-    WFIFOW (fd, 2) = index;
-    WFIFOW (fd, 4) = amount;
-    WFIFOB (fd, 6) = fail;
-    WFIFOSET (fd, packet_len_table[0x1b1]);
-
-    return 0;
-}
-
-/*==========================================
- * 取り引きok押し
- *------------------------------------------
- */
-int clif_tradedeal_lock (struct map_session_data *sd, int fail)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xec;
-    WFIFOB (fd, 2) = fail;      // 0=you 1=the other person
-    WFIFOSET (fd, packet_len_table[0xec]);
-
-    return 0;
-}
-
-/*==========================================
- * 取り引きがキャンセルされました
- *------------------------------------------
- */
-int clif_tradecancelled (struct map_session_data *sd)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xee;
-    WFIFOSET (fd, packet_len_table[0xee]);
-
-    return 0;
-}
-
-/*==========================================
- * 取り引き完了
- *------------------------------------------
- */
-int clif_tradecompleted (struct map_session_data *sd, int fail)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf0;
-    WFIFOB (fd, 2) = fail;
-    WFIFOSET (fd, packet_len_table[0xf0]);
-
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫のアイテム数を更新
- *------------------------------------------
- */
-int clif_updatestorageamount (struct map_session_data *sd,
-                              struct storage *stor)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf2;      // update storage amount
-    WFIFOW (fd, 2) = stor->storage_amount;  //items
-    WFIFOW (fd, 4) = MAX_STORAGE;   //items max
-    WFIFOSET (fd, packet_len_table[0xf2]);
-
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫にアイテムを追加する
- *------------------------------------------
- */
-int clif_storageitemadded (struct map_session_data *sd, struct storage *stor,
-                           int index, int amount)
-{
-    int  fd, j;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf4;      // Storage item added
-    WFIFOW (fd, 2) = index + 1; // index
-    WFIFOL (fd, 4) = amount;    // amount
-/*	if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0)
-		WFIFOW(fd,8) =view;
-	else*/
-    WFIFOW (fd, 8) = stor->storage_[index].nameid;
-    WFIFOB (fd, 10) = stor->storage_[index].identify;   //identify flag
-    if (stor->storage_[index].broken == 1)
-        WFIFOB (fd, 11) = 1;    // is weapon broken [Valaris]
-    else
-        WFIFOB (fd, 11) = stor->storage_[index].attribute;  // attribute
-    WFIFOB (fd, 12) = stor->storage_[index].refine; //refine
-    if (stor->storage_[index].card[0] == 0x00ff
-        || stor->storage_[index].card[0] == 0x00fe
-        || stor->storage_[index].card[0] == (short) 0xff00)
-    {
-        WFIFOW (fd, 13) = stor->storage_[index].card[0];    //card (4w)
-        WFIFOW (fd, 15) = stor->storage_[index].card[1];    //card (4w)
-        WFIFOW (fd, 17) = stor->storage_[index].card[2];    //card (4w)
-        WFIFOW (fd, 19) = stor->storage_[index].card[3];    //card (4w)
-    }
-    else
-    {
-        if (stor->storage_[index].card[0] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[0])) > 0)
-            WFIFOW (fd, 13) = j;
-        else
-            WFIFOW (fd, 13) = stor->storage_[index].card[0];
-        if (stor->storage_[index].card[1] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[1])) > 0)
-            WFIFOW (fd, 15) = j;
-        else
-            WFIFOW (fd, 15) = stor->storage_[index].card[1];
-        if (stor->storage_[index].card[2] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[2])) > 0)
-            WFIFOW (fd, 17) = j;
-        else
-            WFIFOW (fd, 17) = stor->storage_[index].card[2];
-        if (stor->storage_[index].card[3] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[3])) > 0)
-            WFIFOW (fd, 19) = j;
-        else
-            WFIFOW (fd, 19) = stor->storage_[index].card[3];
-    }
-    WFIFOSET (fd, packet_len_table[0xf4]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_updateguildstorageamount (struct map_session_data *sd,
-                                   struct guild_storage *stor)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf2;      // update storage amount
-    WFIFOW (fd, 2) = stor->storage_amount;  //items
-    WFIFOW (fd, 4) = MAX_GUILD_STORAGE; //items max
-    WFIFOSET (fd, packet_len_table[0xf2]);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_guildstorageitemadded (struct map_session_data *sd,
-                                struct guild_storage *stor, int index,
-                                int amount)
-{
-    int  view, fd, j;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf4;      // Storage item added
-    WFIFOW (fd, 2) = index + 1; // index
-    WFIFOL (fd, 4) = amount;    // amount
-    if ((view = itemdb_viewid (stor->storage_[index].nameid)) > 0)
-        WFIFOW (fd, 8) = view;
-    else
-        WFIFOW (fd, 8) = stor->storage_[index].nameid;  // id
-    WFIFOB (fd, 10) = stor->storage_[index].identify;   //identify flag
-    if (stor->storage_[index].broken == 1)
-        WFIFOB (fd, 11) = 1;    // is weapon broken [Valaris]
-    else
-        WFIFOB (fd, 11) = stor->storage_[index].attribute;  // attribute
-    WFIFOB (fd, 12) = stor->storage_[index].refine; //refine
-    if (stor->storage_[index].card[0] == 0x00ff
-        || stor->storage_[index].card[0] == 0x00fe
-        || stor->storage_[index].card[0] == (short) 0xff00)
-    {
-        WFIFOW (fd, 13) = stor->storage_[index].card[0];    //card (4w)
-        WFIFOW (fd, 15) = stor->storage_[index].card[1];    //card (4w)
-        WFIFOW (fd, 17) = stor->storage_[index].card[2];    //card (4w)
-        WFIFOW (fd, 19) = stor->storage_[index].card[3];    //card (4w)
-    }
-    else
-    {
-        if (stor->storage_[index].card[0] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[0])) > 0)
-            WFIFOW (fd, 13) = j;
-        else
-            WFIFOW (fd, 13) = stor->storage_[index].card[0];
-        if (stor->storage_[index].card[1] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[1])) > 0)
-            WFIFOW (fd, 15) = j;
-        else
-            WFIFOW (fd, 15) = stor->storage_[index].card[1];
-        if (stor->storage_[index].card[2] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[2])) > 0)
-            WFIFOW (fd, 17) = j;
-        else
-            WFIFOW (fd, 17) = stor->storage_[index].card[2];
-        if (stor->storage_[index].card[3] > 0
-            && (j = itemdb_viewid (stor->storage_[index].card[3])) > 0)
-            WFIFOW (fd, 19) = j;
-        else
-            WFIFOW (fd, 19) = stor->storage_[index].card[3];
-    }
-    WFIFOSET (fd, packet_len_table[0xf4]);
-
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫からアイテムを取り去る
- *------------------------------------------
- */
-int clif_storageitemremoved (struct map_session_data *sd, int index,
-                             int amount)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf6;      // Storage item removed
-    WFIFOW (fd, 2) = index + 1;
-    WFIFOL (fd, 4) = amount;
-    WFIFOSET (fd, packet_len_table[0xf6]);
-
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫を閉じる
- *------------------------------------------
- */
-int clif_storageclose (struct map_session_data *sd)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xf8;      // Storage Closed
-    WFIFOSET (fd, packet_len_table[0xf8]);
-
-    return 0;
-}
-
-void
-clif_changelook_accessories (struct block_list *bl,
-                             struct map_session_data *dest)
-{
-    int  i;
-
-    for (i = LOOK_SHOES; i <= LOOK_LAST; i++)
-        clif_changelook_towards (bl, i, 0, dest);
-}
-
-//
-// callback系 ?
-//
-/*==========================================
- * PC表示
- *------------------------------------------
- */
-void clif_getareachar_pc (struct map_session_data *sd,
-                          struct map_session_data *dstsd)
-{
-    int  len;
-
-    if (dstsd->status.option & OPTION_INVISIBILITY)
-        return;
-
-    nullpo_retv (sd);
-    nullpo_retv (dstsd);
-
-    if (dstsd->walktimer != -1)
-    {
-        len = clif_set007b (dstsd, WFIFOP (sd->fd, 0));
-        WFIFOSET (sd->fd, len);
-    }
-    else
-    {
-        len = clif_set0078 (dstsd, WFIFOP (sd->fd, 0));
-        WFIFOSET (sd->fd, len);
-    }
-
-    if (dstsd->chatID)
-    {
-        struct chat_data *cd;
-        cd = (struct chat_data *) map_id2bl (dstsd->chatID);
-        if (cd->usersd[0] == dstsd)
-            clif_dispchat (cd, sd->fd);
-    }
-    if (dstsd->spiritball > 0)
-    {
-        clif_set01e1 (dstsd, WFIFOP (sd->fd, 0));
-        WFIFOSET (sd->fd, packet_len_table[0x1e1]);
-    }
-    if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0)
-        clif_changelook (&dstsd->bl, LOOK_CLOTHES_COLOR,
-                         dstsd->status.clothes_color);
-
-    if (sd->status.manner < 0)
-        clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
-
-    clif_changelook_accessories (&sd->bl, dstsd);
-    clif_changelook_accessories (&dstsd->bl, sd);
-}
-
-/*==========================================
- * NPC表示
- *------------------------------------------
- */
-void clif_getareachar_npc (struct map_session_data *sd, struct npc_data *nd)
-{
-    int  len;
-
-    nullpo_retv (sd);
-    nullpo_retv (nd);
-
-    if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS)
-        return;
-
-    len = clif_npc0078 (nd, WFIFOP (sd->fd, 0));
-    WFIFOSET (sd->fd, len);
-
-    if (nd->chat_id)
-    {
-        clif_dispchat ((struct chat_data *) map_id2bl (nd->chat_id), sd->fd);
-    }
-
-}
-
-/*==========================================
- * 移動停止
- *------------------------------------------
- */
-int clif_movemob (struct mob_data *md)
-{
-    unsigned char buf[256];
-    int  len;
-
-    nullpo_retr (0, md);
-
-    len = clif_mob007b (md, buf);
-    clif_send (buf, len, &md->bl, AREA);
-
-    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
-        clif_mob_equip (md, mob_get_equip (md->mob_class));
-
-    return 0;
-}
-
-/*==========================================
- * モンスターの位置修正
- *------------------------------------------
- */
-int clif_fixmobpos (struct mob_data *md)
-{
-    unsigned char buf[256];
-    int  len;
-
-    nullpo_retr (0, md);
-
-    if (md->state.state == MS_WALK)
-    {
-        len = clif_mob007b (md, buf);
-        clif_send (buf, len, &md->bl, AREA);
-    }
-    else
-    {
-        len = clif_mob0078 (md, buf);
-        clif_send (buf, len, &md->bl, AREA);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * PCの位置修正
- *------------------------------------------
- */
-int clif_fixpcpos (struct map_session_data *sd)
-{
-    unsigned char buf[256];
-    int  len;
-
-    nullpo_retr (0, sd);
-
-    if (sd->walktimer != -1)
-    {
-        len = clif_set007b (sd, buf);
-        clif_send (buf, len, &sd->bl, AREA);
-    }
-    else
-    {
-        len = clif_set0078 (sd, buf);
-        clif_send (buf, len, &sd->bl, AREA);
-    }
-    clif_changelook_accessories (&sd->bl, NULL);
-
-    return 0;
-}
-
-/*==========================================
- * 通常攻撃エフェクト&ダメージ
- *------------------------------------------
- */
-int clif_damage (struct block_list *src, struct block_list *dst,
-                 unsigned int tick, int sdelay, int ddelay, int damage,
-                 int div, int type, int damage2)
-{
-    unsigned char buf[256];
-    struct status_change *sc_data;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, dst);
-
-    sc_data = battle_get_sc_data (dst);
-
-    if (type != 4 && dst->type == BL_PC
-        && ((struct map_session_data *) dst)->special_state.infinite_endure)
-        type = 9;
-    if (sc_data)
-    {
-        if (type != 4 && sc_data[SC_ENDURE].timer != -1)
-            type = 9;
-        if (sc_data[SC_HALLUCINATION].timer != -1)
-        {
-            if (damage > 0)
-                damage =
-                    damage * (5 + sc_data[SC_HALLUCINATION].val1) +
-                    MRAND (100);
-            if (damage2 > 0)
-                damage2 =
-                    damage2 * (5 + sc_data[SC_HALLUCINATION].val1) +
-                    MRAND (100);
-        }
-    }
-
-    WBUFW (buf, 0) = 0x8a;
-    WBUFL (buf, 2) = src->id;
-    WBUFL (buf, 6) = dst->id;
-    WBUFL (buf, 10) = tick;
-    WBUFL (buf, 14) = sdelay;
-    WBUFL (buf, 18) = ddelay;
-    WBUFW (buf, 22) = (damage > 0x7fff) ? 0x7fff : damage;
-    WBUFW (buf, 24) = div;
-    WBUFB (buf, 26) = type;
-    WBUFW (buf, 27) = damage2;
-    clif_send (buf, packet_len_table[0x8a], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_getareachar_mob (struct map_session_data *sd, struct mob_data *md)
-{
-    int  len;
-    nullpo_retv (sd);
-    nullpo_retv (md);
-
-    if (md->state.state == MS_WALK)
-    {
-        len = clif_mob007b (md, WFIFOP (sd->fd, 0));
-        WFIFOSET (sd->fd, len);
-    }
-    else
-    {
-        len = clif_mob0078 (md, WFIFOP (sd->fd, 0));
-        WFIFOSET (sd->fd, len);
-    }
-
-    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
-        clif_mob_equip (md, mob_get_equip (md->mob_class));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_getareachar_item (struct map_session_data *sd,
-                            struct flooritem_data *fitem)
-{
-    int  view, fd;
-
-    nullpo_retv (sd);
-    nullpo_retv (fitem);
-
-    fd = sd->fd;
-    //009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B
-    WFIFOW (fd, 0) = 0x9d;
-    WFIFOL (fd, 2) = fitem->bl.id;
-    if ((view = itemdb_viewid (fitem->item_data.nameid)) > 0)
-        WFIFOW (fd, 6) = view;
-    else
-        WFIFOW (fd, 6) = fitem->item_data.nameid;
-    WFIFOB (fd, 8) = fitem->item_data.identify;
-    WFIFOW (fd, 9) = fitem->bl.x;
-    WFIFOW (fd, 11) = fitem->bl.y;
-    WFIFOW (fd, 13) = fitem->item_data.amount;
-    WFIFOB (fd, 15) = fitem->subx;
-    WFIFOB (fd, 16) = fitem->suby;
-
-    WFIFOSET (fd, packet_len_table[0x9d]);
-}
-
-/*==========================================
- * 場所スキルエフェクトが視界に入る
- *------------------------------------------
- */
-int clif_getareachar_skillunit (struct map_session_data *sd,
-                                struct skill_unit *unit)
-{
-    int  fd;
-    struct block_list *bl;
-
-    nullpo_retr (0, unit);
-
-    fd = sd->fd;
-    bl = map_id2bl (unit->group->src_id);
-    memset (WFIFOP (fd, 0), 0, packet_len_table[0x1c9]);
-    WFIFOW (fd, 0) = 0x1c9;
-    WFIFOL (fd, 2) = unit->bl.id;
-    WFIFOL (fd, 6) = unit->group->src_id;
-    WFIFOW (fd, 10) = unit->bl.x;
-    WFIFOW (fd, 12) = unit->bl.y;
-    WFIFOB (fd, 14) = unit->group->unit_id;
-    WFIFOB (fd, 15) = 1;
-    WFIFOL (fd, 15 + 1) = 0;    //1-4調べた限り固定
-    WFIFOL (fd, 15 + 5) = 0;    //5-8調べた限り固定
-    //9-12マップごとで一定の77-80とはまた違う4バイトのかなり大きな数字
-    WFIFOL (fd, 15 + 13) = unit->bl.y - 0x12;   //13-16ユニットのY座標-18っぽい(Y:17でFF FF FF FF)
-    WFIFOL (fd, 15 + 17) = 0x004f37dd;  //17-20調べた限り固定
-    WFIFOL (fd, 15 + 21) = 0x0012f674;  //21-24調べた限り固定
-    WFIFOL (fd, 15 + 25) = 0x0012f664;  //25-28調べた限り固定
-    WFIFOL (fd, 15 + 29) = 0x0012f654;  //29-32調べた限り固定
-    WFIFOL (fd, 15 + 33) = 0x77527bbc;  //33-36調べた限り固定
-    //37-39
-    WFIFOB (fd, 15 + 40) = 0x2d;    //40調べた限り固定
-    WFIFOL (fd, 15 + 41) = 0;   //41-44調べた限り0固定
-    WFIFOL (fd, 15 + 45) = 0;   //45-48調べた限り0固定
-    WFIFOL (fd, 15 + 49) = 0;   //49-52調べた限り0固定
-    WFIFOL (fd, 15 + 53) = 0x0048d919;  //53-56調べた限り固定
-    WFIFOL (fd, 15 + 57) = 0x0000003e;  //57-60調べた限り固定
-    WFIFOL (fd, 15 + 61) = 0x0012f66c;  //61-64調べた限り固定
-    //65-68
-    //69-72
-    if (bl)
-        WFIFOL (fd, 15 + 73) = bl->y;   //73-76術者のY座標
-    WFIFOL (fd, 15 + 77) = unit->bl.m;  //77-80マップIDかなぁ?かなり2バイトで足りそうな数字
-    WFIFOB (fd, 15 + 81) = 0xaa;    //81終端文字0xaa
-
-    /*  Graffiti [Valaris]  */
-    if (unit->group->unit_id == 0xb0)
-    {
-        WFIFOL (fd, 15) = 1;
-        WFIFOL (fd, 16) = 1;
-        memcpy (WFIFOP (fd, 17), unit->group->valstr, 80);
-    }
-
-    WFIFOSET (fd, packet_len_table[0x1c9]);
-    if (unit->group->skill_id == WZ_ICEWALL)
-        clif_set0192 (fd, unit->bl.m, unit->bl.x, unit->bl.y, 5);
-
-    return 0;
-}
-
-/*==========================================
- * 場所スキルエフェクトが視界から消える
- *------------------------------------------
- */
-int clif_clearchar_skillunit (struct skill_unit *unit, int fd)
-{
-    nullpo_retr (0, unit);
-
-    WFIFOW (fd, 0) = 0x120;
-    WFIFOL (fd, 2) = unit->bl.id;
-    WFIFOSET (fd, packet_len_table[0x120]);
-    if (unit->group->skill_id == WZ_ICEWALL)
-        clif_set0192 (fd, unit->bl.m, unit->bl.x, unit->bl.y, unit->val2);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_01ac (struct block_list *bl)
-{
-    char buf[32];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x1ac;
-    WBUFL (buf, 2) = bl->id;
-
-    clif_send (buf, packet_len_table[0x1ac], bl, AREA);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_getareachar (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    sd = va_arg (ap, struct map_session_data *);
-
-    switch (bl->type)
-    {
-        case BL_PC:
-            if (sd == (struct map_session_data *) bl)
-                break;
-            clif_getareachar_pc (sd, (struct map_session_data *) bl);
-            break;
-        case BL_NPC:
-            clif_getareachar_npc (sd, (struct npc_data *) bl);
-            break;
-        case BL_MOB:
-            clif_getareachar_mob (sd, (struct mob_data *) bl);
-            break;
-        case BL_ITEM:
-            clif_getareachar_item (sd, (struct flooritem_data *) bl);
-            break;
-        case BL_SKILL:
-            clif_getareachar_skillunit (sd, (struct skill_unit *) bl);
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("get area char ??? %d\n", bl->type);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_pcoutsight (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd, *dstsd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
-
-    switch (bl->type)
-    {
-        case BL_PC:
-            dstsd = (struct map_session_data *) bl;
-            if (sd != dstsd)
-            {
-                clif_clearchar_id (dstsd->bl.id, 0, sd->fd);
-                clif_clearchar_id (sd->bl.id, 0, dstsd->fd);
-                if (dstsd->chatID)
-                {
-                    struct chat_data *cd;
-                    cd = (struct chat_data *) map_id2bl (dstsd->chatID);
-                    if (cd->usersd[0] == dstsd)
-                        clif_dispchat (cd, sd->fd);
-                }
-            }
-            break;
-        case BL_NPC:
-            if (((struct npc_data *) bl)->npc_class != INVISIBLE_CLASS)
-                clif_clearchar_id (bl->id, 0, sd->fd);
-            break;
-        case BL_MOB:
-            clif_clearchar_id (bl->id, 0, sd->fd);
-            break;
-        case BL_ITEM:
-            clif_clearflooritem ((struct flooritem_data *) bl, sd->fd);
-            break;
-        case BL_SKILL:
-            clif_clearchar_skillunit ((struct skill_unit *) bl, sd->fd);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_pcinsight (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd, *dstsd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
-
-    switch (bl->type)
-    {
-        case BL_PC:
-            dstsd = (struct map_session_data *) bl;
-            if (sd != dstsd)
-            {
-                clif_getareachar_pc (sd, dstsd);
-                clif_getareachar_pc (dstsd, sd);
-            }
-            break;
-        case BL_NPC:
-            clif_getareachar_npc (sd, (struct npc_data *) bl);
-            break;
-        case BL_MOB:
-            clif_getareachar_mob (sd, (struct mob_data *) bl);
-            break;
-        case BL_ITEM:
-            clif_getareachar_item (sd, (struct flooritem_data *) bl);
-            break;
-        case BL_SKILL:
-            clif_getareachar_skillunit (sd, (struct skill_unit *) bl);
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_moboutsight (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-    struct mob_data *md;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
-
-    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
-    {
-        clif_clearchar_id (md->bl.id, 0, sd->fd);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_mobinsight (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-    struct mob_data *md;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    md = va_arg (ap, struct mob_data *);
-    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
-    {
-        clif_getareachar_mob (sd, md);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_skillinfo (struct map_session_data *sd, int skillid, int type,
-                    int range)
-{
-    int  fd, id;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    if ((id = sd->status.skill[skillid].id) <= 0)
-        return 0;
-    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_range (id, sd->status.skill[skillid].lv);
-        if (range < 0)
-            range = battle_get_range (&sd->bl) - (range + 1);
-        WFIFOW (fd, 12) = range;
-    }
-    else
-        WFIFOW (fd, 12) = range;
-    memset (WFIFOP (fd, 14), 0, 24);
-    WFIFOB (fd, 38) =
-        (sd->status.skill[skillid].lv < skill_get_max_raise (id)) ? 1 : 0;
-    WFIFOSET (fd, packet_len_table[0x147]);
-
-    return 0;
-}
-
-/*==========================================
- * スキルリストを送信する
- *------------------------------------------
- */
-int clif_skillinfoblock (struct map_session_data *sd)
-{
-    int  fd;
-    int  i, c, len = 4, id, range;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x10f;
-    for (i = c = 0; i < MAX_SKILL; i++)
-    {
-        if ((id = sd->status.skill[i].id) != 0 && (sd->tmw_version >= 1))
-        {                       // [Fate] Version 1 and later don't crash because of bad skill IDs anymore
-            WFIFOW (fd, len) = id;
-            WFIFOW (fd, len + 2) = skill_get_inf (id);
-            WFIFOW (fd, len + 4) =
-                skill_db[i].poolflags | (sd->status.
-                                         skill[i].flags &
-                                         (SKILL_POOL_ACTIVATED));
-            WFIFOW (fd, len + 6) = sd->status.skill[i].lv;
-            WFIFOW (fd, len + 8) = skill_get_sp (id, sd->status.skill[i].lv);
-            range = skill_get_range (id, sd->status.skill[i].lv);
-            if (range < 0)
-                range = battle_get_range (&sd->bl) - (range + 1);
-            WFIFOW (fd, len + 10) = range;
-            memset (WFIFOP (fd, len + 12), 0, 24);
-            WFIFOB (fd, len + 36) =
-                (sd->status.skill[i].lv < skill_get_max_raise (id)) ? 1 : 0;
-            len += 37;
-            c++;
-        }
-    }
-    WFIFOW (fd, 2) = len;
-    WFIFOSET (fd, len);
-
-    return 0;
-}
-
-/*==========================================
- * スキル割り振り通知
- *------------------------------------------
- */
-int clif_skillup (struct map_session_data *sd, int skill_num)
-{
-    int  range, fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x10e;
-    WFIFOW (fd, 2) = skill_num;
-    WFIFOW (fd, 4) = sd->status.skill[skill_num].lv;
-    WFIFOW (fd, 6) = skill_get_sp (skill_num, sd->status.skill[skill_num].lv);
-    range = skill_get_range (skill_num, sd->status.skill[skill_num].lv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    WFIFOW (fd, 8) = range;
-    WFIFOB (fd, 10) =
-        (sd->status.skill[skill_num].lv <
-         skill_get_max_raise (sd->status.skill[skill_num].id)) ? 1 : 0;
-    WFIFOSET (fd, packet_len_table[0x10e]);
-
-    return 0;
-}
-
-/*==========================================
- * スキル詠唱エフェクトを送信する
- *------------------------------------------
- */
-int clif_skillcasting (struct block_list *bl,
-                       int src_id, int dst_id, int dst_x, int dst_y,
-                       int skill_num, int casttime)
-{
-    unsigned char buf[32];
-    WBUFW (buf, 0) = 0x13e;
-    WBUFL (buf, 2) = src_id;
-    WBUFL (buf, 6) = dst_id;
-    WBUFW (buf, 10) = dst_x;
-    WBUFW (buf, 12) = dst_y;
-    WBUFW (buf, 14) = skill_num;    //魔法詠唱スキル
-    WBUFL (buf, 16) = skill_get_pl (skill_num); //属性
-    WBUFL (buf, 20) = casttime; //skill詠唱時間
-    clif_send (buf, packet_len_table[0x13e], bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_skillcastcancel (struct block_list *bl)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x1b9;
-    WBUFL (buf, 2) = bl->id;
-    clif_send (buf, packet_len_table[0x1b9], bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * スキル詠唱失敗
- *------------------------------------------
- */
-int clif_skill_fail (struct map_session_data *sd, int skill_id, int type,
-                     int btype)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    if (type == 0x4 && battle_config.display_delay_skill_fail == 0)
-    {
-        return 0;
-    }
-
-    WFIFOW (fd, 0) = 0x110;
-    WFIFOW (fd, 2) = skill_id;
-    WFIFOW (fd, 4) = btype;
-    WFIFOW (fd, 6) = 0;
-    WFIFOB (fd, 8) = 0;
-    WFIFOB (fd, 9) = type;
-    WFIFOSET (fd, packet_len_table[0x110]);
-
-    return 0;
-}
-
-/*==========================================
- * スキル攻撃エフェクト&ダメージ
- *------------------------------------------
- */
-int clif_skill_damage (struct block_list *src, struct block_list *dst,
-                       unsigned int tick, int sdelay, int ddelay, int damage,
-                       int div, int skill_id, int skill_lv, int type)
-{
-    unsigned char buf[64];
-    struct status_change *sc_data;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, dst);
-
-    sc_data = battle_get_sc_data (dst);
-
-    if (type != 5 && dst->type == BL_PC
-        && ((struct map_session_data *) dst)->special_state.infinite_endure)
-        type = 9;
-    if (sc_data)
-    {
-        if (type != 5 && sc_data[SC_ENDURE].timer != -1)
-            type = 9;
-        if (sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
-            damage =
-                damage * (5 + sc_data[SC_HALLUCINATION].val1) + MRAND (100);
-    }
-
-    WBUFW (buf, 0) = 0x1de;
-    WBUFW (buf, 2) = skill_id;
-    WBUFL (buf, 4) = src->id;
-    WBUFL (buf, 8) = dst->id;
-    WBUFL (buf, 12) = tick;
-    WBUFL (buf, 16) = sdelay;
-    WBUFL (buf, 20) = ddelay;
-    WBUFL (buf, 24) = damage;
-    WBUFW (buf, 28) = skill_lv;
-    WBUFW (buf, 30) = div;
-    WBUFB (buf, 32) = (type > 0) ? type : skill_get_hit (skill_id);
-    clif_send (buf, packet_len_table[0x1de], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * 吹き飛ばしスキル攻撃エフェクト&ダメージ
- *------------------------------------------
- */
-int clif_skill_damage2 (struct block_list *src, struct block_list *dst,
-                        unsigned int tick, int sdelay, int ddelay, int damage,
-                        int div, int skill_id, int skill_lv, int type)
-{
-    unsigned char buf[64];
-    struct status_change *sc_data;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, dst);
-
-    sc_data = battle_get_sc_data (dst);
-
-    if (type != 5 && dst->type == BL_PC
-        && ((struct map_session_data *) dst)->special_state.infinite_endure)
-        type = 9;
-    if (sc_data)
-    {
-        if (type != 5 && sc_data[SC_ENDURE].timer != -1)
-            type = 9;
-        if (sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
-            damage =
-                damage * (5 + sc_data[SC_HALLUCINATION].val1) + MRAND (100);
-    }
-
-    WBUFW (buf, 0) = 0x115;
-    WBUFW (buf, 2) = skill_id;
-    WBUFL (buf, 4) = src->id;
-    WBUFL (buf, 8) = dst->id;
-    WBUFL (buf, 12) = tick;
-    WBUFL (buf, 16) = sdelay;
-    WBUFL (buf, 20) = ddelay;
-    WBUFW (buf, 24) = dst->x;
-    WBUFW (buf, 26) = dst->y;
-    WBUFW (buf, 28) = damage;
-    WBUFW (buf, 30) = skill_lv;
-    WBUFW (buf, 32) = div;
-    WBUFB (buf, 34) = (type > 0) ? type : skill_get_hit (skill_id);
-    clif_send (buf, packet_len_table[0x115], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * 支援/回復スキルエフェクト
- *------------------------------------------
- */
-int clif_skill_nodamage (struct block_list *src, struct block_list *dst,
-                         int skill_id, int heal, int fail)
-{
-    unsigned char buf[32];
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, dst);
-
-    WBUFW (buf, 0) = 0x11a;
-    WBUFW (buf, 2) = skill_id;
-    WBUFW (buf, 4) = (heal > 0x7fff) ? 0x7fff : heal;
-    WBUFL (buf, 6) = dst->id;
-    WBUFL (buf, 10) = src->id;
-    WBUFB (buf, 14) = fail;
-    clif_send (buf, packet_len_table[0x11a], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * 場所スキルエフェクト
- *------------------------------------------
- */
-int clif_skill_poseffect (struct block_list *src, int skill_id, int val,
-                          int x, int y, int tick)
-{
-    unsigned char buf[32];
-
-    nullpo_retr (0, src);
-
-    WBUFW (buf, 0) = 0x117;
-    WBUFW (buf, 2) = skill_id;
-    WBUFL (buf, 4) = src->id;
-    WBUFW (buf, 8) = val;
-    WBUFW (buf, 10) = x;
-    WBUFW (buf, 12) = y;
-    WBUFL (buf, 14) = tick;
-    clif_send (buf, packet_len_table[0x117], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- * 場所スキルエフェクト表示
- *------------------------------------------
- */
-int clif_skill_setunit (struct skill_unit *unit)
-{
-    unsigned char buf[128];
-    struct block_list *bl;
-
-    nullpo_retr (0, unit);
-
-    bl = map_id2bl (unit->group->src_id);
-
-    memset (WBUFP (buf, 0), 0, packet_len_table[0x1c9]);
-    WBUFW (buf, 0) = 0x1c9;
-    WBUFL (buf, 2) = unit->bl.id;
-    WBUFL (buf, 6) = unit->group->src_id;
-    WBUFW (buf, 10) = unit->bl.x;
-    WBUFW (buf, 12) = unit->bl.y;
-    WBUFB (buf, 14) = unit->group->unit_id;
-    WBUFB (buf, 15) = 1;
-    WBUFL (buf, 15 + 1) = 0;    //1-4調べた限り固定
-    WBUFL (buf, 15 + 5) = 0;    //5-8調べた限り固定
-    //9-12マップごとで一定の77-80とはまた違う4バイトのかなり大きな数字
-    WBUFL (buf, 15 + 13) = unit->bl.y - 0x12;   //13-16ユニットのY座標-18っぽい(Y:17でFF FF FF FF)
-    WBUFL (buf, 15 + 17) = 0x004f37dd;  //17-20調べた限り固定(0x1b2で0x004fdbddだった)
-    WBUFL (buf, 15 + 21) = 0x0012f674;  //21-24調べた限り固定
-    WBUFL (buf, 15 + 25) = 0x0012f664;  //25-28調べた限り固定
-    WBUFL (buf, 15 + 29) = 0x0012f654;  //29-32調べた限り固定
-    WBUFL (buf, 15 + 33) = 0x77527bbc;  //33-36調べた限り固定
-    //37-39
-    WBUFB (buf, 15 + 40) = 0x2d;    //40調べた限り固定
-    WBUFL (buf, 15 + 41) = 0;   //41-44調べた限り0固定
-    WBUFL (buf, 15 + 45) = 0;   //45-48調べた限り0固定
-    WBUFL (buf, 15 + 49) = 0;   //49-52調べた限り0固定
-    WBUFL (buf, 15 + 53) = 0x0048d919;  //53-56調べた限り固定(0x01b2で0x00495119だった)
-    WBUFL (buf, 15 + 57) = 0x0000003e;  //57-60調べた限り固定
-    WBUFL (buf, 15 + 61) = 0x0012f66c;  //61-64調べた限り固定
-    //65-68
-    //69-72
-    if (bl)
-        WBUFL (buf, 15 + 73) = bl->y;   //73-76術者のY座標
-    WBUFL (buf, 15 + 77) = unit->bl.m;  //77-80マップIDかなぁ?かなり2バイトで足りそうな数字
-    WBUFB (buf, 15 + 81) = 0xaa;    //81終端文字0xaa
-
-    /*      Graffiti [Valaris]      */
-    if (unit->group->unit_id == 0xb0)
-    {
-        WBUFL (buf, 15) = 1;
-        WBUFL (buf, 16) = 1;
-        memcpy (WBUFP (buf, 17), unit->group->valstr, 80);
-    }
-
-    clif_send (buf, packet_len_table[0x1c9], &unit->bl, AREA);
-    return 0;
-}
-
-/*==========================================
- * 場所スキルエフェクト削除
- *------------------------------------------
- */
-int clif_skill_delunit (struct skill_unit *unit)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, unit);
-
-    WBUFW (buf, 0) = 0x120;
-    WBUFL (buf, 2) = unit->bl.id;
-    clif_send (buf, packet_len_table[0x120], &unit->bl, AREA);
-    return 0;
-}
-
-/*==========================================
- * ワープ場所選択
- *------------------------------------------
- */
-int clif_skill_warppoint (struct map_session_data *sd, int skill_num,
-                          const char *map1, const char *map2,
-                          const char *map3, const char *map4)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x11c;
-    WFIFOW (fd, 2) = skill_num;
-    memcpy (WFIFOP (fd, 4), map1, 16);
-    memcpy (WFIFOP (fd, 20), map2, 16);
-    memcpy (WFIFOP (fd, 36), map3, 16);
-    memcpy (WFIFOP (fd, 52), map4, 16);
-    WFIFOSET (fd, packet_len_table[0x11c]);
-    return 0;
-}
-
-/*==========================================
- * メモ応答
- *------------------------------------------
- */
-int clif_skill_memo (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x11e;
-    WFIFOB (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x11e]);
-    return 0;
-}
-
-int clif_skill_teleportmessage (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x189;
-    WFIFOW (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x189]);
-    return 0;
-}
-
-/*==========================================
- * モンスター情報
- *------------------------------------------
- */
-int clif_skill_estimation (struct map_session_data *sd,
-                           struct block_list *dst)
-{
-    struct mob_data *md;
-    unsigned char buf[64];
-    int  i;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, dst);
-
-    if (dst->type != BL_MOB)
-        return 0;
-    if ((md = (struct mob_data *) dst) == NULL)
-        return 0;
-
-    WBUFW (buf, 0) = 0x18c;
-    WBUFW (buf, 2) = mob_get_viewclass (md->mob_class);
-    WBUFW (buf, 4) = mob_db[md->mob_class].lv;
-    WBUFW (buf, 6) = mob_db[md->mob_class].size;
-    WBUFL (buf, 8) = md->hp;
-    WBUFW (buf, 12) = battle_get_def2 (&md->bl);
-    WBUFW (buf, 14) = mob_db[md->mob_class].race;
-    WBUFW (buf, 16) =
-        battle_get_mdef2 (&md->bl) - (mob_db[md->mob_class].vit >> 1);
-    WBUFW (buf, 18) = battle_get_elem_type (&md->bl);
-    for (i = 0; i < 9; i++)
-        WBUFB (buf, 20 + i) = battle_attr_fix (100, i + 1, md->def_ele);
-
-    if (sd->status.party_id > 0)
-        clif_send (buf, packet_len_table[0x18c], &sd->bl, PARTY_AREA);
-    else
-    {
-        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x18c]);
-        WFIFOSET (sd->fd, packet_len_table[0x18c]);
-    }
-    return 0;
-}
-
-/*==========================================
- * 状態異常アイコン/メッセージ表示
- *------------------------------------------
- */
-int clif_status_change (struct block_list *bl, int type, int flag)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x0196;
-    WBUFW (buf, 2) = type;
-    WBUFL (buf, 4) = bl->id;
-    WBUFB (buf, 8) = flag;
-    clif_send (buf, packet_len_table[0x196], bl, AREA);
-    return 0;
-}
-
-/*==========================================
- * Send message (modified by [Yor])
- *------------------------------------------
- */
-int clif_displaymessage (const int fd, char *mes)
-{
-    int  len_mes = strlen (mes);
-
-    if (len_mes > 0)
-    {                           // don't send a void message (it's not displaying on the client chat). @help can send void line.
-        WFIFOW (fd, 0) = 0x8e;
-        WFIFOW (fd, 2) = 5 + len_mes;   // 4 + len + NULL teminate
-        memcpy (WFIFOP (fd, 4), mes, len_mes + 1);
-        WFIFOSET (fd, 5 + len_mes);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 天の声を送信する
- *------------------------------------------
- */
-int clif_GMmessage (struct block_list *bl, char *mes, int len, int flag)
-{
-    unsigned char lbuf[255];
-    unsigned char *buf =
-        ((len + 16) >= sizeof (lbuf)) ? (unsigned char*)malloc (len + 16) : lbuf;
-    int  lp = (flag & 0x10) ? 8 : 4;
-
-    WBUFW (buf, 0) = 0x9a;
-    WBUFW (buf, 2) = len + lp;
-    WBUFL (buf, 4) = 0x65756c62;
-    memcpy (WBUFP (buf, lp), mes, len);
-    flag &= 0x07;
-    clif_send (buf, WBUFW (buf, 2), bl,
-               (flag == 1) ? ALL_SAMEMAP :
-               (flag == 2) ? AREA : (flag == 3) ? SELF : ALL_CLIENT);
-    if (buf != lbuf)
-        free (buf);
-    return 0;
-}
-
-/*==========================================
- * HPSP回復エフェクトを送信する
- *------------------------------------------
- */
-int clif_heal (int fd, int type, int val)
-{
-    WFIFOW (fd, 0) = 0x13d;
-    WFIFOW (fd, 2) = type;
-    WFIFOW (fd, 4) = val;
-    WFIFOSET (fd, packet_len_table[0x13d]);
-
-    return 0;
-}
-
-/*==========================================
- * 復活する
- *------------------------------------------
- */
-int clif_resurrection (struct block_list *bl, int type)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-    {                           // disguises [Valaris]
-        struct map_session_data *sd = ((struct map_session_data *) bl);
-        if (sd && sd->disguise > 23 && sd->disguise < 4001)
-            clif_spawnpc (sd);
-    }
-
-    WBUFW (buf, 0) = 0x148;
-    WBUFL (buf, 2) = bl->id;
-    WBUFW (buf, 6) = type;
-
-    clif_send (buf, packet_len_table[0x148], bl, type == 1 ? AREA : AREA_WOS);
-
-    return 0;
-}
-
-/*==========================================
- * PVP実装?(仮)
- *------------------------------------------
- */
-int clif_set0199 (int fd, int type)
-{
-    WFIFOW (fd, 0) = 0x199;
-    WFIFOW (fd, 2) = type;
-    WFIFOSET (fd, packet_len_table[0x199]);
-
-    return 0;
-}
-
-/*==========================================
- * PVP実装?(仮)
- *------------------------------------------
- */
-int clif_pvpset (struct map_session_data *sd, int pvprank, int pvpnum,
-                 int type)
-{
-    nullpo_retr (0, sd);
-
-    if (map[sd->bl.m].flag.nopvp)
-        return 0;
-
-    if (type == 2)
-    {
-        WFIFOW (sd->fd, 0) = 0x19a;
-        WFIFOL (sd->fd, 2) = sd->bl.id;
-        if (pvprank <= 0)
-            pc_calc_pvprank (sd);
-        WFIFOL (sd->fd, 6) = pvprank;
-        WFIFOL (sd->fd, 10) = pvpnum;
-        WFIFOSET (sd->fd, packet_len_table[0x19a]);
-    }
-    else
-    {
-        char buf[32];
-
-        WBUFW (buf, 0) = 0x19a;
-        WBUFL (buf, 2) = sd->bl.id;
-        if (sd->status.option & 0x46)
-            WBUFL (buf, 6) = -1;
-        else if (pvprank <= 0)
-            pc_calc_pvprank (sd);
-        WBUFL (buf, 6) = pvprank;
-        WBUFL (buf, 10) = pvpnum;
-        if (!type)
-            clif_send (buf, packet_len_table[0x19a], &sd->bl, AREA);
-        else
-            clif_send (buf, packet_len_table[0x19a], &sd->bl, ALL_SAMEMAP);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_send0199 (int map, int type)
-{
-    struct block_list bl;
-    char buf[16];
-
-    bl.m = map;
-    WBUFW (buf, 0) = 0x199;
-    WBUFW (buf, 2) = type;
-    clif_send (buf, packet_len_table[0x199], &bl, ALL_SAMEMAP);
-
-    return 0;
-}
-
-/*==========================================
- * 精錬エフェクトを送信する
- *------------------------------------------
- */
-int clif_refine (int fd, struct map_session_data *sd, int fail, int index,
-                 int val)
-{
-    WFIFOW (fd, 0) = 0x188;
-    WFIFOW (fd, 2) = fail;
-    WFIFOW (fd, 4) = index + 2;
-    WFIFOW (fd, 6) = val;
-    WFIFOSET (fd, packet_len_table[0x188]);
-
-    return 0;
-}
-
-/*==========================================
- * Wisp/page is transmitted to the destination player
- *------------------------------------------
- */
-int clif_wis_message (int fd, char *nick, char *mes, int mes_len)   // R 0097 <len>.w <nick>.24B <message>.?B
-{
-    WFIFOW (fd, 0) = 0x97;
-    WFIFOW (fd, 2) = mes_len + 24 + 4;
-    memcpy (WFIFOP (fd, 4), nick, 24);
-    memcpy (WFIFOP (fd, 28), mes, mes_len);
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * The transmission result of Wisp/page is transmitted to the source player
- *------------------------------------------
- */
-int clif_wis_end (int fd, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-{
-    WFIFOW (fd, 0) = 0x98;
-    WFIFOW (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x98]);
-    return 0;
-}
-
-/*==========================================
- * キャラID名前引き結果を送信する
- *------------------------------------------
- */
-int clif_solved_charname (struct map_session_data *sd, int char_id)
-{
-    char *p = map_charid2nick (char_id);
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    if (p != NULL)
-    {
-        WFIFOW (fd, 0) = 0x194;
-        WFIFOL (fd, 2) = char_id;
-        memcpy (WFIFOP (fd, 6), p, 24);
-        WFIFOSET (fd, packet_len_table[0x194]);
-    }
-    else
-    {
-        map_reqchariddb (sd, char_id);
-        chrif_searchcharid (char_id);
-    }
-    return 0;
-}
-
-/*==========================================
- * カードの挿入可能リストを返す
- *------------------------------------------
- */
-int clif_use_card (struct map_session_data *sd, int idx)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->inventory_data[idx])
-    {
-        int  i, c;
-        int  ep = sd->inventory_data[idx]->equip;
-        int  fd = sd->fd;
-        WFIFOW (fd, 0) = 0x017b;
-
-        for (i = c = 0; i < MAX_INVENTORY; i++)
-        {
-            int  j;
-
-            if (sd->inventory_data[i] == NULL)
-                continue;
-            if (sd->inventory_data[i]->type != 4 && sd->inventory_data[i]->type != 5)   // 武器防具じゃない
-                continue;
-            if (sd->status.inventory[i].card[0] == 0x00ff)  // 製造武器
-                continue;
-            if (sd->status.inventory[i].card[0] == (short) 0xff00
-                || sd->status.inventory[i].card[0] == 0x00fe)
-                continue;
-            if (sd->status.inventory[i].identify == 0)  // 未鑑定
-                continue;
-
-            if ((sd->inventory_data[i]->equip & ep) == 0)   // 装備個所が違う
-                continue;
-            if (sd->inventory_data[i]->type == 4 && ep == 32)   // 盾カードと両手武器
-                continue;
-
-            for (j = 0; j < sd->inventory_data[i]->slot; j++)
-            {
-                if (sd->status.inventory[i].card[j] == 0)
-                    break;
-            }
-            if (j == sd->inventory_data[i]->slot)   // すでにカードが一杯
-                continue;
-
-            WFIFOW (fd, 4 + c * 2) = i + 2;
-            c++;
-        }
-        WFIFOW (fd, 2) = 4 + c * 2;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-
-    return 0;
-}
-
-/*==========================================
- * カードの挿入終了
- *------------------------------------------
- */
-int clif_insert_card (struct map_session_data *sd, int idx_equip,
-                      int idx_card, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x17d;
-    WFIFOW (fd, 2) = idx_equip + 2;
-    WFIFOW (fd, 4) = idx_card + 2;
-    WFIFOB (fd, 6) = flag;
-    WFIFOSET (fd, packet_len_table[0x17d]);
-    return 0;
-}
-
-/*==========================================
- * 鑑定可能アイテムリスト送信
- *------------------------------------------
- */
-int clif_item_identify_list (struct map_session_data *sd)
-{
-    int  i, c;
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x177;
-    for (i = c = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid > 0
-            && sd->status.inventory[i].identify != 1)
-        {
-            WFIFOW (fd, c * 2 + 4) = i + 2;
-            c++;
-        }
-    }
-    if (c > 0)
-    {
-        WFIFOW (fd, 2) = c * 2 + 4;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * 鑑定結果
- *------------------------------------------
- */
-int clif_item_identified (struct map_session_data *sd, int idx, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x179;
-    WFIFOW (fd, 2) = idx + 2;
-    WFIFOB (fd, 4) = flag;
-    WFIFOSET (fd, packet_len_table[0x179]);
-    return 0;
-}
-
-/*==========================================
- * 修理可能アイテムリスト送信
- * ※実際のパケットがわからないので動作しません
- *------------------------------------------
- */
-int clif_item_repair_list (struct map_session_data *sd)
-{
-    int  i, c;
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x0;
-    for (i = c = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid > 0
-            && sd->status.inventory[i].broken != 0)
-        {
-            WFIFOW (fd, c * 2 + 4) = i + 2;
-            c++;
-        }
-    }
-    if (c > 0)
-    {
-        WFIFOW (fd, 2) = c * 2 + 4;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * アイテムによる一時的なスキル効果
- *------------------------------------------
- */
-int clif_item_skill (struct map_session_data *sd, int skillid, int skilllv,
-                     const char *name)
-{
-    int  range, fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x147;
-    WFIFOW (fd, 2) = skillid;
-    WFIFOW (fd, 4) = skill_get_inf (skillid);
-    WFIFOW (fd, 6) = 0;
-    WFIFOW (fd, 8) = skilllv;
-    WFIFOW (fd, 10) = skill_get_sp (skillid, skilllv);
-    range = skill_get_range (skillid, skilllv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    WFIFOW (fd, 12) = range;
-    memcpy (WFIFOP (fd, 14), name, 24);
-    WFIFOB (fd, 38) = 0;
-    WFIFOSET (fd, packet_len_table[0x147]);
-    return 0;
-}
-
-/*==========================================
- * カートにアイテム追加
- *------------------------------------------
- */
-int clif_cart_additem (struct map_session_data *sd, int n, int amount,
-                       int fail)
-{
-    int  view, j, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    if (n < 0 || n >= MAX_CART || sd->status.cart[n].nameid <= 0)
-        return 1;
-
-    WBUFW (buf, 0) = 0x124;
-    WBUFW (buf, 2) = n + 2;
-    WBUFL (buf, 4) = amount;
-    if ((view = itemdb_viewid (sd->status.cart[n].nameid)) > 0)
-        WBUFW (buf, 8) = view;
-    else
-        WBUFW (buf, 8) = sd->status.cart[n].nameid;
-    WBUFB (buf, 10) = sd->status.cart[n].identify;
-    if (sd->status.cart[n].broken == 1) //is weapon broken [Valaris]
-        WBUFB (buf, 11) = 1;
-    else
-        WBUFB (buf, 11) = sd->status.cart[n].attribute;
-    WBUFB (buf, 12) = sd->status.cart[n].refine;
-    if (sd->status.cart[n].card[0] == 0x00ff
-        || sd->status.cart[n].card[0] == 0x00fe
-        || sd->status.cart[n].card[0] == (short) 0xff00)
-    {
-        WBUFW (buf, 13) = sd->status.cart[n].card[0];
-        WBUFW (buf, 15) = sd->status.cart[n].card[1];
-        WBUFW (buf, 17) = sd->status.cart[n].card[2];
-        WBUFW (buf, 19) = sd->status.cart[n].card[3];
-    }
-    else
-    {
-        if (sd->status.cart[n].card[0] > 0
-            && (j = itemdb_viewid (sd->status.cart[n].card[0])) > 0)
-            WBUFW (buf, 13) = j;
-        else
-            WBUFW (buf, 13) = sd->status.cart[n].card[0];
-        if (sd->status.cart[n].card[1] > 0
-            && (j = itemdb_viewid (sd->status.cart[n].card[1])) > 0)
-            WBUFW (buf, 15) = j;
-        else
-            WBUFW (buf, 15) = sd->status.cart[n].card[1];
-        if (sd->status.cart[n].card[2] > 0
-            && (j = itemdb_viewid (sd->status.cart[n].card[2])) > 0)
-            WBUFW (buf, 17) = j;
-        else
-            WBUFW (buf, 17) = sd->status.cart[n].card[2];
-        if (sd->status.cart[n].card[3] > 0
-            && (j = itemdb_viewid (sd->status.cart[n].card[3])) > 0)
-            WBUFW (buf, 19) = j;
-        else
-            WBUFW (buf, 19) = sd->status.cart[n].card[3];
-    }
-    WFIFOSET (fd, packet_len_table[0x124]);
-    return 0;
-}
-
-/*==========================================
- * カートからアイテム削除
- *------------------------------------------
- */
-int clif_cart_delitem (struct map_session_data *sd, int n, int amount)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-
-    WFIFOW (fd, 0) = 0x125;
-    WFIFOW (fd, 2) = n + 2;
-    WFIFOL (fd, 4) = amount;
-
-    WFIFOSET (fd, packet_len_table[0x125]);
-
-    return 0;
-}
-
-/*==========================================
- * カートのアイテムリスト
- *------------------------------------------
- */
-int clif_cart_itemlist (struct map_session_data *sd)
-{
-    struct item_data *id;
-    int  i, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-    WBUFW (buf, 0) = 0x1ef;
-    for (i = 0, n = 0; i < MAX_CART; i++)
-    {
-        if (sd->status.cart[i].nameid <= 0)
-            continue;
-        id = itemdb_search (sd->status.cart[i].nameid);
-        if (itemdb_isequip2 (id))
-            continue;
-        WBUFW (buf, n * 18 + 4) = i + 2;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 18 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 18 + 6) = sd->status.cart[i].nameid;
-        WBUFB (buf, n * 18 + 8) = id->type;
-        WBUFB (buf, n * 18 + 9) = sd->status.cart[i].identify;
-        WBUFW (buf, n * 18 + 10) = sd->status.cart[i].amount;
-        WBUFW (buf, n * 18 + 12) = 0;
-        WBUFW (buf, n * 18 + 14) = sd->status.cart[i].card[0];
-        WBUFW (buf, n * 18 + 16) = sd->status.cart[i].card[1];
-        WBUFW (buf, n * 18 + 18) = sd->status.cart[i].card[2];
-        WBUFW (buf, n * 18 + 20) = sd->status.cart[i].card[3];
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 18;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * カートの装備品リスト
- *------------------------------------------
- */
-int clif_cart_equiplist (struct map_session_data *sd)
-{
-    struct item_data *id;
-    int  i, j, n, fd;
-    unsigned char *buf;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    buf = WFIFOP (fd, 0);
-
-    WBUFW (buf, 0) = 0x122;
-    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.cart[i].nameid <= 0)
-            continue;
-        id = itemdb_search (sd->status.cart[i].nameid);
-        if (!itemdb_isequip2 (id))
-            continue;
-        WBUFW (buf, n * 20 + 4) = i + 2;
-        if (id->view_id > 0)
-            WBUFW (buf, n * 20 + 6) = id->view_id;
-        else
-            WBUFW (buf, n * 20 + 6) = sd->status.cart[i].nameid;
-        WBUFB (buf, n * 20 + 8) = id->type;
-        WBUFB (buf, n * 20 + 9) = sd->status.cart[i].identify;
-        WBUFW (buf, n * 20 + 10) = id->equip;
-        WBUFW (buf, n * 20 + 12) = sd->status.cart[i].equip;
-        if (sd->status.cart[i].broken == 1)
-            WBUFB (buf, n * 20 + 14) = 1;   //is weapon broken [Valaris]
-        else
-            WBUFB (buf, n * 20 + 14) = sd->status.cart[i].attribute;
-        WBUFB (buf, n * 20 + 15) = sd->status.cart[i].refine;
-        if (sd->status.cart[i].card[0] == 0x00ff
-            || sd->status.cart[i].card[0] == 0x00fe
-            || sd->status.cart[i].card[0] == (short) 0xff00)
-        {
-            WBUFW (buf, n * 20 + 16) = sd->status.cart[i].card[0];
-            WBUFW (buf, n * 20 + 18) = sd->status.cart[i].card[1];
-            WBUFW (buf, n * 20 + 20) = sd->status.cart[i].card[2];
-            WBUFW (buf, n * 20 + 22) = sd->status.cart[i].card[3];
-        }
-        else
-        {
-            if (sd->status.cart[i].card[0] > 0
-                && (j = itemdb_viewid (sd->status.cart[i].card[0])) > 0)
-                WBUFW (buf, n * 20 + 16) = j;
-            else
-                WBUFW (buf, n * 20 + 16) = sd->status.cart[i].card[0];
-            if (sd->status.cart[i].card[1] > 0
-                && (j = itemdb_viewid (sd->status.cart[i].card[1])) > 0)
-                WBUFW (buf, n * 20 + 18) = j;
-            else
-                WBUFW (buf, n * 20 + 18) = sd->status.cart[i].card[1];
-            if (sd->status.cart[i].card[2] > 0
-                && (j = itemdb_viewid (sd->status.cart[i].card[2])) > 0)
-                WBUFW (buf, n * 20 + 20) = j;
-            else
-                WBUFW (buf, n * 20 + 20) = sd->status.cart[i].card[2];
-            if (sd->status.cart[i].card[3] > 0
-                && (j = itemdb_viewid (sd->status.cart[i].card[3])) > 0)
-                WBUFW (buf, n * 20 + 22) = j;
-            else
-                WBUFW (buf, n * 20 + 22) = sd->status.cart[i].card[3];
-        }
-        n++;
-    }
-    if (n)
-    {
-        WBUFW (buf, 2) = 4 + n * 20;
-        WFIFOSET (fd, WFIFOW (fd, 2));
-    }
-    return 0;
-}
-
-/*==========================================
- * パーティ作成完了
- * Relay the result of party creation.
- *
- * (R 00fa <flag>.B)
- *
- * flag:
- *  0 The party was created.
- *  1 The party name is invalid/taken.
- *  2 The character is already in a party.
- *------------------------------------------
- */
-int clif_party_created (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xfa;
-    WFIFOB (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0xfa]);
-    return 0;
-}
-
-/*==========================================
- * パーティ情報送信
- *------------------------------------------
- */
-int clif_party_info (struct party *p, int fd)
-{
-    unsigned char buf[1024];
-    int  i, c;
-    struct map_session_data *sd = NULL;
-
-    nullpo_retr (0, p);
-
-    WBUFW (buf, 0) = 0xfb;
-    memcpy (WBUFP (buf, 4), p->name, 24);
-    for (i = c = 0; i < MAX_PARTY; i++)
-    {
-        struct party_member *m = &p->member[i];
-        if (m->account_id > 0)
-        {
-            if (sd == NULL)
-                sd = m->sd;
-            WBUFL (buf, 28 + c * 46) = m->account_id;
-            memcpy (WBUFP (buf, 28 + c * 46 + 4), m->name, 24);
-            memcpy (WBUFP (buf, 28 + c * 46 + 28), m->map, 16);
-            WBUFB (buf, 28 + c * 46 + 44) = (m->leader) ? 0 : 1;
-            WBUFB (buf, 28 + c * 46 + 45) = (m->online) ? 0 : 1;
-            c++;
-        }
-    }
-    WBUFW (buf, 2) = 28 + c * 46;
-    if (fd >= 0)
-    {                           // fdが設定されてるならそれに送る
-        memcpy (WFIFOP (fd, 0), buf, WBUFW (buf, 2));
-        WFIFOSET (fd, WFIFOW (fd, 2));
-        return 9;
-    }
-    if (sd != NULL)
-        clif_send (buf, WBUFW (buf, 2), &sd->bl, PARTY);
-    return 0;
-}
-
-/*==========================================
- * パーティ勧誘
- * Relay a party invitation.
- *
- * (R 00fe <sender_ID>.l <party_name>.24B)
- *------------------------------------------
- */
-int clif_party_invite (struct map_session_data *sd,
-                       struct map_session_data *tsd)
-{
-    int  fd;
-    struct party *p;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, tsd);
-
-    fd = tsd->fd;
-
-    if (!(p = party_search (sd->status.party_id)))
-        return 0;
-
-    WFIFOW (fd, 0) = 0xfe;
-    WFIFOL (fd, 2) = sd->status.account_id;
-    memcpy (WFIFOP (fd, 6), p->name, 24);
-    WFIFOSET (fd, packet_len_table[0xfe]);
-    return 0;
-}
-
-/*==========================================
- * パーティ勧誘結果
- * Relay the response to a party invitation.
- *
- * (R 00fd <name>.24B <flag>.B)
- *
- * flag:
- *  0 The character is already in a party.
- *  1 The invitation was rejected.
- *  2 The invitation was accepted.
- *  3 The party is full.
- *  4 The character is in the same party.
- *------------------------------------------
- */
-int clif_party_inviteack (struct map_session_data *sd, char *nick, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xfd;
-    memcpy (WFIFOP (fd, 2), nick, 24);
-    WFIFOB (fd, 26) = flag;
-    WFIFOSET (fd, packet_len_table[0xfd]);
-    return 0;
-}
-
-/*==========================================
- * パーティ設定送信
- * flag & 0x001=exp変更ミス
- *        0x010=item変更ミス
- *        0x100=一人にのみ送信
- *------------------------------------------
- */
-int clif_party_option (struct party *p, struct map_session_data *sd, int flag)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, p);
-
-//  if(battle_config.etc_log)
-//      printf("clif_party_option: %d %d %d\n",p->exp,p->item,flag);
-    if (sd == NULL && flag == 0)
-    {
-        int  i;
-        for (i = 0; i < MAX_PARTY; i++)
-            if ((sd = map_id2sd (p->member[i].account_id)) != NULL)
-                break;
-    }
-    if (sd == NULL)
-        return 0;
-    WBUFW (buf, 0) = 0x101;
-    WBUFW (buf, 2) = ((flag & 0x01) ? 2 : p->exp);
-    WBUFW (buf, 4) = ((flag & 0x10) ? 2 : p->item);
-    if (flag == 0)
-        clif_send (buf, packet_len_table[0x101], &sd->bl, PARTY);
-    else
-    {
-        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x101]);
-        WFIFOSET (sd->fd, packet_len_table[0x101]);
-    }
-    return 0;
-}
-
-/*==========================================
- * パーティ脱退(脱退前に呼ぶこと)
- *------------------------------------------
- */
-int clif_party_leaved (struct party *p, struct map_session_data *sd,
-                       int account_id, char *name, int flag)
-{
-    unsigned char buf[64];
-    int  i;
-
-    nullpo_retr (0, p);
-
-    WBUFW (buf, 0) = 0x105;
-    WBUFL (buf, 2) = account_id;
-    memcpy (WBUFP (buf, 6), name, 24);
-    WBUFB (buf, 30) = flag & 0x0f;
-
-    if ((flag & 0xf0) == 0)
-    {
-        if (sd == NULL)
-            for (i = 0; i < MAX_PARTY; i++)
-                if ((sd = p->member[i].sd) != NULL)
-                    break;
-        if (sd != NULL)
-            clif_send (buf, packet_len_table[0x105], &sd->bl, PARTY);
-    }
-    else if (sd != NULL)
-    {
-        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x105]);
-        WFIFOSET (sd->fd, packet_len_table[0x105]);
-    }
-    return 0;
-}
-
-/*==========================================
- * パーティメッセージ送信
- *------------------------------------------
- */
-int clif_party_message (struct party *p, int account_id, char *mes, int len)
-{
-    struct map_session_data *sd;
-    int  i;
-
-    nullpo_retr (0, p);
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        if ((sd = p->member[i].sd) != NULL)
-            break;
-    }
-    if (sd != NULL)
-    {
-        unsigned char buf[1024];
-        WBUFW (buf, 0) = 0x109;
-        WBUFW (buf, 2) = len + 8;
-        WBUFL (buf, 4) = account_id;
-        memcpy (WBUFP (buf, 8), mes, len);
-        clif_send (buf, len + 8, &sd->bl, PARTY);
-    }
-    return 0;
-}
-
-/*==========================================
- * パーティ座標通知
- *------------------------------------------
- */
-int clif_party_xy (struct party *p, struct map_session_data *sd)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x107;
-    WBUFL (buf, 2) = sd->status.account_id;
-    WBUFW (buf, 6) = sd->bl.x;
-    WBUFW (buf, 8) = sd->bl.y;
-    clif_send (buf, packet_len_table[0x107], &sd->bl, PARTY_SAMEMAP_WOS);
-//  if(battle_config.etc_log)
-//      printf("clif_party_xy %d\n",sd->status.account_id);
-    return 0;
-}
-
-/*==========================================
- * パーティHP通知
- *------------------------------------------
- */
-int clif_party_hp (struct party *p, struct map_session_data *sd)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x106;
-    WBUFL (buf, 2) = sd->status.account_id;
-    WBUFW (buf, 6) = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp;
-    WBUFW (buf, 8) =
-        (sd->status.max_hp > 0x7fff) ? 0x7fff : sd->status.max_hp;
-    clif_send (buf, packet_len_table[0x106], &sd->bl, PARTY_AREA_WOS);
-//  if(battle_config.etc_log)
-//      printf("clif_party_hp %d\n",sd->status.account_id);
-    return 0;
-}
-
-/*==========================================
- * パーティ場所移動(未使用)
- *------------------------------------------
- */
-int clif_party_move (struct party *p, struct map_session_data *sd, int online)
-{
-    unsigned char buf[128];
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, p);
-
-    WBUFW (buf, 0) = 0x104;
-    WBUFL (buf, 2) = sd->status.account_id;
-    WBUFL (buf, 6) = 0;
-    WBUFW (buf, 10) = sd->bl.x;
-    WBUFW (buf, 12) = sd->bl.y;
-    WBUFB (buf, 14) = !online;
-    memcpy (WBUFP (buf, 15), p->name, 24);
-    memcpy (WBUFP (buf, 39), sd->status.name, 24);
-    memcpy (WBUFP (buf, 63), map[sd->bl.m].name, 16);
-    clif_send (buf, packet_len_table[0x104], &sd->bl, PARTY);
-    return 0;
-}
-
-/*==========================================
- * 攻撃するために移動が必要
- *------------------------------------------
- */
-int clif_movetoattack (struct map_session_data *sd, struct block_list *bl)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, bl);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x139;
-    WFIFOL (fd, 2) = bl->id;
-    WFIFOW (fd, 6) = bl->x;
-    WFIFOW (fd, 8) = bl->y;
-    WFIFOW (fd, 10) = sd->bl.x;
-    WFIFOW (fd, 12) = sd->bl.y;
-    WFIFOW (fd, 14) = sd->attackrange;
-    WFIFOSET (fd, packet_len_table[0x139]);
-    return 0;
-}
-
-/*==========================================
- * 製造エフェクト
- *------------------------------------------
- */
-int clif_produceeffect (struct map_session_data *sd, int flag, int nameid)
-{
-    int  view, fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    // 名前の登録と送信を先にしておく
-    if (map_charid2nick (sd->status.char_id) == NULL)
-        map_addchariddb (sd->status.char_id, sd->status.name);
-    clif_solved_charname (sd, sd->status.char_id);
-
-    WFIFOW (fd, 0) = 0x18f;
-    WFIFOW (fd, 2) = flag;
-    if ((view = itemdb_viewid (nameid)) > 0)
-        WFIFOW (fd, 4) = view;
-    else
-        WFIFOW (fd, 4) = nameid;
-    WFIFOSET (fd, packet_len_table[0x18f]);
-    return 0;
-}
-
-/*==========================================
- * オートスペル リスト送信
- *------------------------------------------
- */
-int clif_autospell (struct map_session_data *sd, int skilllv)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1cd;
-
-    if (skilllv > 0 && pc_checkskill (sd, MG_NAPALMBEAT) > 0)
-        WFIFOL (fd, 2) = MG_NAPALMBEAT;
-    else
-        WFIFOL (fd, 2) = 0x00000000;
-    if (skilllv > 1 && pc_checkskill (sd, MG_COLDBOLT) > 0)
-        WFIFOL (fd, 6) = MG_COLDBOLT;
-    else
-        WFIFOL (fd, 6) = 0x00000000;
-    if (skilllv > 1 && pc_checkskill (sd, MG_FIREBOLT) > 0)
-        WFIFOL (fd, 10) = MG_FIREBOLT;
-    else
-        WFIFOL (fd, 10) = 0x00000000;
-    if (skilllv > 1 && pc_checkskill (sd, MG_LIGHTNINGBOLT) > 0)
-        WFIFOL (fd, 14) = MG_LIGHTNINGBOLT;
-    else
-        WFIFOL (fd, 14) = 0x00000000;
-    if (skilllv > 4 && pc_checkskill (sd, MG_SOULSTRIKE) > 0)
-        WFIFOL (fd, 18) = MG_SOULSTRIKE;
-    else
-        WFIFOL (fd, 18) = 0x00000000;
-    if (skilllv > 7 && pc_checkskill (sd, MG_FIREBALL) > 0)
-        WFIFOL (fd, 22) = MG_FIREBALL;
-    else
-        WFIFOL (fd, 22) = 0x00000000;
-    if (skilllv > 9 && pc_checkskill (sd, MG_FROSTDIVER) > 0)
-        WFIFOL (fd, 26) = MG_FROSTDIVER;
-    else
-        WFIFOL (fd, 26) = 0x00000000;
-
-    WFIFOSET (fd, packet_len_table[0x1cd]);
-    return 0;
-}
-
-/*==========================================
- * ディボーションの青い糸
- *------------------------------------------
- */
-int clif_devotion (struct map_session_data *sd, int target)
-{
-    unsigned char buf[56];
-    int  n;
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x1cf;
-    WBUFL (buf, 2) = sd->bl.id;
-//  WBUFL(buf,6)=target;
-    for (n = 0; n < 5; n++)
-        WBUFL (buf, 6 + 4 * n) = sd->dev.val2[n];
-//      WBUFL(buf,10+4*n)=0;
-    WBUFB (buf, 26) = 8;
-    WBUFB (buf, 27) = 0;
-
-    clif_send (buf, packet_len_table[0x1cf], &sd->bl, AREA);
-    return 0;
-}
-
-/*==========================================
- * 氣球
- *------------------------------------------
- */
-int clif_spiritball (struct map_session_data *sd)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x1d0;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFW (buf, 6) = sd->spiritball;
-    clif_send (buf, packet_len_table[0x1d0], &sd->bl, AREA);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_combo_delay (struct block_list *bl, int wait)
-{
-    unsigned char buf[32];
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x1d2;
-    WBUFL (buf, 2) = bl->id;
-    WBUFL (buf, 6) = wait;
-    clif_send (buf, packet_len_table[0x1d2], bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *白刃取り
- *------------------------------------------
- */
-int clif_bladestop (struct block_list *src, struct block_list *dst, int boolean)
-{
-    unsigned char buf[32];
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, dst);
-
-    WBUFW (buf, 0) = 0x1d1;
-    WBUFL (buf, 2) = src->id;
-    WBUFL (buf, 6) = dst->id;
-    WBUFL (buf, 10) = boolean;
-
-    clif_send (buf, packet_len_table[0x1d1], src, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_changemapcell (int m, int x, int y, int cell_type, int type)
-{
-    struct block_list bl;
-    char buf[32];
-
-    bl.m = m;
-    bl.x = x;
-    bl.y = y;
-    WBUFW (buf, 0) = 0x192;
-    WBUFW (buf, 2) = x;
-    WBUFW (buf, 4) = y;
-    WBUFW (buf, 6) = cell_type;
-    memcpy (WBUFP (buf, 8), map[m].name, 16);
-    if (!type)
-        clif_send (buf, packet_len_table[0x192], &bl, AREA);
-    else
-        clif_send (buf, packet_len_table[0x192], &bl, ALL_SAMEMAP);
-
-    return 0;
-}
-
-/*==========================================
- * MVPエフェクト
- *------------------------------------------
- */
-int clif_mvp_effect (struct map_session_data *sd)
-{
-    unsigned char buf[16];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x10c;
-    WBUFL (buf, 2) = sd->bl.id;
-    clif_send (buf, packet_len_table[0x10c], &sd->bl, AREA);
-    return 0;
-}
-
-/*==========================================
- * MVPアイテム所得
- *------------------------------------------
- */
-int clif_mvp_item (struct map_session_data *sd, int nameid)
-{
-    int  view, fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x10a;
-    if ((view = itemdb_viewid (nameid)) > 0)
-        WFIFOW (fd, 2) = view;
-    else
-        WFIFOW (fd, 2) = nameid;
-    WFIFOSET (fd, packet_len_table[0x10a]);
-    return 0;
-}
-
-/*==========================================
- * MVP経験値所得
- *------------------------------------------
- */
-int clif_mvp_exp (struct map_session_data *sd, int exp)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x10b;
-    WFIFOL (fd, 2) = exp;
-    WFIFOSET (fd, packet_len_table[0x10b]);
-    return 0;
-}
-
-/*==========================================
- * ギルド作成可否通知
- * Relay the result of guild creation.
- *
- * (R 0167 <flag>.B)
- *
- * flag:
- *  0 The guild was created.
- *  1 The character is already in a guild.
- *  2 The guild name is invalid/taken.
- *  3 The Emperium item is required.
- *------------------------------------------
- */
-int clif_guild_created (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x167;
-    WFIFOB (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x167]);
-    return 0;
-}
-
-/*==========================================
- * ギルド所属通知
- *------------------------------------------
- */
-int clif_guild_belonginfo (struct map_session_data *sd, struct guild *g)
-{
-    int  ps, fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, g);
-
-    fd = sd->fd;
-    ps = guild_getposition (sd, g);
-
-    memset (WFIFOP (fd, 0), 0, packet_len_table[0x16c]);
-    WFIFOW (fd, 0) = 0x16c;
-    WFIFOL (fd, 2) = g->guild_id;
-    WFIFOL (fd, 6) = g->emblem_id;
-    WFIFOL (fd, 10) = g->position[ps].mode;
-    memcpy (WFIFOP (fd, 19), g->name, 24);
-    WFIFOSET (fd, packet_len_table[0x16c]);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバログイン通知
- *------------------------------------------
- */
-int clif_guild_memberlogin_notice (struct guild *g, int idx, int flag)
-{
-    unsigned char buf[64];
-
-    nullpo_retr (0, g);
-
-    WBUFW (buf, 0) = 0x16d;
-    WBUFL (buf, 2) = g->member[idx].account_id;
-    WBUFL (buf, 6) = 0;
-    WBUFL (buf, 10) = flag;
-    if (g->member[idx].sd == NULL)
-    {
-        struct map_session_data *sd = guild_getavailablesd (g);
-        if (sd != NULL)
-            clif_send (buf, packet_len_table[0x16d], &sd->bl, GUILD);
-    }
-    else
-        clif_send (buf, packet_len_table[0x16d], &g->member[idx].sd->bl,
-                   GUILD_WOS);
-    return 0;
-}
-
-/*==========================================
- * ギルドマスター通知(14dへの応答)
- *------------------------------------------
- */
-int clif_guild_masterormember (struct map_session_data *sd)
-{
-    int  type = 0x57, fd;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g != NULL && strcmp (g->master, sd->status.name) == 0)
-        type = 0xd7;
-    WFIFOW (fd, 0) = 0x14e;
-    WFIFOL (fd, 2) = type;
-    WFIFOSET (fd, packet_len_table[0x14e]);
-    return 0;
-}
-
-/*==========================================
- * Basic Info (Territories [Valaris])
- *------------------------------------------
- */
-int clif_guild_basicinfo (struct map_session_data *sd)
-{
-    int  fd, i, t = 0;
-    struct guild *g;
-    struct guild_castle *gc = NULL;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-
-    WFIFOW (fd, 0) = 0x1b6;     //0x150;
-    WFIFOL (fd, 2) = g->guild_id;
-    WFIFOL (fd, 6) = g->guild_lv;
-    WFIFOL (fd, 10) = g->connect_member;
-    WFIFOL (fd, 14) = g->max_member;
-    WFIFOL (fd, 18) = g->average_lv;
-    WFIFOL (fd, 22) = g->exp;
-    WFIFOL (fd, 26) = g->next_exp;
-    WFIFOL (fd, 30) = 0;        // 上納
-    WFIFOL (fd, 34) = 0;        // VW(性格の悪さ?:性向グラフ左右)
-    WFIFOL (fd, 38) = 0;        // RF(正義の度合い?:性向グラフ上下)
-    WFIFOL (fd, 42) = 0;        // 人数?
-    memcpy (WFIFOP (fd, 46), g->name, 24);
-    memcpy (WFIFOP (fd, 70), g->master, 24);
-
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        gc = guild_castle_search (i);
-        if (!gc)
-            continue;
-        if (g->guild_id == gc->guild_id)
-            t++;
-    }
-
-    if (t == 1)
-        memcpy (WFIFOP (fd, 94), "One Castle", 20);
-    else if (t == 2)
-        memcpy (WFIFOP (fd, 94), "Two Castles", 20);
-    else if (t == 3)
-        memcpy (WFIFOP (fd, 94), "Three Castles", 20);
-    else if (t == 4)
-        memcpy (WFIFOP (fd, 94), "Four Castles", 20);
-    else if (t == 5)
-        memcpy (WFIFOP (fd, 94), "Five Castles", 20);
-    else if (t == 6)
-        memcpy (WFIFOP (fd, 94), "Six Castles", 20);
-    else if (t == 7)
-        memcpy (WFIFOP (fd, 94), "Seven Castles", 20);
-    else if (t == 8)
-        memcpy (WFIFOP (fd, 94), "Eight Castles", 20);
-    else if (t == 9)
-        memcpy (WFIFOP (fd, 94), "Nine Castles", 20);
-    else if (t == 10)
-        memcpy (WFIFOP (fd, 94), "Ten Castles", 20);
-    else if (t == 11)
-        memcpy (WFIFOP (fd, 94), "Eleven Castles", 20);
-    else if (t == 12)
-        memcpy (WFIFOP (fd, 94), "Twelve Castles", 20);
-    else if (t == 13)
-        memcpy (WFIFOP (fd, 94), "Thirteen Castles", 20);
-    else if (t == 14)
-        memcpy (WFIFOP (fd, 94), "Fourteen Castles", 20);
-    else if (t == 15)
-        memcpy (WFIFOP (fd, 94), "Fifteen Castles", 20);
-    else if (t == 16)
-        memcpy (WFIFOP (fd, 94), "Sixteen Castles", 20);
-    else if (t == 17)
-        memcpy (WFIFOP (fd, 94), "Seventeen Castles", 20);
-    else if (t == 18)
-        memcpy (WFIFOP (fd, 94), "Eighteen Castles", 20);
-    else if (t == 19)
-        memcpy (WFIFOP (fd, 94), "Nineteen Castles", 20);
-    else if (t == 20)
-        memcpy (WFIFOP (fd, 94), "Twenty Castles", 20);
-    else if (t == 21)
-        memcpy (WFIFOP (fd, 94), "Twenty One Castles", 20);
-    else if (t == 22)
-        memcpy (WFIFOP (fd, 94), "Twenty Two Castles", 20);
-    else if (t == 23)
-        memcpy (WFIFOP (fd, 94), "Twenty Three Castles", 20);
-    else if (t == 24)
-        memcpy (WFIFOP (fd, 94), "Twenty Four Castles", 20);
-    else if (t == MAX_GUILDCASTLE)
-        memcpy (WFIFOP (fd, 94), "Total Domination", 20);
-    else
-        memcpy (WFIFOP (fd, 94), "None Taken", 20);
-
-    WFIFOSET (fd, packet_len_table[WFIFOW (fd, 0)]);
-    clif_guild_emblem (sd, g);  // Guild emblem vanish fix [Valaris]
-    return 0;
-}
-
-/*==========================================
- * ギルド同盟/敵対情報
- *------------------------------------------
- */
-int clif_guild_allianceinfo (struct map_session_data *sd)
-{
-    int  fd, i, c;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-    WFIFOW (fd, 0) = 0x14c;
-    for (i = c = 0; i < MAX_GUILDALLIANCE; i++)
-    {
-        struct guild_alliance *a = &g->alliance[i];
-        if (a->guild_id > 0)
-        {
-            WFIFOL (fd, c * 32 + 4) = a->opposition;
-            WFIFOL (fd, c * 32 + 8) = a->guild_id;
-            memcpy (WFIFOP (fd, c * 32 + 12), a->name, 24);
-            c++;
-        }
-    }
-    WFIFOW (fd, 2) = c * 32 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバーリスト
- *------------------------------------------
- */
-int clif_guild_memberlist (struct map_session_data *sd)
-{
-    int  fd;
-    int  i, c;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-
-    WFIFOW (fd, 0) = 0x154;
-    for (i = 0, c = 0; i < g->max_member; i++)
-    {
-        struct guild_member *m = &g->member[i];
-        if (m->account_id == 0)
-            continue;
-        WFIFOL (fd, c * 104 + 4) = m->account_id;
-        WFIFOL (fd, c * 104 + 8) = 0;
-        WFIFOW (fd, c * 104 + 12) = m->hair;
-        WFIFOW (fd, c * 104 + 14) = m->hair_color;
-        WFIFOW (fd, c * 104 + 16) = m->gender;
-        WFIFOW (fd, c * 104 + 18) = m->pc_class;
-        WFIFOW (fd, c * 104 + 20) = m->lv;
-        WFIFOL (fd, c * 104 + 22) = m->exp;
-        WFIFOL (fd, c * 104 + 26) = m->online;
-        WFIFOL (fd, c * 104 + 30) = m->position;
-        memset (WFIFOP (fd, c * 104 + 34), 0, 50);  // メモ?
-        memcpy (WFIFOP (fd, c * 104 + 84), m->name, 24);
-        c++;
-    }
-    WFIFOW (fd, 2) = c * 104 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルド役職名リスト
- *------------------------------------------
- */
-int clif_guild_positionnamelist (struct map_session_data *sd)
-{
-    int  i, fd;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-    WFIFOW (fd, 0) = 0x166;
-    for (i = 0; i < MAX_GUILDPOSITION; i++)
-    {
-        WFIFOL (fd, i * 28 + 4) = i;
-        memcpy (WFIFOP (fd, i * 28 + 8), g->position[i].name, 24);
-    }
-    WFIFOW (fd, 2) = i * 28 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルド役職情報リスト
- *------------------------------------------
- */
-int clif_guild_positioninfolist (struct map_session_data *sd)
-{
-    int  i, fd;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-    WFIFOW (fd, 0) = 0x160;
-    for (i = 0; i < MAX_GUILDPOSITION; i++)
-    {
-        struct guild_position *p = &g->position[i];
-        WFIFOL (fd, i * 16 + 4) = i;
-        WFIFOL (fd, i * 16 + 8) = p->mode;
-        WFIFOL (fd, i * 16 + 12) = i;
-        WFIFOL (fd, i * 16 + 16) = p->exp_mode;
-    }
-    WFIFOW (fd, 2) = i * 16 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルド役職変更通知
- *------------------------------------------
- */
-int clif_guild_positionchanged (struct guild *g, int idx)
-{
-    struct map_session_data *sd;
-    unsigned char buf[128];
-
-    nullpo_retr (0, g);
-
-    WBUFW (buf, 0) = 0x174;
-    WBUFW (buf, 2) = 44;
-    WBUFL (buf, 4) = idx;
-    WBUFL (buf, 8) = g->position[idx].mode;
-    WBUFL (buf, 12) = idx;
-    WBUFL (buf, 16) = g->position[idx].exp_mode;
-    memcpy (WBUFP (buf, 20), g->position[idx].name, 24);
-    if ((sd = guild_getavailablesd (g)) != NULL)
-        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバ変更通知
- *------------------------------------------
- */
-int clif_guild_memberpositionchanged (struct guild *g, int idx)
-{
-    struct map_session_data *sd;
-    unsigned char buf[64];
-
-    nullpo_retr (0, g);
-
-    WBUFW (buf, 0) = 0x156;
-    WBUFW (buf, 2) = 16;
-    WBUFL (buf, 4) = g->member[idx].account_id;
-    WBUFL (buf, 8) = 0;
-    WBUFL (buf, 12) = g->member[idx].position;
-    if ((sd = guild_getavailablesd (g)) != NULL)
-        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
-    return 0;
-}
-
-/*==========================================
- * ギルドエンブレム送信
- *------------------------------------------
- */
-int clif_guild_emblem (struct map_session_data *sd, struct guild *g)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, g);
-
-    fd = sd->fd;
-
-    if (g->emblem_len <= 0)
-        return 0;
-    WFIFOW (fd, 0) = 0x152;
-    WFIFOW (fd, 2) = g->emblem_len + 12;
-    WFIFOL (fd, 4) = g->guild_id;
-    WFIFOL (fd, 8) = g->emblem_id;
-    memcpy (WFIFOP (fd, 12), g->emblem_data, g->emblem_len);
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルドスキル送信
- *------------------------------------------
- */
-int clif_guild_skillinfo (struct map_session_data *sd)
-{
-    int  fd;
-    int  i, id, c;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-    WFIFOW (fd, 0) = 0x0162;
-    WFIFOW (fd, 4) = g->skill_point;
-    for (i = c = 0; i < MAX_GUILDSKILL; i++)
-    {
-        if (g->skill[i].id > 0)
-        {
-            WFIFOW (fd, c * 37 + 6) = id = g->skill[i].id;
-            WFIFOW (fd, c * 37 + 8) = guild_skill_get_inf (id);
-            WFIFOW (fd, c * 37 + 10) = 0;
-            WFIFOW (fd, c * 37 + 12) = g->skill[i].lv;
-            WFIFOW (fd, c * 37 + 14) =
-                guild_skill_get_sp (id, g->skill[i].lv);
-            WFIFOW (fd, c * 37 + 16) = guild_skill_get_range (id);
-            memset (WFIFOP (fd, c * 37 + 18), 0, 24);
-            WFIFOB (fd, c * 37 + 42) =  //up;
-                (g->skill[i].lv < guild_skill_get_max (id)) ? 1 : 0;
-            c++;
-        }
-    }
-    WFIFOW (fd, 2) = c * 37 + 6;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルド告知送信
- *------------------------------------------
- */
-int clif_guild_notice (struct map_session_data *sd, struct guild *g)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, g);
-
-    fd = sd->fd;
-    if (*g->mes1 == 0 && *g->mes2 == 0)
-        return 0;
-    WFIFOW (fd, 0) = 0x16f;
-    memcpy (WFIFOP (fd, 2), g->mes1, 60);
-    memcpy (WFIFOP (fd, 62), g->mes2, 120);
-    WFIFOSET (fd, packet_len_table[0x16f]);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバ勧誘
- *------------------------------------------
- */
-int clif_guild_invite (struct map_session_data *sd, struct guild *g)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, g);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x16a;
-    WFIFOL (fd, 2) = g->guild_id;
-    memcpy (WFIFOP (fd, 6), g->name, 24);
-    WFIFOSET (fd, packet_len_table[0x16a]);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバ勧誘結果
- *------------------------------------------
- */
-int clif_guild_inviteack (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x169;
-    WFIFOB (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x169]);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバ脱退通知
- *------------------------------------------
- */
-int clif_guild_leave (struct map_session_data *sd, const char *name,
-                      const char *mes)
-{
-    unsigned char buf[128];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x15a;
-    memcpy (WBUFP (buf, 2), name, 24);
-    memcpy (WBUFP (buf, 26), mes, 40);
-    clif_send (buf, packet_len_table[0x15a], &sd->bl, GUILD);
-    return 0;
-}
-
-/*==========================================
- * ギルドメンバ追放通知
- *------------------------------------------
- */
-int clif_guild_explusion (struct map_session_data *sd, const char *name,
-                          const char *mes, int account_id)
-{
-    unsigned char buf[128];
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x15c;
-    memcpy (WBUFP (buf, 2), name, 24);
-    memcpy (WBUFP (buf, 26), mes, 40);
-    memcpy (WBUFP (buf, 66), "dummy", 24);
-    clif_send (buf, packet_len_table[0x15c], &sd->bl, GUILD);
-    return 0;
-}
-
-/*==========================================
- * ギルド追放メンバリスト
- *------------------------------------------
- */
-int clif_guild_explusionlist (struct map_session_data *sd)
-{
-    int  fd;
-    int  i, c;
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-    WFIFOW (fd, 0) = 0x163;
-    for (i = c = 0; i < MAX_GUILDEXPLUSION; i++)
-    {
-        struct guild_explusion *e = &g->explusion[i];
-        if (e->account_id > 0)
-        {
-            memcpy (WFIFOP (fd, c * 88 + 4), e->name, 24);
-            memcpy (WFIFOP (fd, c * 88 + 28), e->acc, 24);
-            memcpy (WFIFOP (fd, c * 88 + 52), e->mes, 44);
-            c++;
-        }
-    }
-    WFIFOW (fd, 2) = c * 88 + 4;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-    return 0;
-}
-
-/*==========================================
- * ギルド会話
- *------------------------------------------
- */
-int clif_guild_message (struct guild *g, int account_id, const char *mes,
-                        int len)
-{
-    struct map_session_data *sd;
-    unsigned char lbuf[255];
-    unsigned char *buf = lbuf;
-    if (len + 32 >= sizeof (lbuf))
-        buf = (unsigned char *)malloc (len + 32);
-    WBUFW (buf, 0) = 0x17f;
-    WBUFW (buf, 2) = len + 4;
-    memcpy (WBUFP (buf, 4), mes, len);
-
-    if ((sd = guild_getavailablesd (g)) != NULL)
-        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
-    if (buf != lbuf)
-        free (buf);
-    return 0;
-}
-
-/*==========================================
- * ギルドスキル割り振り通知
- *------------------------------------------
- */
-int clif_guild_skillup (struct map_session_data *sd, int skill_num, int lv)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x10e;
-    WFIFOW (fd, 2) = skill_num;
-    WFIFOW (fd, 4) = lv;
-    WFIFOW (fd, 6) = guild_skill_get_sp (skill_num, lv);
-    WFIFOW (fd, 8) = guild_skill_get_range (skill_num);
-    WFIFOB (fd, 10) = 1;
-    WFIFOSET (fd, 11);
-    return 0;
-}
-
-/*==========================================
- * ギルド同盟要請
- *------------------------------------------
- */
-int clif_guild_reqalliance (struct map_session_data *sd, int account_id,
-                            const char *name)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x171;
-    WFIFOL (fd, 2) = account_id;
-    memcpy (WFIFOP (fd, 6), name, 24);
-    WFIFOSET (fd, packet_len_table[0x171]);
-    return 0;
-}
-
-/*==========================================
- * ギルド同盟結果
- *------------------------------------------
- */
-int clif_guild_allianceack (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x173;
-    WFIFOL (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x173]);
-    return 0;
-}
-
-/*==========================================
- * ギルド関係解消通知
- *------------------------------------------
- */
-int clif_guild_delalliance (struct map_session_data *sd, int guild_id,
-                            int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x184;
-    WFIFOL (fd, 2) = guild_id;
-    WFIFOL (fd, 6) = flag;
-    WFIFOSET (fd, packet_len_table[0x184]);
-    return 0;
-}
-
-/*==========================================
- * ギルド敵対結果
- *------------------------------------------
- */
-int clif_guild_oppositionack (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x181;
-    WFIFOB (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x181]);
-    return 0;
-}
-
-/*==========================================
- * ギルド関係追加
- *------------------------------------------
- */
-/*int clif_guild_allianceadded(struct guild *g,int idx)
-{
-	unsigned char buf[64];
-	WBUFW(fd,0)=0x185;
-	WBUFL(fd,2)=g->alliance[idx].opposition;
-	WBUFL(fd,6)=g->alliance[idx].guild_id;
-	memcpy(WBUFP(fd,10),g->alliance[idx].name,24);
-	clif_send(buf,packet_len_table[0x185],guild_getavailablesd(g),GUILD);
-	return 0;
-}*/
-
-/*==========================================
- * ギルド解散通知
- *------------------------------------------
- */
-int clif_guild_broken (struct map_session_data *sd, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x15e;
-    WFIFOL (fd, 2) = flag;
-    WFIFOSET (fd, packet_len_table[0x15e]);
-    return 0;
-}
-
-/*==========================================
- * エモーション
- *------------------------------------------
- */
-void clif_emotion (struct block_list *bl, int type)
-{
-    unsigned char buf[8];
-
-    nullpo_retv (bl);
-
-    WBUFW (buf, 0) = 0xc0;
-    WBUFL (buf, 2) = bl->id;
-    WBUFB (buf, 6) = type;
-    clif_send (buf, packet_len_table[0xc0], bl, AREA);
-}
-
-static void clif_emotion_towards (struct block_list *bl,
-                                  struct block_list *target, int type)
-{
-    unsigned char buf[8];
-    int  len = packet_len_table[0xc0];
-    struct map_session_data *sd = (struct map_session_data *) target;
-
-    nullpo_retv (bl);
-    nullpo_retv (target);
-
-    if (target->type != BL_PC)
-        return;
-
-    WBUFW (buf, 0) = 0xc0;
-    WBUFL (buf, 2) = bl->id;
-    WBUFB (buf, 6) = type;
-
-    memcpy (WFIFOP (sd->fd, 0), buf, len);
-    WFIFOSET (sd->fd, len);
-}
-
-/*==========================================
- * トーキーボックス
- *------------------------------------------
- */
-void clif_talkiebox (struct block_list *bl, char *talkie)
-{
-    unsigned char buf[86];
-
-    nullpo_retv (bl);
-
-    WBUFW (buf, 0) = 0x191;
-    WBUFL (buf, 2) = bl->id;
-    memcpy (WBUFP (buf, 6), talkie, 80);
-    clif_send (buf, packet_len_table[0x191], bl, AREA);
-}
-
-/*==========================================
- * 結婚エフェクト
- *------------------------------------------
- */
-void clif_wedding_effect (struct block_list *bl)
-{
-    unsigned char buf[6];
-
-    nullpo_retv (bl);
-
-    WBUFW (buf, 0) = 0x1ea;
-    WBUFL (buf, 2) = bl->id;
-    clif_send (buf, packet_len_table[0x1ea], bl, AREA);
-}
-
-/*==========================================
- * あなたに逢いたい使用時名前叫び
- *------------------------------------------
-
-void clif_callpartner(struct map_session_data *sd)
-{
-	unsigned char buf[26];
-	char *p;
-
-	nullpo_retv(sd);
-
-	if(sd->status.partner_id){
-		WBUFW(buf,0)=0x1e6;
-		p = map_charid2nick(sd->status.partner_id);
-		if(p){
-			memcpy(WBUFP(buf,2),p,24);
-		}else{
-			map_reqchariddb(sd,sd->status.partner_id);
-			chrif_searchcharid(sd->status.partner_id);
-			WBUFB(buf,2) = 0;
-		}
-		clif_send(buf,packet_len_table[0x1e6]&sd->bl,AREA);
-	}
-	return;
-}
-*/
-/*==========================================
- * 座る
- *------------------------------------------
- */
-void clif_sitting (int fd, struct map_session_data *sd)
-{
-    unsigned char buf[64];
-
-    nullpo_retv (sd);
-
-    WBUFW (buf, 0) = 0x8a;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFB (buf, 26) = 2;
-    clif_send (buf, packet_len_table[0x8a], &sd->bl, AREA);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int clif_disp_onlyself (struct map_session_data *sd, char *mes, int len)
-{
-    unsigned char lbuf[255];
-    unsigned char *buf =
-        (len + 32 >= sizeof (lbuf)) ? (unsigned char *)malloc (len + 32) : lbuf;
-
-    nullpo_retr (0, sd);
-
-    WBUFW (buf, 0) = 0x17f;
-    WBUFW (buf, 2) = len + 8;
-    memcpy (WBUFP (buf, 4), mes, len + 4);
-
-    clif_send (buf, WBUFW (buf, 2), &sd->bl, SELF);
-
-    if (buf != lbuf)
-        free (buf);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-
-int clif_GM_kickack (struct map_session_data *sd, int id)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xcd;
-    WFIFOL (fd, 2) = id;
-    WFIFOSET (fd, packet_len_table[0xcd]);
-    return 0;
-}
-
-void clif_parse_QuitGame (int fd, struct map_session_data *sd);
-
-int clif_GM_kick (struct map_session_data *sd, struct map_session_data *tsd,
-                  int type)
-{
-    nullpo_retr (0, tsd);
-
-    if (type)
-        clif_GM_kickack (sd, tsd->status.account_id);
-    tsd->opt1 = tsd->opt2 = 0;
-    clif_parse_QuitGame (tsd->fd, tsd);
-
-    return 0;
-}
-
-/*==========================================
- * Wis拒否許可応答
- *------------------------------------------
- */
-int clif_wisexin (struct map_session_data *sd, int type, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xd1;
-    WFIFOB (fd, 2) = type;
-    WFIFOB (fd, 3) = flag;
-    WFIFOSET (fd, packet_len_table[0xd1]);
-
-    return 0;
-}
-
-/*==========================================
- * Wis全拒否許可応答
- *------------------------------------------
- */
-int clif_wisall (struct map_session_data *sd, int type, int flag)
-{
-    int  fd;
-
-    nullpo_retr (0, sd);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0xd2;
-    WFIFOB (fd, 2) = type;
-    WFIFOB (fd, 3) = flag;
-    WFIFOSET (fd, packet_len_table[0xd2]);
-
-    return 0;
-}
-
-/*==========================================
- * サウンドエフェクト
- *------------------------------------------
- */
-void clif_soundeffect (struct map_session_data *sd, struct block_list *bl,
-                       char *name, int type)
-{
-    int  fd;
-
-    nullpo_retv (sd);
-    nullpo_retv (bl);
-
-    fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1d3;
-    memcpy (WFIFOP (fd, 2), name, 24);
-    WFIFOB (fd, 26) = type;
-    WFIFOL (fd, 27) = 0;
-    WFIFOL (fd, 31) = bl->id;
-    WFIFOSET (fd, packet_len_table[0x1d3]);
-
-    return;
-}
-
-// displaying special effects (npcs, weather, etc) [Valaris]
-int clif_specialeffect (struct block_list *bl, int type, int flag)
-{
-    unsigned char buf[24];
-
-    nullpo_retr (0, bl);
-
-    memset (buf, 0, packet_len_table[0x19b]);
-
-    WBUFW (buf, 0) = 0x19b;
-    WBUFL (buf, 2) = bl->id;
-    WBUFL (buf, 6) = type;
-
-    if (flag == 2)
-    {
-        struct map_session_data *sd = NULL;
-        int  i;
-        for (i = 0; i < fd_max; i++)
-        {
-            if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
-                && sd->state.auth && sd->bl.m == bl->m)
-                clif_specialeffect (&sd->bl, type, 1);
-        }
-    }
-
-    else if (flag == 1)
-        clif_send (buf, packet_len_table[0x19b], bl, SELF);
-    else if (!flag)
-        clif_send (buf, packet_len_table[0x19b], bl, AREA);
-
-    return 0;
-
-}
-
-// ------------
-// clif_parse_*
-// ------------
-// パケット読み取って色々操作
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_WantToConnection (int fd, struct map_session_data *sd)
-{
-    struct map_session_data *old_sd;
-    int  account_id;            // account_id in the packet
-
-    if (sd)
-    {
-        if (battle_config.error_log)
-            printf ("clif_parse_WantToConnection : invalid request?\n");
-        return;
-    }
-
-    if (RFIFOW (fd, 0) == 0x72)
-    {
-        account_id = RFIFOL (fd, 2);
-    }
-    else
-        return;                 // Not the auth packet
-
-    WFIFOL (fd, 0) = account_id;
-    WFIFOSET (fd, 4);
-
-    // if same account already connected, we disconnect the 2 sessions
-    if ((old_sd = map_id2sd (account_id)) != NULL)
-    {
-        clif_authfail_fd (fd, 2);   // same id
-        clif_authfail_fd (old_sd->fd, 2);   // same id
-        printf
-            ("clif_parse_WantToConnection: Double connection for account %d (sessions: #%d (new) and #%d (old)).\n",
-             account_id, fd, old_sd->fd);
-    }
-    else
-    {
-        CREATE (sd, struct map_session_data, 1);
-        session[fd]->session_data = sd;
-        sd->fd = fd;
-
-        pc_setnewpc (sd, account_id, RFIFOL (fd, 6), RFIFOL (fd, 10),
-                     RFIFOL (fd, 14), RFIFOB (fd, 18), fd);
-
-        map_addiddb (&sd->bl);
-
-        chrif_authreq (sd);
-    }
-
-    return;
-}
-
-/*==========================================
- * 007d クライアント側マップ読み込み完了
- * map侵入時に必要なデータを全て送りつける
- *------------------------------------------
- */
-void clif_parse_LoadEndAck (int fd, struct map_session_data *sd)
-{
-//  struct item_data* item;
-    int  i;
-    nullpo_retv (sd);
-
-    if (sd->bl.prev != NULL)
-        return;
-
-    // 接続ok時
-    //clif_authok();
-    if (sd->npc_id)
-        npc_event_dequeue (sd);
-    clif_skillinfoblock (sd);
-    pc_checkitem (sd);
-    //guild_info();
-
-    // loadendack時
-    // next exp
-    clif_updatestatus (sd, SP_NEXTBASEEXP);
-    clif_updatestatus (sd, SP_NEXTJOBEXP);
-    // skill point
-    clif_updatestatus (sd, SP_SKILLPOINT);
-    // item
-    clif_itemlist (sd);
-    clif_equiplist (sd);
-    // cart
-    if (pc_iscarton (sd))
-    {
-        clif_cart_itemlist (sd);
-        clif_cart_equiplist (sd);
-        clif_updatestatus (sd, SP_CARTINFO);
-    }
-    // param all
-    clif_initialstatus (sd);
-    // party
-    party_send_movemap (sd);
-    // guild
-    guild_send_memberinfoshort (sd, 1);
-    // 119
-    // 78
-
-    if (battle_config.pc_invincible_time > 0)
-    {
-        if (map[sd->bl.m].flag.gvg)
-            pc_setinvincibletimer (sd, battle_config.pc_invincible_time << 1);
-        else
-            pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
-    }
-
-    map_addblock (&sd->bl);     // ブロック登録
-    clif_spawnpc (sd);          // spawn
-
-    // weight max , now
-    clif_updatestatus (sd, SP_MAXWEIGHT);
-    clif_updatestatus (sd, SP_WEIGHT);
-
-    // pvp
-    if (sd->pvp_timer != -1 && !battle_config.pk_mode)
-        delete_timer (sd->pvp_timer, pc_calc_pvprank_timer);
-    if (map[sd->bl.m].flag.pvp)
-    {
-        if (!battle_config.pk_mode)
-        {                       // remove pvp stuff for pk_mode [Valaris]
-            sd->pvp_timer =
-                add_timer (gettick () + 200, pc_calc_pvprank_timer, sd->bl.id,
-                           0);
-            sd->pvp_rank = 0;
-            sd->pvp_lastusers = 0;
-            sd->pvp_point = 5;
-        }
-        clif_set0199 (sd->fd, 1);
-    }
-    else
-    {
-        sd->pvp_timer = -1;
-    }
-    if (map[sd->bl.m].flag.gvg)
-    {
-        clif_set0199 (sd->fd, 3);
-    }
-
-    if (sd->state.connect_new)
-    {
-        sd->state.connect_new = 0;
-        if (sd->status.pc_class != sd->view_class)
-            clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);
-
-/*						Stop players from spawning inside castles [Valaris]					*/
-
-        {
-            struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
-            if (gc)
-                pc_setpos (sd, sd->status.save_point.map,
-                           sd->status.save_point.x, sd->status.save_point.y,
-                           2);
-        }
-
-/*						End Addition [Valaris]			*/
-
-    }
-
-    // view equipment item
-    clif_changelook (&sd->bl, LOOK_WEAPON, 0);
-    if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0)
-        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
-                         sd->status.clothes_color);
-
-    if (sd->status.hp < sd->status.max_hp >> 2
-        && pc_checkskill (sd, SM_AUTOBERSERK) > 0
-        && (sd->sc_data[SC_PROVOKE].timer == -1
-            || sd->sc_data[SC_PROVOKE].val2 == 0))
-        // オートバーサーク発動
-        skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0, 0);
-
-//  if(time(&timer) < ((weddingtime=pc_readglobalreg(sd,"PC_WEDDING_TIME")) + 3600))
-//      skill_status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0);
-
-    if (battle_config.muting_players && sd->status.manner < 0)
-        skill_status_change_start (&sd->bl, SC_NOCHAT, 0, 0, 0, 0, 0, 0);
-
-    // option
-    clif_changeoption (&sd->bl);
-    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
-        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
-    if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
-        && !battle_check_undead (7, sd->def_ele))
-        skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
-    if (sd->special_state.infinite_endure
-        && sd->sc_data[SC_ENDURE].timer == -1)
-        skill_status_change_start (&sd->bl, SC_ENDURE, 10, 1, 0, 0, 0, 0);
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].equip
-            && sd->status.inventory[i].equip & 0x0002
-            && sd->status.inventory[i].broken == 1)
-            skill_status_change_start (&sd->bl, SC_BROKNWEAPON, 0, 0, 0, 0, 0,
-                                       0);
-        if (sd->status.inventory[i].equip
-            && sd->status.inventory[i].equip & 0x0010
-            && sd->status.inventory[i].broken == 1)
-            skill_status_change_start (&sd->bl, SC_BROKNARMOR, 0, 0, 0, 0, 0,
-                                       0);
-    }
-
-//        clif_changelook_accessories(sd, NULL);
-
-    map_foreachinarea (clif_getareachar, sd->bl.m, sd->bl.x - AREA_SIZE,
-                       sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
-                       sd->bl.y + AREA_SIZE, 0, sd);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_TickSend (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    sd->client_tick = RFIFOL (fd, 2);
-    sd->server_tick = gettick ();
-    clif_servertick (sd);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_WalkToXY (int fd, struct map_session_data *sd)
-{
-    int  x, y;
-
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-
-    if (sd->npc_id != 0 || sd->state.storage_flag)
-        return;
-
-    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) <= 0)   // フリーキャスト
-        return;
-
-    if (sd->chatID)
-        return;
-
-    if (sd->canmove_tick > gettick ())
-        return;
-
-    // ステータス異常やハイディング中(トンネルドライブ無)で動けない
-    if ((sd->opt1 > 0 && sd->opt1 != 6) || sd->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
-        sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||  //オートカウンター
-        sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
-        sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
-        sd->sc_data[SC_SPIDERWEB].timer != -1 ||    //スパイダーウェッブ
-        (sd->sc_data[SC_DANCING].timer != -1 && sd->sc_data[SC_DANCING].val4))  //合奏スキル演奏中は動けない
-        return;
-    if ((sd->status.option & 2) && pc_checkskill (sd, RG_TUNNELDRIVE) <= 0)
-        return;
-
-    if (sd->invincible_timer != -1)
-        pc_delinvincibletimer (sd);
-
-    pc_stopattack (sd);
-
-    x = RFIFOB (fd, 2) * 4 + (RFIFOB (fd, 3) >> 6);
-    y = ((RFIFOB (fd, 3) & 0x3f) << 4) + (RFIFOB (fd, 4) >> 4);
-    pc_walktoxy (sd, x, y);
-
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_QuitGame (int fd, struct map_session_data *sd)
-{
-    unsigned int tick = gettick ();
-    struct skill_unit_group *sg;
-
-    nullpo_retv (sd);
-
-    WFIFOW (fd, 0) = 0x18b;
-    if ((!pc_isdead (sd)
-         && (sd->opt1
-             || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND))))
-        || sd->skilltimer != -1 || (DIFF_TICK (tick, sd->canact_tick) < 0)
-        || (sd->sc_data && sd->sc_data[SC_DANCING].timer != -1
-            && sd->sc_data[SC_DANCING].val4
-            && (sg = (struct skill_unit_group *) sd->sc_data[SC_DANCING].val2)
-            && sg->src_id == sd->bl.id))
-    {
-        WFIFOW (fd, 2) = 1;
-        WFIFOSET (fd, packet_len_table[0x18b]);
-        return;
-    }
-
-    /*  Rovert's prevent logout option fixed [Valaris]  */
-    if ((battle_config.prevent_logout
-         && (gettick () - sd->canlog_tick) >= 10000)
-        || (!battle_config.prevent_logout))
-    {
-        clif_setwaitclose (fd);
-        WFIFOW (fd, 2) = 0;
-    }
-    else
-    {
-        WFIFOW (fd, 2) = 1;
-    }
-    WFIFOSET (fd, packet_len_table[0x18b]);
-
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_GetCharNameRequest (int fd, struct map_session_data *sd)
-{
-    struct block_list *bl;
-    int  account_id;
-
-    account_id = RFIFOL (fd, 2);
-    bl = map_id2bl (account_id);
-    if (bl == NULL)
-        return;
-
-    WFIFOW (fd, 0) = 0x95;
-    WFIFOL (fd, 2) = account_id;
-
-    switch (bl->type)
-    {
-        case BL_PC:
-        {
-            struct map_session_data *ssd = (struct map_session_data *) bl;
-
-            nullpo_retv (ssd);
-
-            if (ssd->state.shroud_active)
-                memset (WFIFOP (fd, 6), 0, 24);
-            else
-                memcpy (WFIFOP (fd, 6), ssd->status.name, 24);
-            WFIFOSET (fd, packet_len_table[0x95]);
-
-            struct guild *g = NULL;
-            struct party *p = NULL;
-
-            char *guild_name = "", *guild_pos = "", *party_name = "";
-
-            int send = 0;
-
-            if (ssd->status.guild_id > 0 && (g = guild_search (ssd->status.guild_id)) != NULL)
-            {
-                // there used to be a comment near here, but the code has changed slightly
-                // ギルド所属ならパケット0195を返す
-                // google says that means: 0195 return if the packet belongs Guild
-                int  i, ps = -1;
-                for (i = 0; i < g->max_member; i++)
-                {
-                    if (g->member[i].account_id == ssd->status.account_id)
-                        ps = g->member[i].position;
-                }
-                if (ps >= 0 && ps < MAX_GUILDPOSITION)
-                {
-                    guild_name = g->name;
-                    guild_pos = g->position[ps].name;
-                    send = 1;
-                }
-            }
-            if (ssd->status.party_id > 0 && (p = party_search (ssd->status.party_id)) != NULL)
-            {
-                party_name = p->name;
-                send = 1;
-            }
-
-            if (send)
-            {
-                WFIFOW (fd, 0) = 0x195;
-                WFIFOL (fd, 2) = account_id;
-                memcpy (WFIFOP (fd, 6), party_name, 24);
-                memcpy (WFIFOP (fd, 30), guild_name, 24);
-                memcpy (WFIFOP (fd, 54), guild_pos, 24);
-                memcpy (WFIFOP (fd, 78), guild_pos, 24); // We send this value twice because the client expects it
-                WFIFOSET (fd, packet_len_table[0x195]);
-
-            }
-
-            if (pc_isGM(sd) >= battle_config.hack_info_GM_level)
-            {
-                in_addr_t ip = ssd->ip;
-                WFIFOW (fd, 0) = 0x20C;
-
-                // Mask the IP using the char-server password
-                if (battle_config.mask_ip_gms)
-                    ip = MD5_ip(chrif_getpasswd (), ssd->ip);
-
-                WFIFOL (fd, 2) = account_id;
-                WFIFOL (fd, 6) = ip;
-                WFIFOSET (fd, packet_len_table[0x20C]);
-             }
-
-        }
-            break;
-        case BL_NPC:
-            memcpy (WFIFOP (fd, 6), ((struct npc_data *) bl)->name, 24);
-            {
-                char *start = WFIFOP (fd, 6);
-                char *end = strchr (start, '#');    // [fate] elim hashed out/invisible names for the client
-                if (end)
-                    while (*end)
-                        *end++ = 0;
-
-                // [fate] Elim preceding underscores for (hackish) name position fine-tuning
-                while (*start == '_')
-                    *start++ = ' ';
-            }
-            WFIFOSET (fd, packet_len_table[0x95]);
-            break;
-        case BL_MOB:
-        {
-            struct mob_data *md = (struct mob_data *) bl;
-
-            nullpo_retv (md);
-
-            memcpy (WFIFOP (fd, 6), md->name, 24);
-            WFIFOSET (fd, packet_len_table[0x95]);
-        }
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("clif_parse_GetCharNameRequest : bad type %d(%d)\n",
-                        bl->type, account_id);
-            break;
-    }
-}
-
-/*==========================================
- * Validate and process transmission of a
- * global/public message.
- *
- * (S 008c <len>.w <message>.?B)
- *------------------------------------------
- */
-void clif_parse_GlobalMessage (int fd, struct map_session_data *sd)
-{
-    int msg_len = RFIFOW (fd, 2) - 4; /* Header (2) + length (2). */
-    size_t message_len = 0;
-    char *buf = NULL;
-    char *message = NULL;   /* The message text only. */
-
-    nullpo_retv (sd);
-
-    if (!(buf = clif_validate_chat (sd, 2, &message, &message_len)))
-    {
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
-            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
-                                || sd->sc_data[SC_NOCHAT].timer != -1)))//チャット禁止
-    {
-        free (buf);
-        return;
-    }
-
-    if (!magic_message (sd, buf, msg_len))
-    {
-        /* Don't send chat that results in an automatic ban. */
-        if (tmw_CheckChatSpam (sd, message))
-        {
-            free (buf);
-            /* "Your message could not be sent." */
-            clif_displaymessage (fd, msg_txt (505));
-            return;
-        }
-
-        /* It's not a spell/magic message, so send the message to others. */
-        WBUFW (buf, 0) = 0x8d;
-        WBUFW (buf, 2) = msg_len + 8;   /* Header (2) + length (2) + ID (4). */
-        WBUFL (buf, 4) = sd->bl.id;
-
-        clif_send (buf, msg_len + 8, &sd->bl,
-                   sd->chatID ? CHAT_WOS : AREA_CHAT_WOC);
-    }
-
-    /* Send the message back to the speaker. */
-    memcpy (WFIFOP (fd, 0), RFIFOP (fd, 0), RFIFOW (fd, 2));
-    WFIFOW (fd, 0) = 0x8e;
-    WFIFOSET (fd, WFIFOW (fd, 2));
-
-    free (buf);
-    return;
-}
-
-int clif_message (struct block_list *bl, char *msg)
-{
-    unsigned short msg_len = strlen (msg) + 1;
-    unsigned char buf[512];
-
-    if (msg_len + 16 > 512)
-        return 0;
-
-    nullpo_retr (0, bl);
-
-    WBUFW (buf, 0) = 0x8d;
-    WBUFW (buf, 2) = msg_len + 8;
-    WBUFL (buf, 4) = bl->id;
-    memcpy (WBUFP (buf, 8), msg, msg_len);
-
-    clif_send (buf, WBUFW (buf, 2), bl, AREA);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_MapMove (int fd, struct map_session_data *sd)
-{
-// /m /mapmove (as @rura GM command)
-    char output[100];
-    char map_name[17];
-
-    nullpo_retv (sd);
-
-    memset (output, '\0', sizeof (output));
-    memset (map_name, '\0', sizeof (map_name));
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_MapMove)))
-    {
-        memcpy (map_name, RFIFOP (fd, 2), 16);
-        sprintf (output, "%s %d %d", map_name, RFIFOW (fd, 18),
-                 RFIFOW (fd, 20));
-        log_atcommand (sd, "@warp %s", output);
-        atcommand_warp (fd, sd, "@warp", output);
-    }
-
-    return;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ChangeDir (int fd, struct map_session_data *sd)
-{
-    unsigned char buf[64];
-    short dir;
-
-    nullpo_retv (sd);
-
-//  RFIFOW(fd,2); // Apparently does nothing?
-    dir = RFIFOB (fd, 4);
-
-    if (dir == sd->dir)
-        return;
-
-    pc_setdir (sd, dir);
-
-    WBUFW (buf, 0) = 0x9c;
-    WBUFL (buf, 2) = sd->bl.id;
-    WBUFW (buf, 6) = 0;
-    WBUFB (buf, 8) = dir;
-    if (sd->disguise > 23 && sd->disguise < 4001)   // mob disguises [Valaris]
-        clif_send (buf, packet_len_table[0x9c], &sd->bl, AREA);
-    else
-        clif_send (buf, packet_len_table[0x9c], &sd->bl, AREA_WOS);
-
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_Emotion (int fd, struct map_session_data *sd)
-{
-    unsigned char buf[64];
-
-    nullpo_retv (sd);
-
-    if (battle_config.basic_skill_check == 0
-        || pc_checkskill (sd, NV_EMOTE) >= 1)
-    {
-        WBUFW (buf, 0) = 0xc0;
-        WBUFL (buf, 2) = sd->bl.id;
-        WBUFB (buf, 6) = RFIFOB (fd, 2);
-        clif_send (buf, packet_len_table[0xc0], &sd->bl, AREA);
-    }
-    else
-        clif_skill_fail (sd, 1, 0, 1);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_HowManyConnections (int fd, struct map_session_data *sd)
-{
-    WFIFOW (fd, 0) = 0xc2;
-    WFIFOL (fd, 2) = map_getusers ();
-    WFIFOSET (fd, packet_len_table[0xc2]);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ActionRequest (int fd, struct map_session_data *sd)
-{
-    unsigned int tick;
-    unsigned char buf[64];
-    int  action_type, target_id;
-
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    if (sd->npc_id != 0 || sd->opt1 > 0 || sd->status.option & 2 || sd->state.storage_flag ||
-            (sd->sc_data && (sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||   //オートカウンター
-            sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
-            sd->sc_data[SC_DANCING].timer != -1)))
-        return;
-
-    tick = gettick ();
-
-    pc_stop_walking (sd, 0);
-    pc_stopattack (sd);
-
-    target_id = RFIFOL (fd, 2);
-    action_type = RFIFOB (fd, 6);
-
-    switch (action_type)
-    {
-        case 0x00:             // once attack
-        case 0x07:             // continuous attack
-            if (sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22
-                || sd->status.option & OPTION_HIDE)
-                return;
-            if (!battle_config.sdelay_attack_enable
-                && pc_checkskill (sd, SA_FREECAST) <= 0)
-            {
-                if (DIFF_TICK (tick, sd->canact_tick) < 0)
-                {
-                    clif_skill_fail (sd, 1, 4, 0);
-                    return;
-                }
-            }
-            if (sd->invincible_timer != -1)
-                pc_delinvincibletimer (sd);
-            if (sd->attacktarget > 0)   // [Valaris]
-                sd->attacktarget = 0;
-            pc_attack (sd, target_id, action_type != 0);
-            break;
-        case 0x02:             // sitdown
-            pc_stop_walking (sd, 1);
-            skill_gangsterparadise (sd, 1); // ギャングスターパラダイス設定
-            pc_setsit (sd);
-            clif_sitting (fd, sd);
-            break;
-        case 0x03:             // standup
-            skill_gangsterparadise (sd, 0); // ギャングスターパラダイス解除
-            pc_setstand (sd);
-            WBUFW (buf, 0) = 0x8a;
-            WBUFL (buf, 2) = sd->bl.id;
-            WBUFB (buf, 26) = 3;
-            clif_send (buf, packet_len_table[0x8a], &sd->bl, AREA);
-            break;
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_Restart (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    switch (RFIFOB (fd, 2))
-    {
-        case 0x00:
-            if (pc_isdead (sd))
-            {
-                pc_setstand (sd);
-                pc_setrestartvalue (sd, 3);
-                pc_setpos (sd, sd->status.save_point.map,
-                           sd->status.save_point.x, sd->status.save_point.y,
-                           2);
-            }
-            break;
-        case 0x01:
-            /*if(!pc_isdead(sd) && (sd->opt1 || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND))))
-             * return; */
-
-            /*  Rovert's Prevent logout option - Fixed [Valaris]    */
-            if ((battle_config.prevent_logout
-                 && (gettick () - sd->canlog_tick) >= 10000)
-                || (!battle_config.prevent_logout))
-            {
-                chrif_charselectreq (sd);
-            }
-            else
-            {
-                WFIFOW (fd, 0) = 0x18b;
-                WFIFOW (fd, 2) = 1;
-
-                WFIFOSET (fd, packet_len_table[0x018b]);
-            }
-            break;
-    }
-}
-
-/*==========================================
- * Validate and process transmission of a
- * whisper/private message.
- *
- * (S 0096 <len>.w <nick>.24B <message>.?B)
- *
- * rewritten by [Yor], then partially by
- * [remoitnane]
- *------------------------------------------
- */
-void clif_parse_Wis (int fd, struct map_session_data *sd)
-{
-    size_t message_len = 0;
-    char *buf = NULL;
-    char *message = NULL;   /* The message text only. */
-    struct map_session_data *dstsd = NULL;
-
-    nullpo_retv (sd);
-
-    if (!(buf = clif_validate_chat (sd, 1, &message, &message_len)))
-    {
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
-            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1
-                                || sd->sc_data[SC_NOCHAT].timer != -1)))
-    {
-        free (buf);
-        return;
-    }
-
-    /* Don't send chat that results in an automatic ban. */
-    if (tmw_CheckChatSpam (sd, message))
-    {
-        free (buf);
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    /*
-     * The player is not on this server. Only send the whisper if the name is
-     * exactly the same, because if there are multiple map-servers and a name
-     * conflict (for instance, "Test" versus "test"), the char-server must
-     * settle the discrepancy.
-     */
-    if (!(dstsd = map_nick2sd (RFIFOP (fd, 4)))
-            || strcmp (dstsd->status.name, RFIFOP (fd, 4)) != 0)
-        intif_wis_message (sd, RFIFOP (fd, 4), message,  RFIFOW (fd, 2) - 28);
-    else
-    {
-        /* Refuse messages addressed to self. */
-        if (dstsd->fd == fd)
-        {
-            /* "You cannot page yourself." */
-            char *mes = msg_txt (504);
-            clif_wis_message (fd, wisp_server_name, mes, strlen (mes) + 1);
-        }
-        else
-        {
-            /* The target is ignoring all whispers. */
-            if (dstsd->ignoreAll == 1)
-                /* Ignored by target. */
-                clif_wis_end (fd, 2);
-            else
-            {
-                int i;
-                size_t end = sizeof (dstsd->ignore) / sizeof (dstsd->ignore[0]);
-
-                /* See if the source player is being ignored. */
-                for (i = 0; i < end; ++i)
-                    if (strcmp (dstsd->ignore[i].name, sd->status.name) == 0)
-                    {
-                        /* Ignored by target. */
-                        clif_wis_end (fd, 2);
-                        break;
-                    }
-
-                /* The player is not being ignored. */
-                if (i == end)
-                {
-                    clif_wis_message (dstsd->fd, sd->status.name, message,
-                                      RFIFOW (fd, 2) - 28);
-                    /* The whisper was sent successfully. */
-                    clif_wis_end (fd, 0);
-                }
-            }
-        }
-    }
-
-    free (buf);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_GMmessage (int fd, struct map_session_data *sd)
-{
-    char m[512];
-    char output[200];
-    nullpo_retv (sd);
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Broadcast)))
-    {
-        strncpy (m, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
-        m[RFIFOW (fd, 2) - 4] = 0;
-        log_atcommand (sd, "/announce %s", m);
-
-        memset (output, '\0', sizeof (output));
-        snprintf (output, 199, "%s : %s", sd->status.name, m);
-
-        intif_GMmessage (output, strlen (output) + 1, 0);
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_TakeItem (int fd, struct map_session_data *sd)
-{
-    struct flooritem_data *fitem;
-    int  map_object_id;
-
-    nullpo_retv (sd);
-
-    map_object_id = RFIFOL (fd, 2);
-    fitem = (struct flooritem_data *) map_id2bl (map_object_id);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-
-    if (sd->npc_id != 0 || sd->opt1 > 0 || (sd->sc_data &&
-            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
-            sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
-            sd->sc_data[SC_BERSERK].timer != -1 ||  //バーサーク
-            sd->sc_data[SC_NOCHAT].timer != -1)))   //会話禁止
-        return;
-
-    if (fitem == NULL || fitem->bl.m != sd->bl.m)
-        return;
-
-    if (abs (sd->bl.x - fitem->bl.x) >= 2
-        || abs (sd->bl.y - fitem->bl.y) >= 2)
-        return;                 // too far away to pick up
-
-    if (sd->state.shroud_active && sd->state.shroud_disappears_on_pickup)
-        magic_unshroud (sd);
-
-    pc_takeitem (sd, fitem);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_DropItem (int fd, struct map_session_data *sd)
-{
-    int  item_index, item_amount;
-
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    if (map[sd->bl.m].flag.no_player_drops)
-    {
-        clif_displaymessage(sd->fd, "Can't drop items here.");
-        return;
-    }
-    if (sd->npc_id != 0 || sd->opt1 > 0 ||
-            (sd->sc_data && (sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||    //オートカウンター
-            sd->sc_data[SC_BLADESTOP].timer != -1 ||  //白刃取り
-            sd->sc_data[SC_BERSERK].timer != -1)))    //バーサーク
-    {
-        clif_displaymessage(sd->fd, "Can't drop items right now.");
-        return;
-    }
-
-    item_index = RFIFOW (fd, 2) - 2;
-    item_amount = RFIFOW (fd, 4);
-
-    pc_dropitem (sd, item_index, item_amount);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_UseItem (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    if (sd->npc_id != 0 || sd->opt1 > 0 || (sd->sc_data &&
-            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
-            sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
-            sd->sc_data[SC_BERSERK].timer != -1 ||  //バーサーク
-            sd->sc_data[SC_NOCHAT].timer != -1)))   //会話禁止
-        return;
-
-    if (sd->invincible_timer != -1)
-        pc_delinvincibletimer (sd);
-
-    pc_useitem (sd, RFIFOW (fd, 2) - 2);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_EquipItem (int fd, struct map_session_data *sd)
-{
-    int  index;
-
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    index = RFIFOW (fd, 2) - 2;
-    if (sd->npc_id != 0)
-        return;
-    if (sd->sc_data
-        && (sd->sc_data[SC_BLADESTOP].timer != -1
-            || sd->sc_data[SC_BERSERK].timer != -1))
-        return;
-
-    if (sd->status.inventory[index].identify != 1)
-    {                           // 未鑑定
-        // Bjorn: Auto-identify items when equipping them as there
-        //  is no nice way to do this in the client yet.
-        sd->status.inventory[index].identify = 1;
-        //clif_equipitemack(sd,index,0,0);  // fail
-        //return;
-    }
-    //ペット用装備であるかないか
-    if (sd->inventory_data[index])
-    {
-        if (sd->inventory_data[index]->type == 10)
-            RFIFOW (fd, 4) = 0x8000;    // 矢を無理やり装備できるように(−−;
-        pc_equipitem (sd, index, RFIFOW (fd, 4));
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_UnequipItem (int fd, struct map_session_data *sd)
-{
-    int  index;
-
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    index = RFIFOW (fd, 2) - 2;
-    if (sd->status.inventory[index].broken == 1 && sd->sc_data
-        && sd->sc_data[SC_BROKNWEAPON].timer != -1)
-        skill_status_change_end (&sd->bl, SC_BROKNWEAPON, -1);
-    if (sd->status.inventory[index].broken == 1 && sd->sc_data
-        && sd->sc_data[SC_BROKNARMOR].timer != -1)
-        skill_status_change_end (&sd->bl, SC_BROKNARMOR, -1);
-    if (sd->sc_data
-        && (sd->sc_data[SC_BLADESTOP].timer != -1
-            || sd->sc_data[SC_BERSERK].timer != -1))
-        return;
-
-    if (sd->npc_id != 0 || sd->opt1 > 0)
-        return;
-    pc_unequipitem (sd, index, 0);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcClicked (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (pc_isdead (sd))
-    {
-        clif_clearchar_area (&sd->bl, 1);
-        return;
-    }
-    if (sd->npc_id != 0)
-        return;
-    npc_click (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcBuySellSelected (int fd, struct map_session_data *sd)
-{
-    npc_buysellsel (sd, RFIFOL (fd, 2), RFIFOB (fd, 6));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcBuyListSend (int fd, struct map_session_data *sd)
-{
-    int  fail = 0, n;
-    unsigned short *item_list;
-
-    n = (RFIFOW (fd, 2) - 4) / 4;
-    item_list = (unsigned short *) RFIFOP (fd, 4);
-
-    fail = npc_buylist (sd, n, item_list);
-
-    WFIFOW (fd, 0) = 0xca;
-    WFIFOB (fd, 2) = fail;
-    WFIFOSET (fd, packet_len_table[0xca]);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcSellListSend (int fd, struct map_session_data *sd)
-{
-    int  fail = 0, n;
-    unsigned short *item_list;
-
-    n = (RFIFOW (fd, 2) - 4) / 4;
-    item_list = (unsigned short *) RFIFOP (fd, 4);
-
-    fail = npc_selllist (sd, n, item_list);
-
-    WFIFOW (fd, 0) = 0xcb;
-    WFIFOB (fd, 2) = fail;
-    WFIFOSET (fd, packet_len_table[0xcb]);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_CreateChatRoom (int fd, struct map_session_data *sd)
-{
-    chat_createchat (sd, RFIFOW (fd, 4), RFIFOB (fd, 6), RFIFOP (fd, 7),
-                     RFIFOP (fd, 15), RFIFOW (fd, 2) - 15);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ChatAddMember (int fd, struct map_session_data *sd)
-{
-    chat_joinchat (sd, RFIFOL (fd, 2), RFIFOP (fd, 6));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ChatRoomStatusChange (int fd, struct map_session_data *sd)
-{
-    chat_changechatstatus (sd, RFIFOW (fd, 4), RFIFOB (fd, 6), RFIFOP (fd, 7),
-                           RFIFOP (fd, 15), RFIFOW (fd, 2) - 15);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ChangeChatOwner (int fd, struct map_session_data *sd)
-{
-    chat_changechatowner (sd, RFIFOP (fd, 6));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_KickFromChat (int fd, struct map_session_data *sd)
-{
-    chat_kickchat (sd, RFIFOP (fd, 2));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_ChatLeave (int fd, struct map_session_data *sd)
-{
-    chat_leavechat (sd);
-}
-
-/*==========================================
- * 取引要請を相手に送る
- *------------------------------------------
- */
-void clif_parse_TradeRequest (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (battle_config.basic_skill_check == 0
-        || pc_checkskill (sd, NV_TRADE) >= 1)
-    {
-        trade_traderequest (sd, RFIFOL (sd->fd, 2));
-    }
-    else
-        clif_skill_fail (sd, 1, 0, 0);
-}
-
-/*==========================================
- * 取引要請
- *------------------------------------------
- */
-void clif_parse_TradeAck (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    trade_tradeack (sd, RFIFOB (sd->fd, 2));
-}
-
-/*==========================================
- * アイテム追加
- *------------------------------------------
- */
-void clif_parse_TradeAddItem (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    trade_tradeadditem (sd, RFIFOW (sd->fd, 2), RFIFOL (sd->fd, 4));
-}
-
-/*==========================================
- * アイテム追加完了(ok押し)
- *------------------------------------------
- */
-void clif_parse_TradeOk (int fd, struct map_session_data *sd)
-{
-    trade_tradeok (sd);
-}
-
-/*==========================================
- * 取引キャンセル
- *------------------------------------------
- */
-void clif_parse_TradeCansel (int fd, struct map_session_data *sd)
-{
-    trade_tradecancel (sd);
-}
-
-/*==========================================
- * 取引許諾(trade押し)
- *------------------------------------------
- */
-void clif_parse_TradeCommit (int fd, struct map_session_data *sd)
-{
-    trade_tradecommit (sd);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_StopAttack (int fd, struct map_session_data *sd)
-{
-    pc_stopattack (sd);
-}
-
-/*==========================================
- * カートへアイテムを移す
- *------------------------------------------
- */
-void clif_parse_PutItemToCart (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (sd->npc_id != 0 || sd->trade_partner != 0)
-        return;
-    pc_putitemtocart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
-}
-
-/*==========================================
- * カートからアイテムを出す
- *------------------------------------------
- */
-void clif_parse_GetItemFromCart (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (sd->npc_id != 0 || sd->trade_partner != 0)
-        return;
-    pc_getitemfromcart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
-}
-
-/*==========================================
- * 付属品(鷹,ペコ,カート)をはずす
- *------------------------------------------
- */
-void clif_parse_RemoveOption (int fd, struct map_session_data *sd)
-{
-    if (pc_isriding (sd))
-    {                           // jobchange when removing peco [Valaris]
-        if (sd->status.pc_class == 13)
-            sd->status.pc_class = sd->view_class = 7;
-
-        if (sd->status.pc_class == 21)
-            sd->status.pc_class = sd->view_class = 14;
-
-        if (sd->status.pc_class == 4014)
-            sd->status.pc_class = sd->view_class = 4008;
-
-        if (sd->status.pc_class == 4022)
-            sd->status.pc_class = sd->view_class = 4015;
-    }
-
-    pc_setoption (sd, 0);
-}
-
-/*==========================================
- * チェンジカート
- *------------------------------------------
- */
-void clif_parse_ChangeCart (int fd, struct map_session_data *sd)
-{
-    pc_setcart (sd, RFIFOW (fd, 2));
-}
-
-/*==========================================
- * ステータスアップ
- *------------------------------------------
- */
-void clif_parse_StatusUp (int fd, struct map_session_data *sd)
-{
-    pc_statusup (sd, RFIFOW (fd, 2));
-}
-
-/*==========================================
- * スキルレベルアップ
- *------------------------------------------
- */
-void clif_parse_SkillUp (int fd, struct map_session_data *sd)
-{
-    pc_skillup (sd, RFIFOW (fd, 2));
-}
-
-/*==========================================
- * スキル使用(ID指定)
- *------------------------------------------
- */
-void clif_parse_UseSkillToId (int fd, struct map_session_data *sd)
-{
-    int  skillnum, skilllv, lv, target_id;
-    unsigned int tick = gettick ();
-
-    nullpo_retv (sd);
-
-    if (map[sd->bl.m].flag.noskill)
-        return;
-    if (sd->chatID || sd->npc_id != 0 || sd->state.storage_flag)
-        return;
-
-    skilllv = RFIFOW (fd, 2);
-    skillnum = RFIFOW (fd, 4);
-    target_id = RFIFOL (fd, 6);
-
-    if (sd->skilltimer != -1)
-    {
-        if (skillnum != SA_CASTCANCEL)
-            return;
-    }
-    else if (DIFF_TICK (tick, sd->canact_tick) < 0)
-    {
-        clif_skill_fail (sd, skillnum, 4, 0);
-        return;
-    }
-
-    if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
-        sd->sc_data[SC_BERSERK].timer != -1
-        || sd->sc_data[SC_NOCHAT].timer != -1
-        || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
-        return;
-    if (sd->invincible_timer != -1)
-        pc_delinvincibletimer (sd);
-    if (sd->skillitem >= 0 && sd->skillitem == skillnum)
-    {
-        if (skilllv != sd->skillitemlv)
-            skilllv = sd->skillitemlv;
-        skill_use_id (sd, target_id, skillnum, skilllv);
-    }
-    else
-    {
-        sd->skillitem = sd->skillitemlv = -1;
-        if (skillnum == MO_EXTREMITYFIST)
-        {
-            if ((sd->sc_data[SC_COMBO].timer == -1
-                 || (sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH
-                     && sd->sc_data[SC_COMBO].val1 != CH_CHAINCRUSH)))
-            {
-                if (!sd->state.skill_flag)
-                {
-                    sd->state.skill_flag = 1;
-                    clif_skillinfo (sd, MO_EXTREMITYFIST, 1, -1);
-                    return;
-                }
-                else if (sd->bl.id == target_id)
-                {
-                    clif_skillinfo (sd, MO_EXTREMITYFIST, 1, -1);
-                    return;
-                }
-            }
-        }
-        if ((lv = pc_checkskill (sd, skillnum)) > 0)
-        {
-            if (skilllv > lv)
-                skilllv = lv;
-            skill_use_id (sd, target_id, skillnum, skilllv);
-            if (sd->state.skill_flag)
-                sd->state.skill_flag = 0;
-        }
-    }
-}
-
-/*==========================================
- * スキル使用(場所指定)
- *------------------------------------------
- */
-void clif_parse_UseSkillToPos (int fd, struct map_session_data *sd)
-{
-    int  skillnum, skilllv, lv, x, y;
-    unsigned int tick = gettick ();
-    int  skillmoreinfo;
-
-    nullpo_retv (sd);
-
-    if (map[sd->bl.m].flag.noskill)
-        return;
-    if (sd->npc_id != 0 || sd->state.storage_flag)
-        return;
-    if (sd->chatID)
-        return;
-
-    skillmoreinfo = -1;
-    skilllv = RFIFOW (fd, 2);
-    skillnum = RFIFOW (fd, 4);
-    x = RFIFOW (fd, 6);
-    y = RFIFOW (fd, 8);
-    if (RFIFOW (fd, 0) == 0x190)
-        skillmoreinfo = 10;
-
-    if (skillmoreinfo != -1)
-    {
-        if (pc_issit (sd))
-        {
-            clif_skill_fail (sd, skillnum, 0, 0);
-            return;
-        }
-        memcpy (talkie_mes, RFIFOP (fd, skillmoreinfo), 80);
-    }
-
-    if (sd->skilltimer != -1)
-        return;
-    else if (DIFF_TICK (tick, sd->canact_tick) < 0)
-    {
-        clif_skill_fail (sd, skillnum, 4, 0);
-        return;
-    }
-
-    if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
-        sd->sc_data[SC_BERSERK].timer != -1
-        || sd->sc_data[SC_NOCHAT].timer != -1
-        || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
-        return;
-    if (sd->invincible_timer != -1)
-        pc_delinvincibletimer (sd);
-    if (sd->skillitem >= 0 && sd->skillitem == skillnum)
-    {
-        if (skilllv != sd->skillitemlv)
-            skilllv = sd->skillitemlv;
-        skill_use_pos (sd, x, y, skillnum, skilllv);
-    }
-    else
-    {
-        sd->skillitem = sd->skillitemlv = -1;
-        if ((lv = pc_checkskill (sd, skillnum)) > 0)
-        {
-            if (skilllv > lv)
-                skilllv = lv;
-            skill_use_pos (sd, x, y, skillnum, skilllv);
-        }
-    }
-}
-
-/*==========================================
- * スキル使用(map指定)
- *------------------------------------------
- */
-void clif_parse_UseSkillMap (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (map[sd->bl.m].flag.noskill)
-        return;
-    if (sd->chatID)
-        return;
-
-    if (sd->npc_id != 0 || (sd->sc_data &&
-                            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||
-                             sd->sc_data[SC_BERSERK].timer != -1 ||
-                             sd->sc_data[SC_NOCHAT].timer != -1 ||
-                             sd->sc_data[SC_WEDDING].timer != -1 ||
-                             sd->view_class == 22)))
-        return;
-
-    if (sd->invincible_timer != -1)
-        pc_delinvincibletimer (sd);
-
-    skill_castend_map (sd, RFIFOW (fd, 2), RFIFOP (fd, 4));
-}
-
-/*==========================================
- * メモ要求
- *------------------------------------------
- */
-void clif_parse_RequestMemo (int fd, struct map_session_data *sd)
-{
-    pc_memo (sd, -1);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcSelectMenu (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    sd->npc_menu = RFIFOB (fd, 6);
-    map_scriptcont (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcNextClicked (int fd, struct map_session_data *sd)
-{
-    map_scriptcont (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcAmountInput (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-#define RFIFOL_(fd,pos) (*(int*)(session[fd]->rdata+session[fd]->rdata_pos+(pos)))
-    //Input Value overflow Exploit FIX
-    sd->npc_amount = RFIFOL_ (fd, 6);   //fixed by Lupus. npc_amount is (int) but was RFIFOL changing it to (unsigned int)
-
-#undef RFIFOL_
-
-    map_scriptcont (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * Process string-based input for an NPC.
- *
- * (S 01d5 <len>.w <npc_ID>.l <message>.?B)
- *------------------------------------------
- */
-void clif_parse_NpcStringInput (int fd, struct map_session_data *sd)
-{
-    int  len;
-    nullpo_retv (sd);
-
-    len = RFIFOW (fd, 2) - 8;
-
-    /*
-     * If we check for equal to 0, too, we'll freeze clients that send (or
-     * claim to have sent) an "empty" message.
-     */
-    if (len < 0)
-        return;
-
-    if (len >= sizeof (sd->npc_str) - 1)
-    {
-        printf ("clif_parse_NpcStringInput(): Input string too long!\n");
-        len = sizeof (sd->npc_str) - 1;
-    }
-
-    if (len > 0)
-        strncpy (sd->npc_str, RFIFOP (fd, 8), len);
-    sd->npc_str[len] = '\0';
-
-    map_scriptcont (sd, RFIFOL (fd, 4));
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void clif_parse_NpcCloseClicked (int fd, struct map_session_data *sd)
-{
-    map_scriptcont (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * アイテム鑑定
- *------------------------------------------
- */
-void clif_parse_ItemIdentify (int fd, struct map_session_data *sd)
-{
-    pc_item_identify (sd, RFIFOW (fd, 2) - 2);
-}
-
-/*==========================================
- * オートスペル受信
- *------------------------------------------
- */
-void clif_parse_AutoSpell (int fd, struct map_session_data *sd)
-{
-    skill_autospell (sd, RFIFOW (fd, 2));
-}
-
-/*==========================================
- * カード使用
- *------------------------------------------
- */
-void clif_parse_UseCard (int fd, struct map_session_data *sd)
-{
-    clif_use_card (sd, RFIFOW (fd, 2) - 2);
-}
-
-/*==========================================
- * カード挿入装備選択
- *------------------------------------------
- */
-void clif_parse_InsertCard (int fd, struct map_session_data *sd)
-{
-    pc_insert_card (sd, RFIFOW (fd, 2) - 2, RFIFOW (fd, 4) - 2);
-}
-
-/*==========================================
- * 0193 キャラID名前引き
- *------------------------------------------
- */
-void clif_parse_SolveCharName (int fd, struct map_session_data *sd)
-{
-    int  char_id;
-
-    char_id = RFIFOL (fd, 2);
-    clif_solved_charname (sd, char_id);
-}
-
-/*==========================================
- * 0197 /resetskill /resetstate
- *------------------------------------------
- */
-void clif_parse_ResetChar (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (battle_config.atc_gmonly == 0 || pc_isGM (sd))
-    {
-        switch (RFIFOW (fd, 2))
-        {
-            case 0:
-                log_atcommand (sd, "@charstreset %s", sd->status.name);
-                if (pc_isGM (sd) >=
-                    get_atcommand_level (AtCommand_ResetState))
-                    pc_resetstate (sd);
-                break;
-            case 1:
-                log_atcommand (sd, "@charskreset %s", sd->status.name);
-                if (pc_isGM (sd) >=
-                    get_atcommand_level (AtCommand_ResetState))
-                    pc_resetskill (sd);
-                break;
-        }
-    }
-}
-
-/*==========================================
- * 019c /lb等
- *------------------------------------------
- */
-void clif_parse_LGMmessage (int fd, struct map_session_data *sd)
-{
-    unsigned char buf[64];
-
-    nullpo_retv (sd);
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_LocalBroadcast)))
-    {
-        WBUFW (buf, 0) = 0x9a;
-        WBUFW (buf, 2) = RFIFOW (fd, 2);
-        memcpy (WBUFP (buf, 4), RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
-        clif_send (buf, RFIFOW (fd, 2), &sd->bl, ALL_SAMEMAP);
-    }
-}
-
-/*==========================================
- * カプラ倉庫へ入れる
- *------------------------------------------
- */
-void clif_parse_MoveToKafra (int fd, struct map_session_data *sd)
-{
-    int  item_index, item_amount;
-
-    nullpo_retv (sd);
-
-    item_index = RFIFOW (fd, 2) - 2;
-    item_amount = RFIFOL (fd, 4);
-
-    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
-        || !sd->state.storage_flag)
-        return;
-
-    if (sd->state.storage_flag == 1)
-        storage_storageadd (sd, item_index, item_amount);
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storageadd (sd, item_index, item_amount);
-}
-
-/*==========================================
- * カプラ倉庫から出す
- *------------------------------------------
- */
-void clif_parse_MoveFromKafra (int fd, struct map_session_data *sd)
-{
-    int  item_index, item_amount;
-
-    nullpo_retv (sd);
-
-    item_index = RFIFOW (fd, 2) - 1;
-    item_amount = RFIFOL (fd, 4);
-
-    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
-        || !sd->state.storage_flag)
-        return;
-
-    if (sd->state.storage_flag == 1)
-        storage_storageget (sd, item_index, item_amount);
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storageget (sd, item_index, item_amount);
-}
-
-/*==========================================
- * カプラ倉庫へカートから入れる
- *------------------------------------------
- */
-void clif_parse_MoveToKafraFromCart (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
-        || !sd->state.storage_flag)
-        return;
-    if (sd->state.storage_flag == 1)
-        storage_storageaddfromcart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storageaddfromcart (sd, RFIFOW (fd, 2) - 2,
-                                          RFIFOL (fd, 4));
-}
-
-/*==========================================
- * カプラ倉庫から出す
- *------------------------------------------
- */
-void clif_parse_MoveFromKafraToCart (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
-        || !sd->state.storage_flag)
-        return;
-    if (sd->state.storage_flag == 1)
-        storage_storagegettocart (sd, RFIFOW (fd, 2) - 1, RFIFOL (fd, 4));
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storagegettocart (sd, RFIFOW (fd, 2) - 1,
-                                        RFIFOL (fd, 4));
-}
-
-/*==========================================
- * カプラ倉庫を閉じる
- *------------------------------------------
- */
-void clif_parse_CloseKafra (int fd, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (sd->state.storage_flag == 1)
-        storage_storageclose (sd);
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storageclose (sd);
-}
-
-/*==========================================
- * パーティを作る
- * Process request to create a party.
- *
- * (S 00f9 <party_name>.24B)
- *------------------------------------------
- */
-void clif_parse_CreateParty (int fd, struct map_session_data *sd)
-{
-    if (battle_config.basic_skill_check == 0
-        || pc_checkskill (sd, NV_PARTY) >= 2)
-    {
-        party_create (sd, RFIFOP (fd, 2));
-    }
-    else
-        clif_skill_fail (sd, 1, 0, 4);
-}
-
-/*==========================================
- * パーティを作る
- * Process request to create a party.
- *
- * (S 01e8 <party_name>.24B <exp>.B <itm>.B)
- *
- * Note: Upstream eAthena uses this to
- *       specify experience/item sharing,
- *       respectively, but it was left
- *       incomplete here.
- *------------------------------------------
- */
-void clif_parse_CreateParty2 (int fd, struct map_session_data *sd)
-{
-    if (battle_config.basic_skill_check == 0
-        || pc_checkskill (sd, NV_PARTY) >= 2)
-    {
-        party_create (sd, RFIFOP (fd, 2));
-    }
-    else
-        clif_skill_fail (sd, 1, 0, 4);
-}
-
-/*==========================================
- * パーティに勧誘
- * Process invitation to join a party.
- *
- * (S 00fc <account_ID>.l)
- *------------------------------------------
- */
-void clif_parse_PartyInvite (int fd, struct map_session_data *sd)
-{
-    party_invite (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * パーティ勧誘返答
- * Process reply to party invitation.
- *
- * (S 00ff <account_ID>.l <flag>.l)
- *------------------------------------------
- */
-void clif_parse_ReplyPartyInvite (int fd, struct map_session_data *sd)
-{
-    if (battle_config.basic_skill_check == 0
-        || pc_checkskill (sd, NV_PARTY) >= 1)
-    {
-        party_reply_invite (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
-    }
-    else
-    {
-        party_reply_invite (sd, RFIFOL (fd, 2), 0);
-        clif_skill_fail (sd, 1, 0, 4);
-    }
-}
-
-/*==========================================
- * パーティ脱退要求
- *------------------------------------------
- */
-void clif_parse_LeaveParty (int fd, struct map_session_data *sd)
-{
-    party_leave (sd);
-}
-
-/*==========================================
- * パーティ除名要求
- *------------------------------------------
- */
-void clif_parse_RemovePartyMember (int fd, struct map_session_data *sd)
-{
-    party_removemember (sd, RFIFOL (fd, 2), RFIFOP (fd, 6));
-}
-
-/*==========================================
- * パーティ設定変更要求
- *------------------------------------------
- */
-void clif_parse_PartyChangeOption (int fd, struct map_session_data *sd)
-{
-    party_changeoption (sd, RFIFOW (fd, 2), RFIFOW (fd, 4));
-}
-
-/*==========================================
- * パーティメッセージ送信要求
- * Validate and process transmission of a
- * party message.
- *
- * (S 0108 <len>.w <message>.?B)
- *------------------------------------------
- */
-void clif_parse_PartyMessage (int fd, struct map_session_data *sd)
-{
-    size_t message_len = 0;
-    char *buf = NULL;
-    char *message = NULL;   /* The message text only. */
-
-    nullpo_retv (sd);
-
-    if (!(buf = clif_validate_chat (sd, 0, &message, &message_len)))
-    {
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
-            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
-                                || sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
-    {
-        free (buf);
-        return;
-    }
-
-    /* Don't send chat that results in an automatic ban. */
-    if (tmw_CheckChatSpam (sd, message))
-    {
-        free (buf);
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    party_send_message (sd, message, RFIFOW (fd, 2) - 4);
-    free (buf);
-}
-
-/*==========================================
- * /monster /item rewriten by [Yor]
- *------------------------------------------
- */
-void clif_parse_GM_Monster_Item (int fd, struct map_session_data *sd)
-{
-    char monster_item_name[25];
-
-    nullpo_retv (sd);
-
-    memset (monster_item_name, '\0', sizeof (monster_item_name));
-
-    if (battle_config.atc_gmonly == 0 || pc_isGM (sd))
-    {
-        memcpy (monster_item_name, RFIFOP (fd, 2), 24);
-
-        if (mobdb_searchname (monster_item_name) != 0)
-        {
-            if (pc_isGM (sd) >= get_atcommand_level (AtCommand_Monster))
-            {
-                log_atcommand (sd, "@spawn %s", monster_item_name);
-                atcommand_spawn (fd, sd, "@spawn", monster_item_name);  // as @spawn
-            }
-        }
-        else if (itemdb_searchname (monster_item_name) != NULL)
-        {
-            if (pc_isGM (sd) >= get_atcommand_level (AtCommand_Item))
-            {
-                log_atcommand (sd, "@item %s", monster_item_name);
-                atcommand_item (fd, sd, "@item", monster_item_name);    // as @item
-            }
-        }
-
-    }
-}
-
-/*==========================================
- * ギルドを作る
- * Process request to create a guild.
- *
- * (S 0165 <account_ID>.l <guild_name>.24B)
- *
- * Note: The account ID seems to be ignored.
- *------------------------------------------
- */
-void clif_parse_CreateGuild (int fd, struct map_session_data *sd)
-{
-    guild_create (sd, RFIFOP (fd, 6));
-}
-
-/*==========================================
- * ギルドマスターかどうか確認
- *------------------------------------------
- */
-void clif_parse_GuildCheckMaster (int fd, struct map_session_data *sd)
-{
-    clif_guild_masterormember (sd);
-}
-
-/*==========================================
- * ギルド情報要求
- *------------------------------------------
- */
-void clif_parse_GuildReqeustInfo (int fd, struct map_session_data *sd)
-{
-    switch (RFIFOL (fd, 2))
-    {
-        case 0:                // ギルド基本情報、同盟敵対情報
-            clif_guild_basicinfo (sd);
-            clif_guild_allianceinfo (sd);
-            break;
-        case 1:                // メンバーリスト、役職名リスト
-            clif_guild_positionnamelist (sd);
-            clif_guild_memberlist (sd);
-            break;
-        case 2:                // 役職名リスト、役職情報リスト
-            clif_guild_positionnamelist (sd);
-            clif_guild_positioninfolist (sd);
-            break;
-        case 3:                // スキルリスト
-            clif_guild_skillinfo (sd);
-            break;
-        case 4:                // 追放リスト
-            clif_guild_explusionlist (sd);
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("clif: guild request info: unknown type %d\n",
-                        RFIFOL (fd, 2));
-            break;
-    }
-}
-
-/*==========================================
- * ギルド役職変更
- *------------------------------------------
- */
-void clif_parse_GuildChangePositionInfo (int fd, struct map_session_data *sd)
-{
-    struct guild *g;
-    int  i, ps;
-
-    nullpo_retv (sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || (!(g->position[ps].mode & 0x0010) && strcmp (g->master, sd->status.name)))
-        return;
-
-    for (i = 4; i < RFIFOW (fd, 2); i += 40)
-    {
-        guild_change_position (sd, RFIFOL (fd, i), RFIFOL (fd, i + 4),
-                               RFIFOL (fd, i + 12), RFIFOP (fd, i + 16));
-    }
-}
-
-/*==========================================
- * ギルドメンバ役職変更
- *------------------------------------------
- */
-void clif_parse_GuildChangeMemberPosition (int fd,
-                                           struct map_session_data *sd)
-{
-    struct guild *g;
-    int  i, ps;
-
-    nullpo_retv (sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || (!(g->position[ps].mode & 0x0010) && strcmp (g->master, sd->status.name)))
-        return;
-
-    for (i = 4; i < RFIFOW (fd, 2); i += 12)
-    {
-        guild_change_memberposition (sd->status.guild_id,
-                                     RFIFOL (fd, i), RFIFOL (fd, i + 4),
-                                     RFIFOL (fd, i + 8));
-    }
-}
-
-/*==========================================
- * ギルドエンブレム要求
- *------------------------------------------
- */
-void clif_parse_GuildRequestEmblem (int fd, struct map_session_data *sd)
-{
-    struct guild *g = guild_search (RFIFOL (fd, 2));
-    if (g != NULL)
-        clif_guild_emblem (sd, g);
-}
-
-/*==========================================
- * ギルドエンブレム変更
- *------------------------------------------
- */
-void clif_parse_GuildChangeEmblem (int fd, struct map_session_data *sd)
-{
-    guild_change_emblem (sd, RFIFOW (fd, 2) - 4, RFIFOP (fd, 4));
-}
-
-/*==========================================
- * ギルド告知変更
- *------------------------------------------
- */
-void clif_parse_GuildChangeNotice (int fd, struct map_session_data *sd)
-{
-    guild_change_notice (sd, RFIFOL (fd, 2), RFIFOP (fd, 6), RFIFOP (fd, 66));
-}
-
-/*==========================================
- * ギルド勧誘
- *------------------------------------------
- */
-void clif_parse_GuildInvite (int fd, struct map_session_data *sd)
-{
-    guild_invite (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * ギルド勧誘返信
- *------------------------------------------
- */
-void clif_parse_GuildReplyInvite (int fd, struct map_session_data *sd)
-{
-    guild_reply_invite (sd, RFIFOL (fd, 2), RFIFOB (fd, 6));
-}
-
-/*==========================================
- * ギルド脱退
- *------------------------------------------
- */
-void clif_parse_GuildLeave (int fd, struct map_session_data *sd)
-{
-    guild_leave (sd, RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
-                 RFIFOP (fd, 14));
-}
-
-/*==========================================
- * ギルド追放
- *------------------------------------------
- */
-void clif_parse_GuildExplusion (int fd, struct map_session_data *sd)
-{
-    guild_explusion (sd, RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
-                     RFIFOP (fd, 14));
-}
-
-/*==========================================
- * ギルド会話
- * Validate and process transmission of a
- * guild message.
- *
- * (S 017e <len>.w <message>.?B)
- *------------------------------------------
- */
-void clif_parse_GuildMessage (int fd, struct map_session_data *sd)
-{
-    size_t message_len = 0;
-    char *buf = NULL;
-    char *message = NULL;   /* The message text only. */
-
-    nullpo_retv (sd);
-
-    if (!(buf = clif_validate_chat (sd, 2, &message, &message_len)))
-    {
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
-            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
-                                || sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
-    {
-        free (buf);
-        return;
-    }
-
-    /* Don't send chat that results in an automatic ban. */
-    if (tmw_CheckChatSpam (sd, message))
-    {
-        free (buf);
-        /* "Your message could not be sent." */
-        clif_displaymessage (fd, msg_txt (505));
-        return;
-    }
-
-    guild_send_message (sd, buf + 8, RFIFOW (fd, 2) - 4);
-    free (buf);
-}
-
-/*==========================================
- * ギルド同盟要求
- *------------------------------------------
- */
-void clif_parse_GuildRequestAlliance (int fd, struct map_session_data *sd)
-{
-    guild_reqalliance (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * ギルド同盟要求返信
- *------------------------------------------
- */
-void clif_parse_GuildReplyAlliance (int fd, struct map_session_data *sd)
-{
-    guild_reply_reqalliance (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
-}
-
-/*==========================================
- * ギルド関係解消
- *------------------------------------------
- */
-void clif_parse_GuildDelAlliance (int fd, struct map_session_data *sd)
-{
-    guild_delalliance (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
-}
-
-/*==========================================
- * ギルド敵対
- *------------------------------------------
- */
-void clif_parse_GuildOpposition (int fd, struct map_session_data *sd)
-{
-    guild_opposition (sd, RFIFOL (fd, 2));
-}
-
-/*==========================================
- * ギルド解散
- *------------------------------------------
- */
-void clif_parse_GuildBreak (int fd, struct map_session_data *sd)
-{
-    guild_break (sd, RFIFOP (fd, 2));
-}
-
-// Kick (right click menu for GM "(name) force to quit")
-void clif_parse_GMKick (int fd, struct map_session_data *sd)
-{
-    struct block_list *target;
-    int  tid = RFIFOL (fd, 2);
-
-    nullpo_retv (sd);
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Kick)))
-    {
-        target = map_id2bl (tid);
-        if (target)
-        {
-            if (target->type == BL_PC)
-            {
-                struct map_session_data *tsd =
-                    (struct map_session_data *) target;
-                log_atcommand (sd, "@kick %s", tsd->status.name);
-                if (pc_isGM (sd) > pc_isGM (tsd))
-                    clif_GM_kick (sd, tsd, 1);
-                else
-                    clif_GM_kickack (sd, 0);
-            }
-            else if (target->type == BL_MOB)
-            {
-                struct mob_data *md = (struct mob_data *) target;
-                sd->state.attack_type = 0;
-                mob_damage (&sd->bl, md, md->hp, 2);
-            }
-            else
-                clif_GM_kickack (sd, 0);
-        }
-        else
-            clif_GM_kickack (sd, 0);
-    }
-}
-
-/*==========================================
- * /shift
- *------------------------------------------
- */
-void clif_parse_Shift (int fd, struct map_session_data *sd)
-{                               // Rewriten by [Yor]
-    char player_name[25];
-
-    nullpo_retv (sd);
-
-    memset (player_name, '\0', sizeof (player_name));
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Goto)))
-    {
-        memcpy (player_name, RFIFOP (fd, 2), 24);
-        log_atcommand (sd, "@goto %s", player_name);
-        atcommand_goto (fd, sd, "@goto", player_name);  // as @jumpto
-    }
-
-    return;
-}
-
-/*==========================================
- * /recall
- *------------------------------------------
- */
-void clif_parse_Recall (int fd, struct map_session_data *sd)
-{                               // Added by RoVeRT
-    char player_name[25];
-
-    nullpo_retv (sd);
-
-    memset (player_name, '\0', sizeof (player_name));
-
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Recall)))
-    {
-        memcpy (player_name, RFIFOP (fd, 2), 24);
-        log_atcommand (sd, "@recall %s", player_name);
-        atcommand_recall (fd, sd, "@recall", player_name);  // as @recall
-    }
-
-    return;
-}
-
-void clif_parse_GMHide (int fd, struct map_session_data *sd)
-{                               // Modified by [Yor]
-    nullpo_retv (sd);
-
-    //printf("%2x %2x %2x\n", RFIFOW(fd,0), RFIFOW(fd,2), RFIFOW(fd,4)); // R 019d <Option_value>.2B <flag>.2B
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Hide)))
-    {
-        log_atcommand (sd, "@hide");
-        if (sd->status.option & OPTION_HIDE)
-        {                       // OPTION_HIDE = 0x40
-            sd->status.option &= ~OPTION_HIDE;  // OPTION_HIDE = 0x40
-            /* "Invisible: Off." */
-            clif_displaymessage (fd, msg_txt (10));
-        }
-        else
-        {
-            sd->status.option |= OPTION_HIDE;   // OPTION_HIDE = 0x40
-            /* "Invisible: On." */
-            clif_displaymessage (fd, msg_txt (11));
-        }
-        clif_changeoption (&sd->bl);
-    }
-}
-
-/*==========================================
- * GMによるチャット禁止時間付与
- *------------------------------------------
- */
-void clif_parse_GMReqNoChat (int fd, struct map_session_data *sd)
-{
-    int  tid = RFIFOL (fd, 2);
-    int  type = RFIFOB (fd, 6);
-    int  limit = RFIFOW (fd, 7);
-    struct block_list *bl = map_id2bl (tid);
-    struct map_session_data *dstsd;
-    int  dstfd;
-
-    nullpo_retv (sd);
-
-    if (!battle_config.muting_players)
-    {
-        /* "Muting is disabled." */
-        clif_displaymessage (fd, msg_txt (245));
-        return;
-    }
-
-    if (type == 0)
-        limit = 0 - limit;
-    if (bl->type == BL_PC && (dstsd = (struct map_session_data *) bl))
-    {
-        if ((tid == bl->id && type == 2 && !pc_isGM (sd))
-            || (pc_isGM (sd) > pc_isGM (dstsd)))
-        {
-            dstfd = dstsd->fd;
-            WFIFOW (dstfd, 0) = 0x14b;
-            WFIFOB (dstfd, 2) = (type == 2) ? 1 : type;
-            memcpy (WFIFOP (dstfd, 3), sd->status.name, 24);
-            WFIFOSET (dstfd, packet_len_table[0x14b]);
-            dstsd->status.manner -= limit;
-            if (dstsd->status.manner < 0)
-                skill_status_change_start (bl, SC_NOCHAT, 0, 0, 0, 0, 0, 0);
-            else
-            {
-                dstsd->status.manner = 0;
-                skill_status_change_end (bl, SC_NOCHAT, -1);
-            }
-            printf ("name:%s type:%d limit:%d manner:%d\n",
-                    dstsd->status.name, type, limit, dstsd->status.manner);
-        }
-    }
-
-    return;
-}
-
-/*==========================================
- * GMによるチャット禁止時間参照(?)
- *------------------------------------------
- */
-void clif_parse_GMReqNoChatCount (int fd, struct map_session_data *sd)
-{
-    int  tid = RFIFOL (fd, 2);
-
-    WFIFOW (fd, 0) = 0x1e0;
-    WFIFOL (fd, 2) = tid;
-    sprintf (WFIFOP (fd, 6), "%d", tid);
-//  memcpy(WFIFOP(fd,6),"TESTNAME",24);
-    WFIFOSET (fd, packet_len_table[0x1e0]);
-
-    return;
-}
-
-void clif_parse_PMIgnore (int fd, struct map_session_data *sd)
-{                               // Rewritten by [Yor]
-    char output[1024];
-    char *nick;                 // S 00cf <nick>.24B <type>.B: 00 (/ex nick) deny speech from nick, 01 (/in nick) allow speech from nick
-    int  i;
-    int  pos;
-
-    memset (output, '\0', sizeof (output));
-
-    nick = RFIFOP (fd, 2);      // speed up
-    //printf("Ignore: char '%s' state: %d\n", nick, RFIFOB(fd,26));
-    // we ask for deny (we add nick only if it's not already exist
-    if (RFIFOB (fd, 26) == 0)
-    {                           // type
-        if (strlen (nick) >= 4 && strlen (nick) < 24)
-        {                       // do something only if nick can be exist
-            pos = -1;
-            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
-                 i++)
-            {
-                if (strcmp (sd->ignore[i].name, nick) == 0)
-                    break;
-                else if (pos == -1 && sd->ignore[i].name[0] == '\0')
-                    pos = i;
-            }
-            WFIFOW (fd, 0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-            WFIFOB (fd, 2) = 0;
-            // if a position is found and name not found, we add it in the list
-            if (pos != -1
-                && i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
-            {
-                memcpy (sd->ignore[pos].name, nick, 24);
-                WFIFOB (fd, 3) = 0; // success
-                WFIFOSET (fd, packet_len_table[0x0d1]);
-                if (strcmp (wisp_server_name, nick) == 0)
-                {               // to found possible bot users that automaticaly ignores people.
-                    sprintf (output,
-                             "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?",
-                             sd->status.name, sd->status.account_id,
-                             wisp_server_name);
-                    intif_wis_message_to_gm (wisp_server_name,
-                                             battle_config.hack_info_GM_level,
-                                             output, strlen (output) + 1);
-                    // send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :)
-                    clif_wis_message (fd, wisp_server_name,
-                                      "Add me in your ignore list, doesn't block my wisps.",
-                                      strlen
-                                      ("Add me in your ignore list, doesn't block my wisps.")
-                                      + 1);
-                }
-            }
-            else
-            {
-                WFIFOB (fd, 3) = 1; // fail
-                if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
-                {
-                    clif_wis_message (fd, wisp_server_name,
-                                      "You can not block more people.",
-                                      strlen
-                                      ("You can not block more people.") + 1);
-                    if (strcmp (wisp_server_name, nick) == 0)
-                    {           // to found possible bot users that automaticaly ignores people.
-                        sprintf (output,
-                                 "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?",
-                                 sd->status.name, sd->status.account_id,
-                                 wisp_server_name);
-                        intif_wis_message_to_gm (wisp_server_name,
-                                                 battle_config.hack_info_GM_level,
-                                                 output, strlen (output) + 1);
-                    }
-                }
-                else
-                {
-                    clif_wis_message (fd, wisp_server_name,
-                                      "This player is already blocked.",
-                                      strlen
-                                      ("This player is already blocked.") +
-                                      1);
-                    if (strcmp (wisp_server_name, nick) == 0)
-                    {           // to found possible bot users that automaticaly ignores people.
-                        sprintf (output,
-                                 "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?",
-                                 sd->status.name, sd->status.account_id,
-                                 wisp_server_name);
-                        intif_wis_message_to_gm (wisp_server_name,
-                                                 battle_config.hack_info_GM_level,
-                                                 output, strlen (output) + 1);
-                    }
-                }
-            }
-        }
-        else
-            clif_wis_message (fd, wisp_server_name,
-                              "It's impossible to block this player.",
-                              strlen ("It's impossible to block this player.")
-                              + 1);
-        // we ask for allow (we remove all same nick if exist)
-    }
-    else
-    {
-        if (strlen (nick) >= 4 && strlen (nick) < 24)
-        {                       // do something only if nick can be exist
-            WFIFOW (fd, 0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-            WFIFOB (fd, 2) = 1;
-            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
-                 i++)
-                if (strcmp (sd->ignore[i].name, nick) == 0)
-                {
-                    memset (sd->ignore[i].name, 0,
-                            sizeof (sd->ignore[i].name));
-                    WFIFOB (fd, 3) = 0; // success
-                    WFIFOSET (fd, packet_len_table[0x0d1]);
-                    break;
-                }
-            if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
-            {
-                WFIFOB (fd, 3) = 1; // fail
-                WFIFOSET (fd, packet_len_table[0x0d1]);
-                clif_wis_message (fd, wisp_server_name,
-                                  "This player is not blocked by you.",
-                                  strlen
-                                  ("This player is not blocked by you.") + 1);
-            }
-        }
-        else
-            clif_wis_message (fd, wisp_server_name,
-                              "It's impossible to unblock this player.",
-                              strlen
-                              ("It's impossible to unblock this player.") +
-                              1);
-    }
-
-//  for(i = 0; i < (sizeof(sd->ignore) / sizeof(sd->ignore[0])); i++) // for debug only
-//      if (sd->ignore[i].name[0] != '\0')
-//          printf("Ignored player: '%s'\n", sd->ignore[i].name);
-
-    return;
-}
-
-void clif_parse_PMIgnoreAll (int fd, struct map_session_data *sd)
-{                               // Rewritten by [Yor]
-    //printf("Ignore all: state: %d\n", RFIFOB(fd,2));
-    if (RFIFOB (fd, 2) == 0)
-    {                           // S 00d0 <type>len.B: 00 (/exall) deny all speech, 01 (/inall) allow all speech
-        WFIFOW (fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-        WFIFOB (fd, 2) = 0;
-        if (sd->ignoreAll == 0)
-        {
-            sd->ignoreAll = 1;
-            WFIFOB (fd, 3) = 0; // success
-            WFIFOSET (fd, packet_len_table[0x0d2]);
-        }
-        else
-        {
-            WFIFOB (fd, 3) = 1; // fail
-            WFIFOSET (fd, packet_len_table[0x0d2]);
-            clif_wis_message (fd, wisp_server_name,
-                              "You already block everyone.",
-                              strlen ("You already block everyone.") + 1);
-        }
-    }
-    else
-    {
-        WFIFOW (fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
-        WFIFOB (fd, 2) = 1;
-        if (sd->ignoreAll == 1)
-        {
-            sd->ignoreAll = 0;
-            WFIFOB (fd, 3) = 0; // success
-            WFIFOSET (fd, packet_len_table[0x0d2]);
-        }
-        else
-        {
-            WFIFOB (fd, 3) = 1; // fail
-            WFIFOSET (fd, packet_len_table[0x0d2]);
-            clif_wis_message (fd, wisp_server_name,
-                              "You already allow everyone.",
-                              strlen ("You already allow everyone.") + 1);
-        }
-    }
-
-    return;
-}
-
-void clif_parse_skillMessage (int fd, struct map_session_data *sd)
-{                               // Added by RoVeRT
-    int  skillid, skilllv, x, y;
-    char *mes;
-
-    skilllv = RFIFOW (fd, 2);
-    skillid = RFIFOW (fd, 4);
-
-    y = RFIFOB (fd, 6);
-    x = RFIFOB (fd, 8);
-
-    mes = RFIFOP (fd, 10);
-
-    // skill 220 = graffiti
-//  printf("skill: %d %d location: %3d %3d message: %s\n", skillid, skilllv, x, y, (char*)mes);
-}
-
-int monk (struct map_session_data *sd, struct block_list *target, int type)
-{
-//R 01d1 <Monk id>L <Target monster id>L <Bool>L
-    int  fd = sd->fd;
-    WFIFOW (fd, 0) = 0x1d1;
-    WFIFOL (fd, 2) = sd->bl.id;
-    WFIFOL (fd, 6) = target->id;
-    WFIFOL (fd, 10) = type;
-    WFIFOSET (fd, packet_len_table[0x1d1]);
-
-    return 0;
-}
-
-/*==========================================
- * スパノビの/doridoriによるSPR2倍
- *------------------------------------------
- */
-void clif_parse_sn_doridori (int fd, struct map_session_data *sd)
-{
-    if (sd)
-        sd->doridori_counter = 1;
-
-    return;
-}
-
-/*==========================================
- * スパノビの爆裂波動
- *------------------------------------------
- */
-void clif_parse_sn_explosionspirits (int fd, struct map_session_data *sd)
-{
-    if (sd)
-    {
-        int  nextbaseexp = pc_nextbaseexp (sd);
-        struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
-        if (battle_config.etc_log)
-        {
-            if (nextbaseexp != 0)
-                printf ("SuperNovice explosionspirits!! %d %d %d %d\n",
-                        sd->bl.id, s_class.job, sd->status.base_exp,
-                        (int) ((double) 1000 * sd->status.base_exp /
-                               nextbaseexp));
-            else
-                printf ("SuperNovice explosionspirits!! %d %d %d 000\n",
-                        sd->bl.id, s_class.job, sd->status.base_exp);
-        }
-        if (s_class.job == 23 && 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, 1);
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable
-                                       [MO_EXPLOSIONSPIRITS], 5, 0, 0, 0,
-                                       skill_get_time (MO_EXPLOSIONSPIRITS,
-                                                       5), 0);
-        }
-    }
-    return;
-}
-
-// functions list. Rate is how many milliseconds are required between
-// calls. Packets exceeding this rate will be dropped. flood_rates in
-// map.h must be the same length as this table. rate 0 is default
-// rate -1 is unlimited
-typedef struct func_table
-{
-	void (*func)(int fd, struct map_session_data *sd);
-	int rate;
-} func_table;
-// *INDENT-OFF*
-func_table clif_parse_func_table[0x220] =
-{
-	{ NULL,					0	},	// 0
-	{ NULL,					0	},	// 1
-	{ NULL,					0	},	// 2
-	{ NULL,					0	},	// 3
-	{ NULL,					0	},	// 4
-	{ NULL,					0	},	// 5
-	{ NULL,					0	},	// 6
-	{ NULL,					0	},	// 7
-	{ NULL,					0	},	// 8
-	{ NULL,					0	},	// 9
-	{ NULL,					0	},	// a
-	{ NULL,					0	},	// b
-	{ NULL,					0	},	// c
-	{ NULL,					0	},	// d
-	{ NULL,					0	},	// e
-	{ NULL,					0	},	// f
-	{ NULL,					0	},	// 10
-	{ NULL,					0	},	// 11
-	{ NULL,					0	},	// 12
-	{ NULL,					0	},	// 13
-	{ NULL,					0	},	// 14
-	{ NULL,					0	},	// 15
-	{ NULL,					0	},	// 16
-	{ NULL,					0	},	// 17
-	{ NULL,					0	},	// 18
-	{ NULL,					0	},	// 19
-	{ NULL,					0	},	// 1a
-	{ NULL,					0	},	// 1b
-	{ NULL,					0	},	// 1c
-	{ NULL,					0	},	// 1d
-	{ NULL,					0	},	// 1e
-	{ NULL,					0	},	// 1f
-	{ NULL,					0	},	// 20
-	{ NULL,					0	},	// 21
-	{ NULL,					0	},	// 22
-	{ NULL,					0	},	// 23
-	{ NULL,					0	},	// 24
-	{ NULL,					0	},	// 25
-	{ NULL,					0	},	// 26
-	{ NULL,					0	},	// 27
-	{ NULL,					0	},	// 28
-	{ NULL,					0	},	// 29
-	{ NULL,					0	},	// 2a
-	{ NULL,					0	},	// 2b
-	{ NULL,					0	},	// 2c
-	{ NULL,					0	},	// 2d
-	{ NULL,					0	},	// 2e
-	{ NULL,					0	},	// 2f
-	{ NULL,					0	},	// 30
-	{ NULL,					0	},	// 31
-	{ NULL,					0	},	// 32
-	{ NULL,					0	},	// 33
-	{ NULL,					0	},	// 34
-	{ NULL,					0	},	// 35
-	{ NULL,					0	},	// 36
-	{ NULL,					0	},	// 37
-	{ NULL,					0	},	// 38
-	{ NULL,					0	},	// 39
-	{ NULL,					0	},	// 3a
-	{ NULL,					0	},	// 3b
-	{ NULL,					0	},	// 3c
-	{ NULL,					0	},	// 3d
-	{ NULL,					0	},	// 3e
-	{ NULL,					0	},	// 3f
-	{ NULL,					0	},	// 40
-	{ NULL,					0	},	// 41
-	{ NULL,					0	},	// 42
-	{ NULL,					0	},	// 43
-	{ NULL,					0	},	// 44
-	{ NULL,					0	},	// 45
-	{ NULL,					0	},	// 46
-	{ NULL,					0	},	// 47
-	{ NULL,					0	},	// 48
-	{ NULL,					0	},	// 49
-	{ NULL,					0	},	// 4a
-	{ NULL,					0	},	// 4b
-	{ NULL,					0	},	// 4c
-	{ NULL,					0	},	// 4d
-	{ NULL,					0	},	// 4e
-	{ NULL,					0	},	// 4f
-	{ NULL,					0	},	// 50
-	{ NULL,					0	},	// 51
-	{ NULL,					0	},	// 52
-	{ NULL,					0	},	// 53
-	{ NULL,					0	},	// 54
-	{ NULL,					0	},	// 55
-	{ NULL,					0	},	// 56
-	{ NULL,					0	},	// 57
-	{ NULL,					0	},	// 58
-	{ NULL,					0	},	// 59
-	{ NULL,					0	},	// 5a
-	{ NULL,					0	},	// 5b
-	{ NULL,					0	},	// 5c
-	{ NULL,					0	},	// 5d
-	{ NULL,					0	},	// 5e
-	{ NULL,					0	},	// 5f
-	{ NULL,					0	},	// 60
-	{ NULL,					0	},	// 61
-	{ NULL,					0	},	// 62
-	{ NULL,					0	},	// 63
-	{ NULL,					0	},	// 64
-	{ NULL,					0	},	// 65
-	{ NULL,					0	},	// 66
-	{ NULL,					0	},	// 67
-	{ NULL,					0	},	// 68
-	{ NULL,					0	},	// 69
-	{ NULL,					0	},	// 6a
-	{ NULL,					0	},	// 6b
-	{ NULL,					0	},	// 6c
-	{ NULL,					0	},	// 6d
-	{ NULL,					0	},	// 6e
-	{ NULL,					0	},	// 6f
-	{ NULL,					0	},	// 70
-	{ NULL,					0	},	// 71
-	{ clif_parse_WantToConnection,		0	},	// 72
-	{ NULL,					0	},	// 73
-	{ NULL,					0	},	// 74
-	{ NULL,					0	},	// 75
-	{ NULL,					0	},	// 76
-	{ NULL,					0	},	// 77
-	{ NULL,					0	},	// 78
-	{ NULL,					0	},	// 79
-	{ NULL,					0	},	// 7a
-	{ NULL,					0	},	// 7b
-	{ NULL,					0	},	// 7c
-	{ clif_parse_LoadEndAck,		-1	},	// 7d
-	{ clif_parse_TickSend,			0	},	// 7e
-	{ NULL,					0	},	// 7f
-	{ NULL,					0	},	// 80
-	{ NULL,					0	},	// 81
-	{ NULL,					0	},	// 82
-	{ NULL,					0	},	// 83
-	{ NULL,					0	},	// 84
-	{ clif_parse_WalkToXY,			-1	},	// 85 Walk code limits this on it's own
-	{ NULL,					0	},	// 86
-	{ NULL,					0	},	// 87
-	{ NULL,					0	},	// 88
-	{ clif_parse_ActionRequest,		1000	},	// 89 Special case - see below
-	{ NULL,					0	},	// 8a
-	{ NULL,					0	},	// 8b
-	{ clif_parse_GlobalMessage,		300	},	// 8c
-	{ NULL,					0	},	// 8d
-	{ NULL,					0	},	// 8e
-	{ NULL,					0	},	// 8f
-	{ clif_parse_NpcClicked,		500	},	// 90
-	{ NULL,					0	},	// 91
-	{ NULL,					0	},	// 92
-	{ NULL,					0	},	// 93
-	{ clif_parse_GetCharNameRequest,	-1	},	// 94
-	{ NULL,					0	},	// 95
-	{ clif_parse_Wis,			300	},	// 96
-	{ NULL,					0	},	// 97
-	{ NULL,					0	},	// 98
-	{ clif_parse_GMmessage,			300	},	// 99
-	{ NULL,					0	},	// 9a
-	{ clif_parse_ChangeDir,			-1	},	// 9b
-	{ NULL,					0	},	// 9c
-	{ NULL,					0	},	// 9d
-	{ NULL,					0	},	// 9e
-	{ clif_parse_TakeItem,			400	},	// 9f
-	{ NULL,					0	},	// a0
-	{ NULL,					0	},	// a1
-	{ clif_parse_DropItem,			50	},	// a2
-	{ NULL,					0	},	// a3
-	{ NULL,					0	},	// a4
-	{ NULL,					0	},	// a5
-	{ NULL,					0	},	// a6
-	{ clif_parse_UseItem,			0	},	// a7
-	{ NULL,					0	},	// a8
-	{ clif_parse_EquipItem,			-1	},	// a9 Special case - outfit window (not implemented yet - needs to allow bursts)
-	{ NULL,					0	},	// aa
-	{ clif_parse_UnequipItem,		-1	},	// ab Special case - outfit window (not implemented yet - needs to allow bursts)
-	{ NULL,					0	},	// ac
-	{ NULL,					0	},	// ad
-	{ NULL,					0	},	// ae
-	{ NULL,					0	},	// af
-	{ NULL,					0	},	// b0
-	{ NULL,					0	},	// b1
-	{ clif_parse_Restart,			0	},	// b2
-	{ NULL,					0	},	// b3
-	{ NULL,					0	},	// b4
-	{ NULL,					0	},	// b5
-	{ NULL,					0	},	// b6
-	{ NULL,					0	},	// b7
-	{ clif_parse_NpcSelectMenu,		0	},	// b8
-	{ clif_parse_NpcNextClicked,		-1	},	// b9
-	{ NULL,					0	},	// ba
-	{ clif_parse_StatusUp,			-1	},	// bb People click this very quickly
-	{ NULL,					0	},	// bc
-	{ NULL,					0	},	// bd
-	{ NULL,					0	},	// be
-	{ clif_parse_Emotion,			1000	},	// bf
-	{ NULL,					0	},	// c0
-	{ clif_parse_HowManyConnections,	0	},	// c1
-	{ NULL,					0	},	// c2
-	{ NULL,					0	},	// c3
-	{ NULL,					0	},	// c4
-	{ clif_parse_NpcBuySellSelected,	0	},	// c5
-	{ NULL,					0	},	// c6
-	{ NULL,					0	},	// c7
-	{ clif_parse_NpcBuyListSend,		-1	},	// c8
-	{ clif_parse_NpcSellListSend,		-1	},	// c9 Selling multiple 1-slot items
-	{ NULL,					0	},	// ca
-	{ NULL,					0	},	// cb
-	{ clif_parse_GMKick,			0	},	// cc
-	{ NULL,					0	},	// cd
-	{ NULL,					0	},	// ce
-	{ clif_parse_PMIgnore,			0	},	// cf
-	{ clif_parse_PMIgnoreAll,		0	},	// d0
-	{ NULL,					0	},	// d1
-	{ NULL,					0	},	// d2
-	{ NULL,					0	},	// d3
-	{ NULL,					0	},	// d4
-	{ clif_parse_CreateChatRoom,		1000	},	// d5
-	{ NULL,					0	},	// d6
-	{ NULL,					0	},	// d7
-	{ NULL,					0	},	// d8
-	{ clif_parse_ChatAddMember,		0	},	// d9
-	{ NULL,					0	},	// da
-	{ NULL,					0	},	// db
-	{ NULL,					0	},	// dc
-	{ NULL,					0	},	// dd
-	{ clif_parse_ChatRoomStatusChange,	0	},	// de
-	{ NULL,					0	},	// df
-	{ clif_parse_ChangeChatOwner,		0	},	// e0
-	{ NULL,					0	},	// e1
-	{ clif_parse_KickFromChat,		0	},	// e2
-	{ clif_parse_ChatLeave,			0	},	// e3
-	{ clif_parse_TradeRequest,		2000	},	// e4
-	{ NULL,					0	},	// e5
-	{ clif_parse_TradeAck,			0	},	// e6
-	{ NULL,					0	},	// e7
-	{ clif_parse_TradeAddItem,		0	},	// e8
-	{ NULL,					0	},	// e9
-	{ NULL,					0	},	// ea
-	{ clif_parse_TradeOk,			0	},	// eb
-	{ NULL,					0	},	// ec
-	{ clif_parse_TradeCansel,		0	},	// ed
-	{ NULL,					0	},	// ee
-	{ clif_parse_TradeCommit,		0	},	// ef
-	{ NULL,					0	},	// f0
-	{ NULL,					0	},	// f1
-	{ NULL,					0	},	// f2
-	{ clif_parse_MoveToKafra,		-1	},	// f3
-	{ NULL,					0	},	// f4
-	{ clif_parse_MoveFromKafra,		-1	},	// f5
-	{ NULL,					0	},	// f6
-	{ clif_parse_CloseKafra,		0	},	// f7
-	{ NULL,					0	},	// f8
-	{ clif_parse_CreateParty,		2000	},	// f9
-	{ NULL,					0	},	// fa
-	{ NULL,					0	},	// fb
-	{ clif_parse_PartyInvite,		2000	},	// fc
-	{ NULL,					0	},	// fd
-	{ NULL,					0	},	// fe
-	{ clif_parse_ReplyPartyInvite,		0	},	// ff
-	{ clif_parse_LeaveParty,		0	},	// 100
-	{ NULL,					0	},	// 101
-	{ clif_parse_PartyChangeOption,		0	},	// 102
-	{ clif_parse_RemovePartyMember,		0	},	// 103
-	{ NULL,					0	},	// 104
-	{ NULL,					0	},	// 105
-	{ NULL,					0	},	// 106
-	{ NULL,					0	},	// 107
-	{ clif_parse_PartyMessage,		300	},	// 108
-	{ NULL,					0	},	// 109
-	{ NULL,					0	},	// 10a
-	{ NULL,					0	},	// 10b
-	{ NULL,					0	},	// 10c
-	{ NULL,					0	},	// 10d
-	{ NULL,					0	},	// 10e
-	{ NULL,					0	},	// 10f
-	{ NULL,					0	},	// 110
-	{ NULL,					0	},	// 111
-	{ clif_parse_SkillUp,			-1	},	// 112
-	{ clif_parse_UseSkillToId,		0	},	// 113
-	{ NULL,					0	},	// 114
-	{ NULL,					0	},	// 115
-	{ clif_parse_UseSkillToPos,		0	},	// 116
-	{ NULL,					0	},	// 117
-	{ clif_parse_StopAttack,		0	},	// 118
-	{ NULL,					0	},	// 119
-	{ NULL,					0	},	// 11a
-	{ clif_parse_UseSkillMap,		0	},	// 11b
-	{ NULL,					0	},	// 11c
-	{ clif_parse_RequestMemo,		0	},	// 11d
-	{ NULL,					0	},	// 11e
-	{ NULL,					0	},	// 11f
-	{ NULL,					0	},	// 120
-	{ NULL,					0	},	// 121
-	{ NULL,					0	},	// 122
-	{ NULL,					0	},	// 123
-	{ NULL,					0	},	// 124
-	{ NULL,					0	},	// 125
-	{ clif_parse_PutItemToCart,		0	},	// 126
-	{ clif_parse_GetItemFromCart,		0	},	// 127
-	{ clif_parse_MoveFromKafraToCart,	0	},	// 128
-	{ clif_parse_MoveToKafraFromCart,	0	},	// 129
-	{ clif_parse_RemoveOption,		0	},	// 12a
-	{ NULL,					0	},	// 12b
-	{ NULL,					0	},	// 12c
-	{ NULL,					0	},	// 12d
-	{ NULL,					0	},	// 12e
-	{ NULL,					0	},	// 12f
-	{ NULL,					0	},	// 130
-	{ NULL,					0	},	// 131
-	{ NULL,					0	},	// 132
-	{ NULL,					0	},	// 133
-	{ NULL,					0	},	// 134
-	{ NULL,					0	},	// 135
-	{ NULL,					0	},	// 136
-	{ NULL,					0	},	// 137
-	{ NULL,					0	},	// 138
-	{ NULL,					0	},	// 139
-	{ NULL,					0	},	// 13a
-	{ NULL,					0	},	// 13b
-	{ NULL,					0	},	// 13c
-	{ NULL,					0	},	// 13d
-	{ NULL,					0	},	// 13e
-	{ clif_parse_GM_Monster_Item,		0	},	// 13f
-	{ clif_parse_MapMove,			0	},	// 140
-	{ NULL,					0	},	// 141
-	{ NULL,					0	},	// 142
-	{ clif_parse_NpcAmountInput,		300	},	// 143
-	{ NULL,					0	},	// 144
-	{ NULL,					0	},	// 145
-	{ clif_parse_NpcCloseClicked,		300	},	// 146
-	{ NULL,					0	},	// 147
-	{ NULL,					0	},	// 148
-	{ clif_parse_GMReqNoChat,		0	},	// 149
-	{ NULL,					0	},	// 14a
-	{ NULL,					0	},	// 14b
-	{ NULL,					0	},	// 14c
-	{ clif_parse_GuildCheckMaster,		0	},	// 14d
-	{ NULL,					0	},	// 14e
-	{ clif_parse_GuildReqeustInfo,		0	},	// 14f
-	{ NULL,					0	},	// 150
-	{ clif_parse_GuildRequestEmblem,	0	},	// 151
-	{ NULL,					0	},	// 152
-	{ clif_parse_GuildChangeEmblem,		0	},	// 153
-	{ NULL,					0	},	// 154
-	{ clif_parse_GuildChangeMemberPosition,	0	},	// 155
-	{ NULL,					0	},	// 156
-	{ NULL,					0	},	// 157
-	{ NULL,					0	},	// 158
-	{ clif_parse_GuildLeave,		0	},	// 159
-	{ NULL,					0	},	// 15a
-	{ clif_parse_GuildExplusion,		0	},	// 15b
-	{ NULL,					0	},	// 15c
-	{ clif_parse_GuildBreak,		0	},	// 15d
-	{ NULL,					0	},	// 15e
-	{ NULL,					0	},	// 15f
-	{ NULL,					0	},	// 160
-	{ clif_parse_GuildChangePositionInfo,	0	},	// 161
-	{ NULL,					0	},	// 162
-	{ NULL,					0	},	// 163
-	{ NULL,					0	},	// 164
-	{ clif_parse_CreateGuild,		0	},	// 165
-	{ NULL,					0	},	// 166
-	{ NULL,					0	},	// 167
-	{ clif_parse_GuildInvite,		2000	},	// 168
-	{ NULL,					0	},	// 169
-	{ NULL,					0	},	// 16a
-	{ clif_parse_GuildReplyInvite,		0	},	// 16b
-	{ NULL,					0	},	// 16c
-	{ NULL,					0	},	// 16d
-	{ clif_parse_GuildChangeNotice,		0	},	// 16e
-	{ NULL,					0	},	// 16f
-	{ clif_parse_GuildRequestAlliance,	0	},	// 170
-	{ NULL,					0	},	// 171
-	{ clif_parse_GuildReplyAlliance,	0	},	// 172
-	{ NULL,					0	},	// 173
-	{ NULL,					0	},	// 174
-	{ NULL,					0	},	// 175
-	{ NULL,					0	},	// 176
-	{ NULL,					0	},	// 177
-	{ clif_parse_ItemIdentify,		0	},	// 178
-	{ NULL,					0	},	// 179
-	{ clif_parse_UseCard,			0	},	// 17a
-	{ NULL,					0	},	// 17b
-	{ clif_parse_InsertCard,		0	},	// 17c
-	{ NULL,					0	},	// 17d
-	{ clif_parse_GuildMessage,		300	},	// 17e
-	{ NULL,					0	},	// 17f
-	{ clif_parse_GuildOpposition,		0	},	// 180
-	{ NULL,					0	},	// 181
-	{ NULL,					0	},	// 182
-	{ clif_parse_GuildDelAlliance,		0	},	// 183
-	{ NULL,					0	},	// 184
-	{ NULL,					0	},	// 185
-	{ NULL,					0	},	// 186
-	{ NULL,					0	},	// 187
-	{ NULL,					0	},	// 188
-	{ NULL,					0	},	// 189
-	{ clif_parse_QuitGame,			0	},	// 18a
-	{ NULL,					0	},	// 18b
-	{ NULL,					0	},	// 18c
-	{ NULL,					0	},	// 18d
-	{ NULL,					0	},	// 18e
-	{ NULL,					0	},	// 18f
-	{ clif_parse_UseSkillToPos,		0	},	// 190
-	{ NULL,					0	},	// 191
-	{ NULL,					0	},	// 192
-	{ clif_parse_SolveCharName,		0	},	// 193
-	{ NULL,					0	},	// 194
-	{ NULL,					0	},	// 195
-	{ NULL,					0	},	// 196
-	{ clif_parse_ResetChar,			0	},	// 197
-	{ NULL,					0	},	// 198
-	{ NULL,					0	},	// 199
-	{ NULL,					0	},	// 19a
-	{ NULL,					0	},	// 19b
-	{ clif_parse_LGMmessage,		0	},	// 19c
-	{ clif_parse_GMHide,			300	},	// 19d
-	{ NULL,					0	},	// 19e
-	{ NULL,					0	},	// 19f
-	{ NULL,					0	},	// 1a0
-	{ NULL,					0	},	// 1a1
-	{ NULL,					0	},	// 1a2
-	{ NULL,					0	},	// 1a3
-	{ NULL,					0	},	// 1a4
-	{ NULL,					0	},	// 1a5
-	{ NULL,					0	},	// 1a6
-	{ NULL,					0	},	// 1a7
-	{ NULL,					0	},	// 1a8
-	{ NULL,					0	},	// 1a9
-	{ NULL,					0	},	// 1aa
-	{ NULL,					0	},	// 1ab
-	{ NULL,					0	},	// 1ac
-	{ NULL,					0	},	// 1ad
-	{ NULL,					0	},	// 1ae
-	{ clif_parse_ChangeCart,		0	},	// 1af
-	{ NULL,					0	},	// 1b0
-	{ NULL,					0	},	// 1b1
-	{ NULL,					0	},	// 1b2
-	{ NULL,					0	},	// 1b3
-	{ NULL,					0	},	// 1b4
-	{ NULL,					0	},	// 1b5
-	{ NULL,					0	},	// 1b6
-	{ NULL,					0	},	// 1b7
-	{ NULL,					0	},	// 1b8
-	{ NULL,					0	},	// 1b9
-	{ clif_parse_Shift,			300	},	// 1ba
-	{ clif_parse_Shift,			300	},	// 1bb
-	{ clif_parse_Recall,			300	},	// 1bc
-	{ clif_parse_Recall,			300	},	// 1bd
-	{ NULL,					0	},	// 1be
-	{ NULL,					0	},	// 1bf
-	{ NULL,					0	},	// 1c0
-	{ NULL,					0	},	// 1c1
-	{ NULL,					0	},	// 1c2
-	{ NULL,					0	},	// 1c3
-	{ NULL,					0	},	// 1c4
-	{ NULL,					0	},	// 1c5
-	{ NULL,					0	},	// 1c6
-	{ NULL,					0	},	// 1c7
-	{ NULL,					0	},	// 1c8
-	{ NULL,					0	},	// 1c9
-	{ NULL,					0	},	// 1ca
-	{ NULL,					0	},	// 1cb
-	{ NULL,					0	},	// 1cc
-	{ NULL,					0	},	// 1cd
-	{ clif_parse_AutoSpell,			0	},	// 1ce
-	{ NULL,					0	},	// 1cf
-	{ NULL,					0	},	// 1d0
-	{ NULL,					0	},	// 1d1
-	{ NULL,					0	},	// 1d2
-	{ NULL,					0	},	// 1d3
-	{ NULL,					0	},	// 1d4
-	{ clif_parse_NpcStringInput,		300	},	// 1d5
-	{ NULL,					0	},	// 1d6
-	{ NULL,					0	},	// 1d7
-	{ NULL,					0	},	// 1d8
-	{ NULL,					0	},	// 1d9
-	{ NULL,					0	},	// 1da
-	{ NULL,					0	},	// 1db
-	{ NULL,					0	},	// 1dc
-	{ NULL,					0	},	// 1dd
-	{ NULL,					0	},	// 1de
-	{ clif_parse_GMReqNoChatCount,		0	},	// 1df
-	{ NULL,					0	},	// 1e0
-	{ NULL,					0	},	// 1e1
-	{ NULL,					0	},	// 1e2
-	{ NULL,					0	},	// 1e3
-	{ NULL,					0	},	// 1e4
-	{ NULL,					0	},	// 1e5
-	{ NULL,					0	},	// 1e6
-	{ clif_parse_sn_doridori,		0	},	// 1e7
-	{ clif_parse_CreateParty2,		1000	},	// 1e8
-	{ NULL,					0	},	// 1e9
-	{ NULL,					0	},	// 1ea
-	{ NULL,					0	},	// 1eb
-	{ NULL,					0	},	// 1ec
-	{ clif_parse_sn_explosionspirits,	0	},	// 1ed
-	{ NULL,					0	},	// 1ee
-	{ NULL,					0	},	// 1ef
-	{ NULL,					0	},	// 1f0
-	{ NULL,					0	},	// 1f1
-	{ NULL,					0	},	// 1f2
-	{ NULL,					0	},	// 1f3
-	{ NULL,					0	},	// 1f4
-	{ NULL,					0	},	// 1f5
-	{ NULL,					0	},	// 1f6
-	{ NULL,					0	},	// 1f7
-	{ NULL,					0	},	// 1f8
-	{ NULL,					0	},	// 1f9
-	{ NULL,					0	},	// 1fa
-	{ NULL,					0	},	// 1fb
-	{ NULL,					0	},	// 1fc
-	{ NULL,					0	},	// 1fd
-	{ NULL,					0	},	// 1fe
-	{ NULL,					0	},	// 1ff
-	{ NULL,					0	},	// 200
-	{ NULL,					0	},	// 201
-	{ NULL,					0	},	// 202
-	{ NULL,					0	},	// 203
-	{ NULL,					0	},	// 204
-	{ NULL,					0	},	// 205
-	{ NULL,					0	},	// 206
-	{ NULL,					0	},	// 207
-	{ NULL,					0	},	// 208
-	{ NULL,					0	},	// 209
-	{ NULL,					0	},	// 20a
-	{ NULL,					0	},	// 20b
-	{ NULL,					0	},	// 20c
-	{ NULL,					0	},	// 20d
-	{ NULL,					0	},	// 20e
-	{ NULL,					0	},	// 20f
-	{ NULL,					0	},	// 210
-	{ NULL,					0	},	// 211
-	{ NULL,					0	},	// 212
-	{ NULL,					0	},	// 213
-	{ NULL,					0	},	// 214
-	{ NULL,					0	},	// 215
-	{ NULL,					0	},	// 216
-	{ NULL,					0	},	// 217
-	{ NULL,					0	},	// 218
-	{ NULL,					0	},	// 219
-	{ NULL,					0	},	// 21a
-	{ NULL,					0	},	// 21b
-	{ NULL,					0	},	// 21c
-	{ NULL,					0	},	// 21d
-	{ NULL,					0	},	// 21e
-	{ NULL,					0	},	// 21f
-};
-// *INDENT-ON*
-
-// Checks for packet flooding
-int clif_check_packet_flood(int fd, int cmd)
-{
-    struct map_session_data *sd = (struct map_session_data *)session[fd]->session_data;
-    unsigned int rate, tick = gettick();
-
-    // sd will not be set if the client hasn't requested
-    // WantToConnection yet. Do not apply flood logic to GMs
-    // as approved bots (GMlvl1) should not have to work around
-    // flood logic.
-    if (!sd || pc_isGM(sd) || clif_parse_func_table[cmd].rate == -1)
-	return 0;
-
-    // Timer has wrapped
-    if (tick < sd->flood_rates[cmd])
-    {
-        sd->flood_rates[cmd] = tick;
-        return 0;
-    }
-
-    // Default rate is 100ms
-    if ((rate = clif_parse_func_table[cmd].rate) == 0)
-        rate = 100;
-
-    // ActionRequest - attacks are allowed a faster rate than sit/stand
-    if (cmd == 0x89)
-    {
-        int action_type = RFIFOB (fd, 6);
-        if (action_type == 0x00 || action_type == 0x07)
-            rate = 20;
-        else
-            rate = 1000;
-    }
-
-// Restore this code when mana1.0 is released
-#if 0
-    // ChangeDir - only apply limit if not walking
-    if (cmd == 0x9b)
-    {
-        // .29 clients spam this packet when walking into a blocked tile
-        if (RFIFOB(fd, 4) == sd->dir || sd->walktimer != -1)
-            return 0;
-
-        rate = 500;
-    }
-#endif
-
-    // They are flooding
-    if (tick < sd->flood_rates[cmd] + rate)
-    {
-        time_t now = time(NULL);
-
-        // If it's a nasty flood we log and possibly kick
-        if (now > sd->packet_flood_reset_due)
-        {
-            sd->packet_flood_reset_due = now + battle_config.packet_spam_threshold;
-            sd->packet_flood_in = 0;
-        }
-
-        sd->packet_flood_in++;
-
-        if (sd->packet_flood_in >= battle_config.packet_spam_flood)
-        {
-            printf("packet flood detected from %s [0x%x]\n", sd->status.name, cmd);
-            if (battle_config.packet_spam_kick)
-            {
-                session[fd]->eof = 1; // Kick
-                return 1;
-            }
-            sd->packet_flood_in = 0;
-        }
-
-        return 1;
-    }
-
-    sd->flood_rates[cmd] = tick;
-    return 0;
-}
-
-#define WARN_MALFORMED_MSG(sd, msg)                             \
-    printf ("clif_validate_chat(): %s (ID %d) sent a malformed" \
-            " message: %s.\n", sd->status.name, sd->status.account_id, msg)
-/**
- * Validate message integrity (inspired by upstream source (eAthena)).
- *
- * @param sd active session data
- * @param type message type:
- *  0 for when the sender's name is not included (party chat)
- *  1 for when the target's name is included (whisper chat)
- *  2 for when the sender's name is given ("sender : text", public/guild chat)
- * @param[out] message the message text (pointing within return value, or NULL)
- * @param[out] message_len the length of the actual text, excluding NUL
- * @return a dynamically allocated copy of the message, or NULL upon failure
- */
-static char *clif_validate_chat (struct map_session_data *sd, int type,
-                                 char **message, size_t *message_len)
-{
-    int fd;
-    unsigned int buf_len;       /* Actual message length. */
-    unsigned int msg_len;       /* Reported message length. */
-    unsigned int min_len;       /* Minimum message length. */
-    size_t name_len;            /* Sender's name length. */
-    char *buf = NULL;           /* Copy of actual message data. */
-    char *p = NULL;             /* Temporary pointer to message. */
-
-    *message = NULL;
-    *message_len = 0;
-
-    nullpo_retr (NULL, sd);
-    /*
-     * Don't send chat in the period between the ban and the connection's
-     * closure.
-     */
-    if (type < 0 || type > 2 || sd->auto_ban_info.in_progress)
-        return NULL;
-
-    fd = sd->fd;
-    msg_len = RFIFOW (fd, 2) - 4;
-    name_len = strlen (sd->status.name);
-    /*
-     * At least one character is required in all instances.
-     * Notes for length checks:
-     *
-     * For all types, header (2) + length (2) is considered empty.
-     * For type 1, the message must be longer than the maximum name length (24)
-     *      to be valid.
-     * For type 2, the message must be longer than the sender's name length
-     *      plus the length of the separator (" : ").
-     */
-    min_len = (type == 1) ? 24 : (type == 2) ? name_len + 3 : 0;
-
-    /* The player just sent the header (2) and length (2) words. */
-    if (!msg_len)
-    {
-        WARN_MALFORMED_MSG (sd, "no message sent");
-        return NULL;
-    }
-
-    /* The client sent (or claims to have sent) an empty message. */
-    if (msg_len == min_len)
-    {
-        WARN_MALFORMED_MSG (sd, "empty message");
-        return NULL;
-    }
-
-    /* The protocol specifies that the target must be 24 bytes long. */
-    if (type == 1 && msg_len < min_len)
-    {
-        /* Disallow malformed messages. */
-        clif_setwaitclose (fd);
-        WARN_MALFORMED_MSG (sd, "illegal target name");
-        return NULL;
-    }
-
-    p = (char *) (type != 1) ? RFIFOP (fd, 4) : RFIFOP (fd, 28);
-    buf_len = (type == 1) ? msg_len - min_len: msg_len;
-
-    /*
-     * The client attempted to exceed the maximum message length.
-     *
-     * The conf suggests up to chat_maxline characters, after which the message
-     * is truncated. But the previous behavior was to drop the message, so
-     * we'll do that, too.
-     */
-    if (buf_len >= battle_config.chat_maxline)
-    {
-        WARN_MALFORMED_MSG (sd, "exceeded maximum message length");
-        return NULL;
-    }
-
-    /* We're leaving an extra eight bytes for public/global chat, 1 for NUL. */
-    buf_len += (type == 2) ? 8 + 1 : 1;
-
-    buf = (char *) malloc (buf_len);
-    memcpy ((type != 2) ? buf : buf + 8, p,
-            (type != 2) ? buf_len - 1 : buf_len - 8 - 1);
-    buf[buf_len - 1] = '\0';
-    p = (type != 2) ? buf : buf + 8;
-
-    if (type != 2)
-    {
-        *message = buf;
-        /* Don't count the NUL. */
-        *message_len = buf_len - 1;
-    }
-    else
-    {
-        char *pos = NULL;
-        if (!(pos = strstr(p, " : "))
-                || strncmp (p, sd->status.name, name_len)
-                || pos - p != name_len)
-        {
-            free (buf);
-            /* Disallow malformed/spoofed messages. */
-            clif_setwaitclose (fd);
-            WARN_MALFORMED_MSG (sd, "spoofed name/invalid format");
-            return NULL;
-        }
-        /* Step beyond the separator. */
-        *message = pos + 3;
-        /* Don't count the sender's name, the extra eight bytes, or the NUL. */
-        *message_len = buf_len - min_len - 8 - 1;
-    }
-
-    return buf;
-}
-
-/*==========================================
- * クライアントからのパケット解析
- * socket.cのdo_parsepacketから呼び出される
- *------------------------------------------
- */
-static void clif_parse (int fd)
-{
-    int  packet_len = 0, cmd = 0;
-    struct map_session_data *sd = (struct map_session_data *)session[fd]->session_data;
-
-    if (!sd || (sd && !sd->state.auth))
-    {
-        if (RFIFOREST (fd) < 2)
-        {                       // too small a packet disconnect
-            session[fd]->eof = 1;
-        }
-        if (RFIFOW (fd, 0) != 0x72)
-        {                       // first packet not auth, disconnect
-            session[fd]->eof = 1;
-        }
-    }
-
-    // 接続が切れてるので後始末
-    if (!chrif_isconnect () || session[fd]->eof)
-    {                           // char鯖に繋がってない間は接続禁止 (!chrif_isconnect())
-        if (sd && sd->state.auth)
-        {
-            pc_logout (sd);
-            clif_quitsave (fd, sd);
-            if (sd->status.name != NULL)
-                printf ("Player [%s] has logged off your server.\n", sd->status.name);  // Player logout display [Valaris]
-            else
-                printf ("Player with account [%d] has logged off your server.\n", sd->bl.id);   // Player logout display [Yor]
-        }
-        else if (sd)
-        {                       // not authentified! (refused by char-server or disconnect before to be authentified)
-            printf ("Player with account [%d] has logged off your server (not auth account).\n", sd->bl.id);    // Player logout display [Yor]
-            map_deliddb (&sd->bl);  // account_id has been included in the DB before auth answer
-        }
-        if (fd)
-            close (fd);
-        if (fd)
-            delete_session (fd);
-        return;
-    }
-
-    if (RFIFOREST (fd) < 2)
-        return;               // Too small (no packet number)
-
-    cmd = RFIFOW (fd, 0);
-
-    // 管理用パケット処理
-    if (cmd >= 30000)
-    {
-        switch (cmd)
-        {
-            case 0x7530:       // Athena情報所得
-                WFIFOW (fd, 0) = 0x7531;
-                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
-                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
-                WFIFOB (fd, 4) = ATHENA_REVISION;
-                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
-                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
-                WFIFOB (fd, 7) = ATHENA_SERVER_MAP;
-                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
-                WFIFOSET (fd, 10);
-                RFIFOSKIP (fd, 2);
-                break;
-            case 0x7532:       // 接続の切断
-                session[fd]->eof = 1;
-                break;
-        }
-        return;
-    }
-    else if (cmd >= 0x200)
-        return;
-
-    // パケット長を計算
-    packet_len = packet_len_table[cmd];
-    if (packet_len == -1)
-    {
-        if (RFIFOREST (fd) < 4)
-        {
-            return;           // Runt packet (variable length without a length sent)
-        }
-        packet_len = RFIFOW (fd, 2);
-        if (packet_len < 4 || packet_len > 32768)
-        {
-            session[fd]->eof = 1;
-            return;           // Runt packet (variable out of bounds)
-        }
-    }
-
-    if (RFIFOREST (fd) < packet_len)
-    {
-        return;               // Runt packet (sent legnth is too small)
-    }
-
-    if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1)
-    {                           // 切断待ちの場合パケットを処理しない
-
-    }
-    else if (clif_parse_func_table[cmd].func)
-    {
-        if (clif_check_packet_flood(fd, cmd))
-        {
-            // Flood triggered. Skip packet.
-            RFIFOSKIP(sd->fd, packet_len);
-            return;
-        }
-
-        clif_parse_func_table[cmd].func (fd, sd);
-    }
-    else
-    {
-        // 不明なパケット
-        if (battle_config.error_log)
-        {
-            if (fd)
-                printf ("\nclif_parse: session #%d, packet 0x%x, lenght %d\n",
-                        fd, cmd, packet_len);
-#ifdef DUMP_UNKNOWN_PACKET
-            {
-                int  i;
-                FILE *fp;
-                char packet_txt[256] = "save/packet.txt";
-                time_t now;
-                printf
-                    ("---- 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)
-                        printf ("\n%04X ", i);
-                    printf ("%02X ", RFIFOB (fd, i));
-                }
-                if (sd && sd->state.auth)
-                {
-                    if (sd->status.name != NULL)
-                        printf
-                            ("\nAccount ID %d, character ID %d, player name %s.\n",
-                             sd->status.account_id, sd->status.char_id,
-                             sd->status.name);
-                    else
-                        printf ("\nAccount ID %d.\n", sd->bl.id);
-                }
-                else if (sd)    // not authentified! (refused by char-server or disconnect before to be authentified)
-                    printf ("\nAccount ID %d.\n", sd->bl.id);
-
-                if ((fp = fopen_ (packet_txt, "a")) == NULL)
-                {
-                    printf ("clif.c: cant write [%s] !!! data is lost !!!\n",
-                            packet_txt);
-                    return;
-                }
-                else
-                {
-                    time (&now);
-                    if (sd && sd->state.auth)
-                    {
-                        if (sd->status.name != NULL)
-                            fprintf (fp,
-                                     "%sPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
-                                     asctime (gmtime (&now)),
-                                     sd->status.account_id,
-                                     sd->status.char_id, sd->status.name);
-                        else
-                            fprintf (fp,
-                                     "%sPlayer with account ID %d sent wrong packet:\n",
-                                     asctime (gmtime (&now)), sd->bl.id);
-                    }
-                    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 (gmtime (&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));
-                    }
-                    fprintf (fp, "\n\n");
-                    fclose_ (fp);
-                }
-            }
-#endif
-        }
-    }
-    RFIFOSKIP (fd, packet_len);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int do_init_clif (void)
-{
-    int  i;
-
-    set_defaultparse (clif_parse);
-    for (i = 0; i < 10; i++)
-    {
-        if (make_listen_port (map_port))
-            break;
-#ifdef LCCWIN32
-        Sleep (20000);
-#else
-        sleep (20);
-#endif
-    }
-    if (i == 10)
-    {
-        printf ("cant bind game port\n");
-        exit (1);
-    }
-
-    return 0;
-}
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
new file mode 100644
index 0000000..2d6ddf1
--- /dev/null
+++ b/src/map/clif.cpp
@@ -0,0 +1,10332 @@
+// $Id: clif.c 164 2004-10-01 16:46:58Z $
+
+#define DUMP_UNKNOWN_PACKET	1
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#ifdef LCCWIN32
+#include <winsock.h>
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <time.h>
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/version.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/md5calc.hpp"
+#include "../common/mt_rand.hpp"
+
+#include "atcommand.hpp"
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "magic.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+#include "tmw.hpp"
+#include "trade.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define STATE_BLIND 0x10
+#define EMOTE_IGNORED 0x0e
+
+static const int packet_len_table[0x220] = {
+    10, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+//#0x0040
+    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, -1, 55, 17, 3, 37, 46, -1, 23, -1, 3, 108, 3, 2,
+    3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
+//#0x0080
+    7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0, // 0x8b unknown... size 2 or 23?
+    7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
+    23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
+    8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
+//#0x00C0
+    7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
+    3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
+    30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
+    3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
+
+//#0x0100
+    2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
+    10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
+    6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
+    6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
+//#0x0140
+    22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
+    110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
+    -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14, 186, 182,
+    14, 30, 10, 3, -1, 6, 106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
+//#0x0180
+    6, 3, 106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
+    90, 86, 24, 6, 30, 102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6,
+    3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
+    11, 7, -1, 67, 12, 18, 114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
+//#0x01C0,   Set 0x1d5=-1
+    2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 30, 6, 28,
+    8, 14, 10, 35, 6, -1, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
+    30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
+    -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
+//#0x200
+    26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 19, 10, -1, 24, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+// local define
+enum
+{
+    ALL_CLIENT,
+    ALL_SAMEMAP,
+    AREA,
+    AREA_WOS,
+    AREA_WOC,
+    AREA_WOSC,
+    AREA_CHAT_WOC,
+    CHAT,
+    CHAT_WOS,
+    PARTY,
+    PARTY_WOS,
+    PARTY_SAMEMAP,
+    PARTY_SAMEMAP_WOS,
+    PARTY_AREA,
+    PARTY_AREA_WOS,
+    GUILD,
+    GUILD_WOS,
+    GUILD_SAMEMAP,              // [Valaris]
+    GUILD_SAMEMAP_WOS,
+    GUILD_AREA,
+    GUILD_AREA_WOS,             // end additions [Valaris]
+    SELF
+};
+
+#define WBUFPOS(p,pos,x,y) { unsigned char *__p = (p); __p+=(pos); __p[0] = (x)>>2; __p[1] = ((x)<<6) | (((y)>>4)&0x3f); __p[2] = (y)<<4; }
+#define WBUFPOS2(p,pos,x0,y0,x1,y1) { unsigned char *__p = (p); __p+=(pos); __p[0] = (x0)>>2; __p[1] = ((x0)<<6) | (((y0)>>4)&0x3f); __p[2] = ((y0)<<4) | (((x1)>>6)&0x0f); __p[3]=((x1)<<2) | (((y1)>>8)&0x03); __p[4]=(y1); }
+
+#define WFIFOPOS(fd,pos,x,y) { WBUFPOS (WFIFOP(fd,pos),0,x,y); }
+#define WFIFOPOS2(fd,pos,x0,y0,x1,y1) { WBUFPOS2(WFIFOP(fd,pos),0,x0,y0,x1,y1); }
+
+static char map_ip_str[16];
+static in_addr_t map_ip;
+static int map_port = 5121;
+int  map_fd;
+char talkie_mes[80];
+
+/*==========================================
+ * map鯖のip設定
+ *------------------------------------------
+ */
+void clif_setip (char *ip)
+{
+    memcpy (map_ip_str, ip, 16);
+    map_ip = inet_addr (map_ip_str);
+}
+
+/*==========================================
+ * map鯖のport設定
+ *------------------------------------------
+ */
+void clif_setport (int port)
+{
+    map_port = port;
+}
+
+/*==========================================
+ * map鯖のip読み出し
+ *------------------------------------------
+ */
+in_addr_t clif_getip (void)
+{
+    return map_ip;
+}
+
+/*==========================================
+ * map鯖のport読み出し
+ *------------------------------------------
+ */
+int clif_getport (void)
+{
+    return map_port;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_countusers (void)
+{
+    int  users = 0, i;
+    struct map_session_data *sd;
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd
+            && sd->state.auth && !(battle_config.hide_GM_session
+                                   && pc_isGM (sd)))
+            users++;
+    }
+    return users;
+}
+
+/*==========================================
+ * 全てのclientに対してfunc()実行
+ *------------------------------------------
+ */
+int clif_foreachclient (int (*func) (struct map_session_data *, va_list), ...)
+{
+    int  i;
+    va_list ap;
+    struct map_session_data *sd;
+
+    va_start (ap, func);
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd
+            && sd->state.auth)
+            func (sd, ap);
+    }
+    va_end (ap);
+    return 0;
+}
+
+static int is_deaf (struct block_list *bl)
+{
+    struct map_session_data *sd = (struct map_session_data *) bl;
+    if (!bl || bl->type != BL_PC)
+        return 0;
+    return sd->special_state.deaf;
+}
+
+static void clif_emotion_towards (struct block_list *bl,
+                                  struct block_list *target, int type);
+
+static char *clif_validate_chat (struct map_session_data *sd, int type,
+                                 char **message, size_t *message_len);
+
+/*==========================================
+ * clif_sendでAREA*指定時用
+ *------------------------------------------
+ */
+int clif_send_sub (struct block_list *bl, va_list ap)
+{
+    unsigned char *buf;
+    int  len;
+    struct block_list *src_bl;
+    int  type;
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = (struct map_session_data *) bl);
+
+    buf = va_arg (ap, unsigned char *);
+    len = va_arg (ap, int);
+    nullpo_retr (0, src_bl = va_arg (ap, struct block_list *));
+    type = va_arg (ap, int);
+
+    switch (type)
+    {
+        case AREA_WOS:
+            if (bl && bl == src_bl)
+                return 0;
+            break;
+
+        case AREA_CHAT_WOC:
+            if (is_deaf (bl)
+                && !(bl->type == BL_PC
+                     && pc_isGM ((struct map_session_data *) src_bl)))
+            {
+                clif_emotion_towards (src_bl, bl, EMOTE_IGNORED);
+                return 0;
+            }
+            /* fall through... */
+        case AREA_WOC:
+            if ((sd && sd->chatID) || (bl && bl == src_bl))
+                return 0;
+
+            break;
+        case AREA_WOSC:
+            if ((sd) && sd->chatID
+                && sd->chatID == ((struct map_session_data *) src_bl)->chatID)
+                return 0;
+            break;
+    }
+
+    if (session[sd->fd] != NULL)
+    {
+        if (WFIFOP (sd->fd, 0) == buf)
+        {
+            printf ("WARNING: Invalid use of clif_send function\n");
+            printf
+                ("         Packet x%4x use a WFIFO of a player instead of to use a buffer.\n",
+                 WBUFW (buf, 0));
+            printf ("         Please correct your code.\n");
+            // don't send to not move the pointer of the packet for next sessions in the loop
+        }
+        else
+        {
+            if (packet_len_table[RBUFW (buf, 0)])
+            {                   // packet must exist
+                memcpy (WFIFOP (sd->fd, 0), buf, len);
+                WFIFOSET (sd->fd, len);
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_send (unsigned char *buf, int len, struct block_list *bl, int type)
+{
+    int  i;
+    struct map_session_data *sd;
+    struct chat_data *cd;
+    struct party *p = NULL;
+    struct guild *g = NULL;
+    int  x0 = 0, x1 = 0, y0 = 0, y1 = 0;
+
+    if (type != ALL_CLIENT)
+    {
+        nullpo_retr (0, bl);
+
+        if (bl->type == BL_PC)
+        {
+            struct map_session_data *sd = (struct map_session_data *) bl;
+            if (sd->status.option & OPTION_INVISIBILITY)
+            {
+                // Obscure hidden GMs
+
+                switch (type)
+                {
+                    case AREA:
+                    case AREA_WOC:
+                        type = SELF;
+                        break;
+
+                    case AREA_WOS:
+                    case AREA_WOSC:
+                        return 1;
+
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
+    switch (type)
+    {
+        case ALL_CLIENT:       // 全クライアントに送信
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
+                    && sd->state.auth)
+                {
+                    if (packet_len_table[RBUFW (buf, 0)])
+                    {           // packet must exist
+                        memcpy (WFIFOP (i, 0), buf, len);
+                        WFIFOSET (i, len);
+                    }
+                }
+            }
+            break;
+        case ALL_SAMEMAP:      // 同じマップの全クライアントに送信
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
+                    && sd->state.auth && sd->bl.m == bl->m)
+                {
+                    if (packet_len_table[RBUFW (buf, 0)])
+                    {           // packet must exist
+                        memcpy (WFIFOP (i, 0), buf, len);
+                        WFIFOSET (i, len);
+                    }
+                }
+            }
+            break;
+        case AREA:
+        case AREA_WOS:
+        case AREA_WOC:
+        case AREA_WOSC:
+            map_foreachinarea (clif_send_sub, bl->m, bl->x - AREA_SIZE,
+                               bl->y - AREA_SIZE, bl->x + AREA_SIZE,
+                               bl->y + AREA_SIZE, BL_PC, buf, len, bl, type);
+            break;
+        case AREA_CHAT_WOC:
+            map_foreachinarea (clif_send_sub, bl->m, bl->x - (AREA_SIZE),
+                               bl->y - (AREA_SIZE),
+                               bl->x + (AREA_SIZE),
+                               bl->y + (AREA_SIZE), BL_PC, buf, len, bl,
+                               AREA_CHAT_WOC);
+            break;
+        case CHAT:
+        case CHAT_WOS:
+            cd = (struct chat_data *) bl;
+            if (bl->type == BL_PC)
+            {
+                sd = (struct map_session_data *) bl;
+                cd = (struct chat_data *) map_id2bl (sd->chatID);
+            }
+            else if (bl->type != BL_CHAT)
+                break;
+            if (cd == NULL)
+                break;
+            for (i = 0; i < cd->users; i++)
+            {
+                if (type == CHAT_WOS
+                    && cd->usersd[i] == (struct map_session_data *) bl)
+                    continue;
+                if (packet_len_table[RBUFW (buf, 0)])
+                {               // packet must exist
+                    memcpy (WFIFOP (cd->usersd[i]->fd, 0), buf, len);
+                    WFIFOSET (cd->usersd[i]->fd, len);
+                }
+            }
+            break;
+
+        case PARTY_AREA:       // 同じ画面内の全パーティーメンバに送信
+        case PARTY_AREA_WOS:   // 自分以外の同じ画面内の全パーティーメンバに送信
+            x0 = bl->x - AREA_SIZE;
+            y0 = bl->y - AREA_SIZE;
+            x1 = bl->x + AREA_SIZE;
+            y1 = bl->y + AREA_SIZE;
+        case PARTY:            // 全パーティーメンバに送信
+        case PARTY_WOS:        // 自分以外の全パーティーメンバに送信
+        case PARTY_SAMEMAP:    // 同じマップの全パーティーメンバに送信
+        case PARTY_SAMEMAP_WOS:    // 自分以外の同じマップの全パーティーメンバに送信
+            if (bl->type == BL_PC)
+            {
+                sd = (struct map_session_data *) bl;
+                if (sd->partyspy > 0)
+                {
+                    p = party_search (sd->partyspy);
+                }
+                else
+                {
+                    if (sd->status.party_id > 0)
+                        p = party_search (sd->status.party_id);
+                }
+            }
+            if (p)
+            {
+                for (i = 0; i < MAX_PARTY; i++)
+                {
+                    if ((sd = p->member[i].sd) != NULL)
+                    {
+                        if (sd->bl.id == bl->id && (type == PARTY_WOS ||
+                                                    type == PARTY_SAMEMAP_WOS
+                                                    || type ==
+                                                    PARTY_AREA_WOS))
+                            continue;
+                        if (type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m)    // マップチェック
+                            continue;
+                        if ((type == PARTY_AREA || type == PARTY_AREA_WOS) &&
+                            (sd->bl.x < x0 || sd->bl.y < y0 ||
+                             sd->bl.x > x1 || sd->bl.y > y1))
+                            continue;
+                        if (packet_len_table[RBUFW (buf, 0)])
+                        {       // packet must exist
+                            memcpy (WFIFOP (sd->fd, 0), buf, len);
+                            WFIFOSET (sd->fd, len);
+                        }
+                    }
+                }
+                for (i = 0; i < fd_max; i++)
+                {
+                    if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
+                        && sd->state.auth)
+                    {
+                        if (sd->partyspy == p->party_id)
+                        {
+                            if (packet_len_table[RBUFW (buf, 0)])
+                            {   // packet must exist
+                                memcpy (WFIFOP (sd->fd, 0), buf, len);
+                                WFIFOSET (sd->fd, len);
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        case SELF:
+            sd = (struct map_session_data *) bl;
+            if (packet_len_table[RBUFW (buf, 0)])
+            {                   // packet must exist
+                memcpy (WFIFOP (sd->fd, 0), buf, len);
+                WFIFOSET (sd->fd, len);
+            }
+            break;
+
+/* New definitions for guilds [Valaris]	*/
+
+        case GUILD_AREA:
+        case GUILD_AREA_WOS:
+            x0 = bl->x - AREA_SIZE;
+            y0 = bl->y - AREA_SIZE;
+            x1 = bl->x + AREA_SIZE;
+            y1 = bl->y + AREA_SIZE;
+        case GUILD:
+        case GUILD_WOS:
+            if (bl && bl->type == BL_PC)
+            {                   // guildspy [Syrus22]
+                sd = (struct map_session_data *) bl;
+                if (sd->guildspy > 0)
+                {
+                    g = guild_search (sd->guildspy);
+                }
+                else
+                {
+                    if (sd->status.guild_id > 0)
+                        g = guild_search (sd->status.guild_id);
+                }
+            }
+            if (g)
+            {
+                for (i = 0; i < g->max_member; i++)
+                {
+                    if ((sd = g->member[i].sd) != NULL)
+                    {
+                        if (type == GUILD_WOS && sd->bl.id == bl->id)
+                            continue;
+                        if (packet_len_table[RBUFW (buf, 0)])
+                        {       // packet must exist
+                            memcpy (WFIFOP (sd->fd, 0), buf, len);
+                            WFIFOSET (sd->fd, len);
+                        }
+                    }
+                }
+                for (i = 0; i < fd_max; i++)
+                {
+                    if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
+                        && sd->state.auth)
+                    {
+                        if (sd->guildspy == g->guild_id)
+                        {
+                            if (packet_len_table[RBUFW (buf, 0)])
+                            {   // packet must exist
+                                memcpy (WFIFOP (sd->fd, 0), buf, len);
+                                WFIFOSET (sd->fd, len);
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+        case GUILD_SAMEMAP:
+        case GUILD_SAMEMAP_WOS:
+            if (bl->type == BL_PC)
+            {
+                sd = (struct map_session_data *) bl;
+                if (sd->status.guild_id > 0)
+                    g = guild_search (sd->status.guild_id);
+            }
+            if (g)
+            {
+                for (i = 0; i < g->max_member; i++)
+                {
+                    if ((sd = g->member[i].sd) != NULL)
+                    {
+                        if (sd->bl.id == bl->id && (type == GUILD_WOS ||
+                                                    type == GUILD_SAMEMAP_WOS
+                                                    || type ==
+                                                    GUILD_AREA_WOS))
+                            continue;
+                        if (type != GUILD && type != GUILD_WOS && bl->m != sd->bl.m)    // マップチェック
+                            continue;
+                        if ((type == GUILD_AREA || type == GUILD_AREA_WOS) &&
+                            (sd->bl.x < x0 || sd->bl.y < y0 ||
+                             sd->bl.x > x1 || sd->bl.y > y1))
+                            continue;
+                        if (packet_len_table[RBUFW (buf, 0)])
+                        {       // packet must exist
+                            memcpy (WFIFOP (sd->fd, 0), buf, len);
+                            WFIFOSET (sd->fd, len);
+                        }
+                    }
+                }
+            }
+            break;
+
+        default:
+            if (battle_config.error_log)
+                printf ("clif_send まだ作ってないよー\n");
+            return -1;
+    }
+
+    return 0;
+}
+
+//
+// パケット作って送信
+//
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_authok (struct map_session_data *sd)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    if (!sd)
+        return 0;
+
+    if (!sd->fd)
+        return 0;
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x73;
+    WFIFOL (fd, 2) = gettick ();
+    WFIFOPOS (fd, 6, sd->bl.x, sd->bl.y);
+    WFIFOB (fd, 9) = 5;
+    WFIFOB (fd, 10) = 5;
+    WFIFOSET (fd, packet_len_table[0x73]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_authfail_fd (int fd, int type)
+{
+    if (!fd || !session[fd])
+        return 0;
+
+    WFIFOW (fd, 0) = 0x81;
+    WFIFOL (fd, 2) = type;
+    WFIFOSET (fd, packet_len_table[0x81]);
+
+    clif_setwaitclose (fd);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_charselectok (int id)
+{
+    struct map_session_data *sd;
+    int  fd;
+
+    if ((sd = map_id2sd (id)) == NULL)
+        return 1;
+
+    if (!sd->fd)
+        return 1;
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xb3;
+    WFIFOB (fd, 2) = 1;
+    WFIFOSET (fd, packet_len_table[0xb3]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_set009e (struct flooritem_data *fitem, char *buf)
+{
+    int  view;
+
+    nullpo_retr (0, fitem);
+
+    //009e <ID>.l <name ID>.w <identify flag>.B <X>.w <Y>.w <subX>.B <subY>.B <amount>.w
+    WBUFW (buf, 0) = 0x9e;
+    WBUFL (buf, 2) = fitem->bl.id;
+    if ((view = itemdb_viewid (fitem->item_data.nameid)) > 0)
+        WBUFW (buf, 6) = view;
+    else
+        WBUFW (buf, 6) = fitem->item_data.nameid;
+    WBUFB (buf, 8) = fitem->item_data.identify;
+    WBUFW (buf, 9) = fitem->bl.x;
+    WBUFW (buf, 11) = fitem->bl.y;
+    WBUFB (buf, 13) = fitem->subx;
+    WBUFB (buf, 14) = fitem->suby;
+    WBUFW (buf, 15) = fitem->item_data.amount;
+
+    return packet_len_table[0x9e];
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_dropflooritem (struct flooritem_data *fitem)
+{
+    char buf[64];
+
+    nullpo_retr (0, fitem);
+
+    if (fitem->item_data.nameid <= 0)
+        return 0;
+    clif_set009e (fitem, buf);
+    clif_send (buf, packet_len_table[0x9e], &fitem->bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_clearflooritem (struct flooritem_data *fitem, int fd)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, fitem);
+
+    WBUFW (buf, 0) = 0xa1;
+    WBUFL (buf, 2) = fitem->bl.id;
+
+    if (fd == 0)
+    {
+        clif_send (buf, packet_len_table[0xa1], &fitem->bl, AREA);
+    }
+    else
+    {
+        memcpy (WFIFOP (fd, 0), buf, 6);
+        WFIFOSET (fd, packet_len_table[0xa1]);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_clearchar (struct block_list *bl, int type)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x80;
+    WBUFL (buf, 2) = bl->id;
+    if (type == 9)
+    {
+        WBUFB (buf, 6) = 0;
+        clif_send (buf, packet_len_table[0x80], bl, AREA);
+    }
+    else
+    {
+        WBUFB (buf, 6) = type;
+        clif_send (buf, packet_len_table[0x80], bl,
+                   type == 1 ? AREA : AREA_WOS);
+    }
+
+    return 0;
+}
+
+static void clif_clearchar_delay_sub (timer_id tid, tick_t tick, custom_id_t id,
+                                     custom_data_t data)
+{
+    struct block_list *bl = (struct block_list *) id;
+
+    clif_clearchar (bl, data);
+    map_freeblock (bl);
+}
+
+int clif_clearchar_delay (unsigned int tick, struct block_list *bl, int type)
+{
+    struct block_list *tmpbl;
+    CREATE (tmpbl, struct block_list, 1);
+
+    memcpy (tmpbl, bl, sizeof (struct block_list));
+    add_timer (tick, clif_clearchar_delay_sub, (custom_id_t) tmpbl, type);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_clearchar_id (int id, int type, int fd)
+{
+    unsigned char buf[16];
+
+    WBUFW (buf, 0) = 0x80;
+    WBUFL (buf, 2) = id;
+    WBUFB (buf, 6) = type;
+    memcpy (WFIFOP (fd, 0), buf, 7);
+    WFIFOSET (fd, packet_len_table[0x80]);
+
+    return 0;
+}
+
+/*
+static int current_weapon(struct map_session_data *sd)
+{
+        if (sd->attack_spell_override)
+                return sd->attack_spell_look_override;
+        else {
+                return sd->status.weapon;
+        }
+}
+*/
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_set0078 (struct map_session_data *sd, unsigned char *buf)
+{
+    int  level = 0;
+
+    nullpo_retr (0, sd);
+
+    if (sd->disguise > 23 && sd->disguise < 4001)
+    {                           // mob disguises [Valaris]
+        WBUFW (buf, 0) = 0x78;
+        WBUFL (buf, 2) = sd->bl.id;
+        WBUFW (buf, 6) = battle_get_speed (&sd->bl);
+        WBUFW (buf, 8) = sd->opt1;
+        WBUFW (buf, 10) = sd->opt2;
+        WBUFW (buf, 12) = sd->status.option;
+        WBUFW (buf, 14) = sd->disguise;
+        WBUFW (buf, 42) = 0;
+        WBUFB (buf, 44) = 0;
+        WBUFPOS (buf, 46, sd->bl.x, sd->bl.y);
+        WBUFB (buf, 48) |= sd->dir & 0x0f;
+        WBUFB (buf, 49) = 5;
+        WBUFB (buf, 50) = 5;
+        WBUFB (buf, 51) = 0;
+        WBUFW (buf, 52) =
+            ((level =
+              battle_get_lv (&sd->bl)) >
+             battle_config.max_lv) ? battle_config.max_lv : level;
+
+        return packet_len_table[0x78];
+    }
+
+    WBUFW (buf, 0) = 0x1d8;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFW (buf, 6) = sd->speed;
+    WBUFW (buf, 8) = sd->opt1;
+    WBUFW (buf, 10) = sd->opt2;
+    WBUFW (buf, 12) = sd->status.option;
+    WBUFW (buf, 14) = sd->view_class;
+    WBUFW (buf, 16) = sd->status.hair;
+    if (sd->attack_spell_override)
+        WBUFB (buf, 18) = sd->attack_spell_look_override;
+    else
+    {
+        if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]]
+            && sd->view_class != 22)
+        {
+            if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
+                WBUFW (buf, 18) =
+                    sd->inventory_data[sd->equip_index[9]]->view_id;
+            else
+                WBUFW (buf, 18) =
+                    sd->status.inventory[sd->equip_index[9]].nameid;
+        }
+        else
+            WBUFW (buf, 18) = 0;
+    }
+    if (sd->equip_index[8] >= 0 && sd->equip_index[8] != sd->equip_index[9]
+        && sd->inventory_data[sd->equip_index[8]] && sd->view_class != 22)
+    {
+        if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
+            WBUFW (buf, 20) = sd->inventory_data[sd->equip_index[8]]->view_id;
+        else
+            WBUFW (buf, 20) = sd->status.inventory[sd->equip_index[8]].nameid;
+    }
+    else
+        WBUFW (buf, 20) = 0;
+    WBUFW (buf, 22) = sd->status.head_bottom;
+    WBUFW (buf, 24) = sd->status.head_top;
+    WBUFW (buf, 26) = sd->status.head_mid;
+    WBUFW (buf, 28) = sd->status.hair_color;
+    WBUFW (buf, 30) = sd->status.clothes_color;
+    WBUFW (buf, 32) = sd->head_dir;
+    WBUFL (buf, 34) = sd->status.guild_id;
+    WBUFW (buf, 38) = sd->guild_emblem_id;
+    WBUFW (buf, 40) = sd->status.manner;
+    WBUFW (buf, 42) = sd->opt3;
+    WBUFB (buf, 44) = sd->status.karma;
+    WBUFB (buf, 45) = sd->sex;
+    WBUFPOS (buf, 46, sd->bl.x, sd->bl.y);
+    WBUFB (buf, 48) |= sd->dir & 0x0f;
+    WBUFW (buf, 49) = (pc_isGM (sd) == 60 || pc_isGM (sd) == 99) ? 0x80 : 0;
+    WBUFB (buf, 51) = sd->state.dead_sit;
+    WBUFW (buf, 52) = 0;
+
+    return packet_len_table[0x1d8];
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_set007b (struct map_session_data *sd, unsigned char *buf)
+{
+    int  level = 0;
+    nullpo_retr (0, sd);
+
+    if (sd->disguise > 23 && sd->disguise < 4001)
+    {                           // mob disguises [Valaris]
+        WBUFW (buf, 0) = 0x7b;
+        WBUFL (buf, 2) = sd->bl.id;
+        WBUFW (buf, 6) = battle_get_speed (&sd->bl);
+        WBUFW (buf, 8) = sd->opt1;
+        WBUFW (buf, 10) = sd->opt2;
+        WBUFW (buf, 12) = sd->status.option;
+        WBUFW (buf, 14) = sd->disguise;
+        WBUFL (buf, 22) = gettick ();
+        WBUFW (buf, 46) = 0;
+        WBUFB (buf, 48) = 0;
+        WBUFPOS2 (buf, 50, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
+        WBUFB (buf, 55) = 0;
+        WBUFB (buf, 56) = 5;
+        WBUFB (buf, 57) = 5;
+        WBUFW (buf, 58) =
+            ((level =
+              battle_get_lv (&sd->bl)) >
+             battle_config.max_lv) ? battle_config.max_lv : level;
+
+        return packet_len_table[0x7b];
+    }
+
+    WBUFW (buf, 0) = 0x1da;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFW (buf, 6) = sd->speed;
+    WBUFW (buf, 8) = sd->opt1;
+    WBUFW (buf, 10) = sd->opt2;
+    WBUFW (buf, 12) = sd->status.option;
+    WBUFW (buf, 14) = sd->view_class;
+    WBUFW (buf, 16) = sd->status.hair;
+    if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]]
+        && sd->view_class != 22)
+    {
+        if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
+            WBUFW (buf, 18) = sd->inventory_data[sd->equip_index[9]]->view_id;
+        else
+            WBUFW (buf, 18) = sd->status.inventory[sd->equip_index[9]].nameid;
+    }
+    else
+        WBUFW (buf, 18) = 0;
+    if (sd->equip_index[8] >= 0 && sd->equip_index[8] != sd->equip_index[9]
+        && sd->inventory_data[sd->equip_index[8]] && sd->view_class != 22)
+    {
+        if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
+            WBUFW (buf, 20) = sd->inventory_data[sd->equip_index[8]]->view_id;
+        else
+            WBUFW (buf, 20) = sd->status.inventory[sd->equip_index[8]].nameid;
+    }
+    else
+        WBUFW (buf, 20) = 0;
+    WBUFW (buf, 22) = sd->status.head_bottom;
+    WBUFL (buf, 24) = gettick ();
+    WBUFW (buf, 28) = sd->status.head_top;
+    WBUFW (buf, 30) = sd->status.head_mid;
+    WBUFW (buf, 32) = sd->status.hair_color;
+    WBUFW (buf, 34) = sd->status.clothes_color;
+    WBUFW (buf, 36) = sd->head_dir;
+    WBUFL (buf, 38) = sd->status.guild_id;
+    WBUFW (buf, 42) = sd->guild_emblem_id;
+    WBUFW (buf, 44) = sd->status.manner;
+    WBUFW (buf, 46) = sd->opt3;
+    WBUFB (buf, 48) = sd->status.karma;
+    WBUFB (buf, 49) = sd->sex;
+    WBUFPOS2 (buf, 50, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
+    WBUFW (buf, 55) = pc_isGM (sd) == 60 ? 0x80 : 0;
+    WBUFB (buf, 57) = 5;
+    WBUFW (buf, 58) = 0;
+
+    return packet_len_table[0x1da];
+}
+
+/*==========================================
+ * クラスチェンジ typeはMobの場合は1で他は0?
+ *------------------------------------------
+ */
+int clif_npc_class_change (struct block_list *bl, int npc_class, int type)
+{
+    char buf[16];
+
+    nullpo_retr (0, bl);
+
+    if (npc_class >= MAX_PC_CLASS)
+    {
+        WBUFW (buf, 0) = 0x1b0;
+        WBUFL (buf, 2) = bl->id;
+        WBUFB (buf, 6) = type;
+        WBUFL (buf, 7) = npc_class;
+
+        clif_send (buf, packet_len_table[0x1b0], bl, AREA);
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_mob_class_change (struct mob_data *md, int class_)
+{
+    char buf[16];
+    int  view = mob_get_viewclass (class_);
+
+    nullpo_retr (0, md);
+
+    if (view >= MAX_PC_CLASS)
+    {
+        WBUFW (buf, 0) = 0x1b0;
+        WBUFL (buf, 2) = md->bl.id;
+        WBUFB (buf, 6) = 1;
+        WBUFL (buf, 7) = view;
+
+        clif_send (buf, packet_len_table[0x1b0], &md->bl, AREA);
+    }
+    return 0;
+}
+
+// mob equipment [Valaris]
+
+int clif_mob_equip (struct mob_data *md, int nameid)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, md);
+
+    memset (buf, 0, packet_len_table[0x1a4]);
+
+    WBUFW (buf, 0) = 0x1a4;
+    WBUFB (buf, 2) = 3;
+    WBUFL (buf, 3) = md->bl.id;
+    WBUFL (buf, 7) = nameid;
+
+    clif_send (buf, packet_len_table[0x1a4], &md->bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * MOB表示1
+ *------------------------------------------
+ */
+static int clif_mob0078 (struct mob_data *md, unsigned char *buf)
+{
+    int  level;
+
+    memset (buf, 0, packet_len_table[0x78]);
+
+    nullpo_retr (0, md);
+
+    WBUFW (buf, 0) = 0x78;
+    WBUFL (buf, 2) = md->bl.id;
+    WBUFW (buf, 6) = battle_get_speed (&md->bl);
+    WBUFW (buf, 8) = md->opt1;
+    WBUFW (buf, 10) = md->opt2;
+    WBUFW (buf, 12) = md->option;
+    WBUFW (buf, 14) = mob_get_viewclass (md->mob_class);
+    if ((mob_get_viewclass (md->mob_class) <= 23)
+        || (mob_get_viewclass (md->mob_class) == 812)
+        || (mob_get_viewclass (md->mob_class) >= 4001))
+    {
+        WBUFW (buf, 12) |= mob_db[md->mob_class].option;
+        WBUFW (buf, 16) = mob_get_hair (md->mob_class);
+        WBUFW (buf, 18) = mob_get_weapon (md->mob_class);
+        WBUFW (buf, 20) = mob_get_head_buttom (md->mob_class);
+        WBUFW (buf, 22) = mob_get_shield (md->mob_class);
+        WBUFW (buf, 24) = mob_get_head_top (md->mob_class);
+        WBUFW (buf, 26) = mob_get_head_mid (md->mob_class);
+        WBUFW (buf, 28) = mob_get_hair_color (md->mob_class);
+        WBUFW (buf, 30) = mob_get_clothes_color (md->mob_class);    //Add for player monster dye - Valaris
+        WBUFB (buf, 45) = mob_get_sex (md->mob_class);
+    }
+
+    if (md->mob_class >= 1285 && md->mob_class <= 1287)
+    {                           // Added guardian emblems [Valaris]
+        struct guild *g;
+        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
+        if (gc && gc->guild_id > 0)
+        {
+            g = guild_search (gc->guild_id);
+            if (g)
+            {
+                WBUFL (buf, 26) = gc->guild_id;
+                WBUFL (buf, 22) = g->emblem_id;
+            }
+        }
+    }                           // End addition
+
+    WBUFPOS (buf, 46, md->bl.x, md->bl.y);
+    WBUFB (buf, 48) |= md->dir & 0x0f;
+    WBUFB (buf, 49) = 5;
+    WBUFB (buf, 50) = 5;
+    WBUFW (buf, 52) =
+        ((level =
+          battle_get_lv (&md->bl)) >
+         battle_config.max_lv) ? battle_config.max_lv : level;
+
+    return packet_len_table[0x78];
+}
+
+/*==========================================
+ * MOB表示2
+ *------------------------------------------
+ */
+static int clif_mob007b (struct mob_data *md, unsigned char *buf)
+{
+    int  level;
+
+    memset (buf, 0, packet_len_table[0x7b]);
+
+    nullpo_retr (0, md);
+
+    WBUFW (buf, 0) = 0x7b;
+    WBUFL (buf, 2) = md->bl.id;
+    WBUFW (buf, 6) = battle_get_speed (&md->bl);
+    WBUFW (buf, 8) = md->opt1;
+    WBUFW (buf, 10) = md->opt2;
+    WBUFW (buf, 12) = md->option;
+    WBUFW (buf, 14) = mob_get_viewclass (md->mob_class);
+    if ((mob_get_viewclass (md->mob_class) < 24)
+        || (mob_get_viewclass (md->mob_class) > 4000))
+    {
+        WBUFW (buf, 12) |= mob_db[md->mob_class].option;
+        WBUFW (buf, 16) = mob_get_hair (md->mob_class);
+        WBUFW (buf, 18) = mob_get_weapon (md->mob_class);
+        WBUFW (buf, 20) = mob_get_head_buttom (md->mob_class);
+        WBUFL (buf, 22) = gettick ();
+        WBUFW (buf, 26) = mob_get_shield (md->mob_class);
+        WBUFW (buf, 28) = mob_get_head_top (md->mob_class);
+        WBUFW (buf, 30) = mob_get_head_mid (md->mob_class);
+        WBUFW (buf, 32) = mob_get_hair_color (md->mob_class);
+        WBUFW (buf, 34) = mob_get_clothes_color (md->mob_class);    //Add for player monster dye - Valaris
+        WBUFB (buf, 49) = mob_get_sex (md->mob_class);
+    }
+    else
+        WBUFL (buf, 22) = gettick ();
+
+    if (md->mob_class >= 1285 && md->mob_class <= 1287)
+    {                           // Added guardian emblems [Valaris]
+        struct guild *g;
+        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
+        if (gc && gc->guild_id > 0)
+        {
+            g = guild_search (gc->guild_id);
+            if (g)
+            {
+                WBUFL (buf, 28) = gc->guild_id;
+                WBUFL (buf, 24) = g->emblem_id;
+            }
+        }
+    }                           // End addition
+
+    WBUFPOS2 (buf, 50, md->bl.x, md->bl.y, md->to_x, md->to_y);
+    WBUFB (buf, 56) = 5;
+    WBUFB (buf, 57) = 5;
+    WBUFW (buf, 58) =
+        ((level =
+          battle_get_lv (&md->bl)) >
+         battle_config.max_lv) ? battle_config.max_lv : level;
+
+    return packet_len_table[0x7b];
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_npc0078 (struct npc_data *nd, unsigned char *buf)
+{
+    struct guild *g;
+
+    nullpo_retr (0, nd);
+
+    memset (buf, 0, packet_len_table[0x78]);
+
+    WBUFW (buf, 0) = 0x78;
+    WBUFL (buf, 2) = nd->bl.id;
+    WBUFW (buf, 6) = nd->speed;
+    WBUFW (buf, 14) = nd->npc_class;
+    if ((nd->npc_class == 722) && (nd->u.scr.guild_id > 0)
+        && ((g = guild_search (nd->u.scr.guild_id)) != NULL))
+    {
+        WBUFL (buf, 22) = g->emblem_id;
+        WBUFL (buf, 26) = g->guild_id;
+    }
+    WBUFPOS (buf, 46, nd->bl.x, nd->bl.y);
+    WBUFB (buf, 48) |= nd->dir & 0x0f;
+    WBUFB (buf, 49) = 5;
+    WBUFB (buf, 50) = 5;
+
+    return packet_len_table[0x78];
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_set01e1 (struct map_session_data *sd, unsigned char *buf)
+{
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x1e1;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFW (buf, 6) = sd->spiritball;
+
+    return packet_len_table[0x1e1];
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int clif_set0192 (int fd, int m, int x, int y, int type)
+{
+    WFIFOW (fd, 0) = 0x192;
+    WFIFOW (fd, 2) = x;
+    WFIFOW (fd, 4) = y;
+    WFIFOW (fd, 6) = type;
+    memcpy (WFIFOP (fd, 8), map[m].name, 16);
+    WFIFOSET (fd, packet_len_table[0x192]);
+
+    return 0;
+}
+
+/* These indices are derived from equip_pos in pc.c and some guesswork */
+static int equip_points[LOOK_LAST + 1] = {
+    -1,                         /* 0: base */
+    -1,                         /* 1: hair */
+    9,                          /* 2: weapon */
+    4,                          /* 3: head botom -- leg armour */
+    6,                          /* 4: head top -- hat */
+    5,                          /* 5: head mid -- torso armour */
+    -1,                         /* 6: hair colour */
+    -1,                         /* 6: clothes colour */
+    8,                          /* 6: shield */
+    2,                          /* 9: shoes */
+    3,                          /* gloves */
+    1,                          /* cape */
+    7,                          /* misc1 */
+    0,                          /* misc2 */
+};
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_spawnpc (struct map_session_data *sd)
+{
+    unsigned char buf[128];
+
+    nullpo_retr (0, sd);
+
+    if (sd->disguise > 23 && sd->disguise < 4001)
+    {                           // mob disguises [Valaris]
+        clif_clearchar (&sd->bl, 9);
+
+        memset (buf, 0, packet_len_table[0x119]);
+
+        WBUFW (buf, 0) = 0x119;
+        WBUFL (buf, 2) = sd->bl.id;
+        WBUFW (buf, 6) = 0;
+        WBUFW (buf, 8) = 0;
+        WBUFW (buf, 10) = 0x40;
+        WBUFB (buf, 12) = 0;
+
+        clif_send (buf, packet_len_table[0x119], &sd->bl, SELF);
+
+        memset (buf, 0, packet_len_table[0x7c]);
+
+        WBUFW (buf, 0) = 0x7c;
+        WBUFL (buf, 2) = sd->bl.id;
+        WBUFW (buf, 6) = sd->speed;
+        WBUFW (buf, 8) = sd->opt1;
+        WBUFW (buf, 10) = sd->opt2;
+        WBUFW (buf, 12) = sd->status.option;
+        WBUFW (buf, 20) = sd->disguise;
+        WBUFPOS (buf, 36, sd->bl.x, sd->bl.y);
+        clif_send (buf, packet_len_table[0x7c], &sd->bl, AREA);
+    }
+
+    clif_set0078 (sd, buf);
+
+    WBUFW (buf, 0) = 0x1d9;
+    WBUFW (buf, 51) = 0;
+    clif_send (buf, packet_len_table[0x1d9], &sd->bl, AREA_WOS);
+
+    if (sd->spiritball > 0)
+        clif_spiritball (sd);
+
+    if (sd->status.guild_id > 0)
+    {                           // force display of guild emblem [Valaris]
+        struct guild *g = guild_search (sd->status.guild_id);
+        if (g)
+            clif_guild_emblem (sd, g);
+    }                           // end addition [Valaris]
+
+    if (sd->status.pc_class == 13 || sd->status.pc_class == 21
+        || sd->status.pc_class == 4014 || sd->status.pc_class == 4022)
+        pc_setoption (sd, sd->status.option | 0x0020);  // [Valaris]
+
+    if ((pc_isriding (sd) && pc_checkskill (sd, KN_RIDING) > 0)
+        && (sd->status.pc_class == 7 || sd->status.pc_class == 14
+            || sd->status.pc_class == 4008 || sd->status.pc_class == 4015))
+        pc_setriding (sd);      // update peco riders for people upgrading athena [Valaris]
+
+    if (map[sd->bl.m].flag.snow)
+        clif_specialeffect (&sd->bl, 162, 1);
+    if (map[sd->bl.m].flag.fog)
+        clif_specialeffect (&sd->bl, 233, 1);
+    if (map[sd->bl.m].flag.sakura)
+        clif_specialeffect (&sd->bl, 163, 1);
+    if (map[sd->bl.m].flag.leaves)
+        clif_specialeffect (&sd->bl, 333, 1);
+    if (map[sd->bl.m].flag.rain)
+        clif_specialeffect (&sd->bl, 161, 1);
+
+//        clif_changelook_accessories(&sd->bl, NULL);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_spawnnpc (struct npc_data *nd)
+{
+    unsigned char buf[64];
+    int  len;
+
+    nullpo_retr (0, nd);
+
+    if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS)
+        return 0;
+
+    memset (buf, 0, packet_len_table[0x7c]);
+
+    WBUFW (buf, 0) = 0x7c;
+    WBUFL (buf, 2) = nd->bl.id;
+    WBUFW (buf, 6) = nd->speed;
+    WBUFW (buf, 20) = nd->npc_class;
+    WBUFPOS (buf, 36, nd->bl.x, nd->bl.y);
+
+    clif_send (buf, packet_len_table[0x7c], &nd->bl, AREA);
+
+    len = clif_npc0078 (nd, buf);
+    clif_send (buf, len, &nd->bl, AREA);
+
+    return 0;
+}
+
+int
+clif_spawn_fake_npc_for_player (struct map_session_data *sd, int fake_npc_id)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    if (!fd)
+        return 0;
+
+    WFIFOW (fd, 0) = 0x7c;
+    WFIFOL (fd, 2) = fake_npc_id;
+    WFIFOW (fd, 6) = 0;
+    WFIFOW (fd, 8) = 0;
+    WFIFOW (fd, 10) = 0;
+    WFIFOW (fd, 12) = 0;
+    WFIFOW (fd, 20) = 127;
+    WFIFOPOS (fd, 36, sd->bl.x, sd->bl.y);
+    WFIFOSET (fd, packet_len_table[0x7c]);
+
+    WFIFOW (fd, 0) = 0x78;
+    WFIFOL (fd, 2) = fake_npc_id;
+    WFIFOW (fd, 6) = 0;
+    WFIFOW (fd, 8) = 0;
+    WFIFOW (fd, 10) = 0;
+    WFIFOW (fd, 12) = 0;
+    WFIFOW (fd, 14) = 127;      // identifies as NPC
+    WFIFOW (fd, 20) = 127;
+    WFIFOPOS (fd, 46, sd->bl.x, sd->bl.y);
+    WFIFOPOS (fd, 36, sd->bl.x, sd->bl.y);
+    WFIFOB (fd, 49) = 5;
+    WFIFOB (fd, 50) = 5;
+    WFIFOSET (fd, packet_len_table[0x78]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_spawnmob (struct mob_data *md)
+{
+    unsigned char buf[64];
+    int  len;
+
+    nullpo_retr (0, md);
+
+    if (mob_get_viewclass (md->mob_class) > 23)
+    {
+        memset (buf, 0, packet_len_table[0x7c]);
+
+        WBUFW (buf, 0) = 0x7c;
+        WBUFL (buf, 2) = md->bl.id;
+        WBUFW (buf, 6) = md->stats[MOB_SPEED];
+        WBUFW (buf, 8) = md->opt1;
+        WBUFW (buf, 10) = md->opt2;
+        WBUFW (buf, 12) = md->option;
+        WBUFW (buf, 20) = mob_get_viewclass (md->mob_class);
+        WBUFPOS (buf, 36, md->bl.x, md->bl.y);
+        clif_send (buf, packet_len_table[0x7c], &md->bl, AREA);
+    }
+
+    len = clif_mob0078 (md, buf);
+    clif_send (buf, len, &md->bl, AREA);
+
+    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
+        clif_mob_equip (md, mob_get_equip (md->mob_class));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_servertick (struct map_session_data *sd)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x7f;
+    WFIFOL (fd, 2) = sd->server_tick;
+    WFIFOSET (fd, packet_len_table[0x7f]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_walkok (struct map_session_data *sd)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x87;
+    WFIFOL (fd, 2) = gettick ();;
+    WFIFOPOS2 (fd, 6, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y);
+    WFIFOB (fd, 11) = 0;
+    WFIFOSET (fd, packet_len_table[0x87]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_movechar (struct map_session_data *sd)
+{
+    int  fd;
+    int  len;
+    unsigned char buf[256];
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    len = clif_set007b (sd, buf);
+
+    if (sd->disguise > 23 && sd->disguise < 4001)
+    {
+        clif_send (buf, len, &sd->bl, AREA);
+        return 0;
+    }
+    else
+        clif_send (buf, len, &sd->bl, AREA_WOS);
+
+    if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0)
+        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
+                         sd->status.clothes_color);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_quitsave (int fd, struct map_session_data *sd)
+{
+    map_quit (sd);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static void clif_waitclose (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    if (session[id])
+        session[id]->eof = 1;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_setwaitclose (int fd)
+{
+    add_timer (gettick () + 5000, clif_waitclose, fd, 0);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_changemap (struct map_session_data *sd, char *mapname, int x, int y)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x91;
+    memcpy (WFIFOP (fd, 2), mapname, 16);
+    WFIFOW (fd, 18) = x;
+    WFIFOW (fd, 20) = y;
+    WFIFOSET (fd, packet_len_table[0x91]);
+
+    if (sd->disguise > 23 && sd->disguise < 4001)   // mob disguises [Valaris]
+        clif_spawnpc (sd);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_changemapserver (struct map_session_data *sd, char *mapname, int x,
+                          int y, int ip, int port)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x92;
+    memcpy (WFIFOP (fd, 2), mapname, 16);
+    WFIFOW (fd, 18) = x;
+    WFIFOW (fd, 20) = y;
+    WFIFOL (fd, 22) = ip;
+    WFIFOW (fd, 26) = port;
+    WFIFOSET (fd, packet_len_table[0x92]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_fixpos (struct block_list *bl)
+{
+    char buf[16];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x88;
+    WBUFL (buf, 2) = bl->id;
+    WBUFW (buf, 6) = bl->x;
+    WBUFW (buf, 8) = bl->y;
+
+    clif_send (buf, packet_len_table[0x88], bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_npcbuysell (struct map_session_data *sd, int id)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xc4;
+    WFIFOL (fd, 2) = id;
+    WFIFOSET (fd, packet_len_table[0xc4]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_buylist (struct map_session_data *sd, struct npc_data *nd)
+{
+    struct item_data *id;
+    int  fd, i, val;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, nd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xc6;
+    for (i = 0; nd->u.shop_item[i].nameid > 0; i++)
+    {
+        id = itemdb_search (nd->u.shop_item[i].nameid);
+        val = nd->u.shop_item[i].value;
+        WFIFOL (fd, 4 + i * 11) = val;
+        if (!id->flag.value_notdc)
+            val = pc_modifybuyvalue (sd, val);
+        WFIFOL (fd, 8 + i * 11) = val;
+        WFIFOB (fd, 12 + i * 11) = id->type;
+        if (id->view_id > 0)
+            WFIFOW (fd, 13 + i * 11) = id->view_id;
+        else
+            WFIFOW (fd, 13 + i * 11) = nd->u.shop_item[i].nameid;
+    }
+    WFIFOW (fd, 2) = i * 11 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_selllist (struct map_session_data *sd)
+{
+    int  fd, i, c = 0, val;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xc7;
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i])
+        {
+            val = sd->inventory_data[i]->value_sell;
+            if (val < 0)
+                continue;
+            WFIFOW (fd, 4 + c * 10) = i + 2;
+            WFIFOL (fd, 6 + c * 10) = val;
+            if (!sd->inventory_data[i]->flag.value_notoc)
+                val = pc_modifysellvalue (sd, val);
+            WFIFOL (fd, 10 + c * 10) = val;
+            c++;
+        }
+    }
+    WFIFOW (fd, 2) = c * 10 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptmes (struct map_session_data *sd, int npcid, char *mes)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xb4;
+    WFIFOW (fd, 2) = strlen (mes) + 9;
+    WFIFOL (fd, 4) = npcid;
+    strcpy (WFIFOP (fd, 8), mes);
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptnext (struct map_session_data *sd, int npcid)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xb5;
+    WFIFOL (fd, 2) = npcid;
+    WFIFOSET (fd, packet_len_table[0xb5]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptclose (struct map_session_data *sd, int npcid)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xb6;
+    WFIFOL (fd, 2) = npcid;
+    WFIFOSET (fd, packet_len_table[0xb6]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptmenu (struct map_session_data *sd, int npcid, char *mes)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xb7;
+    WFIFOW (fd, 2) = strlen (mes) + 8;
+    WFIFOL (fd, 4) = npcid;
+    strcpy (WFIFOP (fd, 8), mes);
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptinput (struct map_session_data *sd, int npcid)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x142;
+    WFIFOL (fd, 2) = npcid;
+    WFIFOSET (fd, packet_len_table[0x142]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_scriptinputstr (struct map_session_data *sd, int npcid)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1d4;
+    WFIFOL (fd, 2) = npcid;
+    WFIFOSET (fd, packet_len_table[0x1d4]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_viewpoint (struct map_session_data *sd, int npc_id, int type, int x,
+                    int y, int id, int color)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x144;
+    WFIFOL (fd, 2) = npc_id;
+    WFIFOL (fd, 6) = type;
+    WFIFOL (fd, 10) = x;
+    WFIFOL (fd, 14) = y;
+    WFIFOB (fd, 18) = id;
+    WFIFOL (fd, 19) = color;
+    WFIFOSET (fd, packet_len_table[0x144]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_cutin (struct map_session_data *sd, char *image, int type)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1b3;
+    memcpy (WFIFOP (fd, 2), image, 64);
+    WFIFOB (fd, 66) = type;
+    WFIFOSET (fd, packet_len_table[0x1b3]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_additem (struct map_session_data *sd, int n, int amount, int fail)
+{
+    int  fd, j;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    if (fail)
+    {
+        WBUFW (buf, 0) = 0xa0;
+        WBUFW (buf, 2) = n + 2;
+        WBUFW (buf, 4) = amount;
+        WBUFW (buf, 6) = 0;
+        WBUFB (buf, 8) = 0;
+        WBUFB (buf, 9) = 0;
+        WBUFB (buf, 10) = 0;
+        WBUFW (buf, 11) = 0;
+        WBUFW (buf, 13) = 0;
+        WBUFW (buf, 15) = 0;
+        WBUFW (buf, 17) = 0;
+        WBUFW (buf, 19) = 0;
+        WBUFB (buf, 21) = 0;
+        WBUFB (buf, 22) = fail;
+    }
+    else
+    {
+        if (n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <= 0
+            || sd->inventory_data[n] == NULL)
+            return 1;
+
+        WBUFW (buf, 0) = 0xa0;
+        WBUFW (buf, 2) = n + 2;
+        WBUFW (buf, 4) = amount;
+        if (sd->inventory_data[n]->view_id > 0)
+            WBUFW (buf, 6) = sd->inventory_data[n]->view_id;
+        else
+            WBUFW (buf, 6) = sd->status.inventory[n].nameid;
+        WBUFB (buf, 8) = sd->status.inventory[n].identify;
+        if (sd->status.inventory[n].broken == 1)
+            WBUFB (buf, 9) = 1; // is weapon broken [Valaris]
+        else
+            WBUFB (buf, 9) = sd->status.inventory[n].attribute;
+        WBUFB (buf, 10) = sd->status.inventory[n].refine;
+        if (sd->status.inventory[n].card[0] == 0x00ff
+            || sd->status.inventory[n].card[0] == 0x00fe
+            || sd->status.inventory[n].card[0] == (short) 0xff00)
+        {
+            WBUFW (buf, 11) = sd->status.inventory[n].card[0];
+            WBUFW (buf, 13) = sd->status.inventory[n].card[1];
+            WBUFW (buf, 15) = sd->status.inventory[n].card[2];
+            WBUFW (buf, 17) = sd->status.inventory[n].card[3];
+        }
+        else
+        {
+            if (sd->status.inventory[n].card[0] > 0
+                && (j = itemdb_viewid (sd->status.inventory[n].card[0])) > 0)
+                WBUFW (buf, 11) = j;
+            else
+                WBUFW (buf, 11) = sd->status.inventory[n].card[0];
+            if (sd->status.inventory[n].card[1] > 0
+                && (j = itemdb_viewid (sd->status.inventory[n].card[1])) > 0)
+                WBUFW (buf, 13) = j;
+            else
+                WBUFW (buf, 13) = sd->status.inventory[n].card[1];
+            if (sd->status.inventory[n].card[2] > 0
+                && (j = itemdb_viewid (sd->status.inventory[n].card[2])) > 0)
+                WBUFW (buf, 15) = j;
+            else
+                WBUFW (buf, 15) = sd->status.inventory[n].card[2];
+            if (sd->status.inventory[n].card[3] > 0
+                && (j = itemdb_viewid (sd->status.inventory[n].card[3])) > 0)
+                WBUFW (buf, 17) = j;
+            else
+                WBUFW (buf, 17) = sd->status.inventory[n].card[3];
+        }
+        WBUFW (buf, 19) = pc_equippoint (sd, n);
+        WBUFB (buf, 21) =
+            (sd->inventory_data[n]->type ==
+             7) ? 4 : sd->inventory_data[n]->type;
+        WBUFB (buf, 22) = fail;
+    }
+
+    WFIFOSET (fd, packet_len_table[0xa0]);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_delitem (struct map_session_data *sd, int n, int amount)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xaf;
+    WFIFOW (fd, 2) = n + 2;
+    WFIFOW (fd, 4) = amount;
+
+    WFIFOSET (fd, packet_len_table[0xaf]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_itemlist (struct map_session_data *sd)
+{
+    int  i, n, fd, arrow = -1;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    WBUFW (buf, 0) = 0x1ee;
+    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid <= 0
+            || sd->inventory_data[i] == NULL
+            || itemdb_isequip2 (sd->inventory_data[i]))
+            continue;
+        WBUFW (buf, n * 18 + 4) = i + 2;
+        if (sd->inventory_data[i]->view_id > 0)
+            WBUFW (buf, n * 18 + 6) = sd->inventory_data[i]->view_id;
+        else
+            WBUFW (buf, n * 18 + 6) = sd->status.inventory[i].nameid;
+        WBUFB (buf, n * 18 + 8) = sd->inventory_data[i]->type;
+        WBUFB (buf, n * 18 + 9) = sd->status.inventory[i].identify;
+        WBUFW (buf, n * 18 + 10) = sd->status.inventory[i].amount;
+        if (sd->inventory_data[i]->equip == 0x8000)
+        {
+            WBUFW (buf, n * 18 + 12) = 0x8000;
+            if (sd->status.inventory[i].equip)
+                arrow = i;      // ついでに矢装備チェック
+        }
+        else
+            WBUFW (buf, n * 18 + 12) = 0;
+        WBUFW (buf, n * 18 + 14) = sd->status.inventory[i].card[0];
+        WBUFW (buf, n * 18 + 16) = sd->status.inventory[i].card[1];
+        WBUFW (buf, n * 18 + 18) = sd->status.inventory[i].card[2];
+        WBUFW (buf, n * 18 + 20) = sd->status.inventory[i].card[3];
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 18;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    if (arrow >= 0)
+        clif_arrowequip (sd, arrow);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_equiplist (struct map_session_data *sd)
+{
+    int  i, j, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    WBUFW (buf, 0) = 0xa4;
+    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid <= 0
+            || sd->inventory_data[i] == NULL
+            || !itemdb_isequip2 (sd->inventory_data[i]))
+            continue;
+        WBUFW (buf, n * 20 + 4) = i + 2;
+        if (sd->inventory_data[i]->view_id > 0)
+            WBUFW (buf, n * 20 + 6) = sd->inventory_data[i]->view_id;
+        else
+            WBUFW (buf, n * 20 + 6) = sd->status.inventory[i].nameid;
+        WBUFB (buf, n * 20 + 8) =
+            (sd->inventory_data[i]->type ==
+             7) ? 4 : sd->inventory_data[i]->type;
+        WBUFB (buf, n * 20 + 9) = sd->status.inventory[i].identify;
+        WBUFW (buf, n * 20 + 10) = pc_equippoint (sd, i);
+        WBUFW (buf, n * 20 + 12) = sd->status.inventory[i].equip;
+        if (sd->status.inventory[i].broken == 1)
+            WBUFB (buf, n * 20 + 14) = 1;   // is weapon broken [Valaris]
+        else
+            WBUFB (buf, n * 20 + 14) = sd->status.inventory[i].attribute;
+        WBUFB (buf, n * 20 + 15) = sd->status.inventory[i].refine;
+        if (sd->status.inventory[i].card[0] == 0x00ff
+            || sd->status.inventory[i].card[0] == 0x00fe
+            || sd->status.inventory[i].card[0] == (short) 0xff00)
+        {
+            WBUFW (buf, n * 20 + 16) = sd->status.inventory[i].card[0];
+            WBUFW (buf, n * 20 + 18) = sd->status.inventory[i].card[1];
+            WBUFW (buf, n * 20 + 20) = sd->status.inventory[i].card[2];
+            WBUFW (buf, n * 20 + 22) = sd->status.inventory[i].card[3];
+        }
+        else
+        {
+            if (sd->status.inventory[i].card[0] > 0
+                && (j = itemdb_viewid (sd->status.inventory[i].card[0])) > 0)
+                WBUFW (buf, n * 20 + 16) = j;
+            else
+                WBUFW (buf, n * 20 + 16) = sd->status.inventory[i].card[0];
+            if (sd->status.inventory[i].card[1] > 0
+                && (j = itemdb_viewid (sd->status.inventory[i].card[1])) > 0)
+                WBUFW (buf, n * 20 + 18) = j;
+            else
+                WBUFW (buf, n * 20 + 18) = sd->status.inventory[i].card[1];
+            if (sd->status.inventory[i].card[2] > 0
+                && (j = itemdb_viewid (sd->status.inventory[i].card[2])) > 0)
+                WBUFW (buf, n * 20 + 20) = j;
+            else
+                WBUFW (buf, n * 20 + 20) = sd->status.inventory[i].card[2];
+            if (sd->status.inventory[i].card[3] > 0
+                && (j = itemdb_viewid (sd->status.inventory[i].card[3])) > 0)
+                WBUFW (buf, n * 20 + 22) = j;
+            else
+                WBUFW (buf, n * 20 + 22) = sd->status.inventory[i].card[3];
+        }
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 20;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * カプラさんに預けてある消耗品&収集品リスト
+ *------------------------------------------
+ */
+int clif_storageitemlist (struct map_session_data *sd, struct storage *stor)
+{
+    struct item_data *id;
+    int  i, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    WBUFW (buf, 0) = 0x1f0;
+    for (i = 0, n = 0; i < MAX_STORAGE; i++)
+    {
+        if (stor->storage_[i].nameid <= 0)
+            continue;
+        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
+        if (itemdb_isequip2 (id))
+            continue;
+
+        WBUFW (buf, n * 18 + 4) = i + 1;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 18 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 18 + 6) = stor->storage_[i].nameid;
+        WBUFB (buf, n * 18 + 8) = id->type;;
+        WBUFB (buf, n * 18 + 9) = stor->storage_[i].identify;
+        WBUFW (buf, n * 18 + 10) = stor->storage_[i].amount;
+        WBUFW (buf, n * 18 + 12) = 0;
+        WBUFW (buf, n * 18 + 14) = stor->storage_[i].card[0];
+        WBUFW (buf, n * 18 + 16) = stor->storage_[i].card[1];
+        WBUFW (buf, n * 18 + 18) = stor->storage_[i].card[2];
+        WBUFW (buf, n * 18 + 20) = stor->storage_[i].card[3];
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 18;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * カプラさんに預けてある装備リスト
+ *------------------------------------------
+ */
+int clif_storageequiplist (struct map_session_data *sd, struct storage *stor)
+{
+    struct item_data *id;
+    int  i, j, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    WBUFW (buf, 0) = 0xa6;
+    for (i = 0, n = 0; i < MAX_STORAGE; i++)
+    {
+        if (stor->storage_[i].nameid <= 0)
+            continue;
+        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
+        if (!itemdb_isequip2 (id))
+            continue;
+        WBUFW (buf, n * 20 + 4) = i + 1;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 20 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 20 + 6) = stor->storage_[i].nameid;
+        WBUFB (buf, n * 20 + 8) = id->type;
+        WBUFB (buf, n * 20 + 9) = stor->storage_[i].identify;
+        WBUFW (buf, n * 20 + 10) = id->equip;
+        WBUFW (buf, n * 20 + 12) = stor->storage_[i].equip;
+        if (stor->storage_[i].broken == 1)
+            WBUFB (buf, n * 20 + 14) = 1;   //is weapon broken [Valaris]
+        else
+            WBUFB (buf, n * 20 + 14) = stor->storage_[i].attribute;
+        WBUFB (buf, n * 20 + 15) = stor->storage_[i].refine;
+        if (stor->storage_[i].card[0] == 0x00ff
+            || stor->storage_[i].card[0] == 0x00fe
+            || stor->storage_[i].card[0] == (short) 0xff00)
+        {
+            WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
+            WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
+            WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
+            WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
+        }
+        else
+        {
+            if (stor->storage_[i].card[0] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[0])) > 0)
+                WBUFW (buf, n * 20 + 16) = j;
+            else
+                WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
+            if (stor->storage_[i].card[1] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[1])) > 0)
+                WBUFW (buf, n * 20 + 18) = j;
+            else
+                WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
+            if (stor->storage_[i].card[2] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[2])) > 0)
+                WBUFW (buf, n * 20 + 20) = j;
+            else
+                WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
+            if (stor->storage_[i].card[3] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[3])) > 0)
+                WBUFW (buf, n * 20 + 22) = j;
+            else
+                WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
+        }
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 20;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_guildstorageitemlist (struct map_session_data *sd,
+                               struct guild_storage *stor)
+{
+    struct item_data *id;
+    int  i, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+
+    WBUFW (buf, 0) = 0x1f0;
+    for (i = 0, n = 0; i < MAX_GUILD_STORAGE; i++)
+    {
+        if (stor->storage_[i].nameid <= 0)
+            continue;
+        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
+        if (itemdb_isequip2 (id))
+            continue;
+
+        WBUFW (buf, n * 18 + 4) = i + 1;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 18 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 18 + 6) = stor->storage_[i].nameid;
+        WBUFB (buf, n * 18 + 8) = id->type;;
+        WBUFB (buf, n * 18 + 9) = stor->storage_[i].identify;
+        WBUFW (buf, n * 18 + 10) = stor->storage_[i].amount;
+        WBUFW (buf, n * 18 + 12) = 0;
+        WBUFW (buf, n * 18 + 14) = stor->storage_[i].card[0];
+        WBUFW (buf, n * 18 + 16) = stor->storage_[i].card[1];
+        WBUFW (buf, n * 18 + 18) = stor->storage_[i].card[2];
+        WBUFW (buf, n * 18 + 20) = stor->storage_[i].card[3];
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 18;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_guildstorageequiplist (struct map_session_data *sd,
+                                struct guild_storage *stor)
+{
+    struct item_data *id;
+    int  i, j, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+
+    WBUFW (buf, 0) = 0xa6;
+    for (i = 0, n = 0; i < MAX_GUILD_STORAGE; i++)
+    {
+        if (stor->storage_[i].nameid <= 0)
+            continue;
+        nullpo_retr (0, id = itemdb_search (stor->storage_[i].nameid));
+        if (!itemdb_isequip2 (id))
+            continue;
+        WBUFW (buf, n * 20 + 4) = i + 1;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 20 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 20 + 6) = stor->storage_[i].nameid;
+        WBUFB (buf, n * 20 + 8) = id->type;
+        WBUFB (buf, n * 20 + 9) = stor->storage_[i].identify;
+        WBUFW (buf, n * 20 + 10) = id->equip;
+        WBUFW (buf, n * 20 + 12) = stor->storage_[i].equip;
+        if (stor->storage_[i].broken == 1)
+            WBUFB (buf, n * 20 + 14) = 1;   // is weapon broken [Valaris]
+        else
+            WBUFB (buf, n * 20 + 14) = stor->storage_[i].attribute;
+        WBUFB (buf, n * 20 + 15) = stor->storage_[i].refine;
+        if (stor->storage_[i].card[0] == 0x00ff
+            || stor->storage_[i].card[0] == 0x00fe
+            || stor->storage_[i].card[0] == (short) 0xff00)
+        {
+            WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
+            WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
+            WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
+            WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
+        }
+        else
+        {
+            if (stor->storage_[i].card[0] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[0])) > 0)
+                WBUFW (buf, n * 20 + 16) = j;
+            else
+                WBUFW (buf, n * 20 + 16) = stor->storage_[i].card[0];
+            if (stor->storage_[i].card[1] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[1])) > 0)
+                WBUFW (buf, n * 20 + 18) = j;
+            else
+                WBUFW (buf, n * 20 + 18) = stor->storage_[i].card[1];
+            if (stor->storage_[i].card[2] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[2])) > 0)
+                WBUFW (buf, n * 20 + 20) = j;
+            else
+                WBUFW (buf, n * 20 + 20) = stor->storage_[i].card[2];
+            if (stor->storage_[i].card[3] > 0
+                && (j = itemdb_viewid (stor->storage_[i].card[3])) > 0)
+                WBUFW (buf, n * 20 + 22) = j;
+            else
+                WBUFW (buf, n * 20 + 22) = stor->storage_[i].card[3];
+        }
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 20;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * ステータスを送りつける
+ * 表示専用数字はこの中で計算して送る
+ *------------------------------------------
+ */
+int clif_updatestatus (struct map_session_data *sd, int type)
+{
+    int  fd, len = 8;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0xb0;
+    WFIFOW (fd, 2) = type;
+    switch (type)
+    {
+            // 00b0
+        case SP_WEIGHT:
+            pc_checkweighticon (sd);
+            WFIFOW (fd, 0) = 0xb0;
+            WFIFOW (fd, 2) = type;
+            WFIFOL (fd, 4) = sd->weight;
+            break;
+        case SP_MAXWEIGHT:
+            WFIFOL (fd, 4) = sd->max_weight;
+            break;
+        case SP_SPEED:
+            WFIFOL (fd, 4) = sd->speed;
+            break;
+        case SP_BASELEVEL:
+            WFIFOL (fd, 4) = sd->status.base_level;
+            break;
+        case SP_JOBLEVEL:
+            WFIFOL (fd, 4) = 0;
+            break;
+        case SP_MANNER:
+            WFIFOL (fd, 4) = sd->status.manner;
+            clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
+            break;
+        case SP_STATUSPOINT:
+            WFIFOL (fd, 4) = sd->status.status_point;
+            break;
+        case SP_SKILLPOINT:
+            WFIFOL (fd, 4) = sd->status.skill_point;
+            break;
+        case SP_HIT:
+            WFIFOL (fd, 4) = sd->hit;
+            break;
+        case SP_FLEE1:
+            WFIFOL (fd, 4) = sd->flee;
+            break;
+        case SP_FLEE2:
+            WFIFOL (fd, 4) = sd->flee2 / 10;
+            break;
+        case SP_MAXHP:
+            WFIFOL (fd, 4) = sd->status.max_hp;
+            break;
+        case SP_MAXSP:
+            WFIFOL (fd, 4) = sd->status.max_sp;
+            break;
+        case SP_HP:
+            WFIFOL (fd, 4) = sd->status.hp;
+            break;
+        case SP_SP:
+            WFIFOL (fd, 4) = sd->status.sp;
+            break;
+        case SP_ASPD:
+            WFIFOL (fd, 4) = sd->aspd;
+            break;
+        case SP_ATK1:
+            WFIFOL (fd, 4) = sd->base_atk + sd->watk;
+            break;
+        case SP_DEF1:
+            WFIFOL (fd, 4) = sd->def;
+            break;
+        case SP_MDEF1:
+            WFIFOL (fd, 4) = sd->mdef;
+            break;
+        case SP_ATK2:
+            WFIFOL (fd, 4) = sd->watk2;
+            break;
+        case SP_DEF2:
+            WFIFOL (fd, 4) = sd->def2;
+            break;
+        case SP_MDEF2:
+            WFIFOL (fd, 4) = sd->mdef2;
+            break;
+        case SP_CRITICAL:
+            WFIFOL (fd, 4) = sd->critical / 10;
+            break;
+        case SP_MATK1:
+            WFIFOL (fd, 4) = sd->matk1;
+            break;
+        case SP_MATK2:
+            WFIFOL (fd, 4) = sd->matk2;
+            break;
+
+        case SP_ZENY:
+            trade_verifyzeny (sd);
+            WFIFOW (fd, 0) = 0xb1;
+            if (sd->status.zeny < 0)
+                sd->status.zeny = 0;
+            WFIFOL (fd, 4) = sd->status.zeny;
+            break;
+        case SP_BASEEXP:
+            WFIFOW (fd, 0) = 0xb1;
+            WFIFOL (fd, 4) = sd->status.base_exp;
+            break;
+        case SP_JOBEXP:
+            WFIFOW (fd, 0) = 0xb1;
+            WFIFOL (fd, 4) = sd->status.job_exp;
+            break;
+        case SP_NEXTBASEEXP:
+            WFIFOW (fd, 0) = 0xb1;
+            WFIFOL (fd, 4) = pc_nextbaseexp (sd);
+            break;
+        case SP_NEXTJOBEXP:
+            WFIFOW (fd, 0) = 0xb1;
+            WFIFOL (fd, 4) = pc_nextjobexp (sd);
+            break;
+
+            // 00be 終了
+        case SP_USTR:
+        case SP_UAGI:
+        case SP_UVIT:
+        case SP_UINT:
+        case SP_UDEX:
+        case SP_ULUK:
+            WFIFOW (fd, 0) = 0xbe;
+            WFIFOB (fd, 4) =
+                pc_need_status_point (sd, type - SP_USTR + SP_STR);
+            len = 5;
+            break;
+
+            // 013a 終了
+        case SP_ATTACKRANGE:
+            WFIFOW (fd, 0) = 0x13a;
+            WFIFOW (fd, 2) = (sd->attack_spell_override)
+                ? sd->attack_spell_range : sd->attackrange;
+            len = 4;
+            break;
+
+            // 0141 終了
+        case SP_STR:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.str;
+            WFIFOL (fd, 10) = sd->paramb[0] + sd->parame[0];
+            len = 14;
+            break;
+        case SP_AGI:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.agi;
+            WFIFOL (fd, 10) = sd->paramb[1] + sd->parame[1];
+            len = 14;
+            break;
+        case SP_VIT:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.vit;
+            WFIFOL (fd, 10) = sd->paramb[2] + sd->parame[2];
+            len = 14;
+            break;
+        case SP_INT:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.int_;
+            WFIFOL (fd, 10) = sd->paramb[3] + sd->parame[3];
+            len = 14;
+            break;
+        case SP_DEX:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.dex;
+            WFIFOL (fd, 10) = sd->paramb[4] + sd->parame[4];
+            len = 14;
+            break;
+        case SP_LUK:
+            WFIFOW (fd, 0) = 0x141;
+            WFIFOL (fd, 2) = type;
+            WFIFOL (fd, 6) = sd->status.luk;
+            WFIFOL (fd, 10) = sd->paramb[5] + sd->parame[5];
+            len = 14;
+            break;
+
+        case SP_CARTINFO:
+            WFIFOW (fd, 0) = 0x121;
+            WFIFOW (fd, 2) = sd->cart_num;
+            WFIFOW (fd, 4) = sd->cart_max_num;
+            WFIFOL (fd, 6) = sd->cart_weight;
+            WFIFOL (fd, 10) = sd->cart_max_weight;
+            len = 14;
+            break;
+
+        case SP_GM:
+            WFIFOL (fd, 4) = pc_isGM (sd);
+            break;
+
+        default:
+            if (battle_config.error_log)
+                printf ("clif_updatestatus : make %d routine\n", type);
+            return 1;
+    }
+    WFIFOSET (fd, len);
+
+    return 0;
+}
+
+int clif_changestatus (struct block_list *bl, int type, int val)
+{
+    unsigned char buf[12];
+    struct map_session_data *sd = NULL;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+        sd = (struct map_session_data *) bl;
+
+//printf("clif_changestatus id:%d type:%d val:%d\n",bl->id,type,val);
+    if (sd)
+    {
+        WBUFW (buf, 0) = 0x1ab;
+        WBUFL (buf, 2) = bl->id;
+        WBUFW (buf, 6) = type;
+        switch (type)
+        {
+            case SP_MANNER:
+                WBUFL (buf, 8) = val;
+                break;
+            default:
+                if (battle_config.error_log)
+                    printf ("clif_changestatus : make %d routine\n", type);
+                return 1;
+        }
+        clif_send (buf, packet_len_table[0x1ab], bl, AREA_WOS);
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_changelook (struct block_list *bl, int type, int val)
+{
+    return clif_changelook_towards (bl, type, val, NULL);
+}
+
+int clif_changelook_towards (struct block_list *bl, int type, int val,
+                             struct map_session_data *dstsd)
+{
+    unsigned char rbuf[32];
+    unsigned char *buf = dstsd ? WFIFOP (dstsd->fd, 0) : rbuf;  // pick target buffer or general-purpose one
+    struct map_session_data *sd = NULL;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+        sd = (struct map_session_data *) bl;
+
+    if (sd && sd->disguise > 23 && sd->disguise < 4001) // mob disguises [Valaris]
+        return 0;
+
+    if (sd && sd->status.option & OPTION_INVISIBILITY)
+        return 0;
+
+    if (sd
+        && (type == LOOK_WEAPON || type == LOOK_SHIELD || type >= LOOK_SHOES))
+    {
+        WBUFW (buf, 0) = 0x1d7;
+        WBUFL (buf, 2) = bl->id;
+        if (type >= LOOK_SHOES)
+        {
+            int  equip_point = equip_points[type];
+
+            WBUFB (buf, 6) = type;
+            if (sd->equip_index[equip_point] >= 0
+                && sd->inventory_data[sd->equip_index[equip_point]])
+            {
+                if (sd->
+                    inventory_data[sd->equip_index[equip_point]]->view_id > 0)
+                    WBUFW (buf, 7) =
+                        sd->inventory_data[sd->
+                                           equip_index[equip_point]]->view_id;
+                else
+                    WBUFW (buf, 7) =
+                        sd->status.inventory[sd->
+                                             equip_index[equip_point]].nameid;
+            }
+            else
+                WBUFW (buf, 7) = 0;
+            WBUFW (buf, 9) = 0;
+        }
+        else
+        {
+            WBUFB (buf, 6) = 2;
+            if (sd->attack_spell_override)
+                WBUFW (buf, 7) = sd->attack_spell_look_override;
+            else
+            {
+                if (sd->equip_index[9] >= 0
+                    && sd->inventory_data[sd->equip_index[9]]
+                    && sd->view_class != 22)
+                {
+                    if (sd->inventory_data[sd->equip_index[9]]->view_id > 0)
+                        WBUFW (buf, 7) =
+                            sd->inventory_data[sd->equip_index[9]]->view_id;
+                    else
+                        WBUFW (buf, 7) =
+                            sd->status.inventory[sd->equip_index[9]].nameid;
+                }
+                else
+                    WBUFW (buf, 7) = 0;
+            }
+            if (sd->equip_index[8] >= 0
+                && sd->equip_index[8] != sd->equip_index[9]
+                && sd->inventory_data[sd->equip_index[8]]
+                && sd->view_class != 22)
+            {
+                if (sd->inventory_data[sd->equip_index[8]]->view_id > 0)
+                    WBUFW (buf, 9) =
+                        sd->inventory_data[sd->equip_index[8]]->view_id;
+                else
+                    WBUFW (buf, 9) =
+                        sd->status.inventory[sd->equip_index[8]].nameid;
+            }
+            else
+                WBUFW (buf, 9) = 0;
+        }
+        if (dstsd)
+            WFIFOSET (dstsd->fd, packet_len_table[0x1d7]);
+        else
+            clif_send (buf, packet_len_table[0x1d7], bl, AREA);
+    }
+    else
+    {
+        WBUFW (buf, 0) = 0x1d7;
+        WBUFL (buf, 2) = bl->id;
+        WBUFB (buf, 6) = type;
+        WBUFW (buf, 7) = val;
+        WBUFW (buf, 9) = 0;
+        if (dstsd)
+            WFIFOSET (dstsd->fd, packet_len_table[0x1d7]);
+        else
+            clif_send (buf, packet_len_table[0x1d7], bl, AREA);
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_initialstatus (struct map_session_data *sd)
+{
+    int  fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+
+    WBUFW (buf, 0) = 0xbd;
+    WBUFW (buf, 2) = sd->status.status_point;
+    WBUFB (buf, 4) = (sd->status.str > 255) ? 255 : sd->status.str;
+    WBUFB (buf, 5) = pc_need_status_point (sd, SP_STR);
+    WBUFB (buf, 6) = (sd->status.agi > 255) ? 255 : sd->status.agi;
+    WBUFB (buf, 7) = pc_need_status_point (sd, SP_AGI);
+    WBUFB (buf, 8) = (sd->status.vit > 255) ? 255 : sd->status.vit;
+    WBUFB (buf, 9) = pc_need_status_point (sd, SP_VIT);
+    WBUFB (buf, 10) = (sd->status.int_ > 255) ? 255 : sd->status.int_;
+    WBUFB (buf, 11) = pc_need_status_point (sd, SP_INT);
+    WBUFB (buf, 12) = (sd->status.dex > 255) ? 255 : sd->status.dex;
+    WBUFB (buf, 13) = pc_need_status_point (sd, SP_DEX);
+    WBUFB (buf, 14) = (sd->status.luk > 255) ? 255 : sd->status.luk;
+    WBUFB (buf, 15) = pc_need_status_point (sd, SP_LUK);
+
+    WBUFW (buf, 16) = sd->base_atk + sd->watk;
+    WBUFW (buf, 18) = sd->watk2;    //atk bonus
+    WBUFW (buf, 20) = sd->matk1;
+    WBUFW (buf, 22) = sd->matk2;
+    WBUFW (buf, 24) = sd->def;  // def
+    WBUFW (buf, 26) = sd->def2;
+    WBUFW (buf, 28) = sd->mdef; // mdef
+    WBUFW (buf, 30) = sd->mdef2;
+    WBUFW (buf, 32) = sd->hit;
+    WBUFW (buf, 34) = sd->flee;
+    WBUFW (buf, 36) = sd->flee2 / 10;
+    WBUFW (buf, 38) = sd->critical / 10;
+    WBUFW (buf, 40) = sd->status.karma;
+    WBUFW (buf, 42) = sd->status.manner;
+
+    WFIFOSET (fd, packet_len_table[0xbd]);
+
+    clif_updatestatus (sd, SP_STR);
+    clif_updatestatus (sd, SP_AGI);
+    clif_updatestatus (sd, SP_VIT);
+    clif_updatestatus (sd, SP_INT);
+    clif_updatestatus (sd, SP_DEX);
+    clif_updatestatus (sd, SP_LUK);
+
+    clif_updatestatus (sd, SP_ATTACKRANGE);
+    clif_updatestatus (sd, SP_ASPD);
+
+    return 0;
+}
+
+/*==========================================
+ *矢装備
+ *------------------------------------------
+ */
+int clif_arrowequip (struct map_session_data *sd, int val)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    if (sd->attacktarget && sd->attacktarget > 0)   // [Valaris]
+        sd->attacktarget = 0;
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x013c;
+    WFIFOW (fd, 2) = val + 2;   //矢のアイテムID
+
+    WFIFOSET (fd, packet_len_table[0x013c]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_arrow_fail (struct map_session_data *sd, int type)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x013b;
+    WFIFOW (fd, 2) = type;
+
+    WFIFOSET (fd, packet_len_table[0x013b]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_statusupack (struct map_session_data *sd, int type, int ok, int val)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xbc;
+    WFIFOW (fd, 2) = type;
+    WFIFOB (fd, 4) = ok;
+    WFIFOB (fd, 5) = val;
+    WFIFOSET (fd, packet_len_table[0xbc]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_equipitemack (struct map_session_data *sd, int n, int pos, int ok)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xaa;
+    WFIFOW (fd, 2) = n + 2;
+    WFIFOW (fd, 4) = pos;
+    WFIFOB (fd, 6) = ok;
+    WFIFOSET (fd, packet_len_table[0xaa]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_unequipitemack (struct map_session_data *sd, int n, int pos, int ok)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xac;
+    WFIFOW (fd, 2) = n + 2;
+    WFIFOW (fd, 4) = pos;
+    WFIFOB (fd, 6) = ok;
+    WFIFOSET (fd, packet_len_table[0xac]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_misceffect (struct block_list *bl, int type)
+{
+    char buf[32];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x19b;
+    WBUFL (buf, 2) = bl->id;
+    WBUFL (buf, 6) = type;
+
+    clif_send (buf, packet_len_table[0x19b], bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * 表示オプション変更
+ *------------------------------------------
+ */
+int clif_changeoption (struct block_list *bl)
+{
+    char buf[32];
+    short option;
+    struct status_change *sc_data;
+    static const int omask[] = { 0x10, 0x20 };
+    static const int scnum[] = { SC_FALCON, SC_RIDING };
+    int  i;
+
+    nullpo_retr (0, bl);
+
+    option = *battle_get_option (bl);
+    sc_data = battle_get_sc_data (bl);
+
+    WBUFW (buf, 0) = 0x119;
+    WBUFL (buf, 2) = bl->id;
+    WBUFW (buf, 6) = *battle_get_opt1 (bl);
+    WBUFW (buf, 8) = *battle_get_opt2 (bl);
+    WBUFW (buf, 10) = option;
+    WBUFB (buf, 12) = 0;        // ??
+
+    if (bl->type == BL_PC)
+    {                           // disguises [Valaris]
+        struct map_session_data *sd = ((struct map_session_data *) bl);
+        if (sd && sd->disguise > 23 && sd->disguise < 4001)
+        {
+            clif_send (buf, packet_len_table[0x119], bl, AREA_WOS);
+            clif_spawnpc (sd);
+        }
+        else
+            clif_send (buf, packet_len_table[0x119], bl, AREA);
+    }
+    else
+        clif_send (buf, packet_len_table[0x119], bl, AREA);
+
+    // アイコンの表示
+    for (i = 0; i < sizeof (omask) / sizeof (omask[0]); i++)
+    {
+        if (option & omask[i])
+        {
+            if (sc_data[scnum[i]].timer == -1)
+                skill_status_change_start (bl, scnum[i], 0, 0, 0, 0, 0, 0);
+        }
+        else
+        {
+            skill_status_change_end (bl, scnum[i], -1);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_useitemack (struct map_session_data *sd, int index, int amount,
+                     int ok)
+{
+    nullpo_retr (0, sd);
+
+    if (!ok)
+    {
+        int  fd = sd->fd;
+        WFIFOW (fd, 0) = 0xa8;
+        WFIFOW (fd, 2) = index + 2;
+        WFIFOW (fd, 4) = amount;
+        WFIFOB (fd, 6) = ok;
+        WFIFOSET (fd, packet_len_table[0xa8]);
+    }
+    else
+    {
+        char buf[32];
+
+        WBUFW (buf, 0) = 0x1c8;
+        WBUFW (buf, 2) = index + 2;
+        if (sd->inventory_data[index]
+            && sd->inventory_data[index]->view_id > 0)
+            WBUFW (buf, 4) = sd->inventory_data[index]->view_id;
+        else
+            WBUFW (buf, 4) = sd->status.inventory[index].nameid;
+        WBUFL (buf, 6) = sd->bl.id;
+        WBUFW (buf, 10) = amount;
+        WBUFB (buf, 12) = ok;
+        clif_send (buf, packet_len_table[0x1c8], &sd->bl, SELF);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_createchat (struct map_session_data *sd, int fail)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xd6;
+    WFIFOB (fd, 2) = fail;
+    WFIFOSET (fd, packet_len_table[0xd6]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_dispchat (struct chat_data *cd, int fd)
+{
+    char buf[128];              // 最大title(60バイト)+17
+
+    if (cd == NULL || *cd->owner == NULL)
+        return 1;
+
+    WBUFW (buf, 0) = 0xd7;
+    WBUFW (buf, 2) = strlen (cd->title) + 17;
+    WBUFL (buf, 4) = (*cd->owner)->id;
+    WBUFL (buf, 8) = cd->bl.id;
+    WBUFW (buf, 12) = cd->limit;
+    WBUFW (buf, 14) = cd->users;
+    WBUFB (buf, 16) = cd->pub;
+    strcpy (WBUFP (buf, 17), cd->title);
+    if (fd)
+    {
+        memcpy (WFIFOP (fd, 0), buf, WBUFW (buf, 2));
+        WFIFOSET (fd, WBUFW (buf, 2));
+    }
+    else
+    {
+        clif_send (buf, WBUFW (buf, 2), *cd->owner, AREA_WOSC);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * chatの状態変更成功
+ * 外部の人用と命令コード(d7->df)が違うだけ
+ *------------------------------------------
+ */
+int clif_changechatstatus (struct chat_data *cd)
+{
+    char buf[128];              // 最大title(60バイト)+17
+
+    if (cd == NULL || cd->usersd[0] == NULL)
+        return 1;
+
+    WBUFW (buf, 0) = 0xdf;
+    WBUFW (buf, 2) = strlen (cd->title) + 17;
+    WBUFL (buf, 4) = cd->usersd[0]->bl.id;
+    WBUFL (buf, 8) = cd->bl.id;
+    WBUFW (buf, 12) = cd->limit;
+    WBUFW (buf, 14) = cd->users;
+    WBUFB (buf, 16) = cd->pub;
+    strcpy (WBUFP (buf, 17), cd->title);
+    clif_send (buf, WBUFW (buf, 2), &cd->usersd[0]->bl, CHAT);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_clearchat (struct chat_data *cd, int fd)
+{
+    char buf[32];
+
+    nullpo_retr (0, cd);
+
+    WBUFW (buf, 0) = 0xd8;
+    WBUFL (buf, 2) = cd->bl.id;
+    if (fd)
+    {
+        memcpy (WFIFOP (fd, 0), buf, packet_len_table[0xd8]);
+        WFIFOSET (fd, packet_len_table[0xd8]);
+    }
+    else
+    {
+        clif_send (buf, packet_len_table[0xd8], *cd->owner, AREA_WOSC);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_joinchatfail (struct map_session_data *sd, int fail)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0xda;
+    WFIFOB (fd, 2) = fail;
+    WFIFOSET (fd, packet_len_table[0xda]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_joinchatok (struct map_session_data *sd, struct chat_data *cd)
+{
+    int  fd;
+    int  i;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, cd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xdb;
+    WFIFOW (fd, 2) = 8 + (28 * cd->users);
+    WFIFOL (fd, 4) = cd->bl.id;
+    for (i = 0; i < cd->users; i++)
+    {
+        WFIFOL (fd, 8 + i * 28) = (i != 0) || ((*cd->owner)->type == BL_NPC);
+        memcpy (WFIFOP (fd, 8 + i * 28 + 4), cd->usersd[i]->status.name, 24);
+    }
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_addchat (struct chat_data *cd, struct map_session_data *sd)
+{
+    char buf[32];
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, cd);
+
+    WBUFW (buf, 0) = 0x0dc;
+    WBUFW (buf, 2) = cd->users;
+    memcpy (WBUFP (buf, 4), sd->status.name, 24);
+    clif_send (buf, packet_len_table[0xdc], &sd->bl, CHAT_WOS);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_changechatowner (struct chat_data *cd, struct map_session_data *sd)
+{
+    char buf[64];
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, cd);
+
+    WBUFW (buf, 0) = 0xe1;
+    WBUFL (buf, 2) = 1;
+    memcpy (WBUFP (buf, 6), cd->usersd[0]->status.name, 24);
+    WBUFW (buf, 30) = 0xe1;
+    WBUFL (buf, 32) = 0;
+    memcpy (WBUFP (buf, 36), sd->status.name, 24);
+
+    clif_send (buf, packet_len_table[0xe1] * 2, &sd->bl, CHAT);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_leavechat (struct chat_data *cd, struct map_session_data *sd)
+{
+    char buf[32];
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, cd);
+
+    WBUFW (buf, 0) = 0xdd;
+    WBUFW (buf, 2) = cd->users - 1;
+    memcpy (WBUFP (buf, 4), sd->status.name, 24);
+    WBUFB (buf, 28) = 0;
+
+    clif_send (buf, packet_len_table[0xdd], &sd->bl, CHAT);
+
+    return 0;
+}
+
+/*==========================================
+ * 取り引き要請受け
+ *------------------------------------------
+ */
+int clif_traderequest (struct map_session_data *sd, char *name)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xe5;
+    strcpy (WFIFOP (fd, 2), name);
+    WFIFOSET (fd, packet_len_table[0xe5]);
+
+    return 0;
+}
+
+/*==========================================
+ * 取り引き要求応答
+ *------------------------------------------
+ */
+int clif_tradestart (struct map_session_data *sd, int type)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xe7;
+    WFIFOB (fd, 2) = type;
+    WFIFOSET (fd, packet_len_table[0xe7]);
+
+    return 0;
+}
+
+/*==========================================
+ * 相手方からのアイテム追加
+ *------------------------------------------
+ */
+int clif_tradeadditem (struct map_session_data *sd,
+                       struct map_session_data *tsd, int index, int amount)
+{
+    int  fd, j;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, tsd);
+
+    fd = tsd->fd;
+    WFIFOW (fd, 0) = 0xe9;
+    WFIFOL (fd, 2) = amount;
+    if (index == 0)
+    {
+        WFIFOW (fd, 6) = 0;     // type id
+        WFIFOB (fd, 8) = 0;     //identify flag
+        WFIFOB (fd, 9) = 0;     // attribute
+        WFIFOB (fd, 10) = 0;    //refine
+        WFIFOW (fd, 11) = 0;    //card (4w)
+        WFIFOW (fd, 13) = 0;    //card (4w)
+        WFIFOW (fd, 15) = 0;    //card (4w)
+        WFIFOW (fd, 17) = 0;    //card (4w)
+    }
+    else
+    {
+        index -= 2;
+        if (sd->inventory_data[index]
+            && sd->inventory_data[index]->view_id > 0)
+            WFIFOW (fd, 6) = sd->inventory_data[index]->view_id;
+        else
+            WFIFOW (fd, 6) = sd->status.inventory[index].nameid;    // type id
+        WFIFOB (fd, 8) = sd->status.inventory[index].identify;  //identify flag
+        if (sd->status.inventory[index].broken == 1)
+            WFIFOB (fd, 9) = 1; // is broke weapon [Valaris]
+        else
+            WFIFOB (fd, 9) = sd->status.inventory[index].attribute; // attribute
+        WFIFOB (fd, 10) = sd->status.inventory[index].refine;   //refine
+        if (sd->status.inventory[index].card[0] == 0x00ff
+            || sd->status.inventory[index].card[0] == 0x00fe
+            || sd->status.inventory[index].card[0] == (short) 0xff00)
+        {
+            WFIFOW (fd, 11) = sd->status.inventory[index].card[0];  //card (4w)
+            WFIFOW (fd, 13) = sd->status.inventory[index].card[1];  //card (4w)
+            WFIFOW (fd, 15) = sd->status.inventory[index].card[2];  //card (4w)
+            WFIFOW (fd, 17) = sd->status.inventory[index].card[3];  //card (4w)
+        }
+        else
+        {
+            if (sd->status.inventory[index].card[0] > 0
+                && (j =
+                    itemdb_viewid (sd->status.inventory[index].card[0])) > 0)
+                WFIFOW (fd, 11) = j;
+            else
+                WFIFOW (fd, 11) = sd->status.inventory[index].card[0];
+            if (sd->status.inventory[index].card[1] > 0
+                && (j =
+                    itemdb_viewid (sd->status.inventory[index].card[1])) > 0)
+                WFIFOW (fd, 13) = j;
+            else
+                WFIFOW (fd, 13) = sd->status.inventory[index].card[1];
+            if (sd->status.inventory[index].card[2] > 0
+                && (j =
+                    itemdb_viewid (sd->status.inventory[index].card[2])) > 0)
+                WFIFOW (fd, 15) = j;
+            else
+                WFIFOW (fd, 15) = sd->status.inventory[index].card[2];
+            if (sd->status.inventory[index].card[3] > 0
+                && (j =
+                    itemdb_viewid (sd->status.inventory[index].card[3])) > 0)
+                WFIFOW (fd, 17) = j;
+            else
+                WFIFOW (fd, 17) = sd->status.inventory[index].card[3];
+        }
+    }
+    WFIFOSET (fd, packet_len_table[0xe9]);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテム追加成功/失敗
+ *------------------------------------------
+ */
+int clif_tradeitemok (struct map_session_data *sd, int index, int amount,
+                      int fail)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1b1;
+    //WFIFOW(fd,0)=0xea;
+    WFIFOW (fd, 2) = index;
+    WFIFOW (fd, 4) = amount;
+    WFIFOB (fd, 6) = fail;
+    WFIFOSET (fd, packet_len_table[0x1b1]);
+
+    return 0;
+}
+
+/*==========================================
+ * 取り引きok押し
+ *------------------------------------------
+ */
+int clif_tradedeal_lock (struct map_session_data *sd, int fail)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xec;
+    WFIFOB (fd, 2) = fail;      // 0=you 1=the other person
+    WFIFOSET (fd, packet_len_table[0xec]);
+
+    return 0;
+}
+
+/*==========================================
+ * 取り引きがキャンセルされました
+ *------------------------------------------
+ */
+int clif_tradecancelled (struct map_session_data *sd)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xee;
+    WFIFOSET (fd, packet_len_table[0xee]);
+
+    return 0;
+}
+
+/*==========================================
+ * 取り引き完了
+ *------------------------------------------
+ */
+int clif_tradecompleted (struct map_session_data *sd, int fail)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf0;
+    WFIFOB (fd, 2) = fail;
+    WFIFOSET (fd, packet_len_table[0xf0]);
+
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫のアイテム数を更新
+ *------------------------------------------
+ */
+int clif_updatestorageamount (struct map_session_data *sd,
+                              struct storage *stor)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf2;      // update storage amount
+    WFIFOW (fd, 2) = stor->storage_amount;  //items
+    WFIFOW (fd, 4) = MAX_STORAGE;   //items max
+    WFIFOSET (fd, packet_len_table[0xf2]);
+
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫にアイテムを追加する
+ *------------------------------------------
+ */
+int clif_storageitemadded (struct map_session_data *sd, struct storage *stor,
+                           int index, int amount)
+{
+    int  fd, j;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf4;      // Storage item added
+    WFIFOW (fd, 2) = index + 1; // index
+    WFIFOL (fd, 4) = amount;    // amount
+/*	if((view = itemdb_viewid(stor->storage_[index].nameid)) > 0)
+		WFIFOW(fd,8) =view;
+	else*/
+    WFIFOW (fd, 8) = stor->storage_[index].nameid;
+    WFIFOB (fd, 10) = stor->storage_[index].identify;   //identify flag
+    if (stor->storage_[index].broken == 1)
+        WFIFOB (fd, 11) = 1;    // is weapon broken [Valaris]
+    else
+        WFIFOB (fd, 11) = stor->storage_[index].attribute;  // attribute
+    WFIFOB (fd, 12) = stor->storage_[index].refine; //refine
+    if (stor->storage_[index].card[0] == 0x00ff
+        || stor->storage_[index].card[0] == 0x00fe
+        || stor->storage_[index].card[0] == (short) 0xff00)
+    {
+        WFIFOW (fd, 13) = stor->storage_[index].card[0];    //card (4w)
+        WFIFOW (fd, 15) = stor->storage_[index].card[1];    //card (4w)
+        WFIFOW (fd, 17) = stor->storage_[index].card[2];    //card (4w)
+        WFIFOW (fd, 19) = stor->storage_[index].card[3];    //card (4w)
+    }
+    else
+    {
+        if (stor->storage_[index].card[0] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[0])) > 0)
+            WFIFOW (fd, 13) = j;
+        else
+            WFIFOW (fd, 13) = stor->storage_[index].card[0];
+        if (stor->storage_[index].card[1] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[1])) > 0)
+            WFIFOW (fd, 15) = j;
+        else
+            WFIFOW (fd, 15) = stor->storage_[index].card[1];
+        if (stor->storage_[index].card[2] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[2])) > 0)
+            WFIFOW (fd, 17) = j;
+        else
+            WFIFOW (fd, 17) = stor->storage_[index].card[2];
+        if (stor->storage_[index].card[3] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[3])) > 0)
+            WFIFOW (fd, 19) = j;
+        else
+            WFIFOW (fd, 19) = stor->storage_[index].card[3];
+    }
+    WFIFOSET (fd, packet_len_table[0xf4]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_updateguildstorageamount (struct map_session_data *sd,
+                                   struct guild_storage *stor)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf2;      // update storage amount
+    WFIFOW (fd, 2) = stor->storage_amount;  //items
+    WFIFOW (fd, 4) = MAX_GUILD_STORAGE; //items max
+    WFIFOSET (fd, packet_len_table[0xf2]);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_guildstorageitemadded (struct map_session_data *sd,
+                                struct guild_storage *stor, int index,
+                                int amount)
+{
+    int  view, fd, j;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf4;      // Storage item added
+    WFIFOW (fd, 2) = index + 1; // index
+    WFIFOL (fd, 4) = amount;    // amount
+    if ((view = itemdb_viewid (stor->storage_[index].nameid)) > 0)
+        WFIFOW (fd, 8) = view;
+    else
+        WFIFOW (fd, 8) = stor->storage_[index].nameid;  // id
+    WFIFOB (fd, 10) = stor->storage_[index].identify;   //identify flag
+    if (stor->storage_[index].broken == 1)
+        WFIFOB (fd, 11) = 1;    // is weapon broken [Valaris]
+    else
+        WFIFOB (fd, 11) = stor->storage_[index].attribute;  // attribute
+    WFIFOB (fd, 12) = stor->storage_[index].refine; //refine
+    if (stor->storage_[index].card[0] == 0x00ff
+        || stor->storage_[index].card[0] == 0x00fe
+        || stor->storage_[index].card[0] == (short) 0xff00)
+    {
+        WFIFOW (fd, 13) = stor->storage_[index].card[0];    //card (4w)
+        WFIFOW (fd, 15) = stor->storage_[index].card[1];    //card (4w)
+        WFIFOW (fd, 17) = stor->storage_[index].card[2];    //card (4w)
+        WFIFOW (fd, 19) = stor->storage_[index].card[3];    //card (4w)
+    }
+    else
+    {
+        if (stor->storage_[index].card[0] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[0])) > 0)
+            WFIFOW (fd, 13) = j;
+        else
+            WFIFOW (fd, 13) = stor->storage_[index].card[0];
+        if (stor->storage_[index].card[1] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[1])) > 0)
+            WFIFOW (fd, 15) = j;
+        else
+            WFIFOW (fd, 15) = stor->storage_[index].card[1];
+        if (stor->storage_[index].card[2] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[2])) > 0)
+            WFIFOW (fd, 17) = j;
+        else
+            WFIFOW (fd, 17) = stor->storage_[index].card[2];
+        if (stor->storage_[index].card[3] > 0
+            && (j = itemdb_viewid (stor->storage_[index].card[3])) > 0)
+            WFIFOW (fd, 19) = j;
+        else
+            WFIFOW (fd, 19) = stor->storage_[index].card[3];
+    }
+    WFIFOSET (fd, packet_len_table[0xf4]);
+
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫からアイテムを取り去る
+ *------------------------------------------
+ */
+int clif_storageitemremoved (struct map_session_data *sd, int index,
+                             int amount)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf6;      // Storage item removed
+    WFIFOW (fd, 2) = index + 1;
+    WFIFOL (fd, 4) = amount;
+    WFIFOSET (fd, packet_len_table[0xf6]);
+
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫を閉じる
+ *------------------------------------------
+ */
+int clif_storageclose (struct map_session_data *sd)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xf8;      // Storage Closed
+    WFIFOSET (fd, packet_len_table[0xf8]);
+
+    return 0;
+}
+
+void
+clif_changelook_accessories (struct block_list *bl,
+                             struct map_session_data *dest)
+{
+    int  i;
+
+    for (i = LOOK_SHOES; i <= LOOK_LAST; i++)
+        clif_changelook_towards (bl, i, 0, dest);
+}
+
+//
+// callback系 ?
+//
+/*==========================================
+ * PC表示
+ *------------------------------------------
+ */
+void clif_getareachar_pc (struct map_session_data *sd,
+                          struct map_session_data *dstsd)
+{
+    int  len;
+
+    if (dstsd->status.option & OPTION_INVISIBILITY)
+        return;
+
+    nullpo_retv (sd);
+    nullpo_retv (dstsd);
+
+    if (dstsd->walktimer != -1)
+    {
+        len = clif_set007b (dstsd, WFIFOP (sd->fd, 0));
+        WFIFOSET (sd->fd, len);
+    }
+    else
+    {
+        len = clif_set0078 (dstsd, WFIFOP (sd->fd, 0));
+        WFIFOSET (sd->fd, len);
+    }
+
+    if (dstsd->chatID)
+    {
+        struct chat_data *cd;
+        cd = (struct chat_data *) map_id2bl (dstsd->chatID);
+        if (cd->usersd[0] == dstsd)
+            clif_dispchat (cd, sd->fd);
+    }
+    if (dstsd->spiritball > 0)
+    {
+        clif_set01e1 (dstsd, WFIFOP (sd->fd, 0));
+        WFIFOSET (sd->fd, packet_len_table[0x1e1]);
+    }
+    if (battle_config.save_clothcolor == 1 && dstsd->status.clothes_color > 0)
+        clif_changelook (&dstsd->bl, LOOK_CLOTHES_COLOR,
+                         dstsd->status.clothes_color);
+
+    if (sd->status.manner < 0)
+        clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
+
+    clif_changelook_accessories (&sd->bl, dstsd);
+    clif_changelook_accessories (&dstsd->bl, sd);
+}
+
+/*==========================================
+ * NPC表示
+ *------------------------------------------
+ */
+void clif_getareachar_npc (struct map_session_data *sd, struct npc_data *nd)
+{
+    int  len;
+
+    nullpo_retv (sd);
+    nullpo_retv (nd);
+
+    if (nd->npc_class < 0 || nd->flag & 1 || nd->npc_class == INVISIBLE_CLASS)
+        return;
+
+    len = clif_npc0078 (nd, WFIFOP (sd->fd, 0));
+    WFIFOSET (sd->fd, len);
+
+    if (nd->chat_id)
+    {
+        clif_dispchat ((struct chat_data *) map_id2bl (nd->chat_id), sd->fd);
+    }
+
+}
+
+/*==========================================
+ * 移動停止
+ *------------------------------------------
+ */
+int clif_movemob (struct mob_data *md)
+{
+    unsigned char buf[256];
+    int  len;
+
+    nullpo_retr (0, md);
+
+    len = clif_mob007b (md, buf);
+    clif_send (buf, len, &md->bl, AREA);
+
+    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
+        clif_mob_equip (md, mob_get_equip (md->mob_class));
+
+    return 0;
+}
+
+/*==========================================
+ * モンスターの位置修正
+ *------------------------------------------
+ */
+int clif_fixmobpos (struct mob_data *md)
+{
+    unsigned char buf[256];
+    int  len;
+
+    nullpo_retr (0, md);
+
+    if (md->state.state == MS_WALK)
+    {
+        len = clif_mob007b (md, buf);
+        clif_send (buf, len, &md->bl, AREA);
+    }
+    else
+    {
+        len = clif_mob0078 (md, buf);
+        clif_send (buf, len, &md->bl, AREA);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * PCの位置修正
+ *------------------------------------------
+ */
+int clif_fixpcpos (struct map_session_data *sd)
+{
+    unsigned char buf[256];
+    int  len;
+
+    nullpo_retr (0, sd);
+
+    if (sd->walktimer != -1)
+    {
+        len = clif_set007b (sd, buf);
+        clif_send (buf, len, &sd->bl, AREA);
+    }
+    else
+    {
+        len = clif_set0078 (sd, buf);
+        clif_send (buf, len, &sd->bl, AREA);
+    }
+    clif_changelook_accessories (&sd->bl, NULL);
+
+    return 0;
+}
+
+/*==========================================
+ * 通常攻撃エフェクト&ダメージ
+ *------------------------------------------
+ */
+int clif_damage (struct block_list *src, struct block_list *dst,
+                 unsigned int tick, int sdelay, int ddelay, int damage,
+                 int div, int type, int damage2)
+{
+    unsigned char buf[256];
+    struct status_change *sc_data;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, dst);
+
+    sc_data = battle_get_sc_data (dst);
+
+    if (type != 4 && dst->type == BL_PC
+        && ((struct map_session_data *) dst)->special_state.infinite_endure)
+        type = 9;
+    if (sc_data)
+    {
+        if (type != 4 && sc_data[SC_ENDURE].timer != -1)
+            type = 9;
+        if (sc_data[SC_HALLUCINATION].timer != -1)
+        {
+            if (damage > 0)
+                damage =
+                    damage * (5 + sc_data[SC_HALLUCINATION].val1) +
+                    MRAND (100);
+            if (damage2 > 0)
+                damage2 =
+                    damage2 * (5 + sc_data[SC_HALLUCINATION].val1) +
+                    MRAND (100);
+        }
+    }
+
+    WBUFW (buf, 0) = 0x8a;
+    WBUFL (buf, 2) = src->id;
+    WBUFL (buf, 6) = dst->id;
+    WBUFL (buf, 10) = tick;
+    WBUFL (buf, 14) = sdelay;
+    WBUFL (buf, 18) = ddelay;
+    WBUFW (buf, 22) = (damage > 0x7fff) ? 0x7fff : damage;
+    WBUFW (buf, 24) = div;
+    WBUFB (buf, 26) = type;
+    WBUFW (buf, 27) = damage2;
+    clif_send (buf, packet_len_table[0x8a], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_getareachar_mob (struct map_session_data *sd, struct mob_data *md)
+{
+    int  len;
+    nullpo_retv (sd);
+    nullpo_retv (md);
+
+    if (md->state.state == MS_WALK)
+    {
+        len = clif_mob007b (md, WFIFOP (sd->fd, 0));
+        WFIFOSET (sd->fd, len);
+    }
+    else
+    {
+        len = clif_mob0078 (md, WFIFOP (sd->fd, 0));
+        WFIFOSET (sd->fd, len);
+    }
+
+    if (mob_get_equip (md->mob_class) > 0)  // mob equipment [Valaris]
+        clif_mob_equip (md, mob_get_equip (md->mob_class));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_getareachar_item (struct map_session_data *sd,
+                            struct flooritem_data *fitem)
+{
+    int  view, fd;
+
+    nullpo_retv (sd);
+    nullpo_retv (fitem);
+
+    fd = sd->fd;
+    //009d <ID>.l <item ID>.w <identify flag>.B <X>.w <Y>.w <amount>.w <subX>.B <subY>.B
+    WFIFOW (fd, 0) = 0x9d;
+    WFIFOL (fd, 2) = fitem->bl.id;
+    if ((view = itemdb_viewid (fitem->item_data.nameid)) > 0)
+        WFIFOW (fd, 6) = view;
+    else
+        WFIFOW (fd, 6) = fitem->item_data.nameid;
+    WFIFOB (fd, 8) = fitem->item_data.identify;
+    WFIFOW (fd, 9) = fitem->bl.x;
+    WFIFOW (fd, 11) = fitem->bl.y;
+    WFIFOW (fd, 13) = fitem->item_data.amount;
+    WFIFOB (fd, 15) = fitem->subx;
+    WFIFOB (fd, 16) = fitem->suby;
+
+    WFIFOSET (fd, packet_len_table[0x9d]);
+}
+
+/*==========================================
+ * 場所スキルエフェクトが視界に入る
+ *------------------------------------------
+ */
+int clif_getareachar_skillunit (struct map_session_data *sd,
+                                struct skill_unit *unit)
+{
+    int  fd;
+    struct block_list *bl;
+
+    nullpo_retr (0, unit);
+
+    fd = sd->fd;
+    bl = map_id2bl (unit->group->src_id);
+    memset (WFIFOP (fd, 0), 0, packet_len_table[0x1c9]);
+    WFIFOW (fd, 0) = 0x1c9;
+    WFIFOL (fd, 2) = unit->bl.id;
+    WFIFOL (fd, 6) = unit->group->src_id;
+    WFIFOW (fd, 10) = unit->bl.x;
+    WFIFOW (fd, 12) = unit->bl.y;
+    WFIFOB (fd, 14) = unit->group->unit_id;
+    WFIFOB (fd, 15) = 1;
+    WFIFOL (fd, 15 + 1) = 0;    //1-4調べた限り固定
+    WFIFOL (fd, 15 + 5) = 0;    //5-8調べた限り固定
+    //9-12マップごとで一定の77-80とはまた違う4バイトのかなり大きな数字
+    WFIFOL (fd, 15 + 13) = unit->bl.y - 0x12;   //13-16ユニットのY座標-18っぽい(Y:17でFF FF FF FF)
+    WFIFOL (fd, 15 + 17) = 0x004f37dd;  //17-20調べた限り固定
+    WFIFOL (fd, 15 + 21) = 0x0012f674;  //21-24調べた限り固定
+    WFIFOL (fd, 15 + 25) = 0x0012f664;  //25-28調べた限り固定
+    WFIFOL (fd, 15 + 29) = 0x0012f654;  //29-32調べた限り固定
+    WFIFOL (fd, 15 + 33) = 0x77527bbc;  //33-36調べた限り固定
+    //37-39
+    WFIFOB (fd, 15 + 40) = 0x2d;    //40調べた限り固定
+    WFIFOL (fd, 15 + 41) = 0;   //41-44調べた限り0固定
+    WFIFOL (fd, 15 + 45) = 0;   //45-48調べた限り0固定
+    WFIFOL (fd, 15 + 49) = 0;   //49-52調べた限り0固定
+    WFIFOL (fd, 15 + 53) = 0x0048d919;  //53-56調べた限り固定
+    WFIFOL (fd, 15 + 57) = 0x0000003e;  //57-60調べた限り固定
+    WFIFOL (fd, 15 + 61) = 0x0012f66c;  //61-64調べた限り固定
+    //65-68
+    //69-72
+    if (bl)
+        WFIFOL (fd, 15 + 73) = bl->y;   //73-76術者のY座標
+    WFIFOL (fd, 15 + 77) = unit->bl.m;  //77-80マップIDかなぁ?かなり2バイトで足りそうな数字
+    WFIFOB (fd, 15 + 81) = 0xaa;    //81終端文字0xaa
+
+    /*  Graffiti [Valaris]  */
+    if (unit->group->unit_id == 0xb0)
+    {
+        WFIFOL (fd, 15) = 1;
+        WFIFOL (fd, 16) = 1;
+        memcpy (WFIFOP (fd, 17), unit->group->valstr, 80);
+    }
+
+    WFIFOSET (fd, packet_len_table[0x1c9]);
+    if (unit->group->skill_id == WZ_ICEWALL)
+        clif_set0192 (fd, unit->bl.m, unit->bl.x, unit->bl.y, 5);
+
+    return 0;
+}
+
+/*==========================================
+ * 場所スキルエフェクトが視界から消える
+ *------------------------------------------
+ */
+int clif_clearchar_skillunit (struct skill_unit *unit, int fd)
+{
+    nullpo_retr (0, unit);
+
+    WFIFOW (fd, 0) = 0x120;
+    WFIFOL (fd, 2) = unit->bl.id;
+    WFIFOSET (fd, packet_len_table[0x120]);
+    if (unit->group->skill_id == WZ_ICEWALL)
+        clif_set0192 (fd, unit->bl.m, unit->bl.x, unit->bl.y, unit->val2);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_01ac (struct block_list *bl)
+{
+    char buf[32];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x1ac;
+    WBUFL (buf, 2) = bl->id;
+
+    clif_send (buf, packet_len_table[0x1ac], bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_getareachar (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    sd = va_arg (ap, struct map_session_data *);
+
+    switch (bl->type)
+    {
+        case BL_PC:
+            if (sd == (struct map_session_data *) bl)
+                break;
+            clif_getareachar_pc (sd, (struct map_session_data *) bl);
+            break;
+        case BL_NPC:
+            clif_getareachar_npc (sd, (struct npc_data *) bl);
+            break;
+        case BL_MOB:
+            clif_getareachar_mob (sd, (struct mob_data *) bl);
+            break;
+        case BL_ITEM:
+            clif_getareachar_item (sd, (struct flooritem_data *) bl);
+            break;
+        case BL_SKILL:
+            clif_getareachar_skillunit (sd, (struct skill_unit *) bl);
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("get area char ??? %d\n", bl->type);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_pcoutsight (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd, *dstsd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
+
+    switch (bl->type)
+    {
+        case BL_PC:
+            dstsd = (struct map_session_data *) bl;
+            if (sd != dstsd)
+            {
+                clif_clearchar_id (dstsd->bl.id, 0, sd->fd);
+                clif_clearchar_id (sd->bl.id, 0, dstsd->fd);
+                if (dstsd->chatID)
+                {
+                    struct chat_data *cd;
+                    cd = (struct chat_data *) map_id2bl (dstsd->chatID);
+                    if (cd->usersd[0] == dstsd)
+                        clif_dispchat (cd, sd->fd);
+                }
+            }
+            break;
+        case BL_NPC:
+            if (((struct npc_data *) bl)->npc_class != INVISIBLE_CLASS)
+                clif_clearchar_id (bl->id, 0, sd->fd);
+            break;
+        case BL_MOB:
+            clif_clearchar_id (bl->id, 0, sd->fd);
+            break;
+        case BL_ITEM:
+            clif_clearflooritem ((struct flooritem_data *) bl, sd->fd);
+            break;
+        case BL_SKILL:
+            clif_clearchar_skillunit ((struct skill_unit *) bl, sd->fd);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_pcinsight (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd, *dstsd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
+
+    switch (bl->type)
+    {
+        case BL_PC:
+            dstsd = (struct map_session_data *) bl;
+            if (sd != dstsd)
+            {
+                clif_getareachar_pc (sd, dstsd);
+                clif_getareachar_pc (dstsd, sd);
+            }
+            break;
+        case BL_NPC:
+            clif_getareachar_npc (sd, (struct npc_data *) bl);
+            break;
+        case BL_MOB:
+            clif_getareachar_mob (sd, (struct mob_data *) bl);
+            break;
+        case BL_ITEM:
+            clif_getareachar_item (sd, (struct flooritem_data *) bl);
+            break;
+        case BL_SKILL:
+            clif_getareachar_skillunit (sd, (struct skill_unit *) bl);
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_moboutsight (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+    struct mob_data *md;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
+
+    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
+    {
+        clif_clearchar_id (md->bl.id, 0, sd->fd);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_mobinsight (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+    struct mob_data *md;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    md = va_arg (ap, struct mob_data *);
+    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
+    {
+        clif_getareachar_mob (sd, md);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_skillinfo (struct map_session_data *sd, int skillid, int type,
+                    int range)
+{
+    int  fd, id;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    if ((id = sd->status.skill[skillid].id) <= 0)
+        return 0;
+    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_range (id, sd->status.skill[skillid].lv);
+        if (range < 0)
+            range = battle_get_range (&sd->bl) - (range + 1);
+        WFIFOW (fd, 12) = range;
+    }
+    else
+        WFIFOW (fd, 12) = range;
+    memset (WFIFOP (fd, 14), 0, 24);
+    WFIFOB (fd, 38) =
+        (sd->status.skill[skillid].lv < skill_get_max_raise (id)) ? 1 : 0;
+    WFIFOSET (fd, packet_len_table[0x147]);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルリストを送信する
+ *------------------------------------------
+ */
+int clif_skillinfoblock (struct map_session_data *sd)
+{
+    int  fd;
+    int  i, c, len = 4, id, range;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x10f;
+    for (i = c = 0; i < MAX_SKILL; i++)
+    {
+        if ((id = sd->status.skill[i].id) != 0 && (sd->tmw_version >= 1))
+        {                       // [Fate] Version 1 and later don't crash because of bad skill IDs anymore
+            WFIFOW (fd, len) = id;
+            WFIFOW (fd, len + 2) = skill_get_inf (id);
+            WFIFOW (fd, len + 4) =
+                skill_db[i].poolflags | (sd->status.
+                                         skill[i].flags &
+                                         (SKILL_POOL_ACTIVATED));
+            WFIFOW (fd, len + 6) = sd->status.skill[i].lv;
+            WFIFOW (fd, len + 8) = skill_get_sp (id, sd->status.skill[i].lv);
+            range = skill_get_range (id, sd->status.skill[i].lv);
+            if (range < 0)
+                range = battle_get_range (&sd->bl) - (range + 1);
+            WFIFOW (fd, len + 10) = range;
+            memset (WFIFOP (fd, len + 12), 0, 24);
+            WFIFOB (fd, len + 36) =
+                (sd->status.skill[i].lv < skill_get_max_raise (id)) ? 1 : 0;
+            len += 37;
+            c++;
+        }
+    }
+    WFIFOW (fd, 2) = len;
+    WFIFOSET (fd, len);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル割り振り通知
+ *------------------------------------------
+ */
+int clif_skillup (struct map_session_data *sd, int skill_num)
+{
+    int  range, fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x10e;
+    WFIFOW (fd, 2) = skill_num;
+    WFIFOW (fd, 4) = sd->status.skill[skill_num].lv;
+    WFIFOW (fd, 6) = skill_get_sp (skill_num, sd->status.skill[skill_num].lv);
+    range = skill_get_range (skill_num, sd->status.skill[skill_num].lv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    WFIFOW (fd, 8) = range;
+    WFIFOB (fd, 10) =
+        (sd->status.skill[skill_num].lv <
+         skill_get_max_raise (sd->status.skill[skill_num].id)) ? 1 : 0;
+    WFIFOSET (fd, packet_len_table[0x10e]);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル詠唱エフェクトを送信する
+ *------------------------------------------
+ */
+int clif_skillcasting (struct block_list *bl,
+                       int src_id, int dst_id, int dst_x, int dst_y,
+                       int skill_num, int casttime)
+{
+    unsigned char buf[32];
+    WBUFW (buf, 0) = 0x13e;
+    WBUFL (buf, 2) = src_id;
+    WBUFL (buf, 6) = dst_id;
+    WBUFW (buf, 10) = dst_x;
+    WBUFW (buf, 12) = dst_y;
+    WBUFW (buf, 14) = skill_num;    //魔法詠唱スキル
+    WBUFL (buf, 16) = skill_get_pl (skill_num); //属性
+    WBUFL (buf, 20) = casttime; //skill詠唱時間
+    clif_send (buf, packet_len_table[0x13e], bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_skillcastcancel (struct block_list *bl)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x1b9;
+    WBUFL (buf, 2) = bl->id;
+    clif_send (buf, packet_len_table[0x1b9], bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル詠唱失敗
+ *------------------------------------------
+ */
+int clif_skill_fail (struct map_session_data *sd, int skill_id, int type,
+                     int btype)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    if (type == 0x4 && battle_config.display_delay_skill_fail == 0)
+    {
+        return 0;
+    }
+
+    WFIFOW (fd, 0) = 0x110;
+    WFIFOW (fd, 2) = skill_id;
+    WFIFOW (fd, 4) = btype;
+    WFIFOW (fd, 6) = 0;
+    WFIFOB (fd, 8) = 0;
+    WFIFOB (fd, 9) = type;
+    WFIFOSET (fd, packet_len_table[0x110]);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル攻撃エフェクト&ダメージ
+ *------------------------------------------
+ */
+int clif_skill_damage (struct block_list *src, struct block_list *dst,
+                       unsigned int tick, int sdelay, int ddelay, int damage,
+                       int div, int skill_id, int skill_lv, int type)
+{
+    unsigned char buf[64];
+    struct status_change *sc_data;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, dst);
+
+    sc_data = battle_get_sc_data (dst);
+
+    if (type != 5 && dst->type == BL_PC
+        && ((struct map_session_data *) dst)->special_state.infinite_endure)
+        type = 9;
+    if (sc_data)
+    {
+        if (type != 5 && sc_data[SC_ENDURE].timer != -1)
+            type = 9;
+        if (sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
+            damage =
+                damage * (5 + sc_data[SC_HALLUCINATION].val1) + MRAND (100);
+    }
+
+    WBUFW (buf, 0) = 0x1de;
+    WBUFW (buf, 2) = skill_id;
+    WBUFL (buf, 4) = src->id;
+    WBUFL (buf, 8) = dst->id;
+    WBUFL (buf, 12) = tick;
+    WBUFL (buf, 16) = sdelay;
+    WBUFL (buf, 20) = ddelay;
+    WBUFL (buf, 24) = damage;
+    WBUFW (buf, 28) = skill_lv;
+    WBUFW (buf, 30) = div;
+    WBUFB (buf, 32) = (type > 0) ? type : skill_get_hit (skill_id);
+    clif_send (buf, packet_len_table[0x1de], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * 吹き飛ばしスキル攻撃エフェクト&ダメージ
+ *------------------------------------------
+ */
+int clif_skill_damage2 (struct block_list *src, struct block_list *dst,
+                        unsigned int tick, int sdelay, int ddelay, int damage,
+                        int div, int skill_id, int skill_lv, int type)
+{
+    unsigned char buf[64];
+    struct status_change *sc_data;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, dst);
+
+    sc_data = battle_get_sc_data (dst);
+
+    if (type != 5 && dst->type == BL_PC
+        && ((struct map_session_data *) dst)->special_state.infinite_endure)
+        type = 9;
+    if (sc_data)
+    {
+        if (type != 5 && sc_data[SC_ENDURE].timer != -1)
+            type = 9;
+        if (sc_data[SC_HALLUCINATION].timer != -1 && damage > 0)
+            damage =
+                damage * (5 + sc_data[SC_HALLUCINATION].val1) + MRAND (100);
+    }
+
+    WBUFW (buf, 0) = 0x115;
+    WBUFW (buf, 2) = skill_id;
+    WBUFL (buf, 4) = src->id;
+    WBUFL (buf, 8) = dst->id;
+    WBUFL (buf, 12) = tick;
+    WBUFL (buf, 16) = sdelay;
+    WBUFL (buf, 20) = ddelay;
+    WBUFW (buf, 24) = dst->x;
+    WBUFW (buf, 26) = dst->y;
+    WBUFW (buf, 28) = damage;
+    WBUFW (buf, 30) = skill_lv;
+    WBUFW (buf, 32) = div;
+    WBUFB (buf, 34) = (type > 0) ? type : skill_get_hit (skill_id);
+    clif_send (buf, packet_len_table[0x115], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * 支援/回復スキルエフェクト
+ *------------------------------------------
+ */
+int clif_skill_nodamage (struct block_list *src, struct block_list *dst,
+                         int skill_id, int heal, int fail)
+{
+    unsigned char buf[32];
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, dst);
+
+    WBUFW (buf, 0) = 0x11a;
+    WBUFW (buf, 2) = skill_id;
+    WBUFW (buf, 4) = (heal > 0x7fff) ? 0x7fff : heal;
+    WBUFL (buf, 6) = dst->id;
+    WBUFL (buf, 10) = src->id;
+    WBUFB (buf, 14) = fail;
+    clif_send (buf, packet_len_table[0x11a], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * 場所スキルエフェクト
+ *------------------------------------------
+ */
+int clif_skill_poseffect (struct block_list *src, int skill_id, int val,
+                          int x, int y, int tick)
+{
+    unsigned char buf[32];
+
+    nullpo_retr (0, src);
+
+    WBUFW (buf, 0) = 0x117;
+    WBUFW (buf, 2) = skill_id;
+    WBUFL (buf, 4) = src->id;
+    WBUFW (buf, 8) = val;
+    WBUFW (buf, 10) = x;
+    WBUFW (buf, 12) = y;
+    WBUFL (buf, 14) = tick;
+    clif_send (buf, packet_len_table[0x117], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ * 場所スキルエフェクト表示
+ *------------------------------------------
+ */
+int clif_skill_setunit (struct skill_unit *unit)
+{
+    unsigned char buf[128];
+    struct block_list *bl;
+
+    nullpo_retr (0, unit);
+
+    bl = map_id2bl (unit->group->src_id);
+
+    memset (WBUFP (buf, 0), 0, packet_len_table[0x1c9]);
+    WBUFW (buf, 0) = 0x1c9;
+    WBUFL (buf, 2) = unit->bl.id;
+    WBUFL (buf, 6) = unit->group->src_id;
+    WBUFW (buf, 10) = unit->bl.x;
+    WBUFW (buf, 12) = unit->bl.y;
+    WBUFB (buf, 14) = unit->group->unit_id;
+    WBUFB (buf, 15) = 1;
+    WBUFL (buf, 15 + 1) = 0;    //1-4調べた限り固定
+    WBUFL (buf, 15 + 5) = 0;    //5-8調べた限り固定
+    //9-12マップごとで一定の77-80とはまた違う4バイトのかなり大きな数字
+    WBUFL (buf, 15 + 13) = unit->bl.y - 0x12;   //13-16ユニットのY座標-18っぽい(Y:17でFF FF FF FF)
+    WBUFL (buf, 15 + 17) = 0x004f37dd;  //17-20調べた限り固定(0x1b2で0x004fdbddだった)
+    WBUFL (buf, 15 + 21) = 0x0012f674;  //21-24調べた限り固定
+    WBUFL (buf, 15 + 25) = 0x0012f664;  //25-28調べた限り固定
+    WBUFL (buf, 15 + 29) = 0x0012f654;  //29-32調べた限り固定
+    WBUFL (buf, 15 + 33) = 0x77527bbc;  //33-36調べた限り固定
+    //37-39
+    WBUFB (buf, 15 + 40) = 0x2d;    //40調べた限り固定
+    WBUFL (buf, 15 + 41) = 0;   //41-44調べた限り0固定
+    WBUFL (buf, 15 + 45) = 0;   //45-48調べた限り0固定
+    WBUFL (buf, 15 + 49) = 0;   //49-52調べた限り0固定
+    WBUFL (buf, 15 + 53) = 0x0048d919;  //53-56調べた限り固定(0x01b2で0x00495119だった)
+    WBUFL (buf, 15 + 57) = 0x0000003e;  //57-60調べた限り固定
+    WBUFL (buf, 15 + 61) = 0x0012f66c;  //61-64調べた限り固定
+    //65-68
+    //69-72
+    if (bl)
+        WBUFL (buf, 15 + 73) = bl->y;   //73-76術者のY座標
+    WBUFL (buf, 15 + 77) = unit->bl.m;  //77-80マップIDかなぁ?かなり2バイトで足りそうな数字
+    WBUFB (buf, 15 + 81) = 0xaa;    //81終端文字0xaa
+
+    /*      Graffiti [Valaris]      */
+    if (unit->group->unit_id == 0xb0)
+    {
+        WBUFL (buf, 15) = 1;
+        WBUFL (buf, 16) = 1;
+        memcpy (WBUFP (buf, 17), unit->group->valstr, 80);
+    }
+
+    clif_send (buf, packet_len_table[0x1c9], &unit->bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ * 場所スキルエフェクト削除
+ *------------------------------------------
+ */
+int clif_skill_delunit (struct skill_unit *unit)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, unit);
+
+    WBUFW (buf, 0) = 0x120;
+    WBUFL (buf, 2) = unit->bl.id;
+    clif_send (buf, packet_len_table[0x120], &unit->bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ * ワープ場所選択
+ *------------------------------------------
+ */
+int clif_skill_warppoint (struct map_session_data *sd, int skill_num,
+                          const char *map1, const char *map2,
+                          const char *map3, const char *map4)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x11c;
+    WFIFOW (fd, 2) = skill_num;
+    memcpy (WFIFOP (fd, 4), map1, 16);
+    memcpy (WFIFOP (fd, 20), map2, 16);
+    memcpy (WFIFOP (fd, 36), map3, 16);
+    memcpy (WFIFOP (fd, 52), map4, 16);
+    WFIFOSET (fd, packet_len_table[0x11c]);
+    return 0;
+}
+
+/*==========================================
+ * メモ応答
+ *------------------------------------------
+ */
+int clif_skill_memo (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x11e;
+    WFIFOB (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x11e]);
+    return 0;
+}
+
+int clif_skill_teleportmessage (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x189;
+    WFIFOW (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x189]);
+    return 0;
+}
+
+/*==========================================
+ * モンスター情報
+ *------------------------------------------
+ */
+int clif_skill_estimation (struct map_session_data *sd,
+                           struct block_list *dst)
+{
+    struct mob_data *md;
+    unsigned char buf[64];
+    int  i;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, dst);
+
+    if (dst->type != BL_MOB)
+        return 0;
+    if ((md = (struct mob_data *) dst) == NULL)
+        return 0;
+
+    WBUFW (buf, 0) = 0x18c;
+    WBUFW (buf, 2) = mob_get_viewclass (md->mob_class);
+    WBUFW (buf, 4) = mob_db[md->mob_class].lv;
+    WBUFW (buf, 6) = mob_db[md->mob_class].size;
+    WBUFL (buf, 8) = md->hp;
+    WBUFW (buf, 12) = battle_get_def2 (&md->bl);
+    WBUFW (buf, 14) = mob_db[md->mob_class].race;
+    WBUFW (buf, 16) =
+        battle_get_mdef2 (&md->bl) - (mob_db[md->mob_class].vit >> 1);
+    WBUFW (buf, 18) = battle_get_elem_type (&md->bl);
+    for (i = 0; i < 9; i++)
+        WBUFB (buf, 20 + i) = battle_attr_fix (100, i + 1, md->def_ele);
+
+    if (sd->status.party_id > 0)
+        clif_send (buf, packet_len_table[0x18c], &sd->bl, PARTY_AREA);
+    else
+    {
+        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x18c]);
+        WFIFOSET (sd->fd, packet_len_table[0x18c]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * 状態異常アイコン/メッセージ表示
+ *------------------------------------------
+ */
+int clif_status_change (struct block_list *bl, int type, int flag)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x0196;
+    WBUFW (buf, 2) = type;
+    WBUFL (buf, 4) = bl->id;
+    WBUFB (buf, 8) = flag;
+    clif_send (buf, packet_len_table[0x196], bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ * Send message (modified by [Yor])
+ *------------------------------------------
+ */
+int clif_displaymessage (const int fd, char *mes)
+{
+    int  len_mes = strlen (mes);
+
+    if (len_mes > 0)
+    {                           // don't send a void message (it's not displaying on the client chat). @help can send void line.
+        WFIFOW (fd, 0) = 0x8e;
+        WFIFOW (fd, 2) = 5 + len_mes;   // 4 + len + NULL teminate
+        memcpy (WFIFOP (fd, 4), mes, len_mes + 1);
+        WFIFOSET (fd, 5 + len_mes);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 天の声を送信する
+ *------------------------------------------
+ */
+int clif_GMmessage (struct block_list *bl, char *mes, int len, int flag)
+{
+    unsigned char lbuf[255];
+    unsigned char *buf =
+        ((len + 16) >= sizeof (lbuf)) ? (unsigned char*)malloc (len + 16) : lbuf;
+    int  lp = (flag & 0x10) ? 8 : 4;
+
+    WBUFW (buf, 0) = 0x9a;
+    WBUFW (buf, 2) = len + lp;
+    WBUFL (buf, 4) = 0x65756c62;
+    memcpy (WBUFP (buf, lp), mes, len);
+    flag &= 0x07;
+    clif_send (buf, WBUFW (buf, 2), bl,
+               (flag == 1) ? ALL_SAMEMAP :
+               (flag == 2) ? AREA : (flag == 3) ? SELF : ALL_CLIENT);
+    if (buf != lbuf)
+        free (buf);
+    return 0;
+}
+
+/*==========================================
+ * HPSP回復エフェクトを送信する
+ *------------------------------------------
+ */
+int clif_heal (int fd, int type, int val)
+{
+    WFIFOW (fd, 0) = 0x13d;
+    WFIFOW (fd, 2) = type;
+    WFIFOW (fd, 4) = val;
+    WFIFOSET (fd, packet_len_table[0x13d]);
+
+    return 0;
+}
+
+/*==========================================
+ * 復活する
+ *------------------------------------------
+ */
+int clif_resurrection (struct block_list *bl, int type)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+    {                           // disguises [Valaris]
+        struct map_session_data *sd = ((struct map_session_data *) bl);
+        if (sd && sd->disguise > 23 && sd->disguise < 4001)
+            clif_spawnpc (sd);
+    }
+
+    WBUFW (buf, 0) = 0x148;
+    WBUFL (buf, 2) = bl->id;
+    WBUFW (buf, 6) = type;
+
+    clif_send (buf, packet_len_table[0x148], bl, type == 1 ? AREA : AREA_WOS);
+
+    return 0;
+}
+
+/*==========================================
+ * PVP実装?(仮)
+ *------------------------------------------
+ */
+int clif_set0199 (int fd, int type)
+{
+    WFIFOW (fd, 0) = 0x199;
+    WFIFOW (fd, 2) = type;
+    WFIFOSET (fd, packet_len_table[0x199]);
+
+    return 0;
+}
+
+/*==========================================
+ * PVP実装?(仮)
+ *------------------------------------------
+ */
+int clif_pvpset (struct map_session_data *sd, int pvprank, int pvpnum,
+                 int type)
+{
+    nullpo_retr (0, sd);
+
+    if (map[sd->bl.m].flag.nopvp)
+        return 0;
+
+    if (type == 2)
+    {
+        WFIFOW (sd->fd, 0) = 0x19a;
+        WFIFOL (sd->fd, 2) = sd->bl.id;
+        if (pvprank <= 0)
+            pc_calc_pvprank (sd);
+        WFIFOL (sd->fd, 6) = pvprank;
+        WFIFOL (sd->fd, 10) = pvpnum;
+        WFIFOSET (sd->fd, packet_len_table[0x19a]);
+    }
+    else
+    {
+        char buf[32];
+
+        WBUFW (buf, 0) = 0x19a;
+        WBUFL (buf, 2) = sd->bl.id;
+        if (sd->status.option & 0x46)
+            WBUFL (buf, 6) = -1;
+        else if (pvprank <= 0)
+            pc_calc_pvprank (sd);
+        WBUFL (buf, 6) = pvprank;
+        WBUFL (buf, 10) = pvpnum;
+        if (!type)
+            clif_send (buf, packet_len_table[0x19a], &sd->bl, AREA);
+        else
+            clif_send (buf, packet_len_table[0x19a], &sd->bl, ALL_SAMEMAP);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_send0199 (int map, int type)
+{
+    struct block_list bl;
+    char buf[16];
+
+    bl.m = map;
+    WBUFW (buf, 0) = 0x199;
+    WBUFW (buf, 2) = type;
+    clif_send (buf, packet_len_table[0x199], &bl, ALL_SAMEMAP);
+
+    return 0;
+}
+
+/*==========================================
+ * 精錬エフェクトを送信する
+ *------------------------------------------
+ */
+int clif_refine (int fd, struct map_session_data *sd, int fail, int index,
+                 int val)
+{
+    WFIFOW (fd, 0) = 0x188;
+    WFIFOW (fd, 2) = fail;
+    WFIFOW (fd, 4) = index + 2;
+    WFIFOW (fd, 6) = val;
+    WFIFOSET (fd, packet_len_table[0x188]);
+
+    return 0;
+}
+
+/*==========================================
+ * Wisp/page is transmitted to the destination player
+ *------------------------------------------
+ */
+int clif_wis_message (int fd, char *nick, char *mes, int mes_len)   // R 0097 <len>.w <nick>.24B <message>.?B
+{
+    WFIFOW (fd, 0) = 0x97;
+    WFIFOW (fd, 2) = mes_len + 24 + 4;
+    memcpy (WFIFOP (fd, 4), nick, 24);
+    memcpy (WFIFOP (fd, 28), mes, mes_len);
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * The transmission result of Wisp/page is transmitted to the source player
+ *------------------------------------------
+ */
+int clif_wis_end (int fd, int flag) // R 0098 <type>.B: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+{
+    WFIFOW (fd, 0) = 0x98;
+    WFIFOW (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x98]);
+    return 0;
+}
+
+/*==========================================
+ * キャラID名前引き結果を送信する
+ *------------------------------------------
+ */
+int clif_solved_charname (struct map_session_data *sd, int char_id)
+{
+    char *p = map_charid2nick (char_id);
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    if (p != NULL)
+    {
+        WFIFOW (fd, 0) = 0x194;
+        WFIFOL (fd, 2) = char_id;
+        memcpy (WFIFOP (fd, 6), p, 24);
+        WFIFOSET (fd, packet_len_table[0x194]);
+    }
+    else
+    {
+        map_reqchariddb (sd, char_id);
+        chrif_searchcharid (char_id);
+    }
+    return 0;
+}
+
+/*==========================================
+ * カードの挿入可能リストを返す
+ *------------------------------------------
+ */
+int clif_use_card (struct map_session_data *sd, int idx)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->inventory_data[idx])
+    {
+        int  i, c;
+        int  ep = sd->inventory_data[idx]->equip;
+        int  fd = sd->fd;
+        WFIFOW (fd, 0) = 0x017b;
+
+        for (i = c = 0; i < MAX_INVENTORY; i++)
+        {
+            int  j;
+
+            if (sd->inventory_data[i] == NULL)
+                continue;
+            if (sd->inventory_data[i]->type != 4 && sd->inventory_data[i]->type != 5)   // 武器防具じゃない
+                continue;
+            if (sd->status.inventory[i].card[0] == 0x00ff)  // 製造武器
+                continue;
+            if (sd->status.inventory[i].card[0] == (short) 0xff00
+                || sd->status.inventory[i].card[0] == 0x00fe)
+                continue;
+            if (sd->status.inventory[i].identify == 0)  // 未鑑定
+                continue;
+
+            if ((sd->inventory_data[i]->equip & ep) == 0)   // 装備個所が違う
+                continue;
+            if (sd->inventory_data[i]->type == 4 && ep == 32)   // 盾カードと両手武器
+                continue;
+
+            for (j = 0; j < sd->inventory_data[i]->slot; j++)
+            {
+                if (sd->status.inventory[i].card[j] == 0)
+                    break;
+            }
+            if (j == sd->inventory_data[i]->slot)   // すでにカードが一杯
+                continue;
+
+            WFIFOW (fd, 4 + c * 2) = i + 2;
+            c++;
+        }
+        WFIFOW (fd, 2) = 4 + c * 2;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * カードの挿入終了
+ *------------------------------------------
+ */
+int clif_insert_card (struct map_session_data *sd, int idx_equip,
+                      int idx_card, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x17d;
+    WFIFOW (fd, 2) = idx_equip + 2;
+    WFIFOW (fd, 4) = idx_card + 2;
+    WFIFOB (fd, 6) = flag;
+    WFIFOSET (fd, packet_len_table[0x17d]);
+    return 0;
+}
+
+/*==========================================
+ * 鑑定可能アイテムリスト送信
+ *------------------------------------------
+ */
+int clif_item_identify_list (struct map_session_data *sd)
+{
+    int  i, c;
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x177;
+    for (i = c = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid > 0
+            && sd->status.inventory[i].identify != 1)
+        {
+            WFIFOW (fd, c * 2 + 4) = i + 2;
+            c++;
+        }
+    }
+    if (c > 0)
+    {
+        WFIFOW (fd, 2) = c * 2 + 4;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * 鑑定結果
+ *------------------------------------------
+ */
+int clif_item_identified (struct map_session_data *sd, int idx, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x179;
+    WFIFOW (fd, 2) = idx + 2;
+    WFIFOB (fd, 4) = flag;
+    WFIFOSET (fd, packet_len_table[0x179]);
+    return 0;
+}
+
+/*==========================================
+ * 修理可能アイテムリスト送信
+ * ※実際のパケットがわからないので動作しません
+ *------------------------------------------
+ */
+int clif_item_repair_list (struct map_session_data *sd)
+{
+    int  i, c;
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x0;
+    for (i = c = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid > 0
+            && sd->status.inventory[i].broken != 0)
+        {
+            WFIFOW (fd, c * 2 + 4) = i + 2;
+            c++;
+        }
+    }
+    if (c > 0)
+    {
+        WFIFOW (fd, 2) = c * 2 + 4;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * アイテムによる一時的なスキル効果
+ *------------------------------------------
+ */
+int clif_item_skill (struct map_session_data *sd, int skillid, int skilllv,
+                     const char *name)
+{
+    int  range, fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x147;
+    WFIFOW (fd, 2) = skillid;
+    WFIFOW (fd, 4) = skill_get_inf (skillid);
+    WFIFOW (fd, 6) = 0;
+    WFIFOW (fd, 8) = skilllv;
+    WFIFOW (fd, 10) = skill_get_sp (skillid, skilllv);
+    range = skill_get_range (skillid, skilllv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    WFIFOW (fd, 12) = range;
+    memcpy (WFIFOP (fd, 14), name, 24);
+    WFIFOB (fd, 38) = 0;
+    WFIFOSET (fd, packet_len_table[0x147]);
+    return 0;
+}
+
+/*==========================================
+ * カートにアイテム追加
+ *------------------------------------------
+ */
+int clif_cart_additem (struct map_session_data *sd, int n, int amount,
+                       int fail)
+{
+    int  view, j, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    if (n < 0 || n >= MAX_CART || sd->status.cart[n].nameid <= 0)
+        return 1;
+
+    WBUFW (buf, 0) = 0x124;
+    WBUFW (buf, 2) = n + 2;
+    WBUFL (buf, 4) = amount;
+    if ((view = itemdb_viewid (sd->status.cart[n].nameid)) > 0)
+        WBUFW (buf, 8) = view;
+    else
+        WBUFW (buf, 8) = sd->status.cart[n].nameid;
+    WBUFB (buf, 10) = sd->status.cart[n].identify;
+    if (sd->status.cart[n].broken == 1) //is weapon broken [Valaris]
+        WBUFB (buf, 11) = 1;
+    else
+        WBUFB (buf, 11) = sd->status.cart[n].attribute;
+    WBUFB (buf, 12) = sd->status.cart[n].refine;
+    if (sd->status.cart[n].card[0] == 0x00ff
+        || sd->status.cart[n].card[0] == 0x00fe
+        || sd->status.cart[n].card[0] == (short) 0xff00)
+    {
+        WBUFW (buf, 13) = sd->status.cart[n].card[0];
+        WBUFW (buf, 15) = sd->status.cart[n].card[1];
+        WBUFW (buf, 17) = sd->status.cart[n].card[2];
+        WBUFW (buf, 19) = sd->status.cart[n].card[3];
+    }
+    else
+    {
+        if (sd->status.cart[n].card[0] > 0
+            && (j = itemdb_viewid (sd->status.cart[n].card[0])) > 0)
+            WBUFW (buf, 13) = j;
+        else
+            WBUFW (buf, 13) = sd->status.cart[n].card[0];
+        if (sd->status.cart[n].card[1] > 0
+            && (j = itemdb_viewid (sd->status.cart[n].card[1])) > 0)
+            WBUFW (buf, 15) = j;
+        else
+            WBUFW (buf, 15) = sd->status.cart[n].card[1];
+        if (sd->status.cart[n].card[2] > 0
+            && (j = itemdb_viewid (sd->status.cart[n].card[2])) > 0)
+            WBUFW (buf, 17) = j;
+        else
+            WBUFW (buf, 17) = sd->status.cart[n].card[2];
+        if (sd->status.cart[n].card[3] > 0
+            && (j = itemdb_viewid (sd->status.cart[n].card[3])) > 0)
+            WBUFW (buf, 19) = j;
+        else
+            WBUFW (buf, 19) = sd->status.cart[n].card[3];
+    }
+    WFIFOSET (fd, packet_len_table[0x124]);
+    return 0;
+}
+
+/*==========================================
+ * カートからアイテム削除
+ *------------------------------------------
+ */
+int clif_cart_delitem (struct map_session_data *sd, int n, int amount)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+
+    WFIFOW (fd, 0) = 0x125;
+    WFIFOW (fd, 2) = n + 2;
+    WFIFOL (fd, 4) = amount;
+
+    WFIFOSET (fd, packet_len_table[0x125]);
+
+    return 0;
+}
+
+/*==========================================
+ * カートのアイテムリスト
+ *------------------------------------------
+ */
+int clif_cart_itemlist (struct map_session_data *sd)
+{
+    struct item_data *id;
+    int  i, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+    WBUFW (buf, 0) = 0x1ef;
+    for (i = 0, n = 0; i < MAX_CART; i++)
+    {
+        if (sd->status.cart[i].nameid <= 0)
+            continue;
+        id = itemdb_search (sd->status.cart[i].nameid);
+        if (itemdb_isequip2 (id))
+            continue;
+        WBUFW (buf, n * 18 + 4) = i + 2;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 18 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 18 + 6) = sd->status.cart[i].nameid;
+        WBUFB (buf, n * 18 + 8) = id->type;
+        WBUFB (buf, n * 18 + 9) = sd->status.cart[i].identify;
+        WBUFW (buf, n * 18 + 10) = sd->status.cart[i].amount;
+        WBUFW (buf, n * 18 + 12) = 0;
+        WBUFW (buf, n * 18 + 14) = sd->status.cart[i].card[0];
+        WBUFW (buf, n * 18 + 16) = sd->status.cart[i].card[1];
+        WBUFW (buf, n * 18 + 18) = sd->status.cart[i].card[2];
+        WBUFW (buf, n * 18 + 20) = sd->status.cart[i].card[3];
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 18;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * カートの装備品リスト
+ *------------------------------------------
+ */
+int clif_cart_equiplist (struct map_session_data *sd)
+{
+    struct item_data *id;
+    int  i, j, n, fd;
+    unsigned char *buf;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    buf = WFIFOP (fd, 0);
+
+    WBUFW (buf, 0) = 0x122;
+    for (i = 0, n = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.cart[i].nameid <= 0)
+            continue;
+        id = itemdb_search (sd->status.cart[i].nameid);
+        if (!itemdb_isequip2 (id))
+            continue;
+        WBUFW (buf, n * 20 + 4) = i + 2;
+        if (id->view_id > 0)
+            WBUFW (buf, n * 20 + 6) = id->view_id;
+        else
+            WBUFW (buf, n * 20 + 6) = sd->status.cart[i].nameid;
+        WBUFB (buf, n * 20 + 8) = id->type;
+        WBUFB (buf, n * 20 + 9) = sd->status.cart[i].identify;
+        WBUFW (buf, n * 20 + 10) = id->equip;
+        WBUFW (buf, n * 20 + 12) = sd->status.cart[i].equip;
+        if (sd->status.cart[i].broken == 1)
+            WBUFB (buf, n * 20 + 14) = 1;   //is weapon broken [Valaris]
+        else
+            WBUFB (buf, n * 20 + 14) = sd->status.cart[i].attribute;
+        WBUFB (buf, n * 20 + 15) = sd->status.cart[i].refine;
+        if (sd->status.cart[i].card[0] == 0x00ff
+            || sd->status.cart[i].card[0] == 0x00fe
+            || sd->status.cart[i].card[0] == (short) 0xff00)
+        {
+            WBUFW (buf, n * 20 + 16) = sd->status.cart[i].card[0];
+            WBUFW (buf, n * 20 + 18) = sd->status.cart[i].card[1];
+            WBUFW (buf, n * 20 + 20) = sd->status.cart[i].card[2];
+            WBUFW (buf, n * 20 + 22) = sd->status.cart[i].card[3];
+        }
+        else
+        {
+            if (sd->status.cart[i].card[0] > 0
+                && (j = itemdb_viewid (sd->status.cart[i].card[0])) > 0)
+                WBUFW (buf, n * 20 + 16) = j;
+            else
+                WBUFW (buf, n * 20 + 16) = sd->status.cart[i].card[0];
+            if (sd->status.cart[i].card[1] > 0
+                && (j = itemdb_viewid (sd->status.cart[i].card[1])) > 0)
+                WBUFW (buf, n * 20 + 18) = j;
+            else
+                WBUFW (buf, n * 20 + 18) = sd->status.cart[i].card[1];
+            if (sd->status.cart[i].card[2] > 0
+                && (j = itemdb_viewid (sd->status.cart[i].card[2])) > 0)
+                WBUFW (buf, n * 20 + 20) = j;
+            else
+                WBUFW (buf, n * 20 + 20) = sd->status.cart[i].card[2];
+            if (sd->status.cart[i].card[3] > 0
+                && (j = itemdb_viewid (sd->status.cart[i].card[3])) > 0)
+                WBUFW (buf, n * 20 + 22) = j;
+            else
+                WBUFW (buf, n * 20 + 22) = sd->status.cart[i].card[3];
+        }
+        n++;
+    }
+    if (n)
+    {
+        WBUFW (buf, 2) = 4 + n * 20;
+        WFIFOSET (fd, WFIFOW (fd, 2));
+    }
+    return 0;
+}
+
+/*==========================================
+ * パーティ作成完了
+ * Relay the result of party creation.
+ *
+ * (R 00fa <flag>.B)
+ *
+ * flag:
+ *  0 The party was created.
+ *  1 The party name is invalid/taken.
+ *  2 The character is already in a party.
+ *------------------------------------------
+ */
+int clif_party_created (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xfa;
+    WFIFOB (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0xfa]);
+    return 0;
+}
+
+/*==========================================
+ * パーティ情報送信
+ *------------------------------------------
+ */
+int clif_party_info (struct party *p, int fd)
+{
+    unsigned char buf[1024];
+    int  i, c;
+    struct map_session_data *sd = NULL;
+
+    nullpo_retr (0, p);
+
+    WBUFW (buf, 0) = 0xfb;
+    memcpy (WBUFP (buf, 4), p->name, 24);
+    for (i = c = 0; i < MAX_PARTY; i++)
+    {
+        struct party_member *m = &p->member[i];
+        if (m->account_id > 0)
+        {
+            if (sd == NULL)
+                sd = m->sd;
+            WBUFL (buf, 28 + c * 46) = m->account_id;
+            memcpy (WBUFP (buf, 28 + c * 46 + 4), m->name, 24);
+            memcpy (WBUFP (buf, 28 + c * 46 + 28), m->map, 16);
+            WBUFB (buf, 28 + c * 46 + 44) = (m->leader) ? 0 : 1;
+            WBUFB (buf, 28 + c * 46 + 45) = (m->online) ? 0 : 1;
+            c++;
+        }
+    }
+    WBUFW (buf, 2) = 28 + c * 46;
+    if (fd >= 0)
+    {                           // fdが設定されてるならそれに送る
+        memcpy (WFIFOP (fd, 0), buf, WBUFW (buf, 2));
+        WFIFOSET (fd, WFIFOW (fd, 2));
+        return 9;
+    }
+    if (sd != NULL)
+        clif_send (buf, WBUFW (buf, 2), &sd->bl, PARTY);
+    return 0;
+}
+
+/*==========================================
+ * パーティ勧誘
+ * Relay a party invitation.
+ *
+ * (R 00fe <sender_ID>.l <party_name>.24B)
+ *------------------------------------------
+ */
+int clif_party_invite (struct map_session_data *sd,
+                       struct map_session_data *tsd)
+{
+    int  fd;
+    struct party *p;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, tsd);
+
+    fd = tsd->fd;
+
+    if (!(p = party_search (sd->status.party_id)))
+        return 0;
+
+    WFIFOW (fd, 0) = 0xfe;
+    WFIFOL (fd, 2) = sd->status.account_id;
+    memcpy (WFIFOP (fd, 6), p->name, 24);
+    WFIFOSET (fd, packet_len_table[0xfe]);
+    return 0;
+}
+
+/*==========================================
+ * パーティ勧誘結果
+ * Relay the response to a party invitation.
+ *
+ * (R 00fd <name>.24B <flag>.B)
+ *
+ * flag:
+ *  0 The character is already in a party.
+ *  1 The invitation was rejected.
+ *  2 The invitation was accepted.
+ *  3 The party is full.
+ *  4 The character is in the same party.
+ *------------------------------------------
+ */
+int clif_party_inviteack (struct map_session_data *sd, char *nick, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xfd;
+    memcpy (WFIFOP (fd, 2), nick, 24);
+    WFIFOB (fd, 26) = flag;
+    WFIFOSET (fd, packet_len_table[0xfd]);
+    return 0;
+}
+
+/*==========================================
+ * パーティ設定送信
+ * flag & 0x001=exp変更ミス
+ *        0x010=item変更ミス
+ *        0x100=一人にのみ送信
+ *------------------------------------------
+ */
+int clif_party_option (struct party *p, struct map_session_data *sd, int flag)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, p);
+
+//  if(battle_config.etc_log)
+//      printf("clif_party_option: %d %d %d\n",p->exp,p->item,flag);
+    if (sd == NULL && flag == 0)
+    {
+        int  i;
+        for (i = 0; i < MAX_PARTY; i++)
+            if ((sd = map_id2sd (p->member[i].account_id)) != NULL)
+                break;
+    }
+    if (sd == NULL)
+        return 0;
+    WBUFW (buf, 0) = 0x101;
+    WBUFW (buf, 2) = ((flag & 0x01) ? 2 : p->exp);
+    WBUFW (buf, 4) = ((flag & 0x10) ? 2 : p->item);
+    if (flag == 0)
+        clif_send (buf, packet_len_table[0x101], &sd->bl, PARTY);
+    else
+    {
+        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x101]);
+        WFIFOSET (sd->fd, packet_len_table[0x101]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * パーティ脱退(脱退前に呼ぶこと)
+ *------------------------------------------
+ */
+int clif_party_leaved (struct party *p, struct map_session_data *sd,
+                       int account_id, char *name, int flag)
+{
+    unsigned char buf[64];
+    int  i;
+
+    nullpo_retr (0, p);
+
+    WBUFW (buf, 0) = 0x105;
+    WBUFL (buf, 2) = account_id;
+    memcpy (WBUFP (buf, 6), name, 24);
+    WBUFB (buf, 30) = flag & 0x0f;
+
+    if ((flag & 0xf0) == 0)
+    {
+        if (sd == NULL)
+            for (i = 0; i < MAX_PARTY; i++)
+                if ((sd = p->member[i].sd) != NULL)
+                    break;
+        if (sd != NULL)
+            clif_send (buf, packet_len_table[0x105], &sd->bl, PARTY);
+    }
+    else if (sd != NULL)
+    {
+        memcpy (WFIFOP (sd->fd, 0), buf, packet_len_table[0x105]);
+        WFIFOSET (sd->fd, packet_len_table[0x105]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * パーティメッセージ送信
+ *------------------------------------------
+ */
+int clif_party_message (struct party *p, int account_id, char *mes, int len)
+{
+    struct map_session_data *sd;
+    int  i;
+
+    nullpo_retr (0, p);
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        if ((sd = p->member[i].sd) != NULL)
+            break;
+    }
+    if (sd != NULL)
+    {
+        unsigned char buf[1024];
+        WBUFW (buf, 0) = 0x109;
+        WBUFW (buf, 2) = len + 8;
+        WBUFL (buf, 4) = account_id;
+        memcpy (WBUFP (buf, 8), mes, len);
+        clif_send (buf, len + 8, &sd->bl, PARTY);
+    }
+    return 0;
+}
+
+/*==========================================
+ * パーティ座標通知
+ *------------------------------------------
+ */
+int clif_party_xy (struct party *p, struct map_session_data *sd)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x107;
+    WBUFL (buf, 2) = sd->status.account_id;
+    WBUFW (buf, 6) = sd->bl.x;
+    WBUFW (buf, 8) = sd->bl.y;
+    clif_send (buf, packet_len_table[0x107], &sd->bl, PARTY_SAMEMAP_WOS);
+//  if(battle_config.etc_log)
+//      printf("clif_party_xy %d\n",sd->status.account_id);
+    return 0;
+}
+
+/*==========================================
+ * パーティHP通知
+ *------------------------------------------
+ */
+int clif_party_hp (struct party *p, struct map_session_data *sd)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x106;
+    WBUFL (buf, 2) = sd->status.account_id;
+    WBUFW (buf, 6) = (sd->status.hp > 0x7fff) ? 0x7fff : sd->status.hp;
+    WBUFW (buf, 8) =
+        (sd->status.max_hp > 0x7fff) ? 0x7fff : sd->status.max_hp;
+    clif_send (buf, packet_len_table[0x106], &sd->bl, PARTY_AREA_WOS);
+//  if(battle_config.etc_log)
+//      printf("clif_party_hp %d\n",sd->status.account_id);
+    return 0;
+}
+
+/*==========================================
+ * パーティ場所移動(未使用)
+ *------------------------------------------
+ */
+int clif_party_move (struct party *p, struct map_session_data *sd, int online)
+{
+    unsigned char buf[128];
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, p);
+
+    WBUFW (buf, 0) = 0x104;
+    WBUFL (buf, 2) = sd->status.account_id;
+    WBUFL (buf, 6) = 0;
+    WBUFW (buf, 10) = sd->bl.x;
+    WBUFW (buf, 12) = sd->bl.y;
+    WBUFB (buf, 14) = !online;
+    memcpy (WBUFP (buf, 15), p->name, 24);
+    memcpy (WBUFP (buf, 39), sd->status.name, 24);
+    memcpy (WBUFP (buf, 63), map[sd->bl.m].name, 16);
+    clif_send (buf, packet_len_table[0x104], &sd->bl, PARTY);
+    return 0;
+}
+
+/*==========================================
+ * 攻撃するために移動が必要
+ *------------------------------------------
+ */
+int clif_movetoattack (struct map_session_data *sd, struct block_list *bl)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, bl);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x139;
+    WFIFOL (fd, 2) = bl->id;
+    WFIFOW (fd, 6) = bl->x;
+    WFIFOW (fd, 8) = bl->y;
+    WFIFOW (fd, 10) = sd->bl.x;
+    WFIFOW (fd, 12) = sd->bl.y;
+    WFIFOW (fd, 14) = sd->attackrange;
+    WFIFOSET (fd, packet_len_table[0x139]);
+    return 0;
+}
+
+/*==========================================
+ * 製造エフェクト
+ *------------------------------------------
+ */
+int clif_produceeffect (struct map_session_data *sd, int flag, int nameid)
+{
+    int  view, fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    // 名前の登録と送信を先にしておく
+    if (map_charid2nick (sd->status.char_id) == NULL)
+        map_addchariddb (sd->status.char_id, sd->status.name);
+    clif_solved_charname (sd, sd->status.char_id);
+
+    WFIFOW (fd, 0) = 0x18f;
+    WFIFOW (fd, 2) = flag;
+    if ((view = itemdb_viewid (nameid)) > 0)
+        WFIFOW (fd, 4) = view;
+    else
+        WFIFOW (fd, 4) = nameid;
+    WFIFOSET (fd, packet_len_table[0x18f]);
+    return 0;
+}
+
+/*==========================================
+ * オートスペル リスト送信
+ *------------------------------------------
+ */
+int clif_autospell (struct map_session_data *sd, int skilllv)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1cd;
+
+    if (skilllv > 0 && pc_checkskill (sd, MG_NAPALMBEAT) > 0)
+        WFIFOL (fd, 2) = MG_NAPALMBEAT;
+    else
+        WFIFOL (fd, 2) = 0x00000000;
+    if (skilllv > 1 && pc_checkskill (sd, MG_COLDBOLT) > 0)
+        WFIFOL (fd, 6) = MG_COLDBOLT;
+    else
+        WFIFOL (fd, 6) = 0x00000000;
+    if (skilllv > 1 && pc_checkskill (sd, MG_FIREBOLT) > 0)
+        WFIFOL (fd, 10) = MG_FIREBOLT;
+    else
+        WFIFOL (fd, 10) = 0x00000000;
+    if (skilllv > 1 && pc_checkskill (sd, MG_LIGHTNINGBOLT) > 0)
+        WFIFOL (fd, 14) = MG_LIGHTNINGBOLT;
+    else
+        WFIFOL (fd, 14) = 0x00000000;
+    if (skilllv > 4 && pc_checkskill (sd, MG_SOULSTRIKE) > 0)
+        WFIFOL (fd, 18) = MG_SOULSTRIKE;
+    else
+        WFIFOL (fd, 18) = 0x00000000;
+    if (skilllv > 7 && pc_checkskill (sd, MG_FIREBALL) > 0)
+        WFIFOL (fd, 22) = MG_FIREBALL;
+    else
+        WFIFOL (fd, 22) = 0x00000000;
+    if (skilllv > 9 && pc_checkskill (sd, MG_FROSTDIVER) > 0)
+        WFIFOL (fd, 26) = MG_FROSTDIVER;
+    else
+        WFIFOL (fd, 26) = 0x00000000;
+
+    WFIFOSET (fd, packet_len_table[0x1cd]);
+    return 0;
+}
+
+/*==========================================
+ * ディボーションの青い糸
+ *------------------------------------------
+ */
+int clif_devotion (struct map_session_data *sd, int target)
+{
+    unsigned char buf[56];
+    int  n;
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x1cf;
+    WBUFL (buf, 2) = sd->bl.id;
+//  WBUFL(buf,6)=target;
+    for (n = 0; n < 5; n++)
+        WBUFL (buf, 6 + 4 * n) = sd->dev.val2[n];
+//      WBUFL(buf,10+4*n)=0;
+    WBUFB (buf, 26) = 8;
+    WBUFB (buf, 27) = 0;
+
+    clif_send (buf, packet_len_table[0x1cf], &sd->bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ * 氣球
+ *------------------------------------------
+ */
+int clif_spiritball (struct map_session_data *sd)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x1d0;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFW (buf, 6) = sd->spiritball;
+    clif_send (buf, packet_len_table[0x1d0], &sd->bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_combo_delay (struct block_list *bl, int wait)
+{
+    unsigned char buf[32];
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x1d2;
+    WBUFL (buf, 2) = bl->id;
+    WBUFL (buf, 6) = wait;
+    clif_send (buf, packet_len_table[0x1d2], bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *白刃取り
+ *------------------------------------------
+ */
+int clif_bladestop (struct block_list *src, struct block_list *dst, int boolean)
+{
+    unsigned char buf[32];
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, dst);
+
+    WBUFW (buf, 0) = 0x1d1;
+    WBUFL (buf, 2) = src->id;
+    WBUFL (buf, 6) = dst->id;
+    WBUFL (buf, 10) = boolean;
+
+    clif_send (buf, packet_len_table[0x1d1], src, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_changemapcell (int m, int x, int y, int cell_type, int type)
+{
+    struct block_list bl;
+    char buf[32];
+
+    bl.m = m;
+    bl.x = x;
+    bl.y = y;
+    WBUFW (buf, 0) = 0x192;
+    WBUFW (buf, 2) = x;
+    WBUFW (buf, 4) = y;
+    WBUFW (buf, 6) = cell_type;
+    memcpy (WBUFP (buf, 8), map[m].name, 16);
+    if (!type)
+        clif_send (buf, packet_len_table[0x192], &bl, AREA);
+    else
+        clif_send (buf, packet_len_table[0x192], &bl, ALL_SAMEMAP);
+
+    return 0;
+}
+
+/*==========================================
+ * MVPエフェクト
+ *------------------------------------------
+ */
+int clif_mvp_effect (struct map_session_data *sd)
+{
+    unsigned char buf[16];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x10c;
+    WBUFL (buf, 2) = sd->bl.id;
+    clif_send (buf, packet_len_table[0x10c], &sd->bl, AREA);
+    return 0;
+}
+
+/*==========================================
+ * MVPアイテム所得
+ *------------------------------------------
+ */
+int clif_mvp_item (struct map_session_data *sd, int nameid)
+{
+    int  view, fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x10a;
+    if ((view = itemdb_viewid (nameid)) > 0)
+        WFIFOW (fd, 2) = view;
+    else
+        WFIFOW (fd, 2) = nameid;
+    WFIFOSET (fd, packet_len_table[0x10a]);
+    return 0;
+}
+
+/*==========================================
+ * MVP経験値所得
+ *------------------------------------------
+ */
+int clif_mvp_exp (struct map_session_data *sd, int exp)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x10b;
+    WFIFOL (fd, 2) = exp;
+    WFIFOSET (fd, packet_len_table[0x10b]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド作成可否通知
+ * Relay the result of guild creation.
+ *
+ * (R 0167 <flag>.B)
+ *
+ * flag:
+ *  0 The guild was created.
+ *  1 The character is already in a guild.
+ *  2 The guild name is invalid/taken.
+ *  3 The Emperium item is required.
+ *------------------------------------------
+ */
+int clif_guild_created (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x167;
+    WFIFOB (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x167]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド所属通知
+ *------------------------------------------
+ */
+int clif_guild_belonginfo (struct map_session_data *sd, struct guild *g)
+{
+    int  ps, fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, g);
+
+    fd = sd->fd;
+    ps = guild_getposition (sd, g);
+
+    memset (WFIFOP (fd, 0), 0, packet_len_table[0x16c]);
+    WFIFOW (fd, 0) = 0x16c;
+    WFIFOL (fd, 2) = g->guild_id;
+    WFIFOL (fd, 6) = g->emblem_id;
+    WFIFOL (fd, 10) = g->position[ps].mode;
+    memcpy (WFIFOP (fd, 19), g->name, 24);
+    WFIFOSET (fd, packet_len_table[0x16c]);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバログイン通知
+ *------------------------------------------
+ */
+int clif_guild_memberlogin_notice (struct guild *g, int idx, int flag)
+{
+    unsigned char buf[64];
+
+    nullpo_retr (0, g);
+
+    WBUFW (buf, 0) = 0x16d;
+    WBUFL (buf, 2) = g->member[idx].account_id;
+    WBUFL (buf, 6) = 0;
+    WBUFL (buf, 10) = flag;
+    if (g->member[idx].sd == NULL)
+    {
+        struct map_session_data *sd = guild_getavailablesd (g);
+        if (sd != NULL)
+            clif_send (buf, packet_len_table[0x16d], &sd->bl, GUILD);
+    }
+    else
+        clif_send (buf, packet_len_table[0x16d], &g->member[idx].sd->bl,
+                   GUILD_WOS);
+    return 0;
+}
+
+/*==========================================
+ * ギルドマスター通知(14dへの応答)
+ *------------------------------------------
+ */
+int clif_guild_masterormember (struct map_session_data *sd)
+{
+    int  type = 0x57, fd;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g != NULL && strcmp (g->master, sd->status.name) == 0)
+        type = 0xd7;
+    WFIFOW (fd, 0) = 0x14e;
+    WFIFOL (fd, 2) = type;
+    WFIFOSET (fd, packet_len_table[0x14e]);
+    return 0;
+}
+
+/*==========================================
+ * Basic Info (Territories [Valaris])
+ *------------------------------------------
+ */
+int clif_guild_basicinfo (struct map_session_data *sd)
+{
+    int  fd, i, t = 0;
+    struct guild *g;
+    struct guild_castle *gc = NULL;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+
+    WFIFOW (fd, 0) = 0x1b6;     //0x150;
+    WFIFOL (fd, 2) = g->guild_id;
+    WFIFOL (fd, 6) = g->guild_lv;
+    WFIFOL (fd, 10) = g->connect_member;
+    WFIFOL (fd, 14) = g->max_member;
+    WFIFOL (fd, 18) = g->average_lv;
+    WFIFOL (fd, 22) = g->exp;
+    WFIFOL (fd, 26) = g->next_exp;
+    WFIFOL (fd, 30) = 0;        // 上納
+    WFIFOL (fd, 34) = 0;        // VW(性格の悪さ?:性向グラフ左右)
+    WFIFOL (fd, 38) = 0;        // RF(正義の度合い?:性向グラフ上下)
+    WFIFOL (fd, 42) = 0;        // 人数?
+    memcpy (WFIFOP (fd, 46), g->name, 24);
+    memcpy (WFIFOP (fd, 70), g->master, 24);
+
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        gc = guild_castle_search (i);
+        if (!gc)
+            continue;
+        if (g->guild_id == gc->guild_id)
+            t++;
+    }
+
+    if (t == 1)
+        memcpy (WFIFOP (fd, 94), "One Castle", 20);
+    else if (t == 2)
+        memcpy (WFIFOP (fd, 94), "Two Castles", 20);
+    else if (t == 3)
+        memcpy (WFIFOP (fd, 94), "Three Castles", 20);
+    else if (t == 4)
+        memcpy (WFIFOP (fd, 94), "Four Castles", 20);
+    else if (t == 5)
+        memcpy (WFIFOP (fd, 94), "Five Castles", 20);
+    else if (t == 6)
+        memcpy (WFIFOP (fd, 94), "Six Castles", 20);
+    else if (t == 7)
+        memcpy (WFIFOP (fd, 94), "Seven Castles", 20);
+    else if (t == 8)
+        memcpy (WFIFOP (fd, 94), "Eight Castles", 20);
+    else if (t == 9)
+        memcpy (WFIFOP (fd, 94), "Nine Castles", 20);
+    else if (t == 10)
+        memcpy (WFIFOP (fd, 94), "Ten Castles", 20);
+    else if (t == 11)
+        memcpy (WFIFOP (fd, 94), "Eleven Castles", 20);
+    else if (t == 12)
+        memcpy (WFIFOP (fd, 94), "Twelve Castles", 20);
+    else if (t == 13)
+        memcpy (WFIFOP (fd, 94), "Thirteen Castles", 20);
+    else if (t == 14)
+        memcpy (WFIFOP (fd, 94), "Fourteen Castles", 20);
+    else if (t == 15)
+        memcpy (WFIFOP (fd, 94), "Fifteen Castles", 20);
+    else if (t == 16)
+        memcpy (WFIFOP (fd, 94), "Sixteen Castles", 20);
+    else if (t == 17)
+        memcpy (WFIFOP (fd, 94), "Seventeen Castles", 20);
+    else if (t == 18)
+        memcpy (WFIFOP (fd, 94), "Eighteen Castles", 20);
+    else if (t == 19)
+        memcpy (WFIFOP (fd, 94), "Nineteen Castles", 20);
+    else if (t == 20)
+        memcpy (WFIFOP (fd, 94), "Twenty Castles", 20);
+    else if (t == 21)
+        memcpy (WFIFOP (fd, 94), "Twenty One Castles", 20);
+    else if (t == 22)
+        memcpy (WFIFOP (fd, 94), "Twenty Two Castles", 20);
+    else if (t == 23)
+        memcpy (WFIFOP (fd, 94), "Twenty Three Castles", 20);
+    else if (t == 24)
+        memcpy (WFIFOP (fd, 94), "Twenty Four Castles", 20);
+    else if (t == MAX_GUILDCASTLE)
+        memcpy (WFIFOP (fd, 94), "Total Domination", 20);
+    else
+        memcpy (WFIFOP (fd, 94), "None Taken", 20);
+
+    WFIFOSET (fd, packet_len_table[WFIFOW (fd, 0)]);
+    clif_guild_emblem (sd, g);  // Guild emblem vanish fix [Valaris]
+    return 0;
+}
+
+/*==========================================
+ * ギルド同盟/敵対情報
+ *------------------------------------------
+ */
+int clif_guild_allianceinfo (struct map_session_data *sd)
+{
+    int  fd, i, c;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+    WFIFOW (fd, 0) = 0x14c;
+    for (i = c = 0; i < MAX_GUILDALLIANCE; i++)
+    {
+        struct guild_alliance *a = &g->alliance[i];
+        if (a->guild_id > 0)
+        {
+            WFIFOL (fd, c * 32 + 4) = a->opposition;
+            WFIFOL (fd, c * 32 + 8) = a->guild_id;
+            memcpy (WFIFOP (fd, c * 32 + 12), a->name, 24);
+            c++;
+        }
+    }
+    WFIFOW (fd, 2) = c * 32 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバーリスト
+ *------------------------------------------
+ */
+int clif_guild_memberlist (struct map_session_data *sd)
+{
+    int  fd;
+    int  i, c;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+
+    WFIFOW (fd, 0) = 0x154;
+    for (i = 0, c = 0; i < g->max_member; i++)
+    {
+        struct guild_member *m = &g->member[i];
+        if (m->account_id == 0)
+            continue;
+        WFIFOL (fd, c * 104 + 4) = m->account_id;
+        WFIFOL (fd, c * 104 + 8) = 0;
+        WFIFOW (fd, c * 104 + 12) = m->hair;
+        WFIFOW (fd, c * 104 + 14) = m->hair_color;
+        WFIFOW (fd, c * 104 + 16) = m->gender;
+        WFIFOW (fd, c * 104 + 18) = m->pc_class;
+        WFIFOW (fd, c * 104 + 20) = m->lv;
+        WFIFOL (fd, c * 104 + 22) = m->exp;
+        WFIFOL (fd, c * 104 + 26) = m->online;
+        WFIFOL (fd, c * 104 + 30) = m->position;
+        memset (WFIFOP (fd, c * 104 + 34), 0, 50);  // メモ?
+        memcpy (WFIFOP (fd, c * 104 + 84), m->name, 24);
+        c++;
+    }
+    WFIFOW (fd, 2) = c * 104 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルド役職名リスト
+ *------------------------------------------
+ */
+int clif_guild_positionnamelist (struct map_session_data *sd)
+{
+    int  i, fd;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+    WFIFOW (fd, 0) = 0x166;
+    for (i = 0; i < MAX_GUILDPOSITION; i++)
+    {
+        WFIFOL (fd, i * 28 + 4) = i;
+        memcpy (WFIFOP (fd, i * 28 + 8), g->position[i].name, 24);
+    }
+    WFIFOW (fd, 2) = i * 28 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルド役職情報リスト
+ *------------------------------------------
+ */
+int clif_guild_positioninfolist (struct map_session_data *sd)
+{
+    int  i, fd;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+    WFIFOW (fd, 0) = 0x160;
+    for (i = 0; i < MAX_GUILDPOSITION; i++)
+    {
+        struct guild_position *p = &g->position[i];
+        WFIFOL (fd, i * 16 + 4) = i;
+        WFIFOL (fd, i * 16 + 8) = p->mode;
+        WFIFOL (fd, i * 16 + 12) = i;
+        WFIFOL (fd, i * 16 + 16) = p->exp_mode;
+    }
+    WFIFOW (fd, 2) = i * 16 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルド役職変更通知
+ *------------------------------------------
+ */
+int clif_guild_positionchanged (struct guild *g, int idx)
+{
+    struct map_session_data *sd;
+    unsigned char buf[128];
+
+    nullpo_retr (0, g);
+
+    WBUFW (buf, 0) = 0x174;
+    WBUFW (buf, 2) = 44;
+    WBUFL (buf, 4) = idx;
+    WBUFL (buf, 8) = g->position[idx].mode;
+    WBUFL (buf, 12) = idx;
+    WBUFL (buf, 16) = g->position[idx].exp_mode;
+    memcpy (WBUFP (buf, 20), g->position[idx].name, 24);
+    if ((sd = guild_getavailablesd (g)) != NULL)
+        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバ変更通知
+ *------------------------------------------
+ */
+int clif_guild_memberpositionchanged (struct guild *g, int idx)
+{
+    struct map_session_data *sd;
+    unsigned char buf[64];
+
+    nullpo_retr (0, g);
+
+    WBUFW (buf, 0) = 0x156;
+    WBUFW (buf, 2) = 16;
+    WBUFL (buf, 4) = g->member[idx].account_id;
+    WBUFL (buf, 8) = 0;
+    WBUFL (buf, 12) = g->member[idx].position;
+    if ((sd = guild_getavailablesd (g)) != NULL)
+        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
+    return 0;
+}
+
+/*==========================================
+ * ギルドエンブレム送信
+ *------------------------------------------
+ */
+int clif_guild_emblem (struct map_session_data *sd, struct guild *g)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, g);
+
+    fd = sd->fd;
+
+    if (g->emblem_len <= 0)
+        return 0;
+    WFIFOW (fd, 0) = 0x152;
+    WFIFOW (fd, 2) = g->emblem_len + 12;
+    WFIFOL (fd, 4) = g->guild_id;
+    WFIFOL (fd, 8) = g->emblem_id;
+    memcpy (WFIFOP (fd, 12), g->emblem_data, g->emblem_len);
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルドスキル送信
+ *------------------------------------------
+ */
+int clif_guild_skillinfo (struct map_session_data *sd)
+{
+    int  fd;
+    int  i, id, c;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+    WFIFOW (fd, 0) = 0x0162;
+    WFIFOW (fd, 4) = g->skill_point;
+    for (i = c = 0; i < MAX_GUILDSKILL; i++)
+    {
+        if (g->skill[i].id > 0)
+        {
+            WFIFOW (fd, c * 37 + 6) = id = g->skill[i].id;
+            WFIFOW (fd, c * 37 + 8) = guild_skill_get_inf (id);
+            WFIFOW (fd, c * 37 + 10) = 0;
+            WFIFOW (fd, c * 37 + 12) = g->skill[i].lv;
+            WFIFOW (fd, c * 37 + 14) =
+                guild_skill_get_sp (id, g->skill[i].lv);
+            WFIFOW (fd, c * 37 + 16) = guild_skill_get_range (id);
+            memset (WFIFOP (fd, c * 37 + 18), 0, 24);
+            WFIFOB (fd, c * 37 + 42) =  //up;
+                (g->skill[i].lv < guild_skill_get_max (id)) ? 1 : 0;
+            c++;
+        }
+    }
+    WFIFOW (fd, 2) = c * 37 + 6;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルド告知送信
+ *------------------------------------------
+ */
+int clif_guild_notice (struct map_session_data *sd, struct guild *g)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, g);
+
+    fd = sd->fd;
+    if (*g->mes1 == 0 && *g->mes2 == 0)
+        return 0;
+    WFIFOW (fd, 0) = 0x16f;
+    memcpy (WFIFOP (fd, 2), g->mes1, 60);
+    memcpy (WFIFOP (fd, 62), g->mes2, 120);
+    WFIFOSET (fd, packet_len_table[0x16f]);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバ勧誘
+ *------------------------------------------
+ */
+int clif_guild_invite (struct map_session_data *sd, struct guild *g)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, g);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x16a;
+    WFIFOL (fd, 2) = g->guild_id;
+    memcpy (WFIFOP (fd, 6), g->name, 24);
+    WFIFOSET (fd, packet_len_table[0x16a]);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバ勧誘結果
+ *------------------------------------------
+ */
+int clif_guild_inviteack (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x169;
+    WFIFOB (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x169]);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバ脱退通知
+ *------------------------------------------
+ */
+int clif_guild_leave (struct map_session_data *sd, const char *name,
+                      const char *mes)
+{
+    unsigned char buf[128];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x15a;
+    memcpy (WBUFP (buf, 2), name, 24);
+    memcpy (WBUFP (buf, 26), mes, 40);
+    clif_send (buf, packet_len_table[0x15a], &sd->bl, GUILD);
+    return 0;
+}
+
+/*==========================================
+ * ギルドメンバ追放通知
+ *------------------------------------------
+ */
+int clif_guild_explusion (struct map_session_data *sd, const char *name,
+                          const char *mes, int account_id)
+{
+    unsigned char buf[128];
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x15c;
+    memcpy (WBUFP (buf, 2), name, 24);
+    memcpy (WBUFP (buf, 26), mes, 40);
+    memcpy (WBUFP (buf, 66), "dummy", 24);
+    clif_send (buf, packet_len_table[0x15c], &sd->bl, GUILD);
+    return 0;
+}
+
+/*==========================================
+ * ギルド追放メンバリスト
+ *------------------------------------------
+ */
+int clif_guild_explusionlist (struct map_session_data *sd)
+{
+    int  fd;
+    int  i, c;
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+    WFIFOW (fd, 0) = 0x163;
+    for (i = c = 0; i < MAX_GUILDEXPLUSION; i++)
+    {
+        struct guild_explusion *e = &g->explusion[i];
+        if (e->account_id > 0)
+        {
+            memcpy (WFIFOP (fd, c * 88 + 4), e->name, 24);
+            memcpy (WFIFOP (fd, c * 88 + 28), e->acc, 24);
+            memcpy (WFIFOP (fd, c * 88 + 52), e->mes, 44);
+            c++;
+        }
+    }
+    WFIFOW (fd, 2) = c * 88 + 4;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+    return 0;
+}
+
+/*==========================================
+ * ギルド会話
+ *------------------------------------------
+ */
+int clif_guild_message (struct guild *g, int account_id, const char *mes,
+                        int len)
+{
+    struct map_session_data *sd;
+    unsigned char lbuf[255];
+    unsigned char *buf = lbuf;
+    if (len + 32 >= sizeof (lbuf))
+        buf = (unsigned char *)malloc (len + 32);
+    WBUFW (buf, 0) = 0x17f;
+    WBUFW (buf, 2) = len + 4;
+    memcpy (WBUFP (buf, 4), mes, len);
+
+    if ((sd = guild_getavailablesd (g)) != NULL)
+        clif_send (buf, WBUFW (buf, 2), &sd->bl, GUILD);
+    if (buf != lbuf)
+        free (buf);
+    return 0;
+}
+
+/*==========================================
+ * ギルドスキル割り振り通知
+ *------------------------------------------
+ */
+int clif_guild_skillup (struct map_session_data *sd, int skill_num, int lv)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x10e;
+    WFIFOW (fd, 2) = skill_num;
+    WFIFOW (fd, 4) = lv;
+    WFIFOW (fd, 6) = guild_skill_get_sp (skill_num, lv);
+    WFIFOW (fd, 8) = guild_skill_get_range (skill_num);
+    WFIFOB (fd, 10) = 1;
+    WFIFOSET (fd, 11);
+    return 0;
+}
+
+/*==========================================
+ * ギルド同盟要請
+ *------------------------------------------
+ */
+int clif_guild_reqalliance (struct map_session_data *sd, int account_id,
+                            const char *name)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x171;
+    WFIFOL (fd, 2) = account_id;
+    memcpy (WFIFOP (fd, 6), name, 24);
+    WFIFOSET (fd, packet_len_table[0x171]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド同盟結果
+ *------------------------------------------
+ */
+int clif_guild_allianceack (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x173;
+    WFIFOL (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x173]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド関係解消通知
+ *------------------------------------------
+ */
+int clif_guild_delalliance (struct map_session_data *sd, int guild_id,
+                            int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x184;
+    WFIFOL (fd, 2) = guild_id;
+    WFIFOL (fd, 6) = flag;
+    WFIFOSET (fd, packet_len_table[0x184]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド敵対結果
+ *------------------------------------------
+ */
+int clif_guild_oppositionack (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x181;
+    WFIFOB (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x181]);
+    return 0;
+}
+
+/*==========================================
+ * ギルド関係追加
+ *------------------------------------------
+ */
+/*int clif_guild_allianceadded(struct guild *g,int idx)
+{
+	unsigned char buf[64];
+	WBUFW(fd,0)=0x185;
+	WBUFL(fd,2)=g->alliance[idx].opposition;
+	WBUFL(fd,6)=g->alliance[idx].guild_id;
+	memcpy(WBUFP(fd,10),g->alliance[idx].name,24);
+	clif_send(buf,packet_len_table[0x185],guild_getavailablesd(g),GUILD);
+	return 0;
+}*/
+
+/*==========================================
+ * ギルド解散通知
+ *------------------------------------------
+ */
+int clif_guild_broken (struct map_session_data *sd, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x15e;
+    WFIFOL (fd, 2) = flag;
+    WFIFOSET (fd, packet_len_table[0x15e]);
+    return 0;
+}
+
+/*==========================================
+ * エモーション
+ *------------------------------------------
+ */
+void clif_emotion (struct block_list *bl, int type)
+{
+    unsigned char buf[8];
+
+    nullpo_retv (bl);
+
+    WBUFW (buf, 0) = 0xc0;
+    WBUFL (buf, 2) = bl->id;
+    WBUFB (buf, 6) = type;
+    clif_send (buf, packet_len_table[0xc0], bl, AREA);
+}
+
+static void clif_emotion_towards (struct block_list *bl,
+                                  struct block_list *target, int type)
+{
+    unsigned char buf[8];
+    int  len = packet_len_table[0xc0];
+    struct map_session_data *sd = (struct map_session_data *) target;
+
+    nullpo_retv (bl);
+    nullpo_retv (target);
+
+    if (target->type != BL_PC)
+        return;
+
+    WBUFW (buf, 0) = 0xc0;
+    WBUFL (buf, 2) = bl->id;
+    WBUFB (buf, 6) = type;
+
+    memcpy (WFIFOP (sd->fd, 0), buf, len);
+    WFIFOSET (sd->fd, len);
+}
+
+/*==========================================
+ * トーキーボックス
+ *------------------------------------------
+ */
+void clif_talkiebox (struct block_list *bl, char *talkie)
+{
+    unsigned char buf[86];
+
+    nullpo_retv (bl);
+
+    WBUFW (buf, 0) = 0x191;
+    WBUFL (buf, 2) = bl->id;
+    memcpy (WBUFP (buf, 6), talkie, 80);
+    clif_send (buf, packet_len_table[0x191], bl, AREA);
+}
+
+/*==========================================
+ * 結婚エフェクト
+ *------------------------------------------
+ */
+void clif_wedding_effect (struct block_list *bl)
+{
+    unsigned char buf[6];
+
+    nullpo_retv (bl);
+
+    WBUFW (buf, 0) = 0x1ea;
+    WBUFL (buf, 2) = bl->id;
+    clif_send (buf, packet_len_table[0x1ea], bl, AREA);
+}
+
+/*==========================================
+ * あなたに逢いたい使用時名前叫び
+ *------------------------------------------
+
+void clif_callpartner(struct map_session_data *sd)
+{
+	unsigned char buf[26];
+	char *p;
+
+	nullpo_retv(sd);
+
+	if(sd->status.partner_id){
+		WBUFW(buf,0)=0x1e6;
+		p = map_charid2nick(sd->status.partner_id);
+		if(p){
+			memcpy(WBUFP(buf,2),p,24);
+		}else{
+			map_reqchariddb(sd,sd->status.partner_id);
+			chrif_searchcharid(sd->status.partner_id);
+			WBUFB(buf,2) = 0;
+		}
+		clif_send(buf,packet_len_table[0x1e6]&sd->bl,AREA);
+	}
+	return;
+}
+*/
+/*==========================================
+ * 座る
+ *------------------------------------------
+ */
+void clif_sitting (int fd, struct map_session_data *sd)
+{
+    unsigned char buf[64];
+
+    nullpo_retv (sd);
+
+    WBUFW (buf, 0) = 0x8a;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFB (buf, 26) = 2;
+    clif_send (buf, packet_len_table[0x8a], &sd->bl, AREA);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int clif_disp_onlyself (struct map_session_data *sd, char *mes, int len)
+{
+    unsigned char lbuf[255];
+    unsigned char *buf =
+        (len + 32 >= sizeof (lbuf)) ? (unsigned char *)malloc (len + 32) : lbuf;
+
+    nullpo_retr (0, sd);
+
+    WBUFW (buf, 0) = 0x17f;
+    WBUFW (buf, 2) = len + 8;
+    memcpy (WBUFP (buf, 4), mes, len + 4);
+
+    clif_send (buf, WBUFW (buf, 2), &sd->bl, SELF);
+
+    if (buf != lbuf)
+        free (buf);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+
+int clif_GM_kickack (struct map_session_data *sd, int id)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xcd;
+    WFIFOL (fd, 2) = id;
+    WFIFOSET (fd, packet_len_table[0xcd]);
+    return 0;
+}
+
+void clif_parse_QuitGame (int fd, struct map_session_data *sd);
+
+int clif_GM_kick (struct map_session_data *sd, struct map_session_data *tsd,
+                  int type)
+{
+    nullpo_retr (0, tsd);
+
+    if (type)
+        clif_GM_kickack (sd, tsd->status.account_id);
+    tsd->opt1 = tsd->opt2 = 0;
+    clif_parse_QuitGame (tsd->fd, tsd);
+
+    return 0;
+}
+
+/*==========================================
+ * Wis拒否許可応答
+ *------------------------------------------
+ */
+int clif_wisexin (struct map_session_data *sd, int type, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xd1;
+    WFIFOB (fd, 2) = type;
+    WFIFOB (fd, 3) = flag;
+    WFIFOSET (fd, packet_len_table[0xd1]);
+
+    return 0;
+}
+
+/*==========================================
+ * Wis全拒否許可応答
+ *------------------------------------------
+ */
+int clif_wisall (struct map_session_data *sd, int type, int flag)
+{
+    int  fd;
+
+    nullpo_retr (0, sd);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0xd2;
+    WFIFOB (fd, 2) = type;
+    WFIFOB (fd, 3) = flag;
+    WFIFOSET (fd, packet_len_table[0xd2]);
+
+    return 0;
+}
+
+/*==========================================
+ * サウンドエフェクト
+ *------------------------------------------
+ */
+void clif_soundeffect (struct map_session_data *sd, struct block_list *bl,
+                       char *name, int type)
+{
+    int  fd;
+
+    nullpo_retv (sd);
+    nullpo_retv (bl);
+
+    fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1d3;
+    memcpy (WFIFOP (fd, 2), name, 24);
+    WFIFOB (fd, 26) = type;
+    WFIFOL (fd, 27) = 0;
+    WFIFOL (fd, 31) = bl->id;
+    WFIFOSET (fd, packet_len_table[0x1d3]);
+
+    return;
+}
+
+// displaying special effects (npcs, weather, etc) [Valaris]
+int clif_specialeffect (struct block_list *bl, int type, int flag)
+{
+    unsigned char buf[24];
+
+    nullpo_retr (0, bl);
+
+    memset (buf, 0, packet_len_table[0x19b]);
+
+    WBUFW (buf, 0) = 0x19b;
+    WBUFL (buf, 2) = bl->id;
+    WBUFL (buf, 6) = type;
+
+    if (flag == 2)
+    {
+        struct map_session_data *sd = NULL;
+        int  i;
+        for (i = 0; i < fd_max; i++)
+        {
+            if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) != NULL
+                && sd->state.auth && sd->bl.m == bl->m)
+                clif_specialeffect (&sd->bl, type, 1);
+        }
+    }
+
+    else if (flag == 1)
+        clif_send (buf, packet_len_table[0x19b], bl, SELF);
+    else if (!flag)
+        clif_send (buf, packet_len_table[0x19b], bl, AREA);
+
+    return 0;
+
+}
+
+// ------------
+// clif_parse_*
+// ------------
+// パケット読み取って色々操作
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_WantToConnection (int fd, struct map_session_data *sd)
+{
+    struct map_session_data *old_sd;
+    int  account_id;            // account_id in the packet
+
+    if (sd)
+    {
+        if (battle_config.error_log)
+            printf ("clif_parse_WantToConnection : invalid request?\n");
+        return;
+    }
+
+    if (RFIFOW (fd, 0) == 0x72)
+    {
+        account_id = RFIFOL (fd, 2);
+    }
+    else
+        return;                 // Not the auth packet
+
+    WFIFOL (fd, 0) = account_id;
+    WFIFOSET (fd, 4);
+
+    // if same account already connected, we disconnect the 2 sessions
+    if ((old_sd = map_id2sd (account_id)) != NULL)
+    {
+        clif_authfail_fd (fd, 2);   // same id
+        clif_authfail_fd (old_sd->fd, 2);   // same id
+        printf
+            ("clif_parse_WantToConnection: Double connection for account %d (sessions: #%d (new) and #%d (old)).\n",
+             account_id, fd, old_sd->fd);
+    }
+    else
+    {
+        CREATE (sd, struct map_session_data, 1);
+        session[fd]->session_data = sd;
+        sd->fd = fd;
+
+        pc_setnewpc (sd, account_id, RFIFOL (fd, 6), RFIFOL (fd, 10),
+                     RFIFOL (fd, 14), RFIFOB (fd, 18), fd);
+
+        map_addiddb (&sd->bl);
+
+        chrif_authreq (sd);
+    }
+
+    return;
+}
+
+/*==========================================
+ * 007d クライアント側マップ読み込み完了
+ * map侵入時に必要なデータを全て送りつける
+ *------------------------------------------
+ */
+void clif_parse_LoadEndAck (int fd, struct map_session_data *sd)
+{
+//  struct item_data* item;
+    int  i;
+    nullpo_retv (sd);
+
+    if (sd->bl.prev != NULL)
+        return;
+
+    // 接続ok時
+    //clif_authok();
+    if (sd->npc_id)
+        npc_event_dequeue (sd);
+    clif_skillinfoblock (sd);
+    pc_checkitem (sd);
+    //guild_info();
+
+    // loadendack時
+    // next exp
+    clif_updatestatus (sd, SP_NEXTBASEEXP);
+    clif_updatestatus (sd, SP_NEXTJOBEXP);
+    // skill point
+    clif_updatestatus (sd, SP_SKILLPOINT);
+    // item
+    clif_itemlist (sd);
+    clif_equiplist (sd);
+    // cart
+    if (pc_iscarton (sd))
+    {
+        clif_cart_itemlist (sd);
+        clif_cart_equiplist (sd);
+        clif_updatestatus (sd, SP_CARTINFO);
+    }
+    // param all
+    clif_initialstatus (sd);
+    // party
+    party_send_movemap (sd);
+    // guild
+    guild_send_memberinfoshort (sd, 1);
+    // 119
+    // 78
+
+    if (battle_config.pc_invincible_time > 0)
+    {
+        if (map[sd->bl.m].flag.gvg)
+            pc_setinvincibletimer (sd, battle_config.pc_invincible_time << 1);
+        else
+            pc_setinvincibletimer (sd, battle_config.pc_invincible_time);
+    }
+
+    map_addblock (&sd->bl);     // ブロック登録
+    clif_spawnpc (sd);          // spawn
+
+    // weight max , now
+    clif_updatestatus (sd, SP_MAXWEIGHT);
+    clif_updatestatus (sd, SP_WEIGHT);
+
+    // pvp
+    if (sd->pvp_timer != -1 && !battle_config.pk_mode)
+        delete_timer (sd->pvp_timer, pc_calc_pvprank_timer);
+    if (map[sd->bl.m].flag.pvp)
+    {
+        if (!battle_config.pk_mode)
+        {                       // remove pvp stuff for pk_mode [Valaris]
+            sd->pvp_timer =
+                add_timer (gettick () + 200, pc_calc_pvprank_timer, sd->bl.id,
+                           0);
+            sd->pvp_rank = 0;
+            sd->pvp_lastusers = 0;
+            sd->pvp_point = 5;
+        }
+        clif_set0199 (sd->fd, 1);
+    }
+    else
+    {
+        sd->pvp_timer = -1;
+    }
+    if (map[sd->bl.m].flag.gvg)
+    {
+        clif_set0199 (sd->fd, 3);
+    }
+
+    if (sd->state.connect_new)
+    {
+        sd->state.connect_new = 0;
+        if (sd->status.pc_class != sd->view_class)
+            clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);
+
+/*						Stop players from spawning inside castles [Valaris]					*/
+
+        {
+            struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
+            if (gc)
+                pc_setpos (sd, sd->status.save_point.map,
+                           sd->status.save_point.x, sd->status.save_point.y,
+                           2);
+        }
+
+/*						End Addition [Valaris]			*/
+
+    }
+
+    // view equipment item
+    clif_changelook (&sd->bl, LOOK_WEAPON, 0);
+    if (battle_config.save_clothcolor == 1 && sd->status.clothes_color > 0)
+        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
+                         sd->status.clothes_color);
+
+    if (sd->status.hp < sd->status.max_hp >> 2
+        && pc_checkskill (sd, SM_AUTOBERSERK) > 0
+        && (sd->sc_data[SC_PROVOKE].timer == -1
+            || sd->sc_data[SC_PROVOKE].val2 == 0))
+        // オートバーサーク発動
+        skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0, 0);
+
+//  if(time(&timer) < ((weddingtime=pc_readglobalreg(sd,"PC_WEDDING_TIME")) + 3600))
+//      skill_status_change_start(&sd->bl,SC_WEDDING,0,weddingtime,0,0,36000,0);
+
+    if (battle_config.muting_players && sd->status.manner < 0)
+        skill_status_change_start (&sd->bl, SC_NOCHAT, 0, 0, 0, 0, 0, 0);
+
+    // option
+    clif_changeoption (&sd->bl);
+    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
+        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
+    if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
+        && !battle_check_undead (7, sd->def_ele))
+        skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
+    if (sd->special_state.infinite_endure
+        && sd->sc_data[SC_ENDURE].timer == -1)
+        skill_status_change_start (&sd->bl, SC_ENDURE, 10, 1, 0, 0, 0, 0);
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].equip
+            && sd->status.inventory[i].equip & 0x0002
+            && sd->status.inventory[i].broken == 1)
+            skill_status_change_start (&sd->bl, SC_BROKNWEAPON, 0, 0, 0, 0, 0,
+                                       0);
+        if (sd->status.inventory[i].equip
+            && sd->status.inventory[i].equip & 0x0010
+            && sd->status.inventory[i].broken == 1)
+            skill_status_change_start (&sd->bl, SC_BROKNARMOR, 0, 0, 0, 0, 0,
+                                       0);
+    }
+
+//        clif_changelook_accessories(sd, NULL);
+
+    map_foreachinarea (clif_getareachar, sd->bl.m, sd->bl.x - AREA_SIZE,
+                       sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
+                       sd->bl.y + AREA_SIZE, 0, sd);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_TickSend (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    sd->client_tick = RFIFOL (fd, 2);
+    sd->server_tick = gettick ();
+    clif_servertick (sd);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_WalkToXY (int fd, struct map_session_data *sd)
+{
+    int  x, y;
+
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+
+    if (sd->npc_id != 0 || sd->state.storage_flag)
+        return;
+
+    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) <= 0)   // フリーキャスト
+        return;
+
+    if (sd->chatID)
+        return;
+
+    if (sd->canmove_tick > gettick ())
+        return;
+
+    // ステータス異常やハイディング中(トンネルドライブ無)で動けない
+    if ((sd->opt1 > 0 && sd->opt1 != 6) || sd->sc_data[SC_ANKLE].timer != -1 || //アンクルスネア
+        sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||  //オートカウンター
+        sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
+        sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
+        sd->sc_data[SC_SPIDERWEB].timer != -1 ||    //スパイダーウェッブ
+        (sd->sc_data[SC_DANCING].timer != -1 && sd->sc_data[SC_DANCING].val4))  //合奏スキル演奏中は動けない
+        return;
+    if ((sd->status.option & 2) && pc_checkskill (sd, RG_TUNNELDRIVE) <= 0)
+        return;
+
+    if (sd->invincible_timer != -1)
+        pc_delinvincibletimer (sd);
+
+    pc_stopattack (sd);
+
+    x = RFIFOB (fd, 2) * 4 + (RFIFOB (fd, 3) >> 6);
+    y = ((RFIFOB (fd, 3) & 0x3f) << 4) + (RFIFOB (fd, 4) >> 4);
+    pc_walktoxy (sd, x, y);
+
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_QuitGame (int fd, struct map_session_data *sd)
+{
+    unsigned int tick = gettick ();
+    struct skill_unit_group *sg;
+
+    nullpo_retv (sd);
+
+    WFIFOW (fd, 0) = 0x18b;
+    if ((!pc_isdead (sd)
+         && (sd->opt1
+             || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND))))
+        || sd->skilltimer != -1 || (DIFF_TICK (tick, sd->canact_tick) < 0)
+        || (sd->sc_data && sd->sc_data[SC_DANCING].timer != -1
+            && sd->sc_data[SC_DANCING].val4
+            && (sg = (struct skill_unit_group *) sd->sc_data[SC_DANCING].val2)
+            && sg->src_id == sd->bl.id))
+    {
+        WFIFOW (fd, 2) = 1;
+        WFIFOSET (fd, packet_len_table[0x18b]);
+        return;
+    }
+
+    /*  Rovert's prevent logout option fixed [Valaris]  */
+    if ((battle_config.prevent_logout
+         && (gettick () - sd->canlog_tick) >= 10000)
+        || (!battle_config.prevent_logout))
+    {
+        clif_setwaitclose (fd);
+        WFIFOW (fd, 2) = 0;
+    }
+    else
+    {
+        WFIFOW (fd, 2) = 1;
+    }
+    WFIFOSET (fd, packet_len_table[0x18b]);
+
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_GetCharNameRequest (int fd, struct map_session_data *sd)
+{
+    struct block_list *bl;
+    int  account_id;
+
+    account_id = RFIFOL (fd, 2);
+    bl = map_id2bl (account_id);
+    if (bl == NULL)
+        return;
+
+    WFIFOW (fd, 0) = 0x95;
+    WFIFOL (fd, 2) = account_id;
+
+    switch (bl->type)
+    {
+        case BL_PC:
+        {
+            struct map_session_data *ssd = (struct map_session_data *) bl;
+
+            nullpo_retv (ssd);
+
+            if (ssd->state.shroud_active)
+                memset (WFIFOP (fd, 6), 0, 24);
+            else
+                memcpy (WFIFOP (fd, 6), ssd->status.name, 24);
+            WFIFOSET (fd, packet_len_table[0x95]);
+
+            struct guild *g = NULL;
+            struct party *p = NULL;
+
+            char *guild_name = "", *guild_pos = "", *party_name = "";
+
+            int send = 0;
+
+            if (ssd->status.guild_id > 0 && (g = guild_search (ssd->status.guild_id)) != NULL)
+            {
+                // there used to be a comment near here, but the code has changed slightly
+                // ギルド所属ならパケット0195を返す
+                // google says that means: 0195 return if the packet belongs Guild
+                int  i, ps = -1;
+                for (i = 0; i < g->max_member; i++)
+                {
+                    if (g->member[i].account_id == ssd->status.account_id)
+                        ps = g->member[i].position;
+                }
+                if (ps >= 0 && ps < MAX_GUILDPOSITION)
+                {
+                    guild_name = g->name;
+                    guild_pos = g->position[ps].name;
+                    send = 1;
+                }
+            }
+            if (ssd->status.party_id > 0 && (p = party_search (ssd->status.party_id)) != NULL)
+            {
+                party_name = p->name;
+                send = 1;
+            }
+
+            if (send)
+            {
+                WFIFOW (fd, 0) = 0x195;
+                WFIFOL (fd, 2) = account_id;
+                memcpy (WFIFOP (fd, 6), party_name, 24);
+                memcpy (WFIFOP (fd, 30), guild_name, 24);
+                memcpy (WFIFOP (fd, 54), guild_pos, 24);
+                memcpy (WFIFOP (fd, 78), guild_pos, 24); // We send this value twice because the client expects it
+                WFIFOSET (fd, packet_len_table[0x195]);
+
+            }
+
+            if (pc_isGM(sd) >= battle_config.hack_info_GM_level)
+            {
+                in_addr_t ip = ssd->ip;
+                WFIFOW (fd, 0) = 0x20C;
+
+                // Mask the IP using the char-server password
+                if (battle_config.mask_ip_gms)
+                    ip = MD5_ip(chrif_getpasswd (), ssd->ip);
+
+                WFIFOL (fd, 2) = account_id;
+                WFIFOL (fd, 6) = ip;
+                WFIFOSET (fd, packet_len_table[0x20C]);
+             }
+
+        }
+            break;
+        case BL_NPC:
+            memcpy (WFIFOP (fd, 6), ((struct npc_data *) bl)->name, 24);
+            {
+                char *start = WFIFOP (fd, 6);
+                char *end = strchr (start, '#');    // [fate] elim hashed out/invisible names for the client
+                if (end)
+                    while (*end)
+                        *end++ = 0;
+
+                // [fate] Elim preceding underscores for (hackish) name position fine-tuning
+                while (*start == '_')
+                    *start++ = ' ';
+            }
+            WFIFOSET (fd, packet_len_table[0x95]);
+            break;
+        case BL_MOB:
+        {
+            struct mob_data *md = (struct mob_data *) bl;
+
+            nullpo_retv (md);
+
+            memcpy (WFIFOP (fd, 6), md->name, 24);
+            WFIFOSET (fd, packet_len_table[0x95]);
+        }
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("clif_parse_GetCharNameRequest : bad type %d(%d)\n",
+                        bl->type, account_id);
+            break;
+    }
+}
+
+/*==========================================
+ * Validate and process transmission of a
+ * global/public message.
+ *
+ * (S 008c <len>.w <message>.?B)
+ *------------------------------------------
+ */
+void clif_parse_GlobalMessage (int fd, struct map_session_data *sd)
+{
+    int msg_len = RFIFOW (fd, 2) - 4; /* Header (2) + length (2). */
+    size_t message_len = 0;
+    char *buf = NULL;
+    char *message = NULL;   /* The message text only. */
+
+    nullpo_retv (sd);
+
+    if (!(buf = clif_validate_chat (sd, 2, &message, &message_len)))
+    {
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
+            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
+                                || sd->sc_data[SC_NOCHAT].timer != -1)))//チャット禁止
+    {
+        free (buf);
+        return;
+    }
+
+    if (!magic_message (sd, buf, msg_len))
+    {
+        /* Don't send chat that results in an automatic ban. */
+        if (tmw_CheckChatSpam (sd, message))
+        {
+            free (buf);
+            /* "Your message could not be sent." */
+            clif_displaymessage (fd, msg_txt (505));
+            return;
+        }
+
+        /* It's not a spell/magic message, so send the message to others. */
+        WBUFW (buf, 0) = 0x8d;
+        WBUFW (buf, 2) = msg_len + 8;   /* Header (2) + length (2) + ID (4). */
+        WBUFL (buf, 4) = sd->bl.id;
+
+        clif_send (buf, msg_len + 8, &sd->bl,
+                   sd->chatID ? CHAT_WOS : AREA_CHAT_WOC);
+    }
+
+    /* Send the message back to the speaker. */
+    memcpy (WFIFOP (fd, 0), RFIFOP (fd, 0), RFIFOW (fd, 2));
+    WFIFOW (fd, 0) = 0x8e;
+    WFIFOSET (fd, WFIFOW (fd, 2));
+
+    free (buf);
+    return;
+}
+
+int clif_message (struct block_list *bl, char *msg)
+{
+    unsigned short msg_len = strlen (msg) + 1;
+    unsigned char buf[512];
+
+    if (msg_len + 16 > 512)
+        return 0;
+
+    nullpo_retr (0, bl);
+
+    WBUFW (buf, 0) = 0x8d;
+    WBUFW (buf, 2) = msg_len + 8;
+    WBUFL (buf, 4) = bl->id;
+    memcpy (WBUFP (buf, 8), msg, msg_len);
+
+    clif_send (buf, WBUFW (buf, 2), bl, AREA);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_MapMove (int fd, struct map_session_data *sd)
+{
+// /m /mapmove (as @rura GM command)
+    char output[100];
+    char map_name[17];
+
+    nullpo_retv (sd);
+
+    memset (output, '\0', sizeof (output));
+    memset (map_name, '\0', sizeof (map_name));
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_MapMove)))
+    {
+        memcpy (map_name, RFIFOP (fd, 2), 16);
+        sprintf (output, "%s %d %d", map_name, RFIFOW (fd, 18),
+                 RFIFOW (fd, 20));
+        log_atcommand (sd, "@warp %s", output);
+        atcommand_warp (fd, sd, "@warp", output);
+    }
+
+    return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChangeDir (int fd, struct map_session_data *sd)
+{
+    unsigned char buf[64];
+    short dir;
+
+    nullpo_retv (sd);
+
+//  RFIFOW(fd,2); // Apparently does nothing?
+    dir = RFIFOB (fd, 4);
+
+    if (dir == sd->dir)
+        return;
+
+    pc_setdir (sd, dir);
+
+    WBUFW (buf, 0) = 0x9c;
+    WBUFL (buf, 2) = sd->bl.id;
+    WBUFW (buf, 6) = 0;
+    WBUFB (buf, 8) = dir;
+    if (sd->disguise > 23 && sd->disguise < 4001)   // mob disguises [Valaris]
+        clif_send (buf, packet_len_table[0x9c], &sd->bl, AREA);
+    else
+        clif_send (buf, packet_len_table[0x9c], &sd->bl, AREA_WOS);
+
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_Emotion (int fd, struct map_session_data *sd)
+{
+    unsigned char buf[64];
+
+    nullpo_retv (sd);
+
+    if (battle_config.basic_skill_check == 0
+        || pc_checkskill (sd, NV_EMOTE) >= 1)
+    {
+        WBUFW (buf, 0) = 0xc0;
+        WBUFL (buf, 2) = sd->bl.id;
+        WBUFB (buf, 6) = RFIFOB (fd, 2);
+        clif_send (buf, packet_len_table[0xc0], &sd->bl, AREA);
+    }
+    else
+        clif_skill_fail (sd, 1, 0, 1);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_HowManyConnections (int fd, struct map_session_data *sd)
+{
+    WFIFOW (fd, 0) = 0xc2;
+    WFIFOL (fd, 2) = map_getusers ();
+    WFIFOSET (fd, packet_len_table[0xc2]);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ActionRequest (int fd, struct map_session_data *sd)
+{
+    unsigned int tick;
+    unsigned char buf[64];
+    int  action_type, target_id;
+
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    if (sd->npc_id != 0 || sd->opt1 > 0 || sd->status.option & 2 || sd->state.storage_flag ||
+            (sd->sc_data && (sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||   //オートカウンター
+            sd->sc_data[SC_BLADESTOP].timer != -1 || //白刃取り
+            sd->sc_data[SC_DANCING].timer != -1)))
+        return;
+
+    tick = gettick ();
+
+    pc_stop_walking (sd, 0);
+    pc_stopattack (sd);
+
+    target_id = RFIFOL (fd, 2);
+    action_type = RFIFOB (fd, 6);
+
+    switch (action_type)
+    {
+        case 0x00:             // once attack
+        case 0x07:             // continuous attack
+            if (sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22
+                || sd->status.option & OPTION_HIDE)
+                return;
+            if (!battle_config.sdelay_attack_enable
+                && pc_checkskill (sd, SA_FREECAST) <= 0)
+            {
+                if (DIFF_TICK (tick, sd->canact_tick) < 0)
+                {
+                    clif_skill_fail (sd, 1, 4, 0);
+                    return;
+                }
+            }
+            if (sd->invincible_timer != -1)
+                pc_delinvincibletimer (sd);
+            if (sd->attacktarget > 0)   // [Valaris]
+                sd->attacktarget = 0;
+            pc_attack (sd, target_id, action_type != 0);
+            break;
+        case 0x02:             // sitdown
+            pc_stop_walking (sd, 1);
+            skill_gangsterparadise (sd, 1); // ギャングスターパラダイス設定
+            pc_setsit (sd);
+            clif_sitting (fd, sd);
+            break;
+        case 0x03:             // standup
+            skill_gangsterparadise (sd, 0); // ギャングスターパラダイス解除
+            pc_setstand (sd);
+            WBUFW (buf, 0) = 0x8a;
+            WBUFL (buf, 2) = sd->bl.id;
+            WBUFB (buf, 26) = 3;
+            clif_send (buf, packet_len_table[0x8a], &sd->bl, AREA);
+            break;
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_Restart (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    switch (RFIFOB (fd, 2))
+    {
+        case 0x00:
+            if (pc_isdead (sd))
+            {
+                pc_setstand (sd);
+                pc_setrestartvalue (sd, 3);
+                pc_setpos (sd, sd->status.save_point.map,
+                           sd->status.save_point.x, sd->status.save_point.y,
+                           2);
+            }
+            break;
+        case 0x01:
+            /*if(!pc_isdead(sd) && (sd->opt1 || (sd->opt2 && !(night_flag == 1 && sd->opt2 == STATE_BLIND))))
+             * return; */
+
+            /*  Rovert's Prevent logout option - Fixed [Valaris]    */
+            if ((battle_config.prevent_logout
+                 && (gettick () - sd->canlog_tick) >= 10000)
+                || (!battle_config.prevent_logout))
+            {
+                chrif_charselectreq (sd);
+            }
+            else
+            {
+                WFIFOW (fd, 0) = 0x18b;
+                WFIFOW (fd, 2) = 1;
+
+                WFIFOSET (fd, packet_len_table[0x018b]);
+            }
+            break;
+    }
+}
+
+/*==========================================
+ * Validate and process transmission of a
+ * whisper/private message.
+ *
+ * (S 0096 <len>.w <nick>.24B <message>.?B)
+ *
+ * rewritten by [Yor], then partially by
+ * [remoitnane]
+ *------------------------------------------
+ */
+void clif_parse_Wis (int fd, struct map_session_data *sd)
+{
+    size_t message_len = 0;
+    char *buf = NULL;
+    char *message = NULL;   /* The message text only. */
+    struct map_session_data *dstsd = NULL;
+
+    nullpo_retv (sd);
+
+    if (!(buf = clif_validate_chat (sd, 1, &message, &message_len)))
+    {
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
+            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1
+                                || sd->sc_data[SC_NOCHAT].timer != -1)))
+    {
+        free (buf);
+        return;
+    }
+
+    /* Don't send chat that results in an automatic ban. */
+    if (tmw_CheckChatSpam (sd, message))
+    {
+        free (buf);
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    /*
+     * The player is not on this server. Only send the whisper if the name is
+     * exactly the same, because if there are multiple map-servers and a name
+     * conflict (for instance, "Test" versus "test"), the char-server must
+     * settle the discrepancy.
+     */
+    if (!(dstsd = map_nick2sd (RFIFOP (fd, 4)))
+            || strcmp (dstsd->status.name, RFIFOP (fd, 4)) != 0)
+        intif_wis_message (sd, RFIFOP (fd, 4), message,  RFIFOW (fd, 2) - 28);
+    else
+    {
+        /* Refuse messages addressed to self. */
+        if (dstsd->fd == fd)
+        {
+            /* "You cannot page yourself." */
+            char *mes = msg_txt (504);
+            clif_wis_message (fd, wisp_server_name, mes, strlen (mes) + 1);
+        }
+        else
+        {
+            /* The target is ignoring all whispers. */
+            if (dstsd->ignoreAll == 1)
+                /* Ignored by target. */
+                clif_wis_end (fd, 2);
+            else
+            {
+                int i;
+                size_t end = sizeof (dstsd->ignore) / sizeof (dstsd->ignore[0]);
+
+                /* See if the source player is being ignored. */
+                for (i = 0; i < end; ++i)
+                    if (strcmp (dstsd->ignore[i].name, sd->status.name) == 0)
+                    {
+                        /* Ignored by target. */
+                        clif_wis_end (fd, 2);
+                        break;
+                    }
+
+                /* The player is not being ignored. */
+                if (i == end)
+                {
+                    clif_wis_message (dstsd->fd, sd->status.name, message,
+                                      RFIFOW (fd, 2) - 28);
+                    /* The whisper was sent successfully. */
+                    clif_wis_end (fd, 0);
+                }
+            }
+        }
+    }
+
+    free (buf);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_GMmessage (int fd, struct map_session_data *sd)
+{
+    char m[512];
+    char output[200];
+    nullpo_retv (sd);
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Broadcast)))
+    {
+        strncpy (m, RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
+        m[RFIFOW (fd, 2) - 4] = 0;
+        log_atcommand (sd, "/announce %s", m);
+
+        memset (output, '\0', sizeof (output));
+        snprintf (output, 199, "%s : %s", sd->status.name, m);
+
+        intif_GMmessage (output, strlen (output) + 1, 0);
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_TakeItem (int fd, struct map_session_data *sd)
+{
+    struct flooritem_data *fitem;
+    int  map_object_id;
+
+    nullpo_retv (sd);
+
+    map_object_id = RFIFOL (fd, 2);
+    fitem = (struct flooritem_data *) map_id2bl (map_object_id);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+
+    if (sd->npc_id != 0 || sd->opt1 > 0 || (sd->sc_data &&
+            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
+            sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
+            sd->sc_data[SC_BERSERK].timer != -1 ||  //バーサーク
+            sd->sc_data[SC_NOCHAT].timer != -1)))   //会話禁止
+        return;
+
+    if (fitem == NULL || fitem->bl.m != sd->bl.m)
+        return;
+
+    if (abs (sd->bl.x - fitem->bl.x) >= 2
+        || abs (sd->bl.y - fitem->bl.y) >= 2)
+        return;                 // too far away to pick up
+
+    if (sd->state.shroud_active && sd->state.shroud_disappears_on_pickup)
+        magic_unshroud (sd);
+
+    pc_takeitem (sd, fitem);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_DropItem (int fd, struct map_session_data *sd)
+{
+    int  item_index, item_amount;
+
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    if (map[sd->bl.m].flag.no_player_drops)
+    {
+        clif_displaymessage(sd->fd, "Can't drop items here.");
+        return;
+    }
+    if (sd->npc_id != 0 || sd->opt1 > 0 ||
+            (sd->sc_data && (sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||    //オートカウンター
+            sd->sc_data[SC_BLADESTOP].timer != -1 ||  //白刃取り
+            sd->sc_data[SC_BERSERK].timer != -1)))    //バーサーク
+    {
+        clif_displaymessage(sd->fd, "Can't drop items right now.");
+        return;
+    }
+
+    item_index = RFIFOW (fd, 2) - 2;
+    item_amount = RFIFOW (fd, 4);
+
+    pc_dropitem (sd, item_index, item_amount);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_UseItem (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    if (sd->npc_id != 0 || sd->opt1 > 0 || (sd->sc_data &&
+            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||    //死んだふり
+            sd->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
+            sd->sc_data[SC_BERSERK].timer != -1 ||  //バーサーク
+            sd->sc_data[SC_NOCHAT].timer != -1)))   //会話禁止
+        return;
+
+    if (sd->invincible_timer != -1)
+        pc_delinvincibletimer (sd);
+
+    pc_useitem (sd, RFIFOW (fd, 2) - 2);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_EquipItem (int fd, struct map_session_data *sd)
+{
+    int  index;
+
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    index = RFIFOW (fd, 2) - 2;
+    if (sd->npc_id != 0)
+        return;
+    if (sd->sc_data
+        && (sd->sc_data[SC_BLADESTOP].timer != -1
+            || sd->sc_data[SC_BERSERK].timer != -1))
+        return;
+
+    if (sd->status.inventory[index].identify != 1)
+    {                           // 未鑑定
+        // Bjorn: Auto-identify items when equipping them as there
+        //  is no nice way to do this in the client yet.
+        sd->status.inventory[index].identify = 1;
+        //clif_equipitemack(sd,index,0,0);  // fail
+        //return;
+    }
+    //ペット用装備であるかないか
+    if (sd->inventory_data[index])
+    {
+        if (sd->inventory_data[index]->type == 10)
+            RFIFOW (fd, 4) = 0x8000;    // 矢を無理やり装備できるように(−−;
+        pc_equipitem (sd, index, RFIFOW (fd, 4));
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_UnequipItem (int fd, struct map_session_data *sd)
+{
+    int  index;
+
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    index = RFIFOW (fd, 2) - 2;
+    if (sd->status.inventory[index].broken == 1 && sd->sc_data
+        && sd->sc_data[SC_BROKNWEAPON].timer != -1)
+        skill_status_change_end (&sd->bl, SC_BROKNWEAPON, -1);
+    if (sd->status.inventory[index].broken == 1 && sd->sc_data
+        && sd->sc_data[SC_BROKNARMOR].timer != -1)
+        skill_status_change_end (&sd->bl, SC_BROKNARMOR, -1);
+    if (sd->sc_data
+        && (sd->sc_data[SC_BLADESTOP].timer != -1
+            || sd->sc_data[SC_BERSERK].timer != -1))
+        return;
+
+    if (sd->npc_id != 0 || sd->opt1 > 0)
+        return;
+    pc_unequipitem (sd, index, 0);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcClicked (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (pc_isdead (sd))
+    {
+        clif_clearchar_area (&sd->bl, 1);
+        return;
+    }
+    if (sd->npc_id != 0)
+        return;
+    npc_click (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcBuySellSelected (int fd, struct map_session_data *sd)
+{
+    npc_buysellsel (sd, RFIFOL (fd, 2), RFIFOB (fd, 6));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcBuyListSend (int fd, struct map_session_data *sd)
+{
+    int  fail = 0, n;
+    unsigned short *item_list;
+
+    n = (RFIFOW (fd, 2) - 4) / 4;
+    item_list = (unsigned short *) RFIFOP (fd, 4);
+
+    fail = npc_buylist (sd, n, item_list);
+
+    WFIFOW (fd, 0) = 0xca;
+    WFIFOB (fd, 2) = fail;
+    WFIFOSET (fd, packet_len_table[0xca]);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcSellListSend (int fd, struct map_session_data *sd)
+{
+    int  fail = 0, n;
+    unsigned short *item_list;
+
+    n = (RFIFOW (fd, 2) - 4) / 4;
+    item_list = (unsigned short *) RFIFOP (fd, 4);
+
+    fail = npc_selllist (sd, n, item_list);
+
+    WFIFOW (fd, 0) = 0xcb;
+    WFIFOB (fd, 2) = fail;
+    WFIFOSET (fd, packet_len_table[0xcb]);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_CreateChatRoom (int fd, struct map_session_data *sd)
+{
+    chat_createchat (sd, RFIFOW (fd, 4), RFIFOB (fd, 6), RFIFOP (fd, 7),
+                     RFIFOP (fd, 15), RFIFOW (fd, 2) - 15);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChatAddMember (int fd, struct map_session_data *sd)
+{
+    chat_joinchat (sd, RFIFOL (fd, 2), RFIFOP (fd, 6));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChatRoomStatusChange (int fd, struct map_session_data *sd)
+{
+    chat_changechatstatus (sd, RFIFOW (fd, 4), RFIFOB (fd, 6), RFIFOP (fd, 7),
+                           RFIFOP (fd, 15), RFIFOW (fd, 2) - 15);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChangeChatOwner (int fd, struct map_session_data *sd)
+{
+    chat_changechatowner (sd, RFIFOP (fd, 6));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_KickFromChat (int fd, struct map_session_data *sd)
+{
+    chat_kickchat (sd, RFIFOP (fd, 2));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_ChatLeave (int fd, struct map_session_data *sd)
+{
+    chat_leavechat (sd);
+}
+
+/*==========================================
+ * 取引要請を相手に送る
+ *------------------------------------------
+ */
+void clif_parse_TradeRequest (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (battle_config.basic_skill_check == 0
+        || pc_checkskill (sd, NV_TRADE) >= 1)
+    {
+        trade_traderequest (sd, RFIFOL (sd->fd, 2));
+    }
+    else
+        clif_skill_fail (sd, 1, 0, 0);
+}
+
+/*==========================================
+ * 取引要請
+ *------------------------------------------
+ */
+void clif_parse_TradeAck (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    trade_tradeack (sd, RFIFOB (sd->fd, 2));
+}
+
+/*==========================================
+ * アイテム追加
+ *------------------------------------------
+ */
+void clif_parse_TradeAddItem (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    trade_tradeadditem (sd, RFIFOW (sd->fd, 2), RFIFOL (sd->fd, 4));
+}
+
+/*==========================================
+ * アイテム追加完了(ok押し)
+ *------------------------------------------
+ */
+void clif_parse_TradeOk (int fd, struct map_session_data *sd)
+{
+    trade_tradeok (sd);
+}
+
+/*==========================================
+ * 取引キャンセル
+ *------------------------------------------
+ */
+void clif_parse_TradeCansel (int fd, struct map_session_data *sd)
+{
+    trade_tradecancel (sd);
+}
+
+/*==========================================
+ * 取引許諾(trade押し)
+ *------------------------------------------
+ */
+void clif_parse_TradeCommit (int fd, struct map_session_data *sd)
+{
+    trade_tradecommit (sd);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_StopAttack (int fd, struct map_session_data *sd)
+{
+    pc_stopattack (sd);
+}
+
+/*==========================================
+ * カートへアイテムを移す
+ *------------------------------------------
+ */
+void clif_parse_PutItemToCart (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (sd->npc_id != 0 || sd->trade_partner != 0)
+        return;
+    pc_putitemtocart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
+}
+
+/*==========================================
+ * カートからアイテムを出す
+ *------------------------------------------
+ */
+void clif_parse_GetItemFromCart (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (sd->npc_id != 0 || sd->trade_partner != 0)
+        return;
+    pc_getitemfromcart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
+}
+
+/*==========================================
+ * 付属品(鷹,ペコ,カート)をはずす
+ *------------------------------------------
+ */
+void clif_parse_RemoveOption (int fd, struct map_session_data *sd)
+{
+    if (pc_isriding (sd))
+    {                           // jobchange when removing peco [Valaris]
+        if (sd->status.pc_class == 13)
+            sd->status.pc_class = sd->view_class = 7;
+
+        if (sd->status.pc_class == 21)
+            sd->status.pc_class = sd->view_class = 14;
+
+        if (sd->status.pc_class == 4014)
+            sd->status.pc_class = sd->view_class = 4008;
+
+        if (sd->status.pc_class == 4022)
+            sd->status.pc_class = sd->view_class = 4015;
+    }
+
+    pc_setoption (sd, 0);
+}
+
+/*==========================================
+ * チェンジカート
+ *------------------------------------------
+ */
+void clif_parse_ChangeCart (int fd, struct map_session_data *sd)
+{
+    pc_setcart (sd, RFIFOW (fd, 2));
+}
+
+/*==========================================
+ * ステータスアップ
+ *------------------------------------------
+ */
+void clif_parse_StatusUp (int fd, struct map_session_data *sd)
+{
+    pc_statusup (sd, RFIFOW (fd, 2));
+}
+
+/*==========================================
+ * スキルレベルアップ
+ *------------------------------------------
+ */
+void clif_parse_SkillUp (int fd, struct map_session_data *sd)
+{
+    pc_skillup (sd, RFIFOW (fd, 2));
+}
+
+/*==========================================
+ * スキル使用(ID指定)
+ *------------------------------------------
+ */
+void clif_parse_UseSkillToId (int fd, struct map_session_data *sd)
+{
+    int  skillnum, skilllv, lv, target_id;
+    unsigned int tick = gettick ();
+
+    nullpo_retv (sd);
+
+    if (map[sd->bl.m].flag.noskill)
+        return;
+    if (sd->chatID || sd->npc_id != 0 || sd->state.storage_flag)
+        return;
+
+    skilllv = RFIFOW (fd, 2);
+    skillnum = RFIFOW (fd, 4);
+    target_id = RFIFOL (fd, 6);
+
+    if (sd->skilltimer != -1)
+    {
+        if (skillnum != SA_CASTCANCEL)
+            return;
+    }
+    else if (DIFF_TICK (tick, sd->canact_tick) < 0)
+    {
+        clif_skill_fail (sd, skillnum, 4, 0);
+        return;
+    }
+
+    if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
+        sd->sc_data[SC_BERSERK].timer != -1
+        || sd->sc_data[SC_NOCHAT].timer != -1
+        || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
+        return;
+    if (sd->invincible_timer != -1)
+        pc_delinvincibletimer (sd);
+    if (sd->skillitem >= 0 && sd->skillitem == skillnum)
+    {
+        if (skilllv != sd->skillitemlv)
+            skilllv = sd->skillitemlv;
+        skill_use_id (sd, target_id, skillnum, skilllv);
+    }
+    else
+    {
+        sd->skillitem = sd->skillitemlv = -1;
+        if (skillnum == MO_EXTREMITYFIST)
+        {
+            if ((sd->sc_data[SC_COMBO].timer == -1
+                 || (sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH
+                     && sd->sc_data[SC_COMBO].val1 != CH_CHAINCRUSH)))
+            {
+                if (!sd->state.skill_flag)
+                {
+                    sd->state.skill_flag = 1;
+                    clif_skillinfo (sd, MO_EXTREMITYFIST, 1, -1);
+                    return;
+                }
+                else if (sd->bl.id == target_id)
+                {
+                    clif_skillinfo (sd, MO_EXTREMITYFIST, 1, -1);
+                    return;
+                }
+            }
+        }
+        if ((lv = pc_checkskill (sd, skillnum)) > 0)
+        {
+            if (skilllv > lv)
+                skilllv = lv;
+            skill_use_id (sd, target_id, skillnum, skilllv);
+            if (sd->state.skill_flag)
+                sd->state.skill_flag = 0;
+        }
+    }
+}
+
+/*==========================================
+ * スキル使用(場所指定)
+ *------------------------------------------
+ */
+void clif_parse_UseSkillToPos (int fd, struct map_session_data *sd)
+{
+    int  skillnum, skilllv, lv, x, y;
+    unsigned int tick = gettick ();
+    int  skillmoreinfo;
+
+    nullpo_retv (sd);
+
+    if (map[sd->bl.m].flag.noskill)
+        return;
+    if (sd->npc_id != 0 || sd->state.storage_flag)
+        return;
+    if (sd->chatID)
+        return;
+
+    skillmoreinfo = -1;
+    skilllv = RFIFOW (fd, 2);
+    skillnum = RFIFOW (fd, 4);
+    x = RFIFOW (fd, 6);
+    y = RFIFOW (fd, 8);
+    if (RFIFOW (fd, 0) == 0x190)
+        skillmoreinfo = 10;
+
+    if (skillmoreinfo != -1)
+    {
+        if (pc_issit (sd))
+        {
+            clif_skill_fail (sd, skillnum, 0, 0);
+            return;
+        }
+        memcpy (talkie_mes, RFIFOP (fd, skillmoreinfo), 80);
+    }
+
+    if (sd->skilltimer != -1)
+        return;
+    else if (DIFF_TICK (tick, sd->canact_tick) < 0)
+    {
+        clif_skill_fail (sd, skillnum, 4, 0);
+        return;
+    }
+
+    if ((sd->sc_data[SC_TRICKDEAD].timer != -1 && skillnum != NV_TRICKDEAD) ||
+        sd->sc_data[SC_BERSERK].timer != -1
+        || sd->sc_data[SC_NOCHAT].timer != -1
+        || sd->sc_data[SC_WEDDING].timer != -1 || sd->view_class == 22)
+        return;
+    if (sd->invincible_timer != -1)
+        pc_delinvincibletimer (sd);
+    if (sd->skillitem >= 0 && sd->skillitem == skillnum)
+    {
+        if (skilllv != sd->skillitemlv)
+            skilllv = sd->skillitemlv;
+        skill_use_pos (sd, x, y, skillnum, skilllv);
+    }
+    else
+    {
+        sd->skillitem = sd->skillitemlv = -1;
+        if ((lv = pc_checkskill (sd, skillnum)) > 0)
+        {
+            if (skilllv > lv)
+                skilllv = lv;
+            skill_use_pos (sd, x, y, skillnum, skilllv);
+        }
+    }
+}
+
+/*==========================================
+ * スキル使用(map指定)
+ *------------------------------------------
+ */
+void clif_parse_UseSkillMap (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (map[sd->bl.m].flag.noskill)
+        return;
+    if (sd->chatID)
+        return;
+
+    if (sd->npc_id != 0 || (sd->sc_data &&
+                            (sd->sc_data[SC_TRICKDEAD].timer != -1 ||
+                             sd->sc_data[SC_BERSERK].timer != -1 ||
+                             sd->sc_data[SC_NOCHAT].timer != -1 ||
+                             sd->sc_data[SC_WEDDING].timer != -1 ||
+                             sd->view_class == 22)))
+        return;
+
+    if (sd->invincible_timer != -1)
+        pc_delinvincibletimer (sd);
+
+    skill_castend_map (sd, RFIFOW (fd, 2), RFIFOP (fd, 4));
+}
+
+/*==========================================
+ * メモ要求
+ *------------------------------------------
+ */
+void clif_parse_RequestMemo (int fd, struct map_session_data *sd)
+{
+    pc_memo (sd, -1);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcSelectMenu (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    sd->npc_menu = RFIFOB (fd, 6);
+    map_scriptcont (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcNextClicked (int fd, struct map_session_data *sd)
+{
+    map_scriptcont (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcAmountInput (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+#define RFIFOL_(fd,pos) (*(int*)(session[fd]->rdata+session[fd]->rdata_pos+(pos)))
+    //Input Value overflow Exploit FIX
+    sd->npc_amount = RFIFOL_ (fd, 6);   //fixed by Lupus. npc_amount is (int) but was RFIFOL changing it to (unsigned int)
+
+#undef RFIFOL_
+
+    map_scriptcont (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * Process string-based input for an NPC.
+ *
+ * (S 01d5 <len>.w <npc_ID>.l <message>.?B)
+ *------------------------------------------
+ */
+void clif_parse_NpcStringInput (int fd, struct map_session_data *sd)
+{
+    int  len;
+    nullpo_retv (sd);
+
+    len = RFIFOW (fd, 2) - 8;
+
+    /*
+     * If we check for equal to 0, too, we'll freeze clients that send (or
+     * claim to have sent) an "empty" message.
+     */
+    if (len < 0)
+        return;
+
+    if (len >= sizeof (sd->npc_str) - 1)
+    {
+        printf ("clif_parse_NpcStringInput(): Input string too long!\n");
+        len = sizeof (sd->npc_str) - 1;
+    }
+
+    if (len > 0)
+        strncpy (sd->npc_str, RFIFOP (fd, 8), len);
+    sd->npc_str[len] = '\0';
+
+    map_scriptcont (sd, RFIFOL (fd, 4));
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void clif_parse_NpcCloseClicked (int fd, struct map_session_data *sd)
+{
+    map_scriptcont (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * アイテム鑑定
+ *------------------------------------------
+ */
+void clif_parse_ItemIdentify (int fd, struct map_session_data *sd)
+{
+    pc_item_identify (sd, RFIFOW (fd, 2) - 2);
+}
+
+/*==========================================
+ * オートスペル受信
+ *------------------------------------------
+ */
+void clif_parse_AutoSpell (int fd, struct map_session_data *sd)
+{
+    skill_autospell (sd, RFIFOW (fd, 2));
+}
+
+/*==========================================
+ * カード使用
+ *------------------------------------------
+ */
+void clif_parse_UseCard (int fd, struct map_session_data *sd)
+{
+    clif_use_card (sd, RFIFOW (fd, 2) - 2);
+}
+
+/*==========================================
+ * カード挿入装備選択
+ *------------------------------------------
+ */
+void clif_parse_InsertCard (int fd, struct map_session_data *sd)
+{
+    pc_insert_card (sd, RFIFOW (fd, 2) - 2, RFIFOW (fd, 4) - 2);
+}
+
+/*==========================================
+ * 0193 キャラID名前引き
+ *------------------------------------------
+ */
+void clif_parse_SolveCharName (int fd, struct map_session_data *sd)
+{
+    int  char_id;
+
+    char_id = RFIFOL (fd, 2);
+    clif_solved_charname (sd, char_id);
+}
+
+/*==========================================
+ * 0197 /resetskill /resetstate
+ *------------------------------------------
+ */
+void clif_parse_ResetChar (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (battle_config.atc_gmonly == 0 || pc_isGM (sd))
+    {
+        switch (RFIFOW (fd, 2))
+        {
+            case 0:
+                log_atcommand (sd, "@charstreset %s", sd->status.name);
+                if (pc_isGM (sd) >=
+                    get_atcommand_level (AtCommand_ResetState))
+                    pc_resetstate (sd);
+                break;
+            case 1:
+                log_atcommand (sd, "@charskreset %s", sd->status.name);
+                if (pc_isGM (sd) >=
+                    get_atcommand_level (AtCommand_ResetState))
+                    pc_resetskill (sd);
+                break;
+        }
+    }
+}
+
+/*==========================================
+ * 019c /lb等
+ *------------------------------------------
+ */
+void clif_parse_LGMmessage (int fd, struct map_session_data *sd)
+{
+    unsigned char buf[64];
+
+    nullpo_retv (sd);
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_LocalBroadcast)))
+    {
+        WBUFW (buf, 0) = 0x9a;
+        WBUFW (buf, 2) = RFIFOW (fd, 2);
+        memcpy (WBUFP (buf, 4), RFIFOP (fd, 4), RFIFOW (fd, 2) - 4);
+        clif_send (buf, RFIFOW (fd, 2), &sd->bl, ALL_SAMEMAP);
+    }
+}
+
+/*==========================================
+ * カプラ倉庫へ入れる
+ *------------------------------------------
+ */
+void clif_parse_MoveToKafra (int fd, struct map_session_data *sd)
+{
+    int  item_index, item_amount;
+
+    nullpo_retv (sd);
+
+    item_index = RFIFOW (fd, 2) - 2;
+    item_amount = RFIFOL (fd, 4);
+
+    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
+        || !sd->state.storage_flag)
+        return;
+
+    if (sd->state.storage_flag == 1)
+        storage_storageadd (sd, item_index, item_amount);
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storageadd (sd, item_index, item_amount);
+}
+
+/*==========================================
+ * カプラ倉庫から出す
+ *------------------------------------------
+ */
+void clif_parse_MoveFromKafra (int fd, struct map_session_data *sd)
+{
+    int  item_index, item_amount;
+
+    nullpo_retv (sd);
+
+    item_index = RFIFOW (fd, 2) - 1;
+    item_amount = RFIFOL (fd, 4);
+
+    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
+        || !sd->state.storage_flag)
+        return;
+
+    if (sd->state.storage_flag == 1)
+        storage_storageget (sd, item_index, item_amount);
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storageget (sd, item_index, item_amount);
+}
+
+/*==========================================
+ * カプラ倉庫へカートから入れる
+ *------------------------------------------
+ */
+void clif_parse_MoveToKafraFromCart (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
+        || !sd->state.storage_flag)
+        return;
+    if (sd->state.storage_flag == 1)
+        storage_storageaddfromcart (sd, RFIFOW (fd, 2) - 2, RFIFOL (fd, 4));
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storageaddfromcart (sd, RFIFOW (fd, 2) - 2,
+                                          RFIFOL (fd, 4));
+}
+
+/*==========================================
+ * カプラ倉庫から出す
+ *------------------------------------------
+ */
+void clif_parse_MoveFromKafraToCart (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if ((sd->npc_id != 0 && !sd->npc_flags.storage) || sd->trade_partner != 0
+        || !sd->state.storage_flag)
+        return;
+    if (sd->state.storage_flag == 1)
+        storage_storagegettocart (sd, RFIFOW (fd, 2) - 1, RFIFOL (fd, 4));
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storagegettocart (sd, RFIFOW (fd, 2) - 1,
+                                        RFIFOL (fd, 4));
+}
+
+/*==========================================
+ * カプラ倉庫を閉じる
+ *------------------------------------------
+ */
+void clif_parse_CloseKafra (int fd, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (sd->state.storage_flag == 1)
+        storage_storageclose (sd);
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storageclose (sd);
+}
+
+/*==========================================
+ * パーティを作る
+ * Process request to create a party.
+ *
+ * (S 00f9 <party_name>.24B)
+ *------------------------------------------
+ */
+void clif_parse_CreateParty (int fd, struct map_session_data *sd)
+{
+    if (battle_config.basic_skill_check == 0
+        || pc_checkskill (sd, NV_PARTY) >= 2)
+    {
+        party_create (sd, RFIFOP (fd, 2));
+    }
+    else
+        clif_skill_fail (sd, 1, 0, 4);
+}
+
+/*==========================================
+ * パーティを作る
+ * Process request to create a party.
+ *
+ * (S 01e8 <party_name>.24B <exp>.B <itm>.B)
+ *
+ * Note: Upstream eAthena uses this to
+ *       specify experience/item sharing,
+ *       respectively, but it was left
+ *       incomplete here.
+ *------------------------------------------
+ */
+void clif_parse_CreateParty2 (int fd, struct map_session_data *sd)
+{
+    if (battle_config.basic_skill_check == 0
+        || pc_checkskill (sd, NV_PARTY) >= 2)
+    {
+        party_create (sd, RFIFOP (fd, 2));
+    }
+    else
+        clif_skill_fail (sd, 1, 0, 4);
+}
+
+/*==========================================
+ * パーティに勧誘
+ * Process invitation to join a party.
+ *
+ * (S 00fc <account_ID>.l)
+ *------------------------------------------
+ */
+void clif_parse_PartyInvite (int fd, struct map_session_data *sd)
+{
+    party_invite (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * パーティ勧誘返答
+ * Process reply to party invitation.
+ *
+ * (S 00ff <account_ID>.l <flag>.l)
+ *------------------------------------------
+ */
+void clif_parse_ReplyPartyInvite (int fd, struct map_session_data *sd)
+{
+    if (battle_config.basic_skill_check == 0
+        || pc_checkskill (sd, NV_PARTY) >= 1)
+    {
+        party_reply_invite (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
+    }
+    else
+    {
+        party_reply_invite (sd, RFIFOL (fd, 2), 0);
+        clif_skill_fail (sd, 1, 0, 4);
+    }
+}
+
+/*==========================================
+ * パーティ脱退要求
+ *------------------------------------------
+ */
+void clif_parse_LeaveParty (int fd, struct map_session_data *sd)
+{
+    party_leave (sd);
+}
+
+/*==========================================
+ * パーティ除名要求
+ *------------------------------------------
+ */
+void clif_parse_RemovePartyMember (int fd, struct map_session_data *sd)
+{
+    party_removemember (sd, RFIFOL (fd, 2), RFIFOP (fd, 6));
+}
+
+/*==========================================
+ * パーティ設定変更要求
+ *------------------------------------------
+ */
+void clif_parse_PartyChangeOption (int fd, struct map_session_data *sd)
+{
+    party_changeoption (sd, RFIFOW (fd, 2), RFIFOW (fd, 4));
+}
+
+/*==========================================
+ * パーティメッセージ送信要求
+ * Validate and process transmission of a
+ * party message.
+ *
+ * (S 0108 <len>.w <message>.?B)
+ *------------------------------------------
+ */
+void clif_parse_PartyMessage (int fd, struct map_session_data *sd)
+{
+    size_t message_len = 0;
+    char *buf = NULL;
+    char *message = NULL;   /* The message text only. */
+
+    nullpo_retv (sd);
+
+    if (!(buf = clif_validate_chat (sd, 0, &message, &message_len)))
+    {
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
+            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
+                                || sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
+    {
+        free (buf);
+        return;
+    }
+
+    /* Don't send chat that results in an automatic ban. */
+    if (tmw_CheckChatSpam (sd, message))
+    {
+        free (buf);
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    party_send_message (sd, message, RFIFOW (fd, 2) - 4);
+    free (buf);
+}
+
+/*==========================================
+ * /monster /item rewriten by [Yor]
+ *------------------------------------------
+ */
+void clif_parse_GM_Monster_Item (int fd, struct map_session_data *sd)
+{
+    char monster_item_name[25];
+
+    nullpo_retv (sd);
+
+    memset (monster_item_name, '\0', sizeof (monster_item_name));
+
+    if (battle_config.atc_gmonly == 0 || pc_isGM (sd))
+    {
+        memcpy (monster_item_name, RFIFOP (fd, 2), 24);
+
+        if (mobdb_searchname (monster_item_name) != 0)
+        {
+            if (pc_isGM (sd) >= get_atcommand_level (AtCommand_Monster))
+            {
+                log_atcommand (sd, "@spawn %s", monster_item_name);
+                atcommand_spawn (fd, sd, "@spawn", monster_item_name);  // as @spawn
+            }
+        }
+        else if (itemdb_searchname (monster_item_name) != NULL)
+        {
+            if (pc_isGM (sd) >= get_atcommand_level (AtCommand_Item))
+            {
+                log_atcommand (sd, "@item %s", monster_item_name);
+                atcommand_item (fd, sd, "@item", monster_item_name);    // as @item
+            }
+        }
+
+    }
+}
+
+/*==========================================
+ * ギルドを作る
+ * Process request to create a guild.
+ *
+ * (S 0165 <account_ID>.l <guild_name>.24B)
+ *
+ * Note: The account ID seems to be ignored.
+ *------------------------------------------
+ */
+void clif_parse_CreateGuild (int fd, struct map_session_data *sd)
+{
+    guild_create (sd, RFIFOP (fd, 6));
+}
+
+/*==========================================
+ * ギルドマスターかどうか確認
+ *------------------------------------------
+ */
+void clif_parse_GuildCheckMaster (int fd, struct map_session_data *sd)
+{
+    clif_guild_masterormember (sd);
+}
+
+/*==========================================
+ * ギルド情報要求
+ *------------------------------------------
+ */
+void clif_parse_GuildReqeustInfo (int fd, struct map_session_data *sd)
+{
+    switch (RFIFOL (fd, 2))
+    {
+        case 0:                // ギルド基本情報、同盟敵対情報
+            clif_guild_basicinfo (sd);
+            clif_guild_allianceinfo (sd);
+            break;
+        case 1:                // メンバーリスト、役職名リスト
+            clif_guild_positionnamelist (sd);
+            clif_guild_memberlist (sd);
+            break;
+        case 2:                // 役職名リスト、役職情報リスト
+            clif_guild_positionnamelist (sd);
+            clif_guild_positioninfolist (sd);
+            break;
+        case 3:                // スキルリスト
+            clif_guild_skillinfo (sd);
+            break;
+        case 4:                // 追放リスト
+            clif_guild_explusionlist (sd);
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("clif: guild request info: unknown type %d\n",
+                        RFIFOL (fd, 2));
+            break;
+    }
+}
+
+/*==========================================
+ * ギルド役職変更
+ *------------------------------------------
+ */
+void clif_parse_GuildChangePositionInfo (int fd, struct map_session_data *sd)
+{
+    struct guild *g;
+    int  i, ps;
+
+    nullpo_retv (sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || (!(g->position[ps].mode & 0x0010) && strcmp (g->master, sd->status.name)))
+        return;
+
+    for (i = 4; i < RFIFOW (fd, 2); i += 40)
+    {
+        guild_change_position (sd, RFIFOL (fd, i), RFIFOL (fd, i + 4),
+                               RFIFOL (fd, i + 12), RFIFOP (fd, i + 16));
+    }
+}
+
+/*==========================================
+ * ギルドメンバ役職変更
+ *------------------------------------------
+ */
+void clif_parse_GuildChangeMemberPosition (int fd,
+                                           struct map_session_data *sd)
+{
+    struct guild *g;
+    int  i, ps;
+
+    nullpo_retv (sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || (!(g->position[ps].mode & 0x0010) && strcmp (g->master, sd->status.name)))
+        return;
+
+    for (i = 4; i < RFIFOW (fd, 2); i += 12)
+    {
+        guild_change_memberposition (sd->status.guild_id,
+                                     RFIFOL (fd, i), RFIFOL (fd, i + 4),
+                                     RFIFOL (fd, i + 8));
+    }
+}
+
+/*==========================================
+ * ギルドエンブレム要求
+ *------------------------------------------
+ */
+void clif_parse_GuildRequestEmblem (int fd, struct map_session_data *sd)
+{
+    struct guild *g = guild_search (RFIFOL (fd, 2));
+    if (g != NULL)
+        clif_guild_emblem (sd, g);
+}
+
+/*==========================================
+ * ギルドエンブレム変更
+ *------------------------------------------
+ */
+void clif_parse_GuildChangeEmblem (int fd, struct map_session_data *sd)
+{
+    guild_change_emblem (sd, RFIFOW (fd, 2) - 4, RFIFOP (fd, 4));
+}
+
+/*==========================================
+ * ギルド告知変更
+ *------------------------------------------
+ */
+void clif_parse_GuildChangeNotice (int fd, struct map_session_data *sd)
+{
+    guild_change_notice (sd, RFIFOL (fd, 2), RFIFOP (fd, 6), RFIFOP (fd, 66));
+}
+
+/*==========================================
+ * ギルド勧誘
+ *------------------------------------------
+ */
+void clif_parse_GuildInvite (int fd, struct map_session_data *sd)
+{
+    guild_invite (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * ギルド勧誘返信
+ *------------------------------------------
+ */
+void clif_parse_GuildReplyInvite (int fd, struct map_session_data *sd)
+{
+    guild_reply_invite (sd, RFIFOL (fd, 2), RFIFOB (fd, 6));
+}
+
+/*==========================================
+ * ギルド脱退
+ *------------------------------------------
+ */
+void clif_parse_GuildLeave (int fd, struct map_session_data *sd)
+{
+    guild_leave (sd, RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
+                 RFIFOP (fd, 14));
+}
+
+/*==========================================
+ * ギルド追放
+ *------------------------------------------
+ */
+void clif_parse_GuildExplusion (int fd, struct map_session_data *sd)
+{
+    guild_explusion (sd, RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
+                     RFIFOP (fd, 14));
+}
+
+/*==========================================
+ * ギルド会話
+ * Validate and process transmission of a
+ * guild message.
+ *
+ * (S 017e <len>.w <message>.?B)
+ *------------------------------------------
+ */
+void clif_parse_GuildMessage (int fd, struct map_session_data *sd)
+{
+    size_t message_len = 0;
+    char *buf = NULL;
+    char *message = NULL;   /* The message text only. */
+
+    nullpo_retv (sd);
+
+    if (!(buf = clif_validate_chat (sd, 2, &message, &message_len)))
+    {
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    if (is_atcommand (fd, sd, message, 0) != AtCommand_None
+            || (sd->sc_data && (sd->sc_data[SC_BERSERK].timer != -1 //バーサーク時は会話も不可
+                                || sd->sc_data[SC_NOCHAT].timer != -1))) //チャット禁止
+    {
+        free (buf);
+        return;
+    }
+
+    /* Don't send chat that results in an automatic ban. */
+    if (tmw_CheckChatSpam (sd, message))
+    {
+        free (buf);
+        /* "Your message could not be sent." */
+        clif_displaymessage (fd, msg_txt (505));
+        return;
+    }
+
+    guild_send_message (sd, buf + 8, RFIFOW (fd, 2) - 4);
+    free (buf);
+}
+
+/*==========================================
+ * ギルド同盟要求
+ *------------------------------------------
+ */
+void clif_parse_GuildRequestAlliance (int fd, struct map_session_data *sd)
+{
+    guild_reqalliance (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * ギルド同盟要求返信
+ *------------------------------------------
+ */
+void clif_parse_GuildReplyAlliance (int fd, struct map_session_data *sd)
+{
+    guild_reply_reqalliance (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
+}
+
+/*==========================================
+ * ギルド関係解消
+ *------------------------------------------
+ */
+void clif_parse_GuildDelAlliance (int fd, struct map_session_data *sd)
+{
+    guild_delalliance (sd, RFIFOL (fd, 2), RFIFOL (fd, 6));
+}
+
+/*==========================================
+ * ギルド敵対
+ *------------------------------------------
+ */
+void clif_parse_GuildOpposition (int fd, struct map_session_data *sd)
+{
+    guild_opposition (sd, RFIFOL (fd, 2));
+}
+
+/*==========================================
+ * ギルド解散
+ *------------------------------------------
+ */
+void clif_parse_GuildBreak (int fd, struct map_session_data *sd)
+{
+    guild_break (sd, RFIFOP (fd, 2));
+}
+
+// Kick (right click menu for GM "(name) force to quit")
+void clif_parse_GMKick (int fd, struct map_session_data *sd)
+{
+    struct block_list *target;
+    int  tid = RFIFOL (fd, 2);
+
+    nullpo_retv (sd);
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Kick)))
+    {
+        target = map_id2bl (tid);
+        if (target)
+        {
+            if (target->type == BL_PC)
+            {
+                struct map_session_data *tsd =
+                    (struct map_session_data *) target;
+                log_atcommand (sd, "@kick %s", tsd->status.name);
+                if (pc_isGM (sd) > pc_isGM (tsd))
+                    clif_GM_kick (sd, tsd, 1);
+                else
+                    clif_GM_kickack (sd, 0);
+            }
+            else if (target->type == BL_MOB)
+            {
+                struct mob_data *md = (struct mob_data *) target;
+                sd->state.attack_type = 0;
+                mob_damage (&sd->bl, md, md->hp, 2);
+            }
+            else
+                clif_GM_kickack (sd, 0);
+        }
+        else
+            clif_GM_kickack (sd, 0);
+    }
+}
+
+/*==========================================
+ * /shift
+ *------------------------------------------
+ */
+void clif_parse_Shift (int fd, struct map_session_data *sd)
+{                               // Rewriten by [Yor]
+    char player_name[25];
+
+    nullpo_retv (sd);
+
+    memset (player_name, '\0', sizeof (player_name));
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Goto)))
+    {
+        memcpy (player_name, RFIFOP (fd, 2), 24);
+        log_atcommand (sd, "@goto %s", player_name);
+        atcommand_goto (fd, sd, "@goto", player_name);  // as @jumpto
+    }
+
+    return;
+}
+
+/*==========================================
+ * /recall
+ *------------------------------------------
+ */
+void clif_parse_Recall (int fd, struct map_session_data *sd)
+{                               // Added by RoVeRT
+    char player_name[25];
+
+    nullpo_retv (sd);
+
+    memset (player_name, '\0', sizeof (player_name));
+
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Recall)))
+    {
+        memcpy (player_name, RFIFOP (fd, 2), 24);
+        log_atcommand (sd, "@recall %s", player_name);
+        atcommand_recall (fd, sd, "@recall", player_name);  // as @recall
+    }
+
+    return;
+}
+
+void clif_parse_GMHide (int fd, struct map_session_data *sd)
+{                               // Modified by [Yor]
+    nullpo_retv (sd);
+
+    //printf("%2x %2x %2x\n", RFIFOW(fd,0), RFIFOW(fd,2), RFIFOW(fd,4)); // R 019d <Option_value>.2B <flag>.2B
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Hide)))
+    {
+        log_atcommand (sd, "@hide");
+        if (sd->status.option & OPTION_HIDE)
+        {                       // OPTION_HIDE = 0x40
+            sd->status.option &= ~OPTION_HIDE;  // OPTION_HIDE = 0x40
+            /* "Invisible: Off." */
+            clif_displaymessage (fd, msg_txt (10));
+        }
+        else
+        {
+            sd->status.option |= OPTION_HIDE;   // OPTION_HIDE = 0x40
+            /* "Invisible: On." */
+            clif_displaymessage (fd, msg_txt (11));
+        }
+        clif_changeoption (&sd->bl);
+    }
+}
+
+/*==========================================
+ * GMによるチャット禁止時間付与
+ *------------------------------------------
+ */
+void clif_parse_GMReqNoChat (int fd, struct map_session_data *sd)
+{
+    int  tid = RFIFOL (fd, 2);
+    int  type = RFIFOB (fd, 6);
+    int  limit = RFIFOW (fd, 7);
+    struct block_list *bl = map_id2bl (tid);
+    struct map_session_data *dstsd;
+    int  dstfd;
+
+    nullpo_retv (sd);
+
+    if (!battle_config.muting_players)
+    {
+        /* "Muting is disabled." */
+        clif_displaymessage (fd, msg_txt (245));
+        return;
+    }
+
+    if (type == 0)
+        limit = 0 - limit;
+    if (bl->type == BL_PC && (dstsd = (struct map_session_data *) bl))
+    {
+        if ((tid == bl->id && type == 2 && !pc_isGM (sd))
+            || (pc_isGM (sd) > pc_isGM (dstsd)))
+        {
+            dstfd = dstsd->fd;
+            WFIFOW (dstfd, 0) = 0x14b;
+            WFIFOB (dstfd, 2) = (type == 2) ? 1 : type;
+            memcpy (WFIFOP (dstfd, 3), sd->status.name, 24);
+            WFIFOSET (dstfd, packet_len_table[0x14b]);
+            dstsd->status.manner -= limit;
+            if (dstsd->status.manner < 0)
+                skill_status_change_start (bl, SC_NOCHAT, 0, 0, 0, 0, 0, 0);
+            else
+            {
+                dstsd->status.manner = 0;
+                skill_status_change_end (bl, SC_NOCHAT, -1);
+            }
+            printf ("name:%s type:%d limit:%d manner:%d\n",
+                    dstsd->status.name, type, limit, dstsd->status.manner);
+        }
+    }
+
+    return;
+}
+
+/*==========================================
+ * GMによるチャット禁止時間参照(?)
+ *------------------------------------------
+ */
+void clif_parse_GMReqNoChatCount (int fd, struct map_session_data *sd)
+{
+    int  tid = RFIFOL (fd, 2);
+
+    WFIFOW (fd, 0) = 0x1e0;
+    WFIFOL (fd, 2) = tid;
+    sprintf (WFIFOP (fd, 6), "%d", tid);
+//  memcpy(WFIFOP(fd,6),"TESTNAME",24);
+    WFIFOSET (fd, packet_len_table[0x1e0]);
+
+    return;
+}
+
+void clif_parse_PMIgnore (int fd, struct map_session_data *sd)
+{                               // Rewritten by [Yor]
+    char output[1024];
+    char *nick;                 // S 00cf <nick>.24B <type>.B: 00 (/ex nick) deny speech from nick, 01 (/in nick) allow speech from nick
+    int  i;
+    int  pos;
+
+    memset (output, '\0', sizeof (output));
+
+    nick = RFIFOP (fd, 2);      // speed up
+    //printf("Ignore: char '%s' state: %d\n", nick, RFIFOB(fd,26));
+    // we ask for deny (we add nick only if it's not already exist
+    if (RFIFOB (fd, 26) == 0)
+    {                           // type
+        if (strlen (nick) >= 4 && strlen (nick) < 24)
+        {                       // do something only if nick can be exist
+            pos = -1;
+            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
+                 i++)
+            {
+                if (strcmp (sd->ignore[i].name, nick) == 0)
+                    break;
+                else if (pos == -1 && sd->ignore[i].name[0] == '\0')
+                    pos = i;
+            }
+            WFIFOW (fd, 0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+            WFIFOB (fd, 2) = 0;
+            // if a position is found and name not found, we add it in the list
+            if (pos != -1
+                && i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
+            {
+                memcpy (sd->ignore[pos].name, nick, 24);
+                WFIFOB (fd, 3) = 0; // success
+                WFIFOSET (fd, packet_len_table[0x0d1]);
+                if (strcmp (wisp_server_name, nick) == 0)
+                {               // to found possible bot users that automaticaly ignores people.
+                    sprintf (output,
+                             "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?",
+                             sd->status.name, sd->status.account_id,
+                             wisp_server_name);
+                    intif_wis_message_to_gm (wisp_server_name,
+                                             battle_config.hack_info_GM_level,
+                                             output, strlen (output) + 1);
+                    // send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :)
+                    clif_wis_message (fd, wisp_server_name,
+                                      "Add me in your ignore list, doesn't block my wisps.",
+                                      strlen
+                                      ("Add me in your ignore list, doesn't block my wisps.")
+                                      + 1);
+                }
+            }
+            else
+            {
+                WFIFOB (fd, 3) = 1; // fail
+                if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
+                {
+                    clif_wis_message (fd, wisp_server_name,
+                                      "You can not block more people.",
+                                      strlen
+                                      ("You can not block more people.") + 1);
+                    if (strcmp (wisp_server_name, nick) == 0)
+                    {           // to found possible bot users that automaticaly ignores people.
+                        sprintf (output,
+                                 "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?",
+                                 sd->status.name, sd->status.account_id,
+                                 wisp_server_name);
+                        intif_wis_message_to_gm (wisp_server_name,
+                                                 battle_config.hack_info_GM_level,
+                                                 output, strlen (output) + 1);
+                    }
+                }
+                else
+                {
+                    clif_wis_message (fd, wisp_server_name,
+                                      "This player is already blocked.",
+                                      strlen
+                                      ("This player is already blocked.") +
+                                      1);
+                    if (strcmp (wisp_server_name, nick) == 0)
+                    {           // to found possible bot users that automaticaly ignores people.
+                        sprintf (output,
+                                 "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?",
+                                 sd->status.name, sd->status.account_id,
+                                 wisp_server_name);
+                        intif_wis_message_to_gm (wisp_server_name,
+                                                 battle_config.hack_info_GM_level,
+                                                 output, strlen (output) + 1);
+                    }
+                }
+            }
+        }
+        else
+            clif_wis_message (fd, wisp_server_name,
+                              "It's impossible to block this player.",
+                              strlen ("It's impossible to block this player.")
+                              + 1);
+        // we ask for allow (we remove all same nick if exist)
+    }
+    else
+    {
+        if (strlen (nick) >= 4 && strlen (nick) < 24)
+        {                       // do something only if nick can be exist
+            WFIFOW (fd, 0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+            WFIFOB (fd, 2) = 1;
+            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
+                 i++)
+                if (strcmp (sd->ignore[i].name, nick) == 0)
+                {
+                    memset (sd->ignore[i].name, 0,
+                            sizeof (sd->ignore[i].name));
+                    WFIFOB (fd, 3) = 0; // success
+                    WFIFOSET (fd, packet_len_table[0x0d1]);
+                    break;
+                }
+            if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
+            {
+                WFIFOB (fd, 3) = 1; // fail
+                WFIFOSET (fd, packet_len_table[0x0d1]);
+                clif_wis_message (fd, wisp_server_name,
+                                  "This player is not blocked by you.",
+                                  strlen
+                                  ("This player is not blocked by you.") + 1);
+            }
+        }
+        else
+            clif_wis_message (fd, wisp_server_name,
+                              "It's impossible to unblock this player.",
+                              strlen
+                              ("It's impossible to unblock this player.") +
+                              1);
+    }
+
+//  for(i = 0; i < (sizeof(sd->ignore) / sizeof(sd->ignore[0])); i++) // for debug only
+//      if (sd->ignore[i].name[0] != '\0')
+//          printf("Ignored player: '%s'\n", sd->ignore[i].name);
+
+    return;
+}
+
+void clif_parse_PMIgnoreAll (int fd, struct map_session_data *sd)
+{                               // Rewritten by [Yor]
+    //printf("Ignore all: state: %d\n", RFIFOB(fd,2));
+    if (RFIFOB (fd, 2) == 0)
+    {                           // S 00d0 <type>len.B: 00 (/exall) deny all speech, 01 (/inall) allow all speech
+        WFIFOW (fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+        WFIFOB (fd, 2) = 0;
+        if (sd->ignoreAll == 0)
+        {
+            sd->ignoreAll = 1;
+            WFIFOB (fd, 3) = 0; // success
+            WFIFOSET (fd, packet_len_table[0x0d2]);
+        }
+        else
+        {
+            WFIFOB (fd, 3) = 1; // fail
+            WFIFOSET (fd, packet_len_table[0x0d2]);
+            clif_wis_message (fd, wisp_server_name,
+                              "You already block everyone.",
+                              strlen ("You already block everyone.") + 1);
+        }
+    }
+    else
+    {
+        WFIFOW (fd, 0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
+        WFIFOB (fd, 2) = 1;
+        if (sd->ignoreAll == 1)
+        {
+            sd->ignoreAll = 0;
+            WFIFOB (fd, 3) = 0; // success
+            WFIFOSET (fd, packet_len_table[0x0d2]);
+        }
+        else
+        {
+            WFIFOB (fd, 3) = 1; // fail
+            WFIFOSET (fd, packet_len_table[0x0d2]);
+            clif_wis_message (fd, wisp_server_name,
+                              "You already allow everyone.",
+                              strlen ("You already allow everyone.") + 1);
+        }
+    }
+
+    return;
+}
+
+void clif_parse_skillMessage (int fd, struct map_session_data *sd)
+{                               // Added by RoVeRT
+    int  skillid, skilllv, x, y;
+    char *mes;
+
+    skilllv = RFIFOW (fd, 2);
+    skillid = RFIFOW (fd, 4);
+
+    y = RFIFOB (fd, 6);
+    x = RFIFOB (fd, 8);
+
+    mes = RFIFOP (fd, 10);
+
+    // skill 220 = graffiti
+//  printf("skill: %d %d location: %3d %3d message: %s\n", skillid, skilllv, x, y, (char*)mes);
+}
+
+int monk (struct map_session_data *sd, struct block_list *target, int type)
+{
+//R 01d1 <Monk id>L <Target monster id>L <Bool>L
+    int  fd = sd->fd;
+    WFIFOW (fd, 0) = 0x1d1;
+    WFIFOL (fd, 2) = sd->bl.id;
+    WFIFOL (fd, 6) = target->id;
+    WFIFOL (fd, 10) = type;
+    WFIFOSET (fd, packet_len_table[0x1d1]);
+
+    return 0;
+}
+
+/*==========================================
+ * スパノビの/doridoriによるSPR2倍
+ *------------------------------------------
+ */
+void clif_parse_sn_doridori (int fd, struct map_session_data *sd)
+{
+    if (sd)
+        sd->doridori_counter = 1;
+
+    return;
+}
+
+/*==========================================
+ * スパノビの爆裂波動
+ *------------------------------------------
+ */
+void clif_parse_sn_explosionspirits (int fd, struct map_session_data *sd)
+{
+    if (sd)
+    {
+        int  nextbaseexp = pc_nextbaseexp (sd);
+        struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
+        if (battle_config.etc_log)
+        {
+            if (nextbaseexp != 0)
+                printf ("SuperNovice explosionspirits!! %d %d %d %d\n",
+                        sd->bl.id, s_class.job, sd->status.base_exp,
+                        (int) ((double) 1000 * sd->status.base_exp /
+                               nextbaseexp));
+            else
+                printf ("SuperNovice explosionspirits!! %d %d %d 000\n",
+                        sd->bl.id, s_class.job, sd->status.base_exp);
+        }
+        if (s_class.job == 23 && 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, 1);
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable
+                                       [MO_EXPLOSIONSPIRITS], 5, 0, 0, 0,
+                                       skill_get_time (MO_EXPLOSIONSPIRITS,
+                                                       5), 0);
+        }
+    }
+    return;
+}
+
+// functions list. Rate is how many milliseconds are required between
+// calls. Packets exceeding this rate will be dropped. flood_rates in
+// map.h must be the same length as this table. rate 0 is default
+// rate -1 is unlimited
+typedef struct func_table
+{
+	void (*func)(int fd, struct map_session_data *sd);
+	int rate;
+} func_table;
+// *INDENT-OFF*
+func_table clif_parse_func_table[0x220] =
+{
+	{ NULL,					0	},	// 0
+	{ NULL,					0	},	// 1
+	{ NULL,					0	},	// 2
+	{ NULL,					0	},	// 3
+	{ NULL,					0	},	// 4
+	{ NULL,					0	},	// 5
+	{ NULL,					0	},	// 6
+	{ NULL,					0	},	// 7
+	{ NULL,					0	},	// 8
+	{ NULL,					0	},	// 9
+	{ NULL,					0	},	// a
+	{ NULL,					0	},	// b
+	{ NULL,					0	},	// c
+	{ NULL,					0	},	// d
+	{ NULL,					0	},	// e
+	{ NULL,					0	},	// f
+	{ NULL,					0	},	// 10
+	{ NULL,					0	},	// 11
+	{ NULL,					0	},	// 12
+	{ NULL,					0	},	// 13
+	{ NULL,					0	},	// 14
+	{ NULL,					0	},	// 15
+	{ NULL,					0	},	// 16
+	{ NULL,					0	},	// 17
+	{ NULL,					0	},	// 18
+	{ NULL,					0	},	// 19
+	{ NULL,					0	},	// 1a
+	{ NULL,					0	},	// 1b
+	{ NULL,					0	},	// 1c
+	{ NULL,					0	},	// 1d
+	{ NULL,					0	},	// 1e
+	{ NULL,					0	},	// 1f
+	{ NULL,					0	},	// 20
+	{ NULL,					0	},	// 21
+	{ NULL,					0	},	// 22
+	{ NULL,					0	},	// 23
+	{ NULL,					0	},	// 24
+	{ NULL,					0	},	// 25
+	{ NULL,					0	},	// 26
+	{ NULL,					0	},	// 27
+	{ NULL,					0	},	// 28
+	{ NULL,					0	},	// 29
+	{ NULL,					0	},	// 2a
+	{ NULL,					0	},	// 2b
+	{ NULL,					0	},	// 2c
+	{ NULL,					0	},	// 2d
+	{ NULL,					0	},	// 2e
+	{ NULL,					0	},	// 2f
+	{ NULL,					0	},	// 30
+	{ NULL,					0	},	// 31
+	{ NULL,					0	},	// 32
+	{ NULL,					0	},	// 33
+	{ NULL,					0	},	// 34
+	{ NULL,					0	},	// 35
+	{ NULL,					0	},	// 36
+	{ NULL,					0	},	// 37
+	{ NULL,					0	},	// 38
+	{ NULL,					0	},	// 39
+	{ NULL,					0	},	// 3a
+	{ NULL,					0	},	// 3b
+	{ NULL,					0	},	// 3c
+	{ NULL,					0	},	// 3d
+	{ NULL,					0	},	// 3e
+	{ NULL,					0	},	// 3f
+	{ NULL,					0	},	// 40
+	{ NULL,					0	},	// 41
+	{ NULL,					0	},	// 42
+	{ NULL,					0	},	// 43
+	{ NULL,					0	},	// 44
+	{ NULL,					0	},	// 45
+	{ NULL,					0	},	// 46
+	{ NULL,					0	},	// 47
+	{ NULL,					0	},	// 48
+	{ NULL,					0	},	// 49
+	{ NULL,					0	},	// 4a
+	{ NULL,					0	},	// 4b
+	{ NULL,					0	},	// 4c
+	{ NULL,					0	},	// 4d
+	{ NULL,					0	},	// 4e
+	{ NULL,					0	},	// 4f
+	{ NULL,					0	},	// 50
+	{ NULL,					0	},	// 51
+	{ NULL,					0	},	// 52
+	{ NULL,					0	},	// 53
+	{ NULL,					0	},	// 54
+	{ NULL,					0	},	// 55
+	{ NULL,					0	},	// 56
+	{ NULL,					0	},	// 57
+	{ NULL,					0	},	// 58
+	{ NULL,					0	},	// 59
+	{ NULL,					0	},	// 5a
+	{ NULL,					0	},	// 5b
+	{ NULL,					0	},	// 5c
+	{ NULL,					0	},	// 5d
+	{ NULL,					0	},	// 5e
+	{ NULL,					0	},	// 5f
+	{ NULL,					0	},	// 60
+	{ NULL,					0	},	// 61
+	{ NULL,					0	},	// 62
+	{ NULL,					0	},	// 63
+	{ NULL,					0	},	// 64
+	{ NULL,					0	},	// 65
+	{ NULL,					0	},	// 66
+	{ NULL,					0	},	// 67
+	{ NULL,					0	},	// 68
+	{ NULL,					0	},	// 69
+	{ NULL,					0	},	// 6a
+	{ NULL,					0	},	// 6b
+	{ NULL,					0	},	// 6c
+	{ NULL,					0	},	// 6d
+	{ NULL,					0	},	// 6e
+	{ NULL,					0	},	// 6f
+	{ NULL,					0	},	// 70
+	{ NULL,					0	},	// 71
+	{ clif_parse_WantToConnection,		0	},	// 72
+	{ NULL,					0	},	// 73
+	{ NULL,					0	},	// 74
+	{ NULL,					0	},	// 75
+	{ NULL,					0	},	// 76
+	{ NULL,					0	},	// 77
+	{ NULL,					0	},	// 78
+	{ NULL,					0	},	// 79
+	{ NULL,					0	},	// 7a
+	{ NULL,					0	},	// 7b
+	{ NULL,					0	},	// 7c
+	{ clif_parse_LoadEndAck,		-1	},	// 7d
+	{ clif_parse_TickSend,			0	},	// 7e
+	{ NULL,					0	},	// 7f
+	{ NULL,					0	},	// 80
+	{ NULL,					0	},	// 81
+	{ NULL,					0	},	// 82
+	{ NULL,					0	},	// 83
+	{ NULL,					0	},	// 84
+	{ clif_parse_WalkToXY,			-1	},	// 85 Walk code limits this on it's own
+	{ NULL,					0	},	// 86
+	{ NULL,					0	},	// 87
+	{ NULL,					0	},	// 88
+	{ clif_parse_ActionRequest,		1000	},	// 89 Special case - see below
+	{ NULL,					0	},	// 8a
+	{ NULL,					0	},	// 8b
+	{ clif_parse_GlobalMessage,		300	},	// 8c
+	{ NULL,					0	},	// 8d
+	{ NULL,					0	},	// 8e
+	{ NULL,					0	},	// 8f
+	{ clif_parse_NpcClicked,		500	},	// 90
+	{ NULL,					0	},	// 91
+	{ NULL,					0	},	// 92
+	{ NULL,					0	},	// 93
+	{ clif_parse_GetCharNameRequest,	-1	},	// 94
+	{ NULL,					0	},	// 95
+	{ clif_parse_Wis,			300	},	// 96
+	{ NULL,					0	},	// 97
+	{ NULL,					0	},	// 98
+	{ clif_parse_GMmessage,			300	},	// 99
+	{ NULL,					0	},	// 9a
+	{ clif_parse_ChangeDir,			-1	},	// 9b
+	{ NULL,					0	},	// 9c
+	{ NULL,					0	},	// 9d
+	{ NULL,					0	},	// 9e
+	{ clif_parse_TakeItem,			400	},	// 9f
+	{ NULL,					0	},	// a0
+	{ NULL,					0	},	// a1
+	{ clif_parse_DropItem,			50	},	// a2
+	{ NULL,					0	},	// a3
+	{ NULL,					0	},	// a4
+	{ NULL,					0	},	// a5
+	{ NULL,					0	},	// a6
+	{ clif_parse_UseItem,			0	},	// a7
+	{ NULL,					0	},	// a8
+	{ clif_parse_EquipItem,			-1	},	// a9 Special case - outfit window (not implemented yet - needs to allow bursts)
+	{ NULL,					0	},	// aa
+	{ clif_parse_UnequipItem,		-1	},	// ab Special case - outfit window (not implemented yet - needs to allow bursts)
+	{ NULL,					0	},	// ac
+	{ NULL,					0	},	// ad
+	{ NULL,					0	},	// ae
+	{ NULL,					0	},	// af
+	{ NULL,					0	},	// b0
+	{ NULL,					0	},	// b1
+	{ clif_parse_Restart,			0	},	// b2
+	{ NULL,					0	},	// b3
+	{ NULL,					0	},	// b4
+	{ NULL,					0	},	// b5
+	{ NULL,					0	},	// b6
+	{ NULL,					0	},	// b7
+	{ clif_parse_NpcSelectMenu,		0	},	// b8
+	{ clif_parse_NpcNextClicked,		-1	},	// b9
+	{ NULL,					0	},	// ba
+	{ clif_parse_StatusUp,			-1	},	// bb People click this very quickly
+	{ NULL,					0	},	// bc
+	{ NULL,					0	},	// bd
+	{ NULL,					0	},	// be
+	{ clif_parse_Emotion,			1000	},	// bf
+	{ NULL,					0	},	// c0
+	{ clif_parse_HowManyConnections,	0	},	// c1
+	{ NULL,					0	},	// c2
+	{ NULL,					0	},	// c3
+	{ NULL,					0	},	// c4
+	{ clif_parse_NpcBuySellSelected,	0	},	// c5
+	{ NULL,					0	},	// c6
+	{ NULL,					0	},	// c7
+	{ clif_parse_NpcBuyListSend,		-1	},	// c8
+	{ clif_parse_NpcSellListSend,		-1	},	// c9 Selling multiple 1-slot items
+	{ NULL,					0	},	// ca
+	{ NULL,					0	},	// cb
+	{ clif_parse_GMKick,			0	},	// cc
+	{ NULL,					0	},	// cd
+	{ NULL,					0	},	// ce
+	{ clif_parse_PMIgnore,			0	},	// cf
+	{ clif_parse_PMIgnoreAll,		0	},	// d0
+	{ NULL,					0	},	// d1
+	{ NULL,					0	},	// d2
+	{ NULL,					0	},	// d3
+	{ NULL,					0	},	// d4
+	{ clif_parse_CreateChatRoom,		1000	},	// d5
+	{ NULL,					0	},	// d6
+	{ NULL,					0	},	// d7
+	{ NULL,					0	},	// d8
+	{ clif_parse_ChatAddMember,		0	},	// d9
+	{ NULL,					0	},	// da
+	{ NULL,					0	},	// db
+	{ NULL,					0	},	// dc
+	{ NULL,					0	},	// dd
+	{ clif_parse_ChatRoomStatusChange,	0	},	// de
+	{ NULL,					0	},	// df
+	{ clif_parse_ChangeChatOwner,		0	},	// e0
+	{ NULL,					0	},	// e1
+	{ clif_parse_KickFromChat,		0	},	// e2
+	{ clif_parse_ChatLeave,			0	},	// e3
+	{ clif_parse_TradeRequest,		2000	},	// e4
+	{ NULL,					0	},	// e5
+	{ clif_parse_TradeAck,			0	},	// e6
+	{ NULL,					0	},	// e7
+	{ clif_parse_TradeAddItem,		0	},	// e8
+	{ NULL,					0	},	// e9
+	{ NULL,					0	},	// ea
+	{ clif_parse_TradeOk,			0	},	// eb
+	{ NULL,					0	},	// ec
+	{ clif_parse_TradeCansel,		0	},	// ed
+	{ NULL,					0	},	// ee
+	{ clif_parse_TradeCommit,		0	},	// ef
+	{ NULL,					0	},	// f0
+	{ NULL,					0	},	// f1
+	{ NULL,					0	},	// f2
+	{ clif_parse_MoveToKafra,		-1	},	// f3
+	{ NULL,					0	},	// f4
+	{ clif_parse_MoveFromKafra,		-1	},	// f5
+	{ NULL,					0	},	// f6
+	{ clif_parse_CloseKafra,		0	},	// f7
+	{ NULL,					0	},	// f8
+	{ clif_parse_CreateParty,		2000	},	// f9
+	{ NULL,					0	},	// fa
+	{ NULL,					0	},	// fb
+	{ clif_parse_PartyInvite,		2000	},	// fc
+	{ NULL,					0	},	// fd
+	{ NULL,					0	},	// fe
+	{ clif_parse_ReplyPartyInvite,		0	},	// ff
+	{ clif_parse_LeaveParty,		0	},	// 100
+	{ NULL,					0	},	// 101
+	{ clif_parse_PartyChangeOption,		0	},	// 102
+	{ clif_parse_RemovePartyMember,		0	},	// 103
+	{ NULL,					0	},	// 104
+	{ NULL,					0	},	// 105
+	{ NULL,					0	},	// 106
+	{ NULL,					0	},	// 107
+	{ clif_parse_PartyMessage,		300	},	// 108
+	{ NULL,					0	},	// 109
+	{ NULL,					0	},	// 10a
+	{ NULL,					0	},	// 10b
+	{ NULL,					0	},	// 10c
+	{ NULL,					0	},	// 10d
+	{ NULL,					0	},	// 10e
+	{ NULL,					0	},	// 10f
+	{ NULL,					0	},	// 110
+	{ NULL,					0	},	// 111
+	{ clif_parse_SkillUp,			-1	},	// 112
+	{ clif_parse_UseSkillToId,		0	},	// 113
+	{ NULL,					0	},	// 114
+	{ NULL,					0	},	// 115
+	{ clif_parse_UseSkillToPos,		0	},	// 116
+	{ NULL,					0	},	// 117
+	{ clif_parse_StopAttack,		0	},	// 118
+	{ NULL,					0	},	// 119
+	{ NULL,					0	},	// 11a
+	{ clif_parse_UseSkillMap,		0	},	// 11b
+	{ NULL,					0	},	// 11c
+	{ clif_parse_RequestMemo,		0	},	// 11d
+	{ NULL,					0	},	// 11e
+	{ NULL,					0	},	// 11f
+	{ NULL,					0	},	// 120
+	{ NULL,					0	},	// 121
+	{ NULL,					0	},	// 122
+	{ NULL,					0	},	// 123
+	{ NULL,					0	},	// 124
+	{ NULL,					0	},	// 125
+	{ clif_parse_PutItemToCart,		0	},	// 126
+	{ clif_parse_GetItemFromCart,		0	},	// 127
+	{ clif_parse_MoveFromKafraToCart,	0	},	// 128
+	{ clif_parse_MoveToKafraFromCart,	0	},	// 129
+	{ clif_parse_RemoveOption,		0	},	// 12a
+	{ NULL,					0	},	// 12b
+	{ NULL,					0	},	// 12c
+	{ NULL,					0	},	// 12d
+	{ NULL,					0	},	// 12e
+	{ NULL,					0	},	// 12f
+	{ NULL,					0	},	// 130
+	{ NULL,					0	},	// 131
+	{ NULL,					0	},	// 132
+	{ NULL,					0	},	// 133
+	{ NULL,					0	},	// 134
+	{ NULL,					0	},	// 135
+	{ NULL,					0	},	// 136
+	{ NULL,					0	},	// 137
+	{ NULL,					0	},	// 138
+	{ NULL,					0	},	// 139
+	{ NULL,					0	},	// 13a
+	{ NULL,					0	},	// 13b
+	{ NULL,					0	},	// 13c
+	{ NULL,					0	},	// 13d
+	{ NULL,					0	},	// 13e
+	{ clif_parse_GM_Monster_Item,		0	},	// 13f
+	{ clif_parse_MapMove,			0	},	// 140
+	{ NULL,					0	},	// 141
+	{ NULL,					0	},	// 142
+	{ clif_parse_NpcAmountInput,		300	},	// 143
+	{ NULL,					0	},	// 144
+	{ NULL,					0	},	// 145
+	{ clif_parse_NpcCloseClicked,		300	},	// 146
+	{ NULL,					0	},	// 147
+	{ NULL,					0	},	// 148
+	{ clif_parse_GMReqNoChat,		0	},	// 149
+	{ NULL,					0	},	// 14a
+	{ NULL,					0	},	// 14b
+	{ NULL,					0	},	// 14c
+	{ clif_parse_GuildCheckMaster,		0	},	// 14d
+	{ NULL,					0	},	// 14e
+	{ clif_parse_GuildReqeustInfo,		0	},	// 14f
+	{ NULL,					0	},	// 150
+	{ clif_parse_GuildRequestEmblem,	0	},	// 151
+	{ NULL,					0	},	// 152
+	{ clif_parse_GuildChangeEmblem,		0	},	// 153
+	{ NULL,					0	},	// 154
+	{ clif_parse_GuildChangeMemberPosition,	0	},	// 155
+	{ NULL,					0	},	// 156
+	{ NULL,					0	},	// 157
+	{ NULL,					0	},	// 158
+	{ clif_parse_GuildLeave,		0	},	// 159
+	{ NULL,					0	},	// 15a
+	{ clif_parse_GuildExplusion,		0	},	// 15b
+	{ NULL,					0	},	// 15c
+	{ clif_parse_GuildBreak,		0	},	// 15d
+	{ NULL,					0	},	// 15e
+	{ NULL,					0	},	// 15f
+	{ NULL,					0	},	// 160
+	{ clif_parse_GuildChangePositionInfo,	0	},	// 161
+	{ NULL,					0	},	// 162
+	{ NULL,					0	},	// 163
+	{ NULL,					0	},	// 164
+	{ clif_parse_CreateGuild,		0	},	// 165
+	{ NULL,					0	},	// 166
+	{ NULL,					0	},	// 167
+	{ clif_parse_GuildInvite,		2000	},	// 168
+	{ NULL,					0	},	// 169
+	{ NULL,					0	},	// 16a
+	{ clif_parse_GuildReplyInvite,		0	},	// 16b
+	{ NULL,					0	},	// 16c
+	{ NULL,					0	},	// 16d
+	{ clif_parse_GuildChangeNotice,		0	},	// 16e
+	{ NULL,					0	},	// 16f
+	{ clif_parse_GuildRequestAlliance,	0	},	// 170
+	{ NULL,					0	},	// 171
+	{ clif_parse_GuildReplyAlliance,	0	},	// 172
+	{ NULL,					0	},	// 173
+	{ NULL,					0	},	// 174
+	{ NULL,					0	},	// 175
+	{ NULL,					0	},	// 176
+	{ NULL,					0	},	// 177
+	{ clif_parse_ItemIdentify,		0	},	// 178
+	{ NULL,					0	},	// 179
+	{ clif_parse_UseCard,			0	},	// 17a
+	{ NULL,					0	},	// 17b
+	{ clif_parse_InsertCard,		0	},	// 17c
+	{ NULL,					0	},	// 17d
+	{ clif_parse_GuildMessage,		300	},	// 17e
+	{ NULL,					0	},	// 17f
+	{ clif_parse_GuildOpposition,		0	},	// 180
+	{ NULL,					0	},	// 181
+	{ NULL,					0	},	// 182
+	{ clif_parse_GuildDelAlliance,		0	},	// 183
+	{ NULL,					0	},	// 184
+	{ NULL,					0	},	// 185
+	{ NULL,					0	},	// 186
+	{ NULL,					0	},	// 187
+	{ NULL,					0	},	// 188
+	{ NULL,					0	},	// 189
+	{ clif_parse_QuitGame,			0	},	// 18a
+	{ NULL,					0	},	// 18b
+	{ NULL,					0	},	// 18c
+	{ NULL,					0	},	// 18d
+	{ NULL,					0	},	// 18e
+	{ NULL,					0	},	// 18f
+	{ clif_parse_UseSkillToPos,		0	},	// 190
+	{ NULL,					0	},	// 191
+	{ NULL,					0	},	// 192
+	{ clif_parse_SolveCharName,		0	},	// 193
+	{ NULL,					0	},	// 194
+	{ NULL,					0	},	// 195
+	{ NULL,					0	},	// 196
+	{ clif_parse_ResetChar,			0	},	// 197
+	{ NULL,					0	},	// 198
+	{ NULL,					0	},	// 199
+	{ NULL,					0	},	// 19a
+	{ NULL,					0	},	// 19b
+	{ clif_parse_LGMmessage,		0	},	// 19c
+	{ clif_parse_GMHide,			300	},	// 19d
+	{ NULL,					0	},	// 19e
+	{ NULL,					0	},	// 19f
+	{ NULL,					0	},	// 1a0
+	{ NULL,					0	},	// 1a1
+	{ NULL,					0	},	// 1a2
+	{ NULL,					0	},	// 1a3
+	{ NULL,					0	},	// 1a4
+	{ NULL,					0	},	// 1a5
+	{ NULL,					0	},	// 1a6
+	{ NULL,					0	},	// 1a7
+	{ NULL,					0	},	// 1a8
+	{ NULL,					0	},	// 1a9
+	{ NULL,					0	},	// 1aa
+	{ NULL,					0	},	// 1ab
+	{ NULL,					0	},	// 1ac
+	{ NULL,					0	},	// 1ad
+	{ NULL,					0	},	// 1ae
+	{ clif_parse_ChangeCart,		0	},	// 1af
+	{ NULL,					0	},	// 1b0
+	{ NULL,					0	},	// 1b1
+	{ NULL,					0	},	// 1b2
+	{ NULL,					0	},	// 1b3
+	{ NULL,					0	},	// 1b4
+	{ NULL,					0	},	// 1b5
+	{ NULL,					0	},	// 1b6
+	{ NULL,					0	},	// 1b7
+	{ NULL,					0	},	// 1b8
+	{ NULL,					0	},	// 1b9
+	{ clif_parse_Shift,			300	},	// 1ba
+	{ clif_parse_Shift,			300	},	// 1bb
+	{ clif_parse_Recall,			300	},	// 1bc
+	{ clif_parse_Recall,			300	},	// 1bd
+	{ NULL,					0	},	// 1be
+	{ NULL,					0	},	// 1bf
+	{ NULL,					0	},	// 1c0
+	{ NULL,					0	},	// 1c1
+	{ NULL,					0	},	// 1c2
+	{ NULL,					0	},	// 1c3
+	{ NULL,					0	},	// 1c4
+	{ NULL,					0	},	// 1c5
+	{ NULL,					0	},	// 1c6
+	{ NULL,					0	},	// 1c7
+	{ NULL,					0	},	// 1c8
+	{ NULL,					0	},	// 1c9
+	{ NULL,					0	},	// 1ca
+	{ NULL,					0	},	// 1cb
+	{ NULL,					0	},	// 1cc
+	{ NULL,					0	},	// 1cd
+	{ clif_parse_AutoSpell,			0	},	// 1ce
+	{ NULL,					0	},	// 1cf
+	{ NULL,					0	},	// 1d0
+	{ NULL,					0	},	// 1d1
+	{ NULL,					0	},	// 1d2
+	{ NULL,					0	},	// 1d3
+	{ NULL,					0	},	// 1d4
+	{ clif_parse_NpcStringInput,		300	},	// 1d5
+	{ NULL,					0	},	// 1d6
+	{ NULL,					0	},	// 1d7
+	{ NULL,					0	},	// 1d8
+	{ NULL,					0	},	// 1d9
+	{ NULL,					0	},	// 1da
+	{ NULL,					0	},	// 1db
+	{ NULL,					0	},	// 1dc
+	{ NULL,					0	},	// 1dd
+	{ NULL,					0	},	// 1de
+	{ clif_parse_GMReqNoChatCount,		0	},	// 1df
+	{ NULL,					0	},	// 1e0
+	{ NULL,					0	},	// 1e1
+	{ NULL,					0	},	// 1e2
+	{ NULL,					0	},	// 1e3
+	{ NULL,					0	},	// 1e4
+	{ NULL,					0	},	// 1e5
+	{ NULL,					0	},	// 1e6
+	{ clif_parse_sn_doridori,		0	},	// 1e7
+	{ clif_parse_CreateParty2,		1000	},	// 1e8
+	{ NULL,					0	},	// 1e9
+	{ NULL,					0	},	// 1ea
+	{ NULL,					0	},	// 1eb
+	{ NULL,					0	},	// 1ec
+	{ clif_parse_sn_explosionspirits,	0	},	// 1ed
+	{ NULL,					0	},	// 1ee
+	{ NULL,					0	},	// 1ef
+	{ NULL,					0	},	// 1f0
+	{ NULL,					0	},	// 1f1
+	{ NULL,					0	},	// 1f2
+	{ NULL,					0	},	// 1f3
+	{ NULL,					0	},	// 1f4
+	{ NULL,					0	},	// 1f5
+	{ NULL,					0	},	// 1f6
+	{ NULL,					0	},	// 1f7
+	{ NULL,					0	},	// 1f8
+	{ NULL,					0	},	// 1f9
+	{ NULL,					0	},	// 1fa
+	{ NULL,					0	},	// 1fb
+	{ NULL,					0	},	// 1fc
+	{ NULL,					0	},	// 1fd
+	{ NULL,					0	},	// 1fe
+	{ NULL,					0	},	// 1ff
+	{ NULL,					0	},	// 200
+	{ NULL,					0	},	// 201
+	{ NULL,					0	},	// 202
+	{ NULL,					0	},	// 203
+	{ NULL,					0	},	// 204
+	{ NULL,					0	},	// 205
+	{ NULL,					0	},	// 206
+	{ NULL,					0	},	// 207
+	{ NULL,					0	},	// 208
+	{ NULL,					0	},	// 209
+	{ NULL,					0	},	// 20a
+	{ NULL,					0	},	// 20b
+	{ NULL,					0	},	// 20c
+	{ NULL,					0	},	// 20d
+	{ NULL,					0	},	// 20e
+	{ NULL,					0	},	// 20f
+	{ NULL,					0	},	// 210
+	{ NULL,					0	},	// 211
+	{ NULL,					0	},	// 212
+	{ NULL,					0	},	// 213
+	{ NULL,					0	},	// 214
+	{ NULL,					0	},	// 215
+	{ NULL,					0	},	// 216
+	{ NULL,					0	},	// 217
+	{ NULL,					0	},	// 218
+	{ NULL,					0	},	// 219
+	{ NULL,					0	},	// 21a
+	{ NULL,					0	},	// 21b
+	{ NULL,					0	},	// 21c
+	{ NULL,					0	},	// 21d
+	{ NULL,					0	},	// 21e
+	{ NULL,					0	},	// 21f
+};
+// *INDENT-ON*
+
+// Checks for packet flooding
+int clif_check_packet_flood(int fd, int cmd)
+{
+    struct map_session_data *sd = (struct map_session_data *)session[fd]->session_data;
+    unsigned int rate, tick = gettick();
+
+    // sd will not be set if the client hasn't requested
+    // WantToConnection yet. Do not apply flood logic to GMs
+    // as approved bots (GMlvl1) should not have to work around
+    // flood logic.
+    if (!sd || pc_isGM(sd) || clif_parse_func_table[cmd].rate == -1)
+	return 0;
+
+    // Timer has wrapped
+    if (tick < sd->flood_rates[cmd])
+    {
+        sd->flood_rates[cmd] = tick;
+        return 0;
+    }
+
+    // Default rate is 100ms
+    if ((rate = clif_parse_func_table[cmd].rate) == 0)
+        rate = 100;
+
+    // ActionRequest - attacks are allowed a faster rate than sit/stand
+    if (cmd == 0x89)
+    {
+        int action_type = RFIFOB (fd, 6);
+        if (action_type == 0x00 || action_type == 0x07)
+            rate = 20;
+        else
+            rate = 1000;
+    }
+
+// Restore this code when mana1.0 is released
+#if 0
+    // ChangeDir - only apply limit if not walking
+    if (cmd == 0x9b)
+    {
+        // .29 clients spam this packet when walking into a blocked tile
+        if (RFIFOB(fd, 4) == sd->dir || sd->walktimer != -1)
+            return 0;
+
+        rate = 500;
+    }
+#endif
+
+    // They are flooding
+    if (tick < sd->flood_rates[cmd] + rate)
+    {
+        time_t now = time(NULL);
+
+        // If it's a nasty flood we log and possibly kick
+        if (now > sd->packet_flood_reset_due)
+        {
+            sd->packet_flood_reset_due = now + battle_config.packet_spam_threshold;
+            sd->packet_flood_in = 0;
+        }
+
+        sd->packet_flood_in++;
+
+        if (sd->packet_flood_in >= battle_config.packet_spam_flood)
+        {
+            printf("packet flood detected from %s [0x%x]\n", sd->status.name, cmd);
+            if (battle_config.packet_spam_kick)
+            {
+                session[fd]->eof = 1; // Kick
+                return 1;
+            }
+            sd->packet_flood_in = 0;
+        }
+
+        return 1;
+    }
+
+    sd->flood_rates[cmd] = tick;
+    return 0;
+}
+
+#define WARN_MALFORMED_MSG(sd, msg)                             \
+    printf ("clif_validate_chat(): %s (ID %d) sent a malformed" \
+            " message: %s.\n", sd->status.name, sd->status.account_id, msg)
+/**
+ * Validate message integrity (inspired by upstream source (eAthena)).
+ *
+ * @param sd active session data
+ * @param type message type:
+ *  0 for when the sender's name is not included (party chat)
+ *  1 for when the target's name is included (whisper chat)
+ *  2 for when the sender's name is given ("sender : text", public/guild chat)
+ * @param[out] message the message text (pointing within return value, or NULL)
+ * @param[out] message_len the length of the actual text, excluding NUL
+ * @return a dynamically allocated copy of the message, or NULL upon failure
+ */
+static char *clif_validate_chat (struct map_session_data *sd, int type,
+                                 char **message, size_t *message_len)
+{
+    int fd;
+    unsigned int buf_len;       /* Actual message length. */
+    unsigned int msg_len;       /* Reported message length. */
+    unsigned int min_len;       /* Minimum message length. */
+    size_t name_len;            /* Sender's name length. */
+    char *buf = NULL;           /* Copy of actual message data. */
+    char *p = NULL;             /* Temporary pointer to message. */
+
+    *message = NULL;
+    *message_len = 0;
+
+    nullpo_retr (NULL, sd);
+    /*
+     * Don't send chat in the period between the ban and the connection's
+     * closure.
+     */
+    if (type < 0 || type > 2 || sd->auto_ban_info.in_progress)
+        return NULL;
+
+    fd = sd->fd;
+    msg_len = RFIFOW (fd, 2) - 4;
+    name_len = strlen (sd->status.name);
+    /*
+     * At least one character is required in all instances.
+     * Notes for length checks:
+     *
+     * For all types, header (2) + length (2) is considered empty.
+     * For type 1, the message must be longer than the maximum name length (24)
+     *      to be valid.
+     * For type 2, the message must be longer than the sender's name length
+     *      plus the length of the separator (" : ").
+     */
+    min_len = (type == 1) ? 24 : (type == 2) ? name_len + 3 : 0;
+
+    /* The player just sent the header (2) and length (2) words. */
+    if (!msg_len)
+    {
+        WARN_MALFORMED_MSG (sd, "no message sent");
+        return NULL;
+    }
+
+    /* The client sent (or claims to have sent) an empty message. */
+    if (msg_len == min_len)
+    {
+        WARN_MALFORMED_MSG (sd, "empty message");
+        return NULL;
+    }
+
+    /* The protocol specifies that the target must be 24 bytes long. */
+    if (type == 1 && msg_len < min_len)
+    {
+        /* Disallow malformed messages. */
+        clif_setwaitclose (fd);
+        WARN_MALFORMED_MSG (sd, "illegal target name");
+        return NULL;
+    }
+
+    p = (char *) (type != 1) ? RFIFOP (fd, 4) : RFIFOP (fd, 28);
+    buf_len = (type == 1) ? msg_len - min_len: msg_len;
+
+    /*
+     * The client attempted to exceed the maximum message length.
+     *
+     * The conf suggests up to chat_maxline characters, after which the message
+     * is truncated. But the previous behavior was to drop the message, so
+     * we'll do that, too.
+     */
+    if (buf_len >= battle_config.chat_maxline)
+    {
+        WARN_MALFORMED_MSG (sd, "exceeded maximum message length");
+        return NULL;
+    }
+
+    /* We're leaving an extra eight bytes for public/global chat, 1 for NUL. */
+    buf_len += (type == 2) ? 8 + 1 : 1;
+
+    buf = (char *) malloc (buf_len);
+    memcpy ((type != 2) ? buf : buf + 8, p,
+            (type != 2) ? buf_len - 1 : buf_len - 8 - 1);
+    buf[buf_len - 1] = '\0';
+    p = (type != 2) ? buf : buf + 8;
+
+    if (type != 2)
+    {
+        *message = buf;
+        /* Don't count the NUL. */
+        *message_len = buf_len - 1;
+    }
+    else
+    {
+        char *pos = NULL;
+        if (!(pos = strstr(p, " : "))
+                || strncmp (p, sd->status.name, name_len)
+                || pos - p != name_len)
+        {
+            free (buf);
+            /* Disallow malformed/spoofed messages. */
+            clif_setwaitclose (fd);
+            WARN_MALFORMED_MSG (sd, "spoofed name/invalid format");
+            return NULL;
+        }
+        /* Step beyond the separator. */
+        *message = pos + 3;
+        /* Don't count the sender's name, the extra eight bytes, or the NUL. */
+        *message_len = buf_len - min_len - 8 - 1;
+    }
+
+    return buf;
+}
+
+/*==========================================
+ * クライアントからのパケット解析
+ * socket.cのdo_parsepacketから呼び出される
+ *------------------------------------------
+ */
+static void clif_parse (int fd)
+{
+    int  packet_len = 0, cmd = 0;
+    struct map_session_data *sd = (struct map_session_data *)session[fd]->session_data;
+
+    if (!sd || (sd && !sd->state.auth))
+    {
+        if (RFIFOREST (fd) < 2)
+        {                       // too small a packet disconnect
+            session[fd]->eof = 1;
+        }
+        if (RFIFOW (fd, 0) != 0x72)
+        {                       // first packet not auth, disconnect
+            session[fd]->eof = 1;
+        }
+    }
+
+    // 接続が切れてるので後始末
+    if (!chrif_isconnect () || session[fd]->eof)
+    {                           // char鯖に繋がってない間は接続禁止 (!chrif_isconnect())
+        if (sd && sd->state.auth)
+        {
+            pc_logout (sd);
+            clif_quitsave (fd, sd);
+            if (sd->status.name != NULL)
+                printf ("Player [%s] has logged off your server.\n", sd->status.name);  // Player logout display [Valaris]
+            else
+                printf ("Player with account [%d] has logged off your server.\n", sd->bl.id);   // Player logout display [Yor]
+        }
+        else if (sd)
+        {                       // not authentified! (refused by char-server or disconnect before to be authentified)
+            printf ("Player with account [%d] has logged off your server (not auth account).\n", sd->bl.id);    // Player logout display [Yor]
+            map_deliddb (&sd->bl);  // account_id has been included in the DB before auth answer
+        }
+        if (fd)
+            close (fd);
+        if (fd)
+            delete_session (fd);
+        return;
+    }
+
+    if (RFIFOREST (fd) < 2)
+        return;               // Too small (no packet number)
+
+    cmd = RFIFOW (fd, 0);
+
+    // 管理用パケット処理
+    if (cmd >= 30000)
+    {
+        switch (cmd)
+        {
+            case 0x7530:       // Athena情報所得
+                WFIFOW (fd, 0) = 0x7531;
+                WFIFOB (fd, 2) = ATHENA_MAJOR_VERSION;
+                WFIFOB (fd, 3) = ATHENA_MINOR_VERSION;
+                WFIFOB (fd, 4) = ATHENA_REVISION;
+                WFIFOB (fd, 5) = ATHENA_RELEASE_FLAG;
+                WFIFOB (fd, 6) = ATHENA_OFFICIAL_FLAG;
+                WFIFOB (fd, 7) = ATHENA_SERVER_MAP;
+                WFIFOW (fd, 8) = ATHENA_MOD_VERSION;
+                WFIFOSET (fd, 10);
+                RFIFOSKIP (fd, 2);
+                break;
+            case 0x7532:       // 接続の切断
+                session[fd]->eof = 1;
+                break;
+        }
+        return;
+    }
+    else if (cmd >= 0x200)
+        return;
+
+    // パケット長を計算
+    packet_len = packet_len_table[cmd];
+    if (packet_len == -1)
+    {
+        if (RFIFOREST (fd) < 4)
+        {
+            return;           // Runt packet (variable length without a length sent)
+        }
+        packet_len = RFIFOW (fd, 2);
+        if (packet_len < 4 || packet_len > 32768)
+        {
+            session[fd]->eof = 1;
+            return;           // Runt packet (variable out of bounds)
+        }
+    }
+
+    if (RFIFOREST (fd) < packet_len)
+    {
+        return;               // Runt packet (sent legnth is too small)
+    }
+
+    if (sd && sd->state.auth == 1 && sd->state.waitingdisconnect == 1)
+    {                           // 切断待ちの場合パケットを処理しない
+
+    }
+    else if (clif_parse_func_table[cmd].func)
+    {
+        if (clif_check_packet_flood(fd, cmd))
+        {
+            // Flood triggered. Skip packet.
+            RFIFOSKIP(sd->fd, packet_len);
+            return;
+        }
+
+        clif_parse_func_table[cmd].func (fd, sd);
+    }
+    else
+    {
+        // 不明なパケット
+        if (battle_config.error_log)
+        {
+            if (fd)
+                printf ("\nclif_parse: session #%d, packet 0x%x, lenght %d\n",
+                        fd, cmd, packet_len);
+#ifdef DUMP_UNKNOWN_PACKET
+            {
+                int  i;
+                FILE *fp;
+                char packet_txt[256] = "save/packet.txt";
+                time_t now;
+                printf
+                    ("---- 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)
+                        printf ("\n%04X ", i);
+                    printf ("%02X ", RFIFOB (fd, i));
+                }
+                if (sd && sd->state.auth)
+                {
+                    if (sd->status.name != NULL)
+                        printf
+                            ("\nAccount ID %d, character ID %d, player name %s.\n",
+                             sd->status.account_id, sd->status.char_id,
+                             sd->status.name);
+                    else
+                        printf ("\nAccount ID %d.\n", sd->bl.id);
+                }
+                else if (sd)    // not authentified! (refused by char-server or disconnect before to be authentified)
+                    printf ("\nAccount ID %d.\n", sd->bl.id);
+
+                if ((fp = fopen_ (packet_txt, "a")) == NULL)
+                {
+                    printf ("clif.c: cant write [%s] !!! data is lost !!!\n",
+                            packet_txt);
+                    return;
+                }
+                else
+                {
+                    time (&now);
+                    if (sd && sd->state.auth)
+                    {
+                        if (sd->status.name != NULL)
+                            fprintf (fp,
+                                     "%sPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
+                                     asctime (gmtime (&now)),
+                                     sd->status.account_id,
+                                     sd->status.char_id, sd->status.name);
+                        else
+                            fprintf (fp,
+                                     "%sPlayer with account ID %d sent wrong packet:\n",
+                                     asctime (gmtime (&now)), sd->bl.id);
+                    }
+                    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 (gmtime (&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));
+                    }
+                    fprintf (fp, "\n\n");
+                    fclose_ (fp);
+                }
+            }
+#endif
+        }
+    }
+    RFIFOSKIP (fd, packet_len);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int do_init_clif (void)
+{
+    int  i;
+
+    set_defaultparse (clif_parse);
+    for (i = 0; i < 10; i++)
+    {
+        if (make_listen_port (map_port))
+            break;
+#ifdef LCCWIN32
+        Sleep (20000);
+#else
+        sleep (20);
+#endif
+    }
+    if (i == 10)
+    {
+        printf ("cant bind game port\n");
+        exit (1);
+    }
+
+    return 0;
+}
diff --git a/src/map/clif.h b/src/map/clif.h
deleted file mode 100644
index a1914e3..0000000
--- a/src/map/clif.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// $Id: clif.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _CLIF_H_
-#define _CLIF_H_
-
-#include <sys/types.h>
-
-#ifdef LCCWIN32
-#include <winsock.h>
-typedef unsigned int in_addr_t;
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-
-#include "map.h"
-
-void clif_setip (char *);
-void clif_setport (int);
-
-in_addr_t clif_getip (void);
-int  clif_getport (void);
-int  clif_countusers (void);
-void clif_setwaitclose (int);
-
-int  clif_authok (struct map_session_data *);
-int  clif_authfail_fd (int, int);
-int  clif_charselectok (int);
-int  clif_dropflooritem (struct flooritem_data *);
-int  clif_clearflooritem (struct flooritem_data *, int);
-int  clif_clearchar (struct block_list *, int); // area or fd
-int  clif_clearchar_delay (unsigned int, struct block_list *, int);
-#define clif_clearchar_area(bl,type) clif_clearchar(bl,type)
-int  clif_clearchar_id (int, int, int);
-int  clif_spawnpc (struct map_session_data *);  //area
-int  clif_spawnnpc (struct npc_data *); // area
-int  clif_spawn_fake_npc_for_player (struct map_session_data *sd,
-                                     int fake_npc_id);
-int  clif_spawnmob (struct mob_data *); // area
-int  clif_walkok (struct map_session_data *);   // self
-int  clif_movechar (struct map_session_data *); // area
-int  clif_movemob (struct mob_data *);  //area
-int  clif_changemap (struct map_session_data *, char *, int, int);  //self
-int  clif_changemapserver (struct map_session_data *, char *, int, int, int, int);  //self
-int  clif_fixpos (struct block_list *); // area
-int  clif_fixmobpos (struct mob_data *md);
-int  clif_fixpcpos (struct map_session_data *sd);
-int  clif_npcbuysell (struct map_session_data *, int);  //self
-int  clif_buylist (struct map_session_data *, struct npc_data *);   //self
-int  clif_selllist (struct map_session_data *); //self
-int  clif_scriptmes (struct map_session_data *, int, char *);   //self
-int  clif_scriptnext (struct map_session_data *, int);  //self
-int  clif_scriptclose (struct map_session_data *, int); //self
-int  clif_scriptmenu (struct map_session_data *, int, char *);  //self
-int  clif_scriptinput (struct map_session_data *, int); //self
-int  clif_scriptinputstr (struct map_session_data *sd, int npcid);  // self
-int  clif_cutin (struct map_session_data *, char *, int);   //self
-int  clif_viewpoint (struct map_session_data *, int, int, int, int, int, int);  //self
-int  clif_additem (struct map_session_data *, int, int, int);   //self
-int  clif_delitem (struct map_session_data *, int, int);    //self
-int  clif_updatestatus (struct map_session_data *, int);    //self
-int  clif_changestatus (struct block_list *, int, int); //area
-int  clif_damage (struct block_list *, struct block_list *, unsigned int, int, int, int, int, int, int);    // area
-#define clif_takeitem(src,dst) clif_damage(src,dst,0,0,0,0,0,1,0)
-int  clif_changelook (struct block_list *, int, int);   // area
-int  clif_changelook_towards (struct block_list *, int, int, struct map_session_data *dst); // area or target
-void clif_changelook_accessories (struct block_list *bl, struct map_session_data *dst); // area or target; list gloves, boots etc.
-int  clif_arrowequip (struct map_session_data *sd, int val);    //self
-int  clif_arrow_fail (struct map_session_data *sd, int type);   //self
-int  clif_statusupack (struct map_session_data *, int, int, int);   // self
-int  clif_equipitemack (struct map_session_data *, int, int, int);  // self
-int  clif_unequipitemack (struct map_session_data *, int, int, int);    // self
-int  clif_misceffect (struct block_list *, int);    // area
-int  clif_changeoption (struct block_list *);   // area
-int  clif_useitemack (struct map_session_data *, int, int, int);    // self
-
-int  clif_createchat (struct map_session_data *, int);  // self
-int  clif_dispchat (struct chat_data *, int);   // area or fd
-int  clif_joinchatfail (struct map_session_data *, int);    // self
-int  clif_joinchatok (struct map_session_data *, struct chat_data *);   // self
-int  clif_addchat (struct chat_data *, struct map_session_data *);  // chat
-int  clif_changechatowner (struct chat_data *, struct map_session_data *);  // chat
-int  clif_clearchat (struct chat_data *, int);  // area or fd
-int  clif_leavechat (struct chat_data *, struct map_session_data *);    // chat
-int  clif_changechatstatus (struct chat_data *);    // chat
-
-void clif_emotion (struct block_list *bl, int type);
-void clif_talkiebox (struct block_list *bl, char *talkie);
-void clif_wedding_effect (struct block_list *bl);
-void clif_sitting (int fd, struct map_session_data *sd);
-//void clif_callpartner(struct map_session_data *sd);
-//void clif_sitting(struct map_session_data *sd);
-void clif_soundeffect (struct map_session_data *sd, struct block_list *bl,
-                       char *name, int type);
-
-// trade
-int  clif_traderequest (struct map_session_data *sd, char *name);
-int  clif_tradestart (struct map_session_data *sd, int type);
-int  clif_tradeadditem (struct map_session_data *sd,
-                        struct map_session_data *tsd, int index, int amount);
-int  clif_tradeitemok (struct map_session_data *sd, int index, int amount,
-                       int fail);
-int  clif_tradedeal_lock (struct map_session_data *sd, int fail);
-int  clif_tradecancelled (struct map_session_data *sd);
-int  clif_tradecompleted (struct map_session_data *sd, int fail);
-
-// storage
-#include "storage.h"
-int  clif_storageitemlist (struct map_session_data *sd, struct storage *stor);
-int  clif_storageequiplist (struct map_session_data *sd,
-                            struct storage *stor);
-int  clif_updatestorageamount (struct map_session_data *sd,
-                               struct storage *stor);
-int  clif_storageitemadded (struct map_session_data *sd, struct storage *stor,
-                            int index, int amount);
-int  clif_storageitemremoved (struct map_session_data *sd, int index,
-                              int amount);
-int  clif_storageclose (struct map_session_data *sd);
-int  clif_guildstorageitemlist (struct map_session_data *sd,
-                                struct guild_storage *stor);
-int  clif_guildstorageequiplist (struct map_session_data *sd,
-                                 struct guild_storage *stor);
-int  clif_updateguildstorageamount (struct map_session_data *sd,
-                                    struct guild_storage *stor);
-int  clif_guildstorageitemadded (struct map_session_data *sd,
-                                 struct guild_storage *stor, int index,
-                                 int amount);
-
-int  clif_pcinsight (struct block_list *, va_list); // map_forallinmovearea callback
-int  clif_pcoutsight (struct block_list *, va_list);    // map_forallinmovearea callback
-int  clif_mobinsight (struct block_list *, va_list);    // map_forallinmovearea callback
-int  clif_moboutsight (struct block_list *, va_list);   // map_forallinmovearea callback
-
-int  clif_npc_class_change (struct block_list *bl, int npc_class, int type);
-int  clif_mob_class_change (struct mob_data *md, int mob_class);
-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_skillcasting (struct block_list *bl,
-                        int src_id, int dst_id, int dst_x, int dst_y,
-                        int skill_num, int casttime);
-int  clif_skillcastcancel (struct block_list *bl);
-int  clif_skill_fail (struct map_session_data *sd, int skill_id, int type,
-                      int btype);
-int  clif_skill_damage (struct block_list *src, struct block_list *dst,
-                        unsigned int tick, int sdelay, int ddelay, int damage,
-                        int div, int skill_id, int skill_lv, int type);
-int  clif_skill_damage2 (struct block_list *src, struct block_list *dst,
-                         unsigned int tick, int sdelay, int ddelay,
-                         int damage, int div, int skill_id, int skill_lv,
-                         int type);
-int  clif_skill_nodamage (struct block_list *src, struct block_list *dst,
-                          int skill_id, int heal, int fail);
-int  clif_skill_poseffect (struct block_list *src, int skill_id, int val,
-                           int x, int y, int tick);
-int  clif_skill_estimation (struct map_session_data *sd,
-                            struct block_list *dst);
-int  clif_skill_warppoint (struct map_session_data *sd, int skill_num,
-                           const char *map1, const char *map2,
-                           const char *map3, const char *map4);
-int  clif_skill_memo (struct map_session_data *sd, int flag);
-int  clif_skill_teleportmessage (struct map_session_data *sd, int flag);
-
-int  clif_produceeffect (struct map_session_data *sd, int flag, int nameid);
-
-int  clif_skill_setunit (struct skill_unit *unit);
-int  clif_skill_delunit (struct skill_unit *unit);
-
-int  clif_01ac (struct block_list *bl);
-
-int  clif_autospell (struct map_session_data *sd, int skilllv);
-int  clif_devotion (struct map_session_data *sd, int target);
-int  clif_spiritball (struct map_session_data *sd);
-int  clif_combo_delay (struct block_list *src, int wait);
-int  clif_bladestop (struct block_list *src, struct block_list *dst,
-                     int boolean);
-int  clif_changemapcell (int m, int x, int y, int cell_type, int type);
-
-int  clif_status_change (struct block_list *bl, int type, int flag);
-
-int  clif_wis_message (int fd, char *nick, char *mes, int mes_len);
-int  clif_wis_end (int fd, int flag);
-
-int  clif_solved_charname (struct map_session_data *sd, int char_id);
-
-int  clif_use_card (struct map_session_data *sd, int idx);
-int  clif_insert_card (struct map_session_data *sd, int idx_equip,
-                       int idx_card, int flag);
-
-int  clif_itemlist (struct map_session_data *sd);
-int  clif_equiplist (struct map_session_data *sd);
-
-int  clif_cart_additem (struct map_session_data *, int, int, int);
-int  clif_cart_delitem (struct map_session_data *, int, int);
-int  clif_cart_itemlist (struct map_session_data *sd);
-int  clif_cart_equiplist (struct map_session_data *sd);
-
-int  clif_item_identify_list (struct map_session_data *sd);
-int  clif_item_identified (struct map_session_data *sd, int idx, int flag);
-int  clif_item_repair_list (struct map_session_data *sd);
-
-int  clif_item_skill (struct map_session_data *sd, int skillid, int skilllv,
-                      const char *name);
-
-int  clif_mvp_effect (struct map_session_data *sd);
-int  clif_mvp_item (struct map_session_data *sd, int nameid);
-int  clif_mvp_exp (struct map_session_data *sd, int exp);
-
-int  clif_movetoattack (struct map_session_data *sd, struct block_list *bl);
-
-// party
-int  clif_party_created (struct map_session_data *sd, int flag);
-int  clif_party_info (struct party *p, int fd);
-int  clif_party_invite (struct map_session_data *sd,
-                        struct map_session_data *tsd);
-int  clif_party_inviteack (struct map_session_data *sd, char *nick, int flag);
-int  clif_party_option (struct party *p, struct map_session_data *sd,
-                        int flag);
-int  clif_party_leaved (struct party *p, struct map_session_data *sd,
-                        int account_id, char *name, int flag);
-int  clif_party_message (struct party *p, int account_id, char *mes, int len);
-int  clif_party_move (struct party *p, struct map_session_data *sd,
-                      int online);
-int  clif_party_xy (struct party *p, struct map_session_data *sd);
-int  clif_party_hp (struct party *p, struct map_session_data *sd);
-
-// guild
-int  clif_guild_created (struct map_session_data *sd, int flag);
-int  clif_guild_belonginfo (struct map_session_data *sd, struct guild *g);
-int  clif_guild_basicinfo (struct map_session_data *sd);
-int  clif_guild_allianceinfo (struct map_session_data *sd);
-int  clif_guild_memberlist (struct map_session_data *sd);
-int  clif_guild_skillinfo (struct map_session_data *sd);
-int  clif_guild_memberlogin_notice (struct guild *g, int idx, int flag);
-int  clif_guild_invite (struct map_session_data *sd, struct guild *g);
-int  clif_guild_inviteack (struct map_session_data *sd, int flag);
-int  clif_guild_leave (struct map_session_data *sd, const char *name,
-                       const char *mes);
-int  clif_guild_explusion (struct map_session_data *sd, const char *name,
-                           const char *mes, int account_id);
-int  clif_guild_positionchanged (struct guild *g, int idx);
-int  clif_guild_memberpositionchanged (struct guild *g, int idx);
-int  clif_guild_emblem (struct map_session_data *sd, struct guild *g);
-int  clif_guild_notice (struct map_session_data *sd, struct guild *g);
-int  clif_guild_message (struct guild *g, int account_id, const char *mes,
-                         int len);
-int  clif_guild_skillup (struct map_session_data *sd, int skill_num, int lv);
-int  clif_guild_reqalliance (struct map_session_data *sd, int account_id,
-                             const char *name);
-int  clif_guild_allianceack (struct map_session_data *sd, int flag);
-int  clif_guild_delalliance (struct map_session_data *sd, int guild_id,
-                             int flag);
-int  clif_guild_oppositionack (struct map_session_data *sd, int flag);
-int  clif_guild_broken (struct map_session_data *sd, int flag);
-
-// atcommand
-int  clif_displaymessage (const int fd, char *mes);
-int  clif_disp_onlyself (struct map_session_data *sd, char *mes, int len);
-int  clif_GMmessage (struct block_list *bl, char *mes, int len, int flag);
-int  clif_heal (int fd, int type, int val);
-int  clif_resurrection (struct block_list *bl, int type);
-int  clif_set0199 (int fd, int type);
-int  clif_pvpset (struct map_session_data *sd, int pvprank, int pvpnum,
-                  int type);
-int  clif_send0199 (int map, int type);
-int  clif_refine (int fd, struct map_session_data *sd, int fail, int index,
-                  int val);
-
-int  clif_specialeffect (struct block_list *bl, int type, int flag);    // special effects [Valaris]
-int  clif_message (struct block_list *bl, char *msg);   // messages (from mobs/npcs) [Valaris]
-
-int  clif_GM_kickack (struct map_session_data *sd, int id);
-int  clif_GM_kick (struct map_session_data *sd, struct map_session_data *tsd,
-                   int type);
-
-int  clif_foreachclient (int (*)(struct map_session_data *, va_list), ...);
-
-int  do_final_clif (void);
-int  do_init_clif (void);
-
-#endif
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
new file mode 100644
index 0000000..f484a18
--- /dev/null
+++ b/src/map/clif.hpp
@@ -0,0 +1,285 @@
+// $Id: clif.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef CLIF_HPP
+#define CLIF_HPP
+
+#include <sys/types.h>
+
+#ifdef LCCWIN32
+#include <winsock.h>
+typedef unsigned int in_addr_t;
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "map.hpp"
+
+void clif_setip (char *);
+void clif_setport (int);
+
+in_addr_t clif_getip (void);
+int  clif_getport (void);
+int  clif_countusers (void);
+void clif_setwaitclose (int);
+
+int  clif_authok (struct map_session_data *);
+int  clif_authfail_fd (int, int);
+int  clif_charselectok (int);
+int  clif_dropflooritem (struct flooritem_data *);
+int  clif_clearflooritem (struct flooritem_data *, int);
+int  clif_clearchar (struct block_list *, int); // area or fd
+int  clif_clearchar_delay (unsigned int, struct block_list *, int);
+#define clif_clearchar_area(bl,type) clif_clearchar(bl,type)
+int  clif_clearchar_id (int, int, int);
+int  clif_spawnpc (struct map_session_data *);  //area
+int  clif_spawnnpc (struct npc_data *); // area
+int  clif_spawn_fake_npc_for_player (struct map_session_data *sd,
+                                     int fake_npc_id);
+int  clif_spawnmob (struct mob_data *); // area
+int  clif_walkok (struct map_session_data *);   // self
+int  clif_movechar (struct map_session_data *); // area
+int  clif_movemob (struct mob_data *);  //area
+int  clif_changemap (struct map_session_data *, char *, int, int);  //self
+int  clif_changemapserver (struct map_session_data *, char *, int, int, int, int);  //self
+int  clif_fixpos (struct block_list *); // area
+int  clif_fixmobpos (struct mob_data *md);
+int  clif_fixpcpos (struct map_session_data *sd);
+int  clif_npcbuysell (struct map_session_data *, int);  //self
+int  clif_buylist (struct map_session_data *, struct npc_data *);   //self
+int  clif_selllist (struct map_session_data *); //self
+int  clif_scriptmes (struct map_session_data *, int, char *);   //self
+int  clif_scriptnext (struct map_session_data *, int);  //self
+int  clif_scriptclose (struct map_session_data *, int); //self
+int  clif_scriptmenu (struct map_session_data *, int, char *);  //self
+int  clif_scriptinput (struct map_session_data *, int); //self
+int  clif_scriptinputstr (struct map_session_data *sd, int npcid);  // self
+int  clif_cutin (struct map_session_data *, char *, int);   //self
+int  clif_viewpoint (struct map_session_data *, int, int, int, int, int, int);  //self
+int  clif_additem (struct map_session_data *, int, int, int);   //self
+int  clif_delitem (struct map_session_data *, int, int);    //self
+int  clif_updatestatus (struct map_session_data *, int);    //self
+int  clif_changestatus (struct block_list *, int, int); //area
+int  clif_damage (struct block_list *, struct block_list *, unsigned int, int, int, int, int, int, int);    // area
+#define clif_takeitem(src,dst) clif_damage(src,dst,0,0,0,0,0,1,0)
+int  clif_changelook (struct block_list *, int, int);   // area
+int  clif_changelook_towards (struct block_list *, int, int, struct map_session_data *dst); // area or target
+void clif_changelook_accessories (struct block_list *bl, struct map_session_data *dst); // area or target; list gloves, boots etc.
+int  clif_arrowequip (struct map_session_data *sd, int val);    //self
+int  clif_arrow_fail (struct map_session_data *sd, int type);   //self
+int  clif_statusupack (struct map_session_data *, int, int, int);   // self
+int  clif_equipitemack (struct map_session_data *, int, int, int);  // self
+int  clif_unequipitemack (struct map_session_data *, int, int, int);    // self
+int  clif_misceffect (struct block_list *, int);    // area
+int  clif_changeoption (struct block_list *);   // area
+int  clif_useitemack (struct map_session_data *, int, int, int);    // self
+
+int  clif_createchat (struct map_session_data *, int);  // self
+int  clif_dispchat (struct chat_data *, int);   // area or fd
+int  clif_joinchatfail (struct map_session_data *, int);    // self
+int  clif_joinchatok (struct map_session_data *, struct chat_data *);   // self
+int  clif_addchat (struct chat_data *, struct map_session_data *);  // chat
+int  clif_changechatowner (struct chat_data *, struct map_session_data *);  // chat
+int  clif_clearchat (struct chat_data *, int);  // area or fd
+int  clif_leavechat (struct chat_data *, struct map_session_data *);    // chat
+int  clif_changechatstatus (struct chat_data *);    // chat
+
+void clif_emotion (struct block_list *bl, int type);
+void clif_talkiebox (struct block_list *bl, char *talkie);
+void clif_wedding_effect (struct block_list *bl);
+void clif_sitting (int fd, struct map_session_data *sd);
+//void clif_callpartner(struct map_session_data *sd);
+//void clif_sitting(struct map_session_data *sd);
+void clif_soundeffect (struct map_session_data *sd, struct block_list *bl,
+                       char *name, int type);
+
+// trade
+int  clif_traderequest (struct map_session_data *sd, char *name);
+int  clif_tradestart (struct map_session_data *sd, int type);
+int  clif_tradeadditem (struct map_session_data *sd,
+                        struct map_session_data *tsd, int index, int amount);
+int  clif_tradeitemok (struct map_session_data *sd, int index, int amount,
+                       int fail);
+int  clif_tradedeal_lock (struct map_session_data *sd, int fail);
+int  clif_tradecancelled (struct map_session_data *sd);
+int  clif_tradecompleted (struct map_session_data *sd, int fail);
+
+// storage
+#include "storage.hpp"
+int  clif_storageitemlist (struct map_session_data *sd, struct storage *stor);
+int  clif_storageequiplist (struct map_session_data *sd,
+                            struct storage *stor);
+int  clif_updatestorageamount (struct map_session_data *sd,
+                               struct storage *stor);
+int  clif_storageitemadded (struct map_session_data *sd, struct storage *stor,
+                            int index, int amount);
+int  clif_storageitemremoved (struct map_session_data *sd, int index,
+                              int amount);
+int  clif_storageclose (struct map_session_data *sd);
+int  clif_guildstorageitemlist (struct map_session_data *sd,
+                                struct guild_storage *stor);
+int  clif_guildstorageequiplist (struct map_session_data *sd,
+                                 struct guild_storage *stor);
+int  clif_updateguildstorageamount (struct map_session_data *sd,
+                                    struct guild_storage *stor);
+int  clif_guildstorageitemadded (struct map_session_data *sd,
+                                 struct guild_storage *stor, int index,
+                                 int amount);
+
+int  clif_pcinsight (struct block_list *, va_list); // map_forallinmovearea callback
+int  clif_pcoutsight (struct block_list *, va_list);    // map_forallinmovearea callback
+int  clif_mobinsight (struct block_list *, va_list);    // map_forallinmovearea callback
+int  clif_moboutsight (struct block_list *, va_list);   // map_forallinmovearea callback
+
+int  clif_npc_class_change (struct block_list *bl, int npc_class, int type);
+int  clif_mob_class_change (struct mob_data *md, int mob_class);
+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_skillcasting (struct block_list *bl,
+                        int src_id, int dst_id, int dst_x, int dst_y,
+                        int skill_num, int casttime);
+int  clif_skillcastcancel (struct block_list *bl);
+int  clif_skill_fail (struct map_session_data *sd, int skill_id, int type,
+                      int btype);
+int  clif_skill_damage (struct block_list *src, struct block_list *dst,
+                        unsigned int tick, int sdelay, int ddelay, int damage,
+                        int div, int skill_id, int skill_lv, int type);
+int  clif_skill_damage2 (struct block_list *src, struct block_list *dst,
+                         unsigned int tick, int sdelay, int ddelay,
+                         int damage, int div, int skill_id, int skill_lv,
+                         int type);
+int  clif_skill_nodamage (struct block_list *src, struct block_list *dst,
+                          int skill_id, int heal, int fail);
+int  clif_skill_poseffect (struct block_list *src, int skill_id, int val,
+                           int x, int y, int tick);
+int  clif_skill_estimation (struct map_session_data *sd,
+                            struct block_list *dst);
+int  clif_skill_warppoint (struct map_session_data *sd, int skill_num,
+                           const char *map1, const char *map2,
+                           const char *map3, const char *map4);
+int  clif_skill_memo (struct map_session_data *sd, int flag);
+int  clif_skill_teleportmessage (struct map_session_data *sd, int flag);
+
+int  clif_produceeffect (struct map_session_data *sd, int flag, int nameid);
+
+int  clif_skill_setunit (struct skill_unit *unit);
+int  clif_skill_delunit (struct skill_unit *unit);
+
+int  clif_01ac (struct block_list *bl);
+
+int  clif_autospell (struct map_session_data *sd, int skilllv);
+int  clif_devotion (struct map_session_data *sd, int target);
+int  clif_spiritball (struct map_session_data *sd);
+int  clif_combo_delay (struct block_list *src, int wait);
+int  clif_bladestop (struct block_list *src, struct block_list *dst,
+                     int boolean);
+int  clif_changemapcell (int m, int x, int y, int cell_type, int type);
+
+int  clif_status_change (struct block_list *bl, int type, int flag);
+
+int  clif_wis_message (int fd, char *nick, char *mes, int mes_len);
+int  clif_wis_end (int fd, int flag);
+
+int  clif_solved_charname (struct map_session_data *sd, int char_id);
+
+int  clif_use_card (struct map_session_data *sd, int idx);
+int  clif_insert_card (struct map_session_data *sd, int idx_equip,
+                       int idx_card, int flag);
+
+int  clif_itemlist (struct map_session_data *sd);
+int  clif_equiplist (struct map_session_data *sd);
+
+int  clif_cart_additem (struct map_session_data *, int, int, int);
+int  clif_cart_delitem (struct map_session_data *, int, int);
+int  clif_cart_itemlist (struct map_session_data *sd);
+int  clif_cart_equiplist (struct map_session_data *sd);
+
+int  clif_item_identify_list (struct map_session_data *sd);
+int  clif_item_identified (struct map_session_data *sd, int idx, int flag);
+int  clif_item_repair_list (struct map_session_data *sd);
+
+int  clif_item_skill (struct map_session_data *sd, int skillid, int skilllv,
+                      const char *name);
+
+int  clif_mvp_effect (struct map_session_data *sd);
+int  clif_mvp_item (struct map_session_data *sd, int nameid);
+int  clif_mvp_exp (struct map_session_data *sd, int exp);
+
+int  clif_movetoattack (struct map_session_data *sd, struct block_list *bl);
+
+// party
+int  clif_party_created (struct map_session_data *sd, int flag);
+int  clif_party_info (struct party *p, int fd);
+int  clif_party_invite (struct map_session_data *sd,
+                        struct map_session_data *tsd);
+int  clif_party_inviteack (struct map_session_data *sd, char *nick, int flag);
+int  clif_party_option (struct party *p, struct map_session_data *sd,
+                        int flag);
+int  clif_party_leaved (struct party *p, struct map_session_data *sd,
+                        int account_id, char *name, int flag);
+int  clif_party_message (struct party *p, int account_id, char *mes, int len);
+int  clif_party_move (struct party *p, struct map_session_data *sd,
+                      int online);
+int  clif_party_xy (struct party *p, struct map_session_data *sd);
+int  clif_party_hp (struct party *p, struct map_session_data *sd);
+
+// guild
+int  clif_guild_created (struct map_session_data *sd, int flag);
+int  clif_guild_belonginfo (struct map_session_data *sd, struct guild *g);
+int  clif_guild_basicinfo (struct map_session_data *sd);
+int  clif_guild_allianceinfo (struct map_session_data *sd);
+int  clif_guild_memberlist (struct map_session_data *sd);
+int  clif_guild_skillinfo (struct map_session_data *sd);
+int  clif_guild_memberlogin_notice (struct guild *g, int idx, int flag);
+int  clif_guild_invite (struct map_session_data *sd, struct guild *g);
+int  clif_guild_inviteack (struct map_session_data *sd, int flag);
+int  clif_guild_leave (struct map_session_data *sd, const char *name,
+                       const char *mes);
+int  clif_guild_explusion (struct map_session_data *sd, const char *name,
+                           const char *mes, int account_id);
+int  clif_guild_positionchanged (struct guild *g, int idx);
+int  clif_guild_memberpositionchanged (struct guild *g, int idx);
+int  clif_guild_emblem (struct map_session_data *sd, struct guild *g);
+int  clif_guild_notice (struct map_session_data *sd, struct guild *g);
+int  clif_guild_message (struct guild *g, int account_id, const char *mes,
+                         int len);
+int  clif_guild_skillup (struct map_session_data *sd, int skill_num, int lv);
+int  clif_guild_reqalliance (struct map_session_data *sd, int account_id,
+                             const char *name);
+int  clif_guild_allianceack (struct map_session_data *sd, int flag);
+int  clif_guild_delalliance (struct map_session_data *sd, int guild_id,
+                             int flag);
+int  clif_guild_oppositionack (struct map_session_data *sd, int flag);
+int  clif_guild_broken (struct map_session_data *sd, int flag);
+
+// atcommand
+int  clif_displaymessage (const int fd, char *mes);
+int  clif_disp_onlyself (struct map_session_data *sd, char *mes, int len);
+int  clif_GMmessage (struct block_list *bl, char *mes, int len, int flag);
+int  clif_heal (int fd, int type, int val);
+int  clif_resurrection (struct block_list *bl, int type);
+int  clif_set0199 (int fd, int type);
+int  clif_pvpset (struct map_session_data *sd, int pvprank, int pvpnum,
+                  int type);
+int  clif_send0199 (int map, int type);
+int  clif_refine (int fd, struct map_session_data *sd, int fail, int index,
+                  int val);
+
+int  clif_specialeffect (struct block_list *bl, int type, int flag);    // special effects [Valaris]
+int  clif_message (struct block_list *bl, char *msg);   // messages (from mobs/npcs) [Valaris]
+
+int  clif_GM_kickack (struct map_session_data *sd, int id);
+int  clif_GM_kick (struct map_session_data *sd, struct map_session_data *tsd,
+                   int type);
+
+int  clif_foreachclient (int (*)(struct map_session_data *, va_list), ...);
+
+int  do_final_clif (void);
+int  do_init_clif (void);
+
+#endif
diff --git a/src/map/guild.c b/src/map/guild.c
deleted file mode 100644
index e4e0ca8..0000000
--- a/src/map/guild.c
+++ /dev/null
@@ -1,1915 +0,0 @@
-// $Id: guild.c,v 1.5 2004/09/25 05:32:18 MouseJstr Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "guild.h"
-#include "storage.h"
-#include "../common/db.h"
-#include "../common/timer.h"
-#include "../common/socket.h"
-#include "../common/nullpo.h"
-#include "battle.h"
-#include "npc.h"
-#include "pc.h"
-#include "map.h"
-#include "mob.h"
-#include "intif.h"
-#include "clif.h"
-#include "tmw.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-static struct dbt *guild_db;
-static struct dbt *castle_db;
-static struct dbt *guild_expcache_db;
-static struct dbt *guild_infoevent_db;
-static struct dbt *guild_castleinfoevent_db;
-
-struct eventlist
-{
-    char name[50];
-    struct eventlist *next;
-};
-
-// ギルドのEXPキャッシュのフラッシュに関連する定数
-#define GUILD_PAYEXP_INVERVAL 10000 // 間隔(キャッシュの最大生存時間、ミリ秒)
-#define GUILD_PAYEXP_LIST 8192  // キャッシュの最大数
-
-// ギルドのEXPキャッシュ
-struct guild_expcache
-{
-    int  guild_id, account_id, char_id, exp;
-};
-
-// ギルドスキルdbのアクセサ(今は直打ちで代用)
-int guild_skill_get_inf (int id)
-{
-    return 0;
-}
-
-int guild_skill_get_sp (int id, int lv)
-{
-    return 0;
-}
-
-int guild_skill_get_range (int id)
-{
-    return 0;
-}
-
-int guild_skill_get_max (int id)
-{
-    return (id == 10004) ? 10 : 1;
-}
-
-// ギルドスキルがあるか確認
-int guild_checkskill (struct guild *g, int id)
-{
-    return g->skill[id - 10000].lv;
-}
-
-void guild_payexp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
-void guild_gvg_eliminate_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
-
-static int guild_read_castledb (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  j, ln = 0;
-    char *str[32], *p;
-    struct guild_castle *gc;
-
-    if ((fp = fopen_ ("db/castle_db.txt", "r")) == NULL)
-    {
-        printf ("can't read db/castle_db.txt\n");
-        return -1;
-    }
-
-    while (fgets (line, 1020, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        memset (str, 0, sizeof (str));
-        CREATE (gc, struct guild_castle, 1);
-        for (j = 0, p = line; j < 6 && p; j++)
-        {
-            str[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-
-        gc->guild_id = 0;       // <Agit> Clear Data for Initialize
-        gc->economy = 0;
-        gc->defense = 0;
-        gc->triggerE = 0;
-        gc->triggerD = 0;
-        gc->nextTime = 0;
-        gc->payTime = 0;
-        gc->createTime = 0;
-        gc->visibleC = 0;
-        gc->visibleG0 = 0;
-        gc->visibleG1 = 0;
-        gc->visibleG2 = 0;
-        gc->visibleG3 = 0;
-        gc->visibleG4 = 0;
-        gc->visibleG5 = 0;
-        gc->visibleG6 = 0;
-        gc->visibleG7 = 0;
-        gc->Ghp0 = 0;
-        gc->Ghp1 = 0;
-        gc->Ghp2 = 0;
-        gc->Ghp3 = 0;
-        gc->Ghp4 = 0;
-        gc->Ghp5 = 0;
-        gc->Ghp6 = 0;
-        gc->Ghp7 = 0;           // guardian HP [Valaris]
-
-        gc->castle_id = atoi (str[0]);
-        memcpy (gc->map_name, str[1], 24);
-        memcpy (gc->castle_name, str[2], 24);
-        memcpy (gc->castle_event, str[3], 24);
-
-        numdb_insert (castle_db, gc->castle_id, gc);
-
-        //intif_guild_castle_info(gc->castle_id);
-
-        ln++;
-    }
-    fclose_ (fp);
-    printf ("read db/castle_db.txt done (count=%d)\n", ln);
-    return 0;
-}
-
-// 初期化
-void do_init_guild (void)
-{
-    guild_db = numdb_init ();
-    castle_db = numdb_init ();
-    guild_expcache_db = numdb_init ();
-    guild_infoevent_db = numdb_init ();
-    guild_castleinfoevent_db = numdb_init ();
-
-    guild_read_castledb ();
-
-    add_timer_interval (gettick () + GUILD_PAYEXP_INVERVAL,
-                        guild_payexp_timer, 0, 0, GUILD_PAYEXP_INVERVAL);
-}
-
-// 検索
-struct guild *guild_search (int guild_id)
-{
-    return (struct guild *)numdb_search (guild_db, guild_id);
-}
-
-void guild_searchname_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild *g = (struct guild *) data, **dst;
-    char *str;
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct guild **);
-    if (strcasecmp (g->name, str) == 0)
-        *dst = g;
-}
-
-// ギルド名検索
-struct guild *guild_searchname (char *str)
-{
-    struct guild *g = NULL;
-    numdb_foreach (guild_db, guild_searchname_sub, str, &g);
-    return g;
-}
-
-struct guild_castle *guild_castle_search (int gcid)
-{
-    return (struct guild_castle *)numdb_search (castle_db, gcid);
-}
-
-// mapnameに対応したアジトのgcを返す
-struct guild_castle *guild_mapname2gc (char *mapname)
-{
-    int  i;
-    struct guild_castle *gc = NULL;
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        gc = guild_castle_search (i);
-        if (!gc)
-            continue;
-        if (strcmp (gc->map_name, mapname) == 0)
-            return gc;
-    }
-    return NULL;
-}
-
-// ログイン中のギルドメンバーの1人のsdを返す
-struct map_session_data *guild_getavailablesd (struct guild *g)
-{
-    int  i;
-
-    nullpo_retr (NULL, g);
-
-    for (i = 0; i < g->max_member; i++)
-        if (g->member[i].sd != NULL)
-            return g->member[i].sd;
-    return NULL;
-}
-
-// ギルドメンバーのインデックスを返す
-int guild_getindex (struct guild *g, int account_id, int char_id)
-{
-    int  i;
-    if (g == NULL)
-        return -1;
-    for (i = 0; i < g->max_member; i++)
-        if (g->member[i].account_id == account_id)
-            return i;
-    return -1;
-}
-
-// ギルドメンバーの役職を返す
-int guild_getposition (struct map_session_data *sd, struct guild *g)
-{
-    int  i;
-
-    nullpo_retr (-1, sd);
-
-    if (g == NULL && (g = guild_search (sd->status.guild_id)) == NULL)
-        return -1;
-    for (i = 0; i < g->max_member; i++)
-        if (g->member[i].account_id == sd->status.account_id)
-            return g->member[i].position;
-    return -1;
-}
-
-// メンバー情報の作成
-void guild_makemember (struct guild_member *m, struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    memset (m, 0, sizeof (struct guild_member));
-    m->account_id = sd->status.account_id;
-    m->char_id = 0;
-    m->hair = sd->status.hair;
-    m->hair_color = sd->status.hair_color;
-    m->gender = sd->sex;
-    m->pc_class = sd->status.pc_class;
-    m->lv = sd->status.base_level;
-    m->exp = 0;
-    m->exp_payper = 0;
-    m->online = 1;
-    m->position = MAX_GUILDPOSITION - 1;
-    memcpy (m->name, sd->status.name, 24);
-    return;
-}
-
-// ギルド競合確認
-int guild_check_conflict (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    intif_guild_checkconflict (sd->status.guild_id,
-                               sd->status.account_id, 0 /*char_id*/);
-    return 0;
-}
-
-// ギルドのEXPキャッシュをinter鯖にフラッシュする
-void guild_payexp_timer_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    int  i, *dellist, *delp, dataid = key.i;
-    struct guild_expcache *c;
-    struct guild *g;
-
-    nullpo_retv (ap);
-    nullpo_retv (c = (struct guild_expcache *) data);
-    nullpo_retv (dellist = va_arg (ap, int *));
-    nullpo_retv (delp = va_arg (ap, int *));
-
-    if (*delp >= GUILD_PAYEXP_LIST
-        || (g = guild_search (c->guild_id)) == NULL)
-        return;
-    if ((i = guild_getindex (g, c->account_id, 0 /*c->char_id*/)) < 0)
-        return;
-
-    g->member[i].exp += c->exp;
-    intif_guild_change_memberinfo (g->guild_id, c->account_id, 0 /*char_id*/,
-                                   GMI_EXP, &g->member[i].exp,
-                                   sizeof (g->member[i].exp));
-    c->exp = 0;
-
-    dellist[(*delp)++] = dataid;
-    free (c);
-}
-
-void guild_payexp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  dellist[GUILD_PAYEXP_LIST], delp = 0, i;
-    numdb_foreach (guild_expcache_db, guild_payexp_timer_sub, dellist, &delp);
-    for (i = 0; i < delp; i++)
-        numdb_erase (guild_expcache_db, dellist[i]);
-//  if(battle_config.etc_log)
-//      printf("guild exp %d charactor's exp flushed !\n",delp);
-}
-
-//------------------------------------------------------------------------
-
-/* Process a guild creation request. */
-int guild_create (struct map_session_data *sd, char *name)
-{
-    char pname[24];
-
-    nullpo_retr (0, sd);
-
-    strncpy (pname, name, 24);
-    pname[23] = '\0';
-    tmw_TrimStr (pname);
-
-    /* The guild name is empty/invalid. */
-    if (!*pname)
-        clif_guild_created (sd, 2);
-
-    /* Make sure the character isn't already in a guild. */
-    if (sd->status.guild_id == 0)
-    {
-        /*
-         * A special item is required to create a guild. This is specified
-         * in battle_athena.conf as guild_emperium_check. This item will
-         * be removed from the player's inventory when used to create a
-         * guild.
-         */
-        if (!battle_config.guild_emperium_check
-            || pc_search_inventory (sd,
-                                    battle_config.guild_emperium_check) >= 0)
-        {
-            struct guild_member m;
-            guild_makemember (&m, sd);
-            m.position = 0;
-            intif_guild_create (pname, &m);
-        }
-        else
-            clif_guild_created (sd, 3);
-    }
-    else
-        clif_guild_created (sd, 1);
-
-    return 0;
-}
-
-/* Relay the result of a guild creation request. */
-int guild_created (int account_id, int guild_id)
-{
-    struct map_session_data *sd = map_id2sd (account_id);
-
-    if (!sd)
-        return 0;
-
-    /* The guild name is valid and not already taken. */
-    if (guild_id > 0)
-    {
-        struct guild *g;
-        sd->status.guild_id = guild_id;
-        sd->guild_sended = 0;
-
-        if ((g = (struct guild *)numdb_search (guild_db, guild_id)) != NULL)
-        {
-            printf ("guild_created(): ID already exists!\n");
-            exit (1);
-        }
-
-        /* The guild was created successfully. */
-        clif_guild_created (sd, 0);
-
-        if (battle_config.guild_emperium_check)
-            pc_delitem (sd,
-                        pc_search_inventory (sd,
-                                             battle_config.
-                                             guild_emperium_check), 1, 0);
-    }
-    else
-        clif_guild_created (sd, 2);
-
-    return 0;
-}
-
-// 情報要求
-int guild_request_info (int guild_id)
-{
-//  if(battle_config.etc_log)
-//      printf("guild_request_info\n");
-    return intif_guild_request_info (guild_id);
-}
-
-// イベント付き情報要求
-int guild_npc_request_info (int guild_id, const char *event)
-{
-    struct eventlist *ev;
-
-    if (guild_search (guild_id))
-    {
-        if (event && *event)
-            npc_event_do (event);
-        return 0;
-    }
-
-    if (event == NULL || *event == 0)
-        return guild_request_info (guild_id);
-
-    CREATE (ev, struct eventlist, 1);
-    memcpy (ev->name, event, sizeof (ev->name));
-    ev->next =
-        (struct eventlist *) numdb_search (guild_infoevent_db, guild_id);
-    numdb_insert (guild_infoevent_db, guild_id, ev);
-    return guild_request_info (guild_id);
-}
-
-// 所属キャラの確認
-int guild_check_member (const struct guild *g)
-{
-    int  i;
-    struct map_session_data *sd;
-
-    nullpo_retr (0, g);
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
-        {
-            if (sd->status.guild_id == g->guild_id)
-            {
-                int  j, f = 1;
-                for (j = 0; j < MAX_GUILD; j++)
-                {               // データがあるか
-                    if (g->member[j].account_id == sd->status.account_id)
-                        f = 0;
-                }
-                if (f)
-                {
-                    sd->status.guild_id = 0;
-                    sd->guild_sended = 0;
-                    sd->guild_emblem_id = 0;
-                    if (battle_config.error_log)
-                        printf ("guild: check_member %d[%s] is not member\n",
-                                sd->status.account_id, sd->status.name);
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-// 情報所得失敗(そのIDのキャラを全部未所属にする)
-int guild_recv_noinfo (int guild_id)
-{
-    int  i;
-    struct map_session_data *sd;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
-        {
-            if (sd->status.guild_id == guild_id)
-                sd->status.guild_id = 0;
-        }
-    }
-    return 0;
-}
-
-// 情報所得
-int guild_recv_info (struct guild *sg)
-{
-    struct guild *g, before;
-    int  i, bm, m;
-    struct eventlist *ev, *ev2;
-
-    nullpo_retr (0, sg);
-
-    if ((g = (struct guild *)numdb_search (guild_db, sg->guild_id)) == NULL)
-    {
-        CREATE (g, struct guild, 1);
-        numdb_insert (guild_db, sg->guild_id, g);
-        before = *sg;
-
-        // 最初のロードなのでユーザーのチェックを行う
-        guild_check_member (sg);
-    }
-    else
-        before = *g;
-    memcpy (g, sg, sizeof (struct guild));
-
-    for (i = bm = m = 0; i < g->max_member; i++)
-    {                           // sdの設定と人数の確認
-        if (g->member[i].account_id > 0)
-        {
-            struct map_session_data *sd = map_id2sd (g->member[i].account_id);
-            g->member[i].sd = (sd != NULL &&
-                               sd->status.guild_id ==
-                               g->guild_id) ? sd : NULL;
-            m++;
-        }
-        else
-            g->member[i].sd = NULL;
-        if (before.member[i].account_id > 0)
-            bm++;
-    }
-
-    for (i = 0; i < g->max_member; i++)
-    {                           // 情報の送信
-        struct map_session_data *sd = g->member[i].sd;
-        if (sd == NULL)
-            continue;
-
-        if (before.guild_lv != g->guild_lv || bm != m ||
-            before.max_member != g->max_member)
-        {
-            clif_guild_basicinfo (sd);  // 基本情報送信
-            clif_guild_emblem (sd, g);  // エンブレム送信
-        }
-
-        if (bm != m)
-        {                       // メンバー情報送信
-            clif_guild_memberlist (g->member[i].sd);
-        }
-
-        if (before.skill_point != g->skill_point)
-            clif_guild_skillinfo (sd);  // スキル情報送信
-
-        if (sd->guild_sended == 0)
-        {                       // 未送信なら所属情報も送る
-            clif_guild_belonginfo (sd, g);
-            clif_guild_notice (sd, g);
-            sd->guild_emblem_id = g->emblem_id;
-            sd->guild_sended = 1;
-        }
-    }
-
-    // イベントの発生
-    if ((ev = (struct eventlist *)numdb_search (guild_infoevent_db, sg->guild_id)) != NULL)
-    {
-        numdb_erase (guild_infoevent_db, sg->guild_id);
-        for (; ev; ev2 = ev->next, free (ev), ev = ev2)
-        {
-            npc_event_do (ev->name);
-        }
-    }
-
-    return 0;
-}
-
-// ギルドへの勧誘
-int guild_invite (struct map_session_data *sd, int account_id)
-{
-    struct map_session_data *tsd;
-    struct guild *g;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    tsd = map_id2sd (account_id);
-    g = guild_search (sd->status.guild_id);
-
-    if (tsd == NULL || g == NULL)
-        return 0;
-    if (!battle_config.invite_request_check)
-    {
-        if (tsd->party_invite > 0 || tsd->trade_partner)
-        {                       // 相手が取引中かどうか
-            clif_guild_inviteack (sd, 0);
-            return 0;
-        }
-    }
-    if (tsd->status.guild_id > 0 || tsd->guild_invite > 0)
-    {                           // 相手の所属確認
-        clif_guild_inviteack (sd, 0);
-        return 0;
-    }
-
-    // 定員確認
-    for (i = 0; i < g->max_member; i++)
-        if (g->member[i].account_id == 0)
-            break;
-    if (i == g->max_member)
-    {
-        clif_guild_inviteack (sd, 3);
-        return 0;
-    }
-
-    tsd->guild_invite = sd->status.guild_id;
-    tsd->guild_invite_account = sd->status.account_id;
-
-    clif_guild_invite (tsd, g);
-    return 0;
-}
-
-// ギルド勧誘への返答
-int guild_reply_invite (struct map_session_data *sd, int guild_id, int flag)
-{
-    struct map_session_data *tsd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, tsd = map_id2sd (sd->guild_invite_account));
-
-    if (sd->guild_invite != guild_id)   // 勧誘とギルドIDが違う
-        return 0;
-
-    if (flag == 1)
-    {                           // 承諾
-        struct guild_member m;
-        struct guild *g;
-        int  i;
-
-        // 定員確認
-        if ((g = guild_search (tsd->status.guild_id)) == NULL)
-        {
-            sd->guild_invite = 0;
-            sd->guild_invite_account = 0;
-            return 0;
-        }
-        for (i = 0; i < g->max_member; i++)
-            if (g->member[i].account_id == 0)
-                break;
-        if (i == g->max_member)
-        {
-            sd->guild_invite = 0;
-            sd->guild_invite_account = 0;
-            clif_guild_inviteack (tsd, 3);
-            return 0;
-        }
-
-        //inter鯖へ追加要求
-        guild_makemember (&m, sd);
-        intif_guild_addmember (sd->guild_invite, &m);
-        return 0;
-    }
-    else
-    {                           // 拒否
-        sd->guild_invite = 0;
-        sd->guild_invite_account = 0;
-        if (tsd == NULL)
-            return 0;
-        clif_guild_inviteack (tsd, 1);
-    }
-    return 0;
-}
-
-// ギルドメンバが追加された
-int guild_member_added (int guild_id, int account_id, int char_id, int flag)
-{
-    struct map_session_data *sd = map_id2sd (account_id), *sd2;
-    struct guild *g;
-
-    if ((g = guild_search (guild_id)) == NULL)
-        return 0;
-
-    if ((sd == NULL || sd->guild_invite == 0) && flag == 0)
-    {
-        // キャラ側に登録できなかったため脱退要求を出す
-        if (battle_config.error_log)
-            printf ("guild: member added error %d is not online\n",
-                    account_id);
-        intif_guild_leave (guild_id, account_id, 0 /*char_id*/, 0, "**登録失敗**");
-        return 0;
-    }
-    sd->guild_invite = 0;
-    sd->guild_invite_account = 0;
-
-    sd2 = map_id2sd (sd->guild_invite_account);
-
-    if (flag == 1)
-    {                           // 失敗
-        if (sd2 != NULL)
-            clif_guild_inviteack (sd2, 3);
-        return 0;
-    }
-
-    // 成功
-    sd->guild_sended = 0;
-    sd->status.guild_id = guild_id;
-
-    if (sd2 != NULL)
-        clif_guild_inviteack (sd2, 2);
-
-    // いちおう競合確認
-    guild_check_conflict (sd);
-
-    return 0;
-}
-
-// ギルド脱退要求
-int guild_leave (struct map_session_data *sd, int guild_id,
-                 int account_id, int char_id, const char *mes)
-{
-    struct guild *g;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return 0;
-
-    if (sd->status.account_id != account_id ||
-        sd->status.guild_id != guild_id)
-        return 0;
-
-    for (i = 0; i < g->max_member; i++)
-    {                           // 所属しているか
-        if (g->member[i].account_id == sd->status.account_id)
-        {
-            intif_guild_leave (g->guild_id, sd->status.account_id,
-                               sd->status.char_id, 0, mes);
-            return 0;
-        }
-    }
-    return 0;
-}
-
-// ギルド追放要求
-int guild_explusion (struct map_session_data *sd, int guild_id,
-                     int account_id, int char_id, const char *mes)
-{
-    struct guild *g;
-    int  i, ps;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return 0;
-
-    if (sd->status.guild_id != guild_id)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || !(g->position[ps].mode & 0x0010))
-        return 0;               // 処罰権限無し
-
-    for (i = 0; i < g->max_member; i++)
-    {                           // 所属しているか
-        if (g->member[i].account_id == account_id)
-        {
-            intif_guild_leave (g->guild_id, account_id, 0 /*char_id*/, 1, mes);
-            return 0;
-        }
-    }
-    return 0;
-}
-
-// ギルドメンバが脱退した
-int guild_member_leaved (int guild_id, int account_id, int char_id, int flag,
-                         const char *name, const char *mes)
-{
-    struct map_session_data *sd = map_id2sd (account_id);
-    struct guild *g = guild_search (guild_id);
-    int  i;
-
-    if (g != NULL)
-    {
-        int  i;
-        for (i = 0; i < g->max_member; i++)
-            if (g->member[i].account_id == account_id)
-            {
-                struct map_session_data *sd2 = sd;
-                if (sd2 == NULL)
-                    sd2 = guild_getavailablesd (g);
-                else
-                {
-                    if (flag == 0)
-                        clif_guild_leave (sd2, name, mes);
-                    else
-                        clif_guild_explusion (sd2, name, mes, account_id);
-                }
-                g->member[i].account_id = 0;
-                g->member[i].sd = NULL;
-            }
-    }
-    if (sd != NULL && sd->status.guild_id == guild_id)
-    {
-        if (sd->state.storage_flag == 2)    //Close the guild storage.
-            storage_guild_storageclose (sd);
-        sd->status.guild_id = 0;
-        sd->guild_emblem_id = 0;
-        sd->guild_sended = 0;
-    }
-
-    // メンバーリストを全員に再通知
-    for (i = 0; i < g->max_member; i++)
-    {
-        if (g->member[i].sd != NULL)
-            clif_guild_memberlist (g->member[i].sd);
-    }
-
-    return 0;
-}
-
-// ギルドメンバのオンライン状態/Lv更新送信
-int guild_send_memberinfoshort (struct map_session_data *sd, int online)
-{
-    struct guild *g;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.guild_id <= 0)
-        return 0;
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL)
-        return 0;
-
-    intif_guild_memberinfoshort (g->guild_id,
-                                 sd->status.account_id, 0 /*char_id*/,
-                                 online, sd->status.base_level,
-                                 sd->status.pc_class);
-
-    if (!online)
-    {                           // ログアウトするならsdをクリアして終了
-        int  i =
-            guild_getindex (g, sd->status.account_id, 0 /*char_id*/);
-        if (i >= 0)
-            g->member[i].sd = NULL;
-        return 0;
-    }
-
-    if (sd->guild_sended != 0)  // ギルド初期送信データは送信済み
-        return 0;
-
-    // 競合確認
-    guild_check_conflict (sd);
-
-    // あるならギルド初期送信データ送信
-    if ((g = guild_search (sd->status.guild_id)) != NULL)
-    {
-        guild_check_member (g); // 所属を確認する
-        if (sd->status.guild_id == g->guild_id)
-        {
-            clif_guild_belonginfo (sd, g);
-            clif_guild_notice (sd, g);
-            sd->guild_sended = 1;
-            sd->guild_emblem_id = g->emblem_id;
-        }
-    }
-    return 0;
-}
-
-// ギルドメンバのオンライン状態/Lv更新通知
-int guild_recv_memberinfoshort (int guild_id, int account_id, int char_id,
-                                int online, int lv, int pc_class)
-{
-    int  i, alv, c, idx = 0, om = 0, oldonline = -1;
-    struct guild *g = guild_search (guild_id);
-    if (g == NULL)
-        return 0;
-    for (i = 0, alv = 0, c = 0, om = 0; i < g->max_member; i++)
-    {
-        struct guild_member *m = &g->member[i];
-        if (m->account_id == account_id)
-        {
-            oldonline = m->online;
-            m->online = online;
-            m->lv = lv;
-            m->pc_class = pc_class;
-            idx = i;
-        }
-        if (m->account_id > 0)
-        {
-            alv += m->lv;
-            c++;
-        }
-        if (m->online)
-            om++;
-    }
-    if (idx == g->max_member)
-    {
-        if (battle_config.error_log)
-            printf ("guild: not found member %d,%d on %d[%s]\n", account_id,
-                    char_id, guild_id, g->name);
-        return 0;
-    }
-    g->average_lv = alv / c;
-    g->connect_member = om;
-
-    if (oldonline != online)    // オンライン状態が変わったので通知
-        clif_guild_memberlogin_notice (g, idx, online);
-
-    for (i = 0; i < g->max_member; i++)
-    {                           // sd再設定
-        struct map_session_data *sd = map_id2sd (g->member[i].account_id);
-        g->member[i].sd = (sd != NULL &&
-                           sd->status.guild_id == guild_id) ? sd : NULL;
-    }
-
-    // ここにクライアントに送信処理が必要
-
-    return 0;
-}
-
-// ギルド会話送信
-int guild_send_message (struct map_session_data *sd, char *mes, int len)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->status.guild_id == 0)
-        return 0;
-    intif_guild_message (sd->status.guild_id, sd->status.account_id, mes,
-                         len);
-    return 0;
-}
-
-// ギルド会話受信
-int guild_recv_message (int guild_id, int account_id, char *mes, int len)
-{
-    struct guild *g;
-    if ((g = guild_search (guild_id)) == NULL)
-        return 0;
-    clif_guild_message (g, account_id, mes, len);
-    return 0;
-}
-
-// ギルドメンバの役職変更
-int guild_change_memberposition (int guild_id, int account_id, int char_id,
-                                 int idx)
-{
-    return intif_guild_change_memberinfo (guild_id, account_id, 0 /*char_id*/,
-                                          GMI_POSITION, &idx, sizeof (idx));
-}
-
-// ギルドメンバの役職変更通知
-int guild_memberposition_changed (struct guild *g, int idx, int pos)
-{
-    nullpo_retr (0, g);
-
-    g->member[idx].position = pos;
-    clif_guild_memberpositionchanged (g, idx);
-    return 0;
-}
-
-// ギルド役職変更
-int guild_change_position (struct map_session_data *sd, int idx,
-                           int mode, int exp_mode, const char *name)
-{
-    struct guild_position p;
-
-    nullpo_retr (0, sd);
-
-    if (exp_mode > battle_config.guild_exp_limit)
-        exp_mode = battle_config.guild_exp_limit;
-    if (exp_mode < 0)
-        exp_mode = 0;
-    p.mode = mode;
-    p.exp_mode = exp_mode;
-    memcpy (p.name, name, 24);
-    return intif_guild_position (sd->status.guild_id, idx, &p);
-}
-
-// ギルド役職変更通知
-int guild_position_changed (int guild_id, int idx, struct guild_position *p)
-{
-    struct guild *g = guild_search (guild_id);
-    if (g == NULL)
-        return 0;
-    memcpy (&g->position[idx], p, sizeof (struct guild_position));
-    clif_guild_positionchanged (g, idx);
-    return 0;
-}
-
-// ギルド告知変更
-int guild_change_notice (struct map_session_data *sd, int guild_id,
-                         const char *mes1, const char *mes2)
-{
-    struct guild *g;
-    int  ps;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || !(g->position[ps].mode & 0x0010))
-        return 0;
-
-    if (guild_id != sd->status.guild_id)
-        return 0;
-
-    return intif_guild_notice (guild_id, mes1, mes2);
-}
-
-// ギルド告知変更通知
-int guild_notice_changed (int guild_id, const char *mes1, const char *mes2)
-{
-    int  i;
-    struct map_session_data *sd;
-    struct guild *g = guild_search (guild_id);
-    if (g == NULL)
-        return 0;
-
-    memcpy (g->mes1, mes1, 60);
-    memcpy (g->mes2, mes2, 120);
-
-    for (i = 0; i < g->max_member; i++)
-    {
-        if ((sd = g->member[i].sd) != NULL)
-            clif_guild_notice (sd, g);
-    }
-    return 0;
-}
-
-// ギルドエンブレム変更
-int guild_change_emblem (struct map_session_data *sd, int len,
-                         const char *data)
-{
-    struct guild *g;
-    int  ps;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || !(g->position[ps].mode & 0x0010))
-        return 0;
-
-    return intif_guild_emblem (sd->status.guild_id, len, data);
-}
-
-// ギルドエンブレム変更通知
-int guild_emblem_changed (int len, int guild_id, int emblem_id,
-                          const char *data)
-{
-    int  i;
-    struct map_session_data *sd;
-    struct guild *g = guild_search (guild_id);
-    if (g == NULL)
-        return 0;
-
-    memcpy (g->emblem_data, data, len);
-    g->emblem_len = len;
-    g->emblem_id = emblem_id;
-
-    for (i = 0; i < g->max_member; i++)
-    {
-        if ((sd = g->member[i].sd) != NULL)
-        {
-            sd->guild_emblem_id = emblem_id;
-            clif_guild_belonginfo (sd, g);
-            clif_guild_emblem (sd, g);
-        }
-    }
-    return 0;
-}
-
-// ギルドのEXP上納
-int guild_payexp (struct map_session_data *sd, int exp)
-{
-    struct guild *g;
-    struct guild_expcache *c;
-    int  per, exp2;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.guild_id == 0
-        || (g = guild_search (sd->status.guild_id)) == NULL)
-        return 0;
-    if ((per = g->position[guild_getposition (sd, g)].exp_mode) <= 0)
-        return 0;
-    if (per > 100)
-        per = 100;
-
-    if ((exp2 = exp * per / 100) <= 0)
-        return 0;
-
-    if ((c = (struct guild_expcache *)numdb_search (guild_expcache_db, sd->status.account_id /*char_id*/)) == NULL)
-    {
-        CREATE (c, struct guild_expcache, 1);
-        c->guild_id = sd->status.guild_id;
-        c->account_id = sd->status.account_id;
-        c->char_id = 0;
-        c->exp = exp2;
-        numdb_insert (guild_expcache_db, c->account_id /*char_id*/, c);
-    }
-    else
-    {
-        c->exp += exp2;
-    }
-    return exp2;
-}
-
-// スキルポイント割り振り
-int guild_skillup (struct map_session_data *sd, int skill_num)
-{
-    struct guild *g;
-    int  idx;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.guild_id == 0
-        || (g = guild_search (sd->status.guild_id)) == NULL)
-        return 0;
-    if (strcmp (sd->status.name, g->master))
-        return 0;
-
-    if (g->skill_point > 0 &&
-        g->skill[(idx = skill_num - 10000)].id != 0 &&
-        g->skill[idx].lv < guild_skill_get_max (skill_num))
-    {
-        intif_guild_skillup (g->guild_id, skill_num, sd->status.account_id);
-    }
-    return 0;
-}
-
-// スキルポイント割り振り通知
-int guild_skillupack (int guild_id, int skill_num, int account_id)
-{
-    struct map_session_data *sd = map_id2sd (account_id);
-    struct guild *g = guild_search (guild_id);
-    int  i;
-    if (g == NULL)
-        return 0;
-    if (sd != NULL)
-        clif_guild_skillup (sd, skill_num, g->skill[skill_num - 10000].lv);
-    // 全員に通知
-    for (i = 0; i < g->max_member; i++)
-        if ((sd = g->member[i].sd) != NULL)
-            clif_guild_skillinfo (sd);
-    return 0;
-}
-
-// ギルド同盟数所得
-int guild_get_alliance_count (struct guild *g, int flag)
-{
-    int  i, c;
-
-    nullpo_retr (0, g);
-
-    for (i = c = 0; i < MAX_GUILDALLIANCE; i++)
-    {
-        if (g->alliance[i].guild_id > 0 && g->alliance[i].opposition == flag)
-            c++;
-    }
-    return c;
-}
-
-// ギルド同盟要求
-int guild_reqalliance (struct map_session_data *sd, int account_id)
-{
-    struct map_session_data *tsd = map_id2sd (account_id);
-    struct guild *g[2];
-    int  i, ps;
-
-    if (agit_flag)
-    {                           // Disable alliance creation during woe [Valaris]
-        clif_displaymessage (sd->fd,
-                             "Alliances cannot be made during Guild Wars!");
-        return 0;
-    }                           // end addition [Valaris]
-
-    nullpo_retr (0, sd);
-
-    if (tsd == NULL || tsd->status.guild_id <= 0)
-        return 0;
-
-    g[0] = guild_search (sd->status.guild_id);
-    g[1] = guild_search (tsd->status.guild_id);
-
-    if (g[0] == NULL || g[1] == NULL)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g[0])) < 0
-        || !(g[0]->position[ps].mode & 0x0010))
-        return 0;
-
-    if (guild_get_alliance_count (g[0], 0) > 3) // 同盟数確認
-        clif_guild_allianceack (sd, 4);
-    if (guild_get_alliance_count (g[1], 0) > 3)
-        clif_guild_allianceack (sd, 3);
-
-    if (tsd->guild_alliance > 0)
-    {                           // 相手が同盟要請状態かどうか確認
-        clif_guild_allianceack (sd, 1);
-        return 0;
-    }
-
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-    {                           // すでに同盟状態か確認
-        if (g[0]->alliance[i].guild_id == tsd->status.guild_id &&
-            g[0]->alliance[i].opposition == 0)
-        {
-            clif_guild_allianceack (sd, 0);
-            return 0;
-        }
-    }
-
-    tsd->guild_alliance = sd->status.guild_id;
-    tsd->guild_alliance_account = sd->status.account_id;
-
-    clif_guild_reqalliance (tsd, sd->status.account_id, g[0]->name);
-    return 0;
-}
-
-// ギルド勧誘への返答
-int guild_reply_reqalliance (struct map_session_data *sd, int account_id,
-                             int flag)
-{
-    struct map_session_data *tsd;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, tsd = map_id2sd (account_id));
-
-    if (sd->guild_alliance != tsd->status.guild_id) // 勧誘とギルドIDが違う
-        return 0;
-
-    if (flag == 1)
-    {                           // 承諾
-        int  i;
-
-        struct guild *g;        // 同盟数再確認
-        if ((g = guild_search (sd->status.guild_id)) == NULL ||
-            guild_get_alliance_count (g, 0) > 3)
-        {
-            clif_guild_allianceack (sd, 4);
-            clif_guild_allianceack (tsd, 3);
-            return 0;
-        }
-        if ((g = guild_search (tsd->status.guild_id)) == NULL ||
-            guild_get_alliance_count (g, 0) > 3)
-        {
-            clif_guild_allianceack (sd, 3);
-            clif_guild_allianceack (tsd, 4);
-            return 0;
-        }
-
-        // 敵対関係なら敵対を止める
-        if ((g = guild_search (sd->status.guild_id)) == NULL)
-            return 0;
-        for (i = 0; i < MAX_GUILDALLIANCE; i++)
-        {
-            if (g->alliance[i].guild_id == tsd->status.guild_id &&
-                g->alliance[i].opposition == 1)
-                intif_guild_alliance (sd->status.guild_id,
-                                      tsd->status.guild_id,
-                                      sd->status.account_id,
-                                      tsd->status.account_id, 9);
-        }
-        if ((g = guild_search (tsd->status.guild_id)) == NULL)
-            return 0;
-        for (i = 0; i < MAX_GUILDALLIANCE; i++)
-        {
-            if (g->alliance[i].guild_id == sd->status.guild_id &&
-                g->alliance[i].opposition == 1)
-                intif_guild_alliance (tsd->status.guild_id,
-                                      sd->status.guild_id,
-                                      tsd->status.account_id,
-                                      sd->status.account_id, 9);
-        }
-
-        // inter鯖へ同盟要請
-        intif_guild_alliance (sd->status.guild_id, tsd->status.guild_id,
-                              sd->status.account_id, tsd->status.account_id,
-                              0);
-        return 0;
-    }
-    else
-    {                           // 拒否
-        sd->guild_alliance = 0;
-        sd->guild_alliance_account = 0;
-        if (tsd != NULL)
-            clif_guild_allianceack (tsd, 3);
-    }
-    return 0;
-}
-
-// ギルド関係解消
-int guild_delalliance (struct map_session_data *sd, int guild_id, int flag)
-{
-    if (agit_flag)
-    {                           // Disable alliance breaking during woe [Valaris]
-        clif_displaymessage (sd->fd,
-                             "Alliances cannot be broken during Guild Wars!");
-        return 0;
-    }                           // end addition [Valaris]
-
-    struct guild *g;
-    int  ps;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-
-    if (g == NULL)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || !(g->position[ps].mode & 0x0010))
-        return 0;
-
-    intif_guild_alliance (sd->status.guild_id, guild_id,
-                          sd->status.account_id, 0, flag | 8);
-    return 0;
-}
-
-// ギルド敵対
-int guild_opposition (struct map_session_data *sd, int account_id /*char_id*/)
-{
-    struct map_session_data *tsd = map_id2sd (account_id /*char_id*/);
-    struct guild *g;
-    int  i, ps;
-
-    nullpo_retr (0, sd);
-
-    g = guild_search (sd->status.guild_id);
-    if (g == NULL || tsd == NULL)
-        return 0;
-
-    if ((ps = guild_getposition (sd, g)) < 0
-        || !(g->position[ps].mode & 0x0010))
-        return 0;
-
-    if (guild_get_alliance_count (g, 1) > 3)    // 敵対数確認
-        clif_guild_oppositionack (sd, 1);
-
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-    {                           // すでに関係を持っているか確認
-        if (g->alliance[i].guild_id == tsd->status.guild_id)
-        {
-            if (g->alliance[i].opposition == 1)
-            {                   // すでに敵対
-                clif_guild_oppositionack (sd, 2);
-                return 0;
-            }
-            else                // 同盟破棄
-                intif_guild_alliance (sd->status.guild_id,
-                                      tsd->status.guild_id,
-                                      sd->status.account_id,
-                                      tsd->status.account_id, 8);
-        }
-    }
-
-    // inter鯖に敵対要請
-    intif_guild_alliance (sd->status.guild_id, tsd->status.guild_id,
-                          sd->status.account_id, tsd->status.account_id, 1);
-    return 0;
-}
-
-// ギルド同盟/敵対通知
-int guild_allianceack (int guild_id1, int guild_id2, int account_id1,
-                       int account_id2, int flag, const char *name1,
-                       const char *name2)
-{
-    struct guild *g[2];
-    int  guild_id[2] = { guild_id1, guild_id2 };
-    const char *guild_name[2] = { name1, name2 };
-    struct map_session_data *sd[2] =
-        { map_id2sd (account_id1), map_id2sd (account_id2) };
-    int  j, i;
-
-    g[0] = guild_search (guild_id1);
-    g[1] = guild_search (guild_id2);
-
-    if (sd[0] != NULL && (flag & 0x0f) == 0)
-    {
-        sd[0]->guild_alliance = 0;
-        sd[0]->guild_alliance_account = 0;
-    }
-
-    if (flag & 0x70)
-    {                           // 失敗
-        for (i = 0; i < 2 - (flag & 1); i++)
-            if (sd[i] != NULL)
-                clif_guild_allianceack (sd[i],
-                                        ((flag >> 4) == i + 1) ? 3 : 4);
-        return 0;
-    }
-//  if(battle_config.etc_log)
-//      printf("guild alliance_ack %d %d %d %d %d %s %s\n",guild_id1,guild_id2,account_id1,account_id2,flag,name1,name2);
-
-    if (!(flag & 0x08))
-    {                           // 関係追加
-        for (i = 0; i < 2 - (flag & 1); i++)
-            if (g[i] != NULL)
-                for (j = 0; j < MAX_GUILDALLIANCE; j++)
-                    if (g[i]->alliance[j].guild_id == 0)
-                    {
-                        g[i]->alliance[j].guild_id = guild_id[1 - i];
-                        memcpy (g[i]->alliance[j].name, guild_name[1 - i],
-                                24);
-                        g[i]->alliance[j].opposition = flag & 1;
-                        break;
-                    }
-    }
-    else
-    {                           // 関係解消
-        for (i = 0; i < 2 - (flag & 1); i++)
-        {
-            if (g[i] != NULL)
-                for (j = 0; j < MAX_GUILDALLIANCE; j++)
-                    if (g[i]->alliance[j].guild_id == guild_id[1 - i] &&
-                        g[i]->alliance[j].opposition == (flag & 1))
-                    {
-                        g[i]->alliance[j].guild_id = 0;
-                        break;
-                    }
-            if (sd[i] != NULL)  // 解消通知
-                clif_guild_delalliance (sd[i], guild_id[1 - i], (flag & 1));
-        }
-    }
-
-    if ((flag & 0x0f) == 0)
-    {                           // 同盟通知
-        if (sd[1] != NULL)
-            clif_guild_allianceack (sd[1], 2);
-    }
-    else if ((flag & 0x0f) == 1)
-    {                           // 敵対通知
-        if (sd[0] != NULL)
-            clif_guild_oppositionack (sd[0], 0);
-    }
-
-    for (i = 0; i < 2 - (flag & 1); i++)
-    {                           // 同盟/敵対リストの再送信
-        struct map_session_data *sd;
-        if (g[i] != NULL)
-            for (j = 0; j < g[i]->max_member; j++)
-                if ((sd = g[i]->member[j].sd) != NULL)
-                    clif_guild_allianceinfo (sd);
-    }
-    return 0;
-}
-
-// ギルド解散通知用
-void guild_broken_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild *g = (struct guild *) data;
-    int  guild_id = va_arg (ap, int);
-    int  i, j;
-    struct map_session_data *sd = NULL;
-
-    nullpo_retv (g);
-
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-    {                           // 関係を破棄
-        if (g->alliance[i].guild_id == guild_id)
-        {
-            for (j = 0; j < g->max_member; j++)
-                if ((sd = g->member[j].sd) != NULL)
-                    clif_guild_delalliance (sd, guild_id,
-                                            g->alliance[i].opposition);
-            g->alliance[i].guild_id = 0;
-        }
-    }
-}
-
-// ギルド解散通知
-int guild_broken (int guild_id, int flag)
-{
-    struct guild *g = guild_search (guild_id);
-    struct map_session_data *sd;
-    int  i;
-    if (flag != 0 || g == NULL)
-        return 0;
-
-    for (i = 0; i < g->max_member; i++)
-    {                           // ギルド解散を通知
-        if ((sd = g->member[i].sd) != NULL)
-        {
-            if (sd->state.storage_flag == 2)
-                storage_guild_storage_quit (sd, 1);
-            sd->status.guild_id = 0;
-            sd->guild_sended = 0;
-            clif_guild_broken (g->member[i].sd, 0);
-        }
-    }
-
-    numdb_foreach (guild_db, guild_broken_sub, guild_id);
-    numdb_erase (guild_db, guild_id);
-    guild_storage_delete (guild_id);
-    free (g);
-    return 0;
-}
-
-// ギルド解散
-int guild_break (struct map_session_data *sd, char *name)
-{
-    struct guild *g;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if ((g = guild_search (sd->status.guild_id)) == NULL)
-        return 0;
-    if (strcmp (g->name, name) != 0)
-        return 0;
-    if (strcmp (sd->status.name, g->master) != 0)
-        return 0;
-    for (i = 0; i < g->max_member; i++)
-    {
-        if (g->member[i].account_id > 0
-            && (g->member[i].account_id != sd->status.account_id))
-            break;
-    }
-    if (i < g->max_member)
-    {
-        clif_guild_broken (sd, 2);
-        return 0;
-    }
-
-    intif_guild_break (g->guild_id);
-    return 0;
-}
-
-// ギルド城データ要求
-int guild_castledataload (int castle_id, int index)
-{
-    return intif_guild_castle_dataload (castle_id, index);
-}
-
-// ギルド城情報所得時イベント追加
-int guild_addcastleinfoevent (int castle_id, int index, const char *name)
-{
-    struct eventlist *ev;
-    int  code = castle_id | (index << 16);
-
-    if (name == NULL || *name == 0)
-        return 0;
-
-    CREATE (ev, struct eventlist, 1);
-    memcpy (ev->name, name, sizeof (ev->name));
-    ev->next = (struct eventlist *)numdb_search (guild_castleinfoevent_db, code);
-    numdb_insert (guild_castleinfoevent_db, code, ev);
-    return 0;
-}
-
-// ギルド城データ要求返信
-int guild_castledataloadack (int castle_id, int index, int value)
-{
-    struct guild_castle *gc = guild_castle_search (castle_id);
-    int  code = castle_id | (index << 16);
-    struct eventlist *ev, *ev2;
-
-    if (gc == NULL)
-    {
-        return 0;
-    }
-    switch (index)
-    {
-        case 1:
-            gc->guild_id = value;
-            break;
-        case 2:
-            gc->economy = value;
-            break;
-        case 3:
-            gc->defense = value;
-            break;
-        case 4:
-            gc->triggerE = value;
-            break;
-        case 5:
-            gc->triggerD = value;
-            break;
-        case 6:
-            gc->nextTime = value;
-            break;
-        case 7:
-            gc->payTime = value;
-            break;
-        case 8:
-            gc->createTime = value;
-            break;
-        case 9:
-            gc->visibleC = value;
-            break;
-        case 10:
-            gc->visibleG0 = value;
-            break;
-        case 11:
-            gc->visibleG1 = value;
-            break;
-        case 12:
-            gc->visibleG2 = value;
-            break;
-        case 13:
-            gc->visibleG3 = value;
-            break;
-        case 14:
-            gc->visibleG4 = value;
-            break;
-        case 15:
-            gc->visibleG5 = value;
-            break;
-        case 16:
-            gc->visibleG6 = value;
-            break;
-        case 17:
-            gc->visibleG7 = value;
-            break;
-        case 18:
-            gc->Ghp0 = value;
-            break;              // guardian HP [Valaris]
-        case 19:
-            gc->Ghp1 = value;
-            break;
-        case 20:
-            gc->Ghp2 = value;
-            break;
-        case 21:
-            gc->Ghp3 = value;
-            break;
-        case 22:
-            gc->Ghp4 = value;
-            break;
-        case 23:
-            gc->Ghp5 = value;
-            break;
-        case 24:
-            gc->Ghp6 = value;
-            break;
-        case 25:
-            gc->Ghp7 = value;
-            break;              // end additions [Valaris]
-        default:
-            printf ("guild_castledataloadack ERROR!! (Not found index=%d)\n",
-                    index);
-            return 0;
-    }
-    if ((ev = (struct eventlist *)numdb_search (guild_castleinfoevent_db, code)) != NULL)
-    {
-        numdb_erase (guild_castleinfoevent_db, code);
-        for (; ev; ev2 = ev->next, free (ev), ev = ev2)
-        {
-            npc_event_do (ev->name);
-        }
-    }
-    return 1;
-}
-
-// ギルド城データ変更要求
-int guild_castledatasave (int castle_id, int index, int value)
-{
-    return intif_guild_castle_datasave (castle_id, index, value);
-}
-
-// ギルド城データ変更通知
-int guild_castledatasaveack (int castle_id, int index, int value)
-{
-    struct guild_castle *gc = guild_castle_search (castle_id);
-    if (gc == NULL)
-    {
-        return 0;
-    }
-    switch (index)
-    {
-        case 1:
-            gc->guild_id = value;
-            break;
-        case 2:
-            gc->economy = value;
-            break;
-        case 3:
-            gc->defense = value;
-            break;
-        case 4:
-            gc->triggerE = value;
-            break;
-        case 5:
-            gc->triggerD = value;
-            break;
-        case 6:
-            gc->nextTime = value;
-            break;
-        case 7:
-            gc->payTime = value;
-            break;
-        case 8:
-            gc->createTime = value;
-            break;
-        case 9:
-            gc->visibleC = value;
-            break;
-        case 10:
-            gc->visibleG0 = value;
-            break;
-        case 11:
-            gc->visibleG1 = value;
-            break;
-        case 12:
-            gc->visibleG2 = value;
-            break;
-        case 13:
-            gc->visibleG3 = value;
-            break;
-        case 14:
-            gc->visibleG4 = value;
-            break;
-        case 15:
-            gc->visibleG5 = value;
-            break;
-        case 16:
-            gc->visibleG6 = value;
-            break;
-        case 17:
-            gc->visibleG7 = value;
-            break;
-        case 18:
-            gc->Ghp0 = value;
-            break;              // guardian HP [Valaris]
-        case 19:
-            gc->Ghp1 = value;
-            break;
-        case 20:
-            gc->Ghp2 = value;
-            break;
-        case 21:
-            gc->Ghp3 = value;
-            break;
-        case 22:
-            gc->Ghp4 = value;
-            break;
-        case 23:
-            gc->Ghp5 = value;
-            break;
-        case 24:
-            gc->Ghp6 = value;
-            break;
-        case 25:
-            gc->Ghp7 = value;
-            break;              // end additions [Valaris]
-        default:
-            printf ("guild_castledatasaveack ERROR!! (Not found index=%d)\n",
-                    index);
-            return 0;
-    }
-    return 1;
-}
-
-// ギルドデータ一括受信(初期化時)
-int guild_castlealldataload (int len, struct guild_castle *gc)
-{
-    int  i;
-    int  n = (len - 4) / sizeof (struct guild_castle), ev = -1;
-
-    nullpo_retr (0, gc);
-
-    // イベント付きで要求するデータ位置を探す(最後の占拠データ)
-    for (i = 0; i < n; i++)
-    {
-        if ((gc + i)->guild_id)
-            ev = i;
-    }
-
-    // 城データ格納とギルド情報要求
-    for (i = 0; i < n; i++, gc++)
-    {
-        struct guild_castle *c = guild_castle_search (gc->castle_id);
-        if (!c)
-        {
-            printf ("guild_castlealldataload ??\n");
-            continue;
-        }
-        memcpy (&c->guild_id, &gc->guild_id,
-                sizeof (struct guild_castle) - ((int) &c->guild_id -
-                                                (int) c));
-        if (c->guild_id)
-        {
-            if (i != ev)
-                guild_request_info (c->guild_id);
-            else
-                guild_npc_request_info (c->guild_id, "::OnAgitInit");
-        }
-    }
-    if (ev == -1)
-        npc_event_doall ("OnAgitInit");
-    return 0;
-}
-
-int guild_agit_start (void)
-{                               // Run All NPC_Event[OnAgitStart]
-    int  c = npc_event_doall ("OnAgitStart");
-    printf ("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n", c);
-    return 0;
-}
-
-int guild_agit_end (void)
-{                               // Run All NPC_Event[OnAgitEnd]
-    int  c = npc_event_doall ("OnAgitEnd");
-    printf ("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n", c);
-    return 0;
-}
-
-void guild_gvg_eliminate_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{                               // Run One NPC_Event[OnAgitEliminate]
-    size_t len = strlen ((const char *) data);
-    char *evname;
-    CREATE (evname, char, len + 4);
-    int  c = 0;
-
-    if (!agit_flag)
-        return;               // Agit already End
-    memcpy (evname, (const char *) data, len - 5);
-    strcpy (evname + len - 5, "Eliminate");
-    c = npc_event_do (evname);
-    printf ("NPC_Event:[%s] Run (%d) Events.\n", evname, c);
-}
-
-int guild_agit_break (struct mob_data *md)
-{                               // Run One NPC_Event[OnAgitBreak]
-    char *evname;
-
-    nullpo_retr (0, md);
-
-    CREATE (evname, char, strlen (md->npc_event) + 1);
-
-    strcpy (evname, md->npc_event);
-// Now By User to Run [OnAgitBreak] NPC Event...
-// It's a little impossible to null point with player disconnect in this!
-// But Script will be stop, so nothing...
-// Maybe will be changed in the futher..
-//      int c = npc_event_do(evname);
-    if (!agit_flag)
-        return 0;               // Agit already End
-    add_timer (gettick () + battle_config.gvg_eliminate_time,
-               guild_gvg_eliminate_timer, md->bl.m, (int) evname);
-    return 0;
-}
-
-// [MouseJstr]
-//   How many castles does this guild have?
-int guild_checkcastles (struct guild *g)
-{
-    int  i, nb_cas = 0, id, cas_id = 0;
-    struct guild_castle *gc;
-    id = g->guild_id;
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        gc = guild_castle_search (i);
-        cas_id = gc->guild_id;
-        if (g->guild_id == cas_id)
-            nb_cas = nb_cas + 1;
-    }                           //end for
-    return nb_cas;
-}
-
-// [MouseJstr]
-//    is this guild allied with this castle?
-int guild_isallied (struct guild *g, struct guild_castle *gc)
-{
-    int  i;
-
-    nullpo_retr (0, g);
-
-    if (g->guild_id == gc->guild_id)
-        return 1;
-
-    if (gc->guild_id == 0)
-        return 0;
-
-    for (i = 0; i < MAX_GUILDALLIANCE; i++)
-        if (g->alliance[i].guild_id == gc->guild_id)
-        {
-            if (g->alliance[i].opposition == 0)
-                return 1;
-            else
-                return 0;
-        }
-
-    return 0;
-}
-
-static void guild_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-static void castle_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-static void guild_expcache_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-static void guild_infoevent_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-void do_final_guild (void)
-{
-    if (guild_db)
-        numdb_final (guild_db, guild_db_final);
-    if (castle_db)
-        numdb_final (castle_db, castle_db_final);
-    if (guild_expcache_db)
-        numdb_final (guild_expcache_db, guild_expcache_db_final);
-    if (guild_infoevent_db)
-        numdb_final (guild_infoevent_db, guild_infoevent_db_final);
-    if (guild_castleinfoevent_db)
-        numdb_final (guild_castleinfoevent_db, guild_infoevent_db_final);
-}
diff --git a/src/map/guild.cpp b/src/map/guild.cpp
new file mode 100644
index 0000000..c001f78
--- /dev/null
+++ b/src/map/guild.cpp
@@ -0,0 +1,1915 @@
+// $Id: guild.c,v 1.5 2004/09/25 05:32:18 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "guild.hpp"
+#include "storage.hpp"
+#include "../common/db.hpp"
+#include "../common/timer.hpp"
+#include "../common/socket.hpp"
+#include "../common/nullpo.hpp"
+#include "battle.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "intif.hpp"
+#include "clif.hpp"
+#include "tmw.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+static struct dbt *guild_db;
+static struct dbt *castle_db;
+static struct dbt *guild_expcache_db;
+static struct dbt *guild_infoevent_db;
+static struct dbt *guild_castleinfoevent_db;
+
+struct eventlist
+{
+    char name[50];
+    struct eventlist *next;
+};
+
+// ギルドのEXPキャッシュのフラッシュに関連する定数
+#define GUILD_PAYEXP_INVERVAL 10000 // 間隔(キャッシュの最大生存時間、ミリ秒)
+#define GUILD_PAYEXP_LIST 8192  // キャッシュの最大数
+
+// ギルドのEXPキャッシュ
+struct guild_expcache
+{
+    int  guild_id, account_id, char_id, exp;
+};
+
+// ギルドスキルdbのアクセサ(今は直打ちで代用)
+int guild_skill_get_inf (int id)
+{
+    return 0;
+}
+
+int guild_skill_get_sp (int id, int lv)
+{
+    return 0;
+}
+
+int guild_skill_get_range (int id)
+{
+    return 0;
+}
+
+int guild_skill_get_max (int id)
+{
+    return (id == 10004) ? 10 : 1;
+}
+
+// ギルドスキルがあるか確認
+int guild_checkskill (struct guild *g, int id)
+{
+    return g->skill[id - 10000].lv;
+}
+
+void guild_payexp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
+void guild_gvg_eliminate_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
+
+static int guild_read_castledb (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  j, ln = 0;
+    char *str[32], *p;
+    struct guild_castle *gc;
+
+    if ((fp = fopen_ ("db/castle_db.txt", "r")) == NULL)
+    {
+        printf ("can't read db/castle_db.txt\n");
+        return -1;
+    }
+
+    while (fgets (line, 1020, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        memset (str, 0, sizeof (str));
+        CREATE (gc, struct guild_castle, 1);
+        for (j = 0, p = line; j < 6 && p; j++)
+        {
+            str[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+
+        gc->guild_id = 0;       // <Agit> Clear Data for Initialize
+        gc->economy = 0;
+        gc->defense = 0;
+        gc->triggerE = 0;
+        gc->triggerD = 0;
+        gc->nextTime = 0;
+        gc->payTime = 0;
+        gc->createTime = 0;
+        gc->visibleC = 0;
+        gc->visibleG0 = 0;
+        gc->visibleG1 = 0;
+        gc->visibleG2 = 0;
+        gc->visibleG3 = 0;
+        gc->visibleG4 = 0;
+        gc->visibleG5 = 0;
+        gc->visibleG6 = 0;
+        gc->visibleG7 = 0;
+        gc->Ghp0 = 0;
+        gc->Ghp1 = 0;
+        gc->Ghp2 = 0;
+        gc->Ghp3 = 0;
+        gc->Ghp4 = 0;
+        gc->Ghp5 = 0;
+        gc->Ghp6 = 0;
+        gc->Ghp7 = 0;           // guardian HP [Valaris]
+
+        gc->castle_id = atoi (str[0]);
+        memcpy (gc->map_name, str[1], 24);
+        memcpy (gc->castle_name, str[2], 24);
+        memcpy (gc->castle_event, str[3], 24);
+
+        numdb_insert (castle_db, gc->castle_id, gc);
+
+        //intif_guild_castle_info(gc->castle_id);
+
+        ln++;
+    }
+    fclose_ (fp);
+    printf ("read db/castle_db.txt done (count=%d)\n", ln);
+    return 0;
+}
+
+// 初期化
+void do_init_guild (void)
+{
+    guild_db = numdb_init ();
+    castle_db = numdb_init ();
+    guild_expcache_db = numdb_init ();
+    guild_infoevent_db = numdb_init ();
+    guild_castleinfoevent_db = numdb_init ();
+
+    guild_read_castledb ();
+
+    add_timer_interval (gettick () + GUILD_PAYEXP_INVERVAL,
+                        guild_payexp_timer, 0, 0, GUILD_PAYEXP_INVERVAL);
+}
+
+// 検索
+struct guild *guild_search (int guild_id)
+{
+    return (struct guild *)numdb_search (guild_db, guild_id);
+}
+
+void guild_searchname_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild *g = (struct guild *) data, **dst;
+    char *str;
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct guild **);
+    if (strcasecmp (g->name, str) == 0)
+        *dst = g;
+}
+
+// ギルド名検索
+struct guild *guild_searchname (char *str)
+{
+    struct guild *g = NULL;
+    numdb_foreach (guild_db, guild_searchname_sub, str, &g);
+    return g;
+}
+
+struct guild_castle *guild_castle_search (int gcid)
+{
+    return (struct guild_castle *)numdb_search (castle_db, gcid);
+}
+
+// mapnameに対応したアジトのgcを返す
+struct guild_castle *guild_mapname2gc (char *mapname)
+{
+    int  i;
+    struct guild_castle *gc = NULL;
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        gc = guild_castle_search (i);
+        if (!gc)
+            continue;
+        if (strcmp (gc->map_name, mapname) == 0)
+            return gc;
+    }
+    return NULL;
+}
+
+// ログイン中のギルドメンバーの1人のsdを返す
+struct map_session_data *guild_getavailablesd (struct guild *g)
+{
+    int  i;
+
+    nullpo_retr (NULL, g);
+
+    for (i = 0; i < g->max_member; i++)
+        if (g->member[i].sd != NULL)
+            return g->member[i].sd;
+    return NULL;
+}
+
+// ギルドメンバーのインデックスを返す
+int guild_getindex (struct guild *g, int account_id, int char_id)
+{
+    int  i;
+    if (g == NULL)
+        return -1;
+    for (i = 0; i < g->max_member; i++)
+        if (g->member[i].account_id == account_id)
+            return i;
+    return -1;
+}
+
+// ギルドメンバーの役職を返す
+int guild_getposition (struct map_session_data *sd, struct guild *g)
+{
+    int  i;
+
+    nullpo_retr (-1, sd);
+
+    if (g == NULL && (g = guild_search (sd->status.guild_id)) == NULL)
+        return -1;
+    for (i = 0; i < g->max_member; i++)
+        if (g->member[i].account_id == sd->status.account_id)
+            return g->member[i].position;
+    return -1;
+}
+
+// メンバー情報の作成
+void guild_makemember (struct guild_member *m, struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    memset (m, 0, sizeof (struct guild_member));
+    m->account_id = sd->status.account_id;
+    m->char_id = 0;
+    m->hair = sd->status.hair;
+    m->hair_color = sd->status.hair_color;
+    m->gender = sd->sex;
+    m->pc_class = sd->status.pc_class;
+    m->lv = sd->status.base_level;
+    m->exp = 0;
+    m->exp_payper = 0;
+    m->online = 1;
+    m->position = MAX_GUILDPOSITION - 1;
+    memcpy (m->name, sd->status.name, 24);
+    return;
+}
+
+// ギルド競合確認
+int guild_check_conflict (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    intif_guild_checkconflict (sd->status.guild_id,
+                               sd->status.account_id, 0 /*char_id*/);
+    return 0;
+}
+
+// ギルドのEXPキャッシュをinter鯖にフラッシュする
+void guild_payexp_timer_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    int  i, *dellist, *delp, dataid = key.i;
+    struct guild_expcache *c;
+    struct guild *g;
+
+    nullpo_retv (ap);
+    nullpo_retv (c = (struct guild_expcache *) data);
+    nullpo_retv (dellist = va_arg (ap, int *));
+    nullpo_retv (delp = va_arg (ap, int *));
+
+    if (*delp >= GUILD_PAYEXP_LIST
+        || (g = guild_search (c->guild_id)) == NULL)
+        return;
+    if ((i = guild_getindex (g, c->account_id, 0 /*c->char_id*/)) < 0)
+        return;
+
+    g->member[i].exp += c->exp;
+    intif_guild_change_memberinfo (g->guild_id, c->account_id, 0 /*char_id*/,
+                                   GMI_EXP, &g->member[i].exp,
+                                   sizeof (g->member[i].exp));
+    c->exp = 0;
+
+    dellist[(*delp)++] = dataid;
+    free (c);
+}
+
+void guild_payexp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  dellist[GUILD_PAYEXP_LIST], delp = 0, i;
+    numdb_foreach (guild_expcache_db, guild_payexp_timer_sub, dellist, &delp);
+    for (i = 0; i < delp; i++)
+        numdb_erase (guild_expcache_db, dellist[i]);
+//  if(battle_config.etc_log)
+//      printf("guild exp %d charactor's exp flushed !\n",delp);
+}
+
+//------------------------------------------------------------------------
+
+/* Process a guild creation request. */
+int guild_create (struct map_session_data *sd, char *name)
+{
+    char pname[24];
+
+    nullpo_retr (0, sd);
+
+    strncpy (pname, name, 24);
+    pname[23] = '\0';
+    tmw_TrimStr (pname);
+
+    /* The guild name is empty/invalid. */
+    if (!*pname)
+        clif_guild_created (sd, 2);
+
+    /* Make sure the character isn't already in a guild. */
+    if (sd->status.guild_id == 0)
+    {
+        /*
+         * A special item is required to create a guild. This is specified
+         * in battle_athena.conf as guild_emperium_check. This item will
+         * be removed from the player's inventory when used to create a
+         * guild.
+         */
+        if (!battle_config.guild_emperium_check
+            || pc_search_inventory (sd,
+                                    battle_config.guild_emperium_check) >= 0)
+        {
+            struct guild_member m;
+            guild_makemember (&m, sd);
+            m.position = 0;
+            intif_guild_create (pname, &m);
+        }
+        else
+            clif_guild_created (sd, 3);
+    }
+    else
+        clif_guild_created (sd, 1);
+
+    return 0;
+}
+
+/* Relay the result of a guild creation request. */
+int guild_created (int account_id, int guild_id)
+{
+    struct map_session_data *sd = map_id2sd (account_id);
+
+    if (!sd)
+        return 0;
+
+    /* The guild name is valid and not already taken. */
+    if (guild_id > 0)
+    {
+        struct guild *g;
+        sd->status.guild_id = guild_id;
+        sd->guild_sended = 0;
+
+        if ((g = (struct guild *)numdb_search (guild_db, guild_id)) != NULL)
+        {
+            printf ("guild_created(): ID already exists!\n");
+            exit (1);
+        }
+
+        /* The guild was created successfully. */
+        clif_guild_created (sd, 0);
+
+        if (battle_config.guild_emperium_check)
+            pc_delitem (sd,
+                        pc_search_inventory (sd,
+                                             battle_config.
+                                             guild_emperium_check), 1, 0);
+    }
+    else
+        clif_guild_created (sd, 2);
+
+    return 0;
+}
+
+// 情報要求
+int guild_request_info (int guild_id)
+{
+//  if(battle_config.etc_log)
+//      printf("guild_request_info\n");
+    return intif_guild_request_info (guild_id);
+}
+
+// イベント付き情報要求
+int guild_npc_request_info (int guild_id, const char *event)
+{
+    struct eventlist *ev;
+
+    if (guild_search (guild_id))
+    {
+        if (event && *event)
+            npc_event_do (event);
+        return 0;
+    }
+
+    if (event == NULL || *event == 0)
+        return guild_request_info (guild_id);
+
+    CREATE (ev, struct eventlist, 1);
+    memcpy (ev->name, event, sizeof (ev->name));
+    ev->next =
+        (struct eventlist *) numdb_search (guild_infoevent_db, guild_id);
+    numdb_insert (guild_infoevent_db, guild_id, ev);
+    return guild_request_info (guild_id);
+}
+
+// 所属キャラの確認
+int guild_check_member (const struct guild *g)
+{
+    int  i;
+    struct map_session_data *sd;
+
+    nullpo_retr (0, g);
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
+        {
+            if (sd->status.guild_id == g->guild_id)
+            {
+                int  j, f = 1;
+                for (j = 0; j < MAX_GUILD; j++)
+                {               // データがあるか
+                    if (g->member[j].account_id == sd->status.account_id)
+                        f = 0;
+                }
+                if (f)
+                {
+                    sd->status.guild_id = 0;
+                    sd->guild_sended = 0;
+                    sd->guild_emblem_id = 0;
+                    if (battle_config.error_log)
+                        printf ("guild: check_member %d[%s] is not member\n",
+                                sd->status.account_id, sd->status.name);
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+// 情報所得失敗(そのIDのキャラを全部未所属にする)
+int guild_recv_noinfo (int guild_id)
+{
+    int  i;
+    struct map_session_data *sd;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
+        {
+            if (sd->status.guild_id == guild_id)
+                sd->status.guild_id = 0;
+        }
+    }
+    return 0;
+}
+
+// 情報所得
+int guild_recv_info (struct guild *sg)
+{
+    struct guild *g, before;
+    int  i, bm, m;
+    struct eventlist *ev, *ev2;
+
+    nullpo_retr (0, sg);
+
+    if ((g = (struct guild *)numdb_search (guild_db, sg->guild_id)) == NULL)
+    {
+        CREATE (g, struct guild, 1);
+        numdb_insert (guild_db, sg->guild_id, g);
+        before = *sg;
+
+        // 最初のロードなのでユーザーのチェックを行う
+        guild_check_member (sg);
+    }
+    else
+        before = *g;
+    memcpy (g, sg, sizeof (struct guild));
+
+    for (i = bm = m = 0; i < g->max_member; i++)
+    {                           // sdの設定と人数の確認
+        if (g->member[i].account_id > 0)
+        {
+            struct map_session_data *sd = map_id2sd (g->member[i].account_id);
+            g->member[i].sd = (sd != NULL &&
+                               sd->status.guild_id ==
+                               g->guild_id) ? sd : NULL;
+            m++;
+        }
+        else
+            g->member[i].sd = NULL;
+        if (before.member[i].account_id > 0)
+            bm++;
+    }
+
+    for (i = 0; i < g->max_member; i++)
+    {                           // 情報の送信
+        struct map_session_data *sd = g->member[i].sd;
+        if (sd == NULL)
+            continue;
+
+        if (before.guild_lv != g->guild_lv || bm != m ||
+            before.max_member != g->max_member)
+        {
+            clif_guild_basicinfo (sd);  // 基本情報送信
+            clif_guild_emblem (sd, g);  // エンブレム送信
+        }
+
+        if (bm != m)
+        {                       // メンバー情報送信
+            clif_guild_memberlist (g->member[i].sd);
+        }
+
+        if (before.skill_point != g->skill_point)
+            clif_guild_skillinfo (sd);  // スキル情報送信
+
+        if (sd->guild_sended == 0)
+        {                       // 未送信なら所属情報も送る
+            clif_guild_belonginfo (sd, g);
+            clif_guild_notice (sd, g);
+            sd->guild_emblem_id = g->emblem_id;
+            sd->guild_sended = 1;
+        }
+    }
+
+    // イベントの発生
+    if ((ev = (struct eventlist *)numdb_search (guild_infoevent_db, sg->guild_id)) != NULL)
+    {
+        numdb_erase (guild_infoevent_db, sg->guild_id);
+        for (; ev; ev2 = ev->next, free (ev), ev = ev2)
+        {
+            npc_event_do (ev->name);
+        }
+    }
+
+    return 0;
+}
+
+// ギルドへの勧誘
+int guild_invite (struct map_session_data *sd, int account_id)
+{
+    struct map_session_data *tsd;
+    struct guild *g;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    tsd = map_id2sd (account_id);
+    g = guild_search (sd->status.guild_id);
+
+    if (tsd == NULL || g == NULL)
+        return 0;
+    if (!battle_config.invite_request_check)
+    {
+        if (tsd->party_invite > 0 || tsd->trade_partner)
+        {                       // 相手が取引中かどうか
+            clif_guild_inviteack (sd, 0);
+            return 0;
+        }
+    }
+    if (tsd->status.guild_id > 0 || tsd->guild_invite > 0)
+    {                           // 相手の所属確認
+        clif_guild_inviteack (sd, 0);
+        return 0;
+    }
+
+    // 定員確認
+    for (i = 0; i < g->max_member; i++)
+        if (g->member[i].account_id == 0)
+            break;
+    if (i == g->max_member)
+    {
+        clif_guild_inviteack (sd, 3);
+        return 0;
+    }
+
+    tsd->guild_invite = sd->status.guild_id;
+    tsd->guild_invite_account = sd->status.account_id;
+
+    clif_guild_invite (tsd, g);
+    return 0;
+}
+
+// ギルド勧誘への返答
+int guild_reply_invite (struct map_session_data *sd, int guild_id, int flag)
+{
+    struct map_session_data *tsd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, tsd = map_id2sd (sd->guild_invite_account));
+
+    if (sd->guild_invite != guild_id)   // 勧誘とギルドIDが違う
+        return 0;
+
+    if (flag == 1)
+    {                           // 承諾
+        struct guild_member m;
+        struct guild *g;
+        int  i;
+
+        // 定員確認
+        if ((g = guild_search (tsd->status.guild_id)) == NULL)
+        {
+            sd->guild_invite = 0;
+            sd->guild_invite_account = 0;
+            return 0;
+        }
+        for (i = 0; i < g->max_member; i++)
+            if (g->member[i].account_id == 0)
+                break;
+        if (i == g->max_member)
+        {
+            sd->guild_invite = 0;
+            sd->guild_invite_account = 0;
+            clif_guild_inviteack (tsd, 3);
+            return 0;
+        }
+
+        //inter鯖へ追加要求
+        guild_makemember (&m, sd);
+        intif_guild_addmember (sd->guild_invite, &m);
+        return 0;
+    }
+    else
+    {                           // 拒否
+        sd->guild_invite = 0;
+        sd->guild_invite_account = 0;
+        if (tsd == NULL)
+            return 0;
+        clif_guild_inviteack (tsd, 1);
+    }
+    return 0;
+}
+
+// ギルドメンバが追加された
+int guild_member_added (int guild_id, int account_id, int char_id, int flag)
+{
+    struct map_session_data *sd = map_id2sd (account_id), *sd2;
+    struct guild *g;
+
+    if ((g = guild_search (guild_id)) == NULL)
+        return 0;
+
+    if ((sd == NULL || sd->guild_invite == 0) && flag == 0)
+    {
+        // キャラ側に登録できなかったため脱退要求を出す
+        if (battle_config.error_log)
+            printf ("guild: member added error %d is not online\n",
+                    account_id);
+        intif_guild_leave (guild_id, account_id, 0 /*char_id*/, 0, "**登録失敗**");
+        return 0;
+    }
+    sd->guild_invite = 0;
+    sd->guild_invite_account = 0;
+
+    sd2 = map_id2sd (sd->guild_invite_account);
+
+    if (flag == 1)
+    {                           // 失敗
+        if (sd2 != NULL)
+            clif_guild_inviteack (sd2, 3);
+        return 0;
+    }
+
+    // 成功
+    sd->guild_sended = 0;
+    sd->status.guild_id = guild_id;
+
+    if (sd2 != NULL)
+        clif_guild_inviteack (sd2, 2);
+
+    // いちおう競合確認
+    guild_check_conflict (sd);
+
+    return 0;
+}
+
+// ギルド脱退要求
+int guild_leave (struct map_session_data *sd, int guild_id,
+                 int account_id, int char_id, const char *mes)
+{
+    struct guild *g;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return 0;
+
+    if (sd->status.account_id != account_id ||
+        sd->status.guild_id != guild_id)
+        return 0;
+
+    for (i = 0; i < g->max_member; i++)
+    {                           // 所属しているか
+        if (g->member[i].account_id == sd->status.account_id)
+        {
+            intif_guild_leave (g->guild_id, sd->status.account_id,
+                               sd->status.char_id, 0, mes);
+            return 0;
+        }
+    }
+    return 0;
+}
+
+// ギルド追放要求
+int guild_explusion (struct map_session_data *sd, int guild_id,
+                     int account_id, int char_id, const char *mes)
+{
+    struct guild *g;
+    int  i, ps;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return 0;
+
+    if (sd->status.guild_id != guild_id)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || !(g->position[ps].mode & 0x0010))
+        return 0;               // 処罰権限無し
+
+    for (i = 0; i < g->max_member; i++)
+    {                           // 所属しているか
+        if (g->member[i].account_id == account_id)
+        {
+            intif_guild_leave (g->guild_id, account_id, 0 /*char_id*/, 1, mes);
+            return 0;
+        }
+    }
+    return 0;
+}
+
+// ギルドメンバが脱退した
+int guild_member_leaved (int guild_id, int account_id, int char_id, int flag,
+                         const char *name, const char *mes)
+{
+    struct map_session_data *sd = map_id2sd (account_id);
+    struct guild *g = guild_search (guild_id);
+    int  i;
+
+    if (g != NULL)
+    {
+        int  i;
+        for (i = 0; i < g->max_member; i++)
+            if (g->member[i].account_id == account_id)
+            {
+                struct map_session_data *sd2 = sd;
+                if (sd2 == NULL)
+                    sd2 = guild_getavailablesd (g);
+                else
+                {
+                    if (flag == 0)
+                        clif_guild_leave (sd2, name, mes);
+                    else
+                        clif_guild_explusion (sd2, name, mes, account_id);
+                }
+                g->member[i].account_id = 0;
+                g->member[i].sd = NULL;
+            }
+    }
+    if (sd != NULL && sd->status.guild_id == guild_id)
+    {
+        if (sd->state.storage_flag == 2)    //Close the guild storage.
+            storage_guild_storageclose (sd);
+        sd->status.guild_id = 0;
+        sd->guild_emblem_id = 0;
+        sd->guild_sended = 0;
+    }
+
+    // メンバーリストを全員に再通知
+    for (i = 0; i < g->max_member; i++)
+    {
+        if (g->member[i].sd != NULL)
+            clif_guild_memberlist (g->member[i].sd);
+    }
+
+    return 0;
+}
+
+// ギルドメンバのオンライン状態/Lv更新送信
+int guild_send_memberinfoshort (struct map_session_data *sd, int online)
+{
+    struct guild *g;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.guild_id <= 0)
+        return 0;
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL)
+        return 0;
+
+    intif_guild_memberinfoshort (g->guild_id,
+                                 sd->status.account_id, 0 /*char_id*/,
+                                 online, sd->status.base_level,
+                                 sd->status.pc_class);
+
+    if (!online)
+    {                           // ログアウトするならsdをクリアして終了
+        int  i =
+            guild_getindex (g, sd->status.account_id, 0 /*char_id*/);
+        if (i >= 0)
+            g->member[i].sd = NULL;
+        return 0;
+    }
+
+    if (sd->guild_sended != 0)  // ギルド初期送信データは送信済み
+        return 0;
+
+    // 競合確認
+    guild_check_conflict (sd);
+
+    // あるならギルド初期送信データ送信
+    if ((g = guild_search (sd->status.guild_id)) != NULL)
+    {
+        guild_check_member (g); // 所属を確認する
+        if (sd->status.guild_id == g->guild_id)
+        {
+            clif_guild_belonginfo (sd, g);
+            clif_guild_notice (sd, g);
+            sd->guild_sended = 1;
+            sd->guild_emblem_id = g->emblem_id;
+        }
+    }
+    return 0;
+}
+
+// ギルドメンバのオンライン状態/Lv更新通知
+int guild_recv_memberinfoshort (int guild_id, int account_id, int char_id,
+                                int online, int lv, int pc_class)
+{
+    int  i, alv, c, idx = 0, om = 0, oldonline = -1;
+    struct guild *g = guild_search (guild_id);
+    if (g == NULL)
+        return 0;
+    for (i = 0, alv = 0, c = 0, om = 0; i < g->max_member; i++)
+    {
+        struct guild_member *m = &g->member[i];
+        if (m->account_id == account_id)
+        {
+            oldonline = m->online;
+            m->online = online;
+            m->lv = lv;
+            m->pc_class = pc_class;
+            idx = i;
+        }
+        if (m->account_id > 0)
+        {
+            alv += m->lv;
+            c++;
+        }
+        if (m->online)
+            om++;
+    }
+    if (idx == g->max_member)
+    {
+        if (battle_config.error_log)
+            printf ("guild: not found member %d,%d on %d[%s]\n", account_id,
+                    char_id, guild_id, g->name);
+        return 0;
+    }
+    g->average_lv = alv / c;
+    g->connect_member = om;
+
+    if (oldonline != online)    // オンライン状態が変わったので通知
+        clif_guild_memberlogin_notice (g, idx, online);
+
+    for (i = 0; i < g->max_member; i++)
+    {                           // sd再設定
+        struct map_session_data *sd = map_id2sd (g->member[i].account_id);
+        g->member[i].sd = (sd != NULL &&
+                           sd->status.guild_id == guild_id) ? sd : NULL;
+    }
+
+    // ここにクライアントに送信処理が必要
+
+    return 0;
+}
+
+// ギルド会話送信
+int guild_send_message (struct map_session_data *sd, char *mes, int len)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->status.guild_id == 0)
+        return 0;
+    intif_guild_message (sd->status.guild_id, sd->status.account_id, mes,
+                         len);
+    return 0;
+}
+
+// ギルド会話受信
+int guild_recv_message (int guild_id, int account_id, char *mes, int len)
+{
+    struct guild *g;
+    if ((g = guild_search (guild_id)) == NULL)
+        return 0;
+    clif_guild_message (g, account_id, mes, len);
+    return 0;
+}
+
+// ギルドメンバの役職変更
+int guild_change_memberposition (int guild_id, int account_id, int char_id,
+                                 int idx)
+{
+    return intif_guild_change_memberinfo (guild_id, account_id, 0 /*char_id*/,
+                                          GMI_POSITION, &idx, sizeof (idx));
+}
+
+// ギルドメンバの役職変更通知
+int guild_memberposition_changed (struct guild *g, int idx, int pos)
+{
+    nullpo_retr (0, g);
+
+    g->member[idx].position = pos;
+    clif_guild_memberpositionchanged (g, idx);
+    return 0;
+}
+
+// ギルド役職変更
+int guild_change_position (struct map_session_data *sd, int idx,
+                           int mode, int exp_mode, const char *name)
+{
+    struct guild_position p;
+
+    nullpo_retr (0, sd);
+
+    if (exp_mode > battle_config.guild_exp_limit)
+        exp_mode = battle_config.guild_exp_limit;
+    if (exp_mode < 0)
+        exp_mode = 0;
+    p.mode = mode;
+    p.exp_mode = exp_mode;
+    memcpy (p.name, name, 24);
+    return intif_guild_position (sd->status.guild_id, idx, &p);
+}
+
+// ギルド役職変更通知
+int guild_position_changed (int guild_id, int idx, struct guild_position *p)
+{
+    struct guild *g = guild_search (guild_id);
+    if (g == NULL)
+        return 0;
+    memcpy (&g->position[idx], p, sizeof (struct guild_position));
+    clif_guild_positionchanged (g, idx);
+    return 0;
+}
+
+// ギルド告知変更
+int guild_change_notice (struct map_session_data *sd, int guild_id,
+                         const char *mes1, const char *mes2)
+{
+    struct guild *g;
+    int  ps;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || !(g->position[ps].mode & 0x0010))
+        return 0;
+
+    if (guild_id != sd->status.guild_id)
+        return 0;
+
+    return intif_guild_notice (guild_id, mes1, mes2);
+}
+
+// ギルド告知変更通知
+int guild_notice_changed (int guild_id, const char *mes1, const char *mes2)
+{
+    int  i;
+    struct map_session_data *sd;
+    struct guild *g = guild_search (guild_id);
+    if (g == NULL)
+        return 0;
+
+    memcpy (g->mes1, mes1, 60);
+    memcpy (g->mes2, mes2, 120);
+
+    for (i = 0; i < g->max_member; i++)
+    {
+        if ((sd = g->member[i].sd) != NULL)
+            clif_guild_notice (sd, g);
+    }
+    return 0;
+}
+
+// ギルドエンブレム変更
+int guild_change_emblem (struct map_session_data *sd, int len,
+                         const char *data)
+{
+    struct guild *g;
+    int  ps;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || !(g->position[ps].mode & 0x0010))
+        return 0;
+
+    return intif_guild_emblem (sd->status.guild_id, len, data);
+}
+
+// ギルドエンブレム変更通知
+int guild_emblem_changed (int len, int guild_id, int emblem_id,
+                          const char *data)
+{
+    int  i;
+    struct map_session_data *sd;
+    struct guild *g = guild_search (guild_id);
+    if (g == NULL)
+        return 0;
+
+    memcpy (g->emblem_data, data, len);
+    g->emblem_len = len;
+    g->emblem_id = emblem_id;
+
+    for (i = 0; i < g->max_member; i++)
+    {
+        if ((sd = g->member[i].sd) != NULL)
+        {
+            sd->guild_emblem_id = emblem_id;
+            clif_guild_belonginfo (sd, g);
+            clif_guild_emblem (sd, g);
+        }
+    }
+    return 0;
+}
+
+// ギルドのEXP上納
+int guild_payexp (struct map_session_data *sd, int exp)
+{
+    struct guild *g;
+    struct guild_expcache *c;
+    int  per, exp2;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.guild_id == 0
+        || (g = guild_search (sd->status.guild_id)) == NULL)
+        return 0;
+    if ((per = g->position[guild_getposition (sd, g)].exp_mode) <= 0)
+        return 0;
+    if (per > 100)
+        per = 100;
+
+    if ((exp2 = exp * per / 100) <= 0)
+        return 0;
+
+    if ((c = (struct guild_expcache *)numdb_search (guild_expcache_db, sd->status.account_id /*char_id*/)) == NULL)
+    {
+        CREATE (c, struct guild_expcache, 1);
+        c->guild_id = sd->status.guild_id;
+        c->account_id = sd->status.account_id;
+        c->char_id = 0;
+        c->exp = exp2;
+        numdb_insert (guild_expcache_db, c->account_id /*char_id*/, c);
+    }
+    else
+    {
+        c->exp += exp2;
+    }
+    return exp2;
+}
+
+// スキルポイント割り振り
+int guild_skillup (struct map_session_data *sd, int skill_num)
+{
+    struct guild *g;
+    int  idx;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.guild_id == 0
+        || (g = guild_search (sd->status.guild_id)) == NULL)
+        return 0;
+    if (strcmp (sd->status.name, g->master))
+        return 0;
+
+    if (g->skill_point > 0 &&
+        g->skill[(idx = skill_num - 10000)].id != 0 &&
+        g->skill[idx].lv < guild_skill_get_max (skill_num))
+    {
+        intif_guild_skillup (g->guild_id, skill_num, sd->status.account_id);
+    }
+    return 0;
+}
+
+// スキルポイント割り振り通知
+int guild_skillupack (int guild_id, int skill_num, int account_id)
+{
+    struct map_session_data *sd = map_id2sd (account_id);
+    struct guild *g = guild_search (guild_id);
+    int  i;
+    if (g == NULL)
+        return 0;
+    if (sd != NULL)
+        clif_guild_skillup (sd, skill_num, g->skill[skill_num - 10000].lv);
+    // 全員に通知
+    for (i = 0; i < g->max_member; i++)
+        if ((sd = g->member[i].sd) != NULL)
+            clif_guild_skillinfo (sd);
+    return 0;
+}
+
+// ギルド同盟数所得
+int guild_get_alliance_count (struct guild *g, int flag)
+{
+    int  i, c;
+
+    nullpo_retr (0, g);
+
+    for (i = c = 0; i < MAX_GUILDALLIANCE; i++)
+    {
+        if (g->alliance[i].guild_id > 0 && g->alliance[i].opposition == flag)
+            c++;
+    }
+    return c;
+}
+
+// ギルド同盟要求
+int guild_reqalliance (struct map_session_data *sd, int account_id)
+{
+    struct map_session_data *tsd = map_id2sd (account_id);
+    struct guild *g[2];
+    int  i, ps;
+
+    if (agit_flag)
+    {                           // Disable alliance creation during woe [Valaris]
+        clif_displaymessage (sd->fd,
+                             "Alliances cannot be made during Guild Wars!");
+        return 0;
+    }                           // end addition [Valaris]
+
+    nullpo_retr (0, sd);
+
+    if (tsd == NULL || tsd->status.guild_id <= 0)
+        return 0;
+
+    g[0] = guild_search (sd->status.guild_id);
+    g[1] = guild_search (tsd->status.guild_id);
+
+    if (g[0] == NULL || g[1] == NULL)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g[0])) < 0
+        || !(g[0]->position[ps].mode & 0x0010))
+        return 0;
+
+    if (guild_get_alliance_count (g[0], 0) > 3) // 同盟数確認
+        clif_guild_allianceack (sd, 4);
+    if (guild_get_alliance_count (g[1], 0) > 3)
+        clif_guild_allianceack (sd, 3);
+
+    if (tsd->guild_alliance > 0)
+    {                           // 相手が同盟要請状態かどうか確認
+        clif_guild_allianceack (sd, 1);
+        return 0;
+    }
+
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+    {                           // すでに同盟状態か確認
+        if (g[0]->alliance[i].guild_id == tsd->status.guild_id &&
+            g[0]->alliance[i].opposition == 0)
+        {
+            clif_guild_allianceack (sd, 0);
+            return 0;
+        }
+    }
+
+    tsd->guild_alliance = sd->status.guild_id;
+    tsd->guild_alliance_account = sd->status.account_id;
+
+    clif_guild_reqalliance (tsd, sd->status.account_id, g[0]->name);
+    return 0;
+}
+
+// ギルド勧誘への返答
+int guild_reply_reqalliance (struct map_session_data *sd, int account_id,
+                             int flag)
+{
+    struct map_session_data *tsd;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, tsd = map_id2sd (account_id));
+
+    if (sd->guild_alliance != tsd->status.guild_id) // 勧誘とギルドIDが違う
+        return 0;
+
+    if (flag == 1)
+    {                           // 承諾
+        int  i;
+
+        struct guild *g;        // 同盟数再確認
+        if ((g = guild_search (sd->status.guild_id)) == NULL ||
+            guild_get_alliance_count (g, 0) > 3)
+        {
+            clif_guild_allianceack (sd, 4);
+            clif_guild_allianceack (tsd, 3);
+            return 0;
+        }
+        if ((g = guild_search (tsd->status.guild_id)) == NULL ||
+            guild_get_alliance_count (g, 0) > 3)
+        {
+            clif_guild_allianceack (sd, 3);
+            clif_guild_allianceack (tsd, 4);
+            return 0;
+        }
+
+        // 敵対関係なら敵対を止める
+        if ((g = guild_search (sd->status.guild_id)) == NULL)
+            return 0;
+        for (i = 0; i < MAX_GUILDALLIANCE; i++)
+        {
+            if (g->alliance[i].guild_id == tsd->status.guild_id &&
+                g->alliance[i].opposition == 1)
+                intif_guild_alliance (sd->status.guild_id,
+                                      tsd->status.guild_id,
+                                      sd->status.account_id,
+                                      tsd->status.account_id, 9);
+        }
+        if ((g = guild_search (tsd->status.guild_id)) == NULL)
+            return 0;
+        for (i = 0; i < MAX_GUILDALLIANCE; i++)
+        {
+            if (g->alliance[i].guild_id == sd->status.guild_id &&
+                g->alliance[i].opposition == 1)
+                intif_guild_alliance (tsd->status.guild_id,
+                                      sd->status.guild_id,
+                                      tsd->status.account_id,
+                                      sd->status.account_id, 9);
+        }
+
+        // inter鯖へ同盟要請
+        intif_guild_alliance (sd->status.guild_id, tsd->status.guild_id,
+                              sd->status.account_id, tsd->status.account_id,
+                              0);
+        return 0;
+    }
+    else
+    {                           // 拒否
+        sd->guild_alliance = 0;
+        sd->guild_alliance_account = 0;
+        if (tsd != NULL)
+            clif_guild_allianceack (tsd, 3);
+    }
+    return 0;
+}
+
+// ギルド関係解消
+int guild_delalliance (struct map_session_data *sd, int guild_id, int flag)
+{
+    if (agit_flag)
+    {                           // Disable alliance breaking during woe [Valaris]
+        clif_displaymessage (sd->fd,
+                             "Alliances cannot be broken during Guild Wars!");
+        return 0;
+    }                           // end addition [Valaris]
+
+    struct guild *g;
+    int  ps;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+
+    if (g == NULL)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || !(g->position[ps].mode & 0x0010))
+        return 0;
+
+    intif_guild_alliance (sd->status.guild_id, guild_id,
+                          sd->status.account_id, 0, flag | 8);
+    return 0;
+}
+
+// ギルド敵対
+int guild_opposition (struct map_session_data *sd, int account_id /*char_id*/)
+{
+    struct map_session_data *tsd = map_id2sd (account_id /*char_id*/);
+    struct guild *g;
+    int  i, ps;
+
+    nullpo_retr (0, sd);
+
+    g = guild_search (sd->status.guild_id);
+    if (g == NULL || tsd == NULL)
+        return 0;
+
+    if ((ps = guild_getposition (sd, g)) < 0
+        || !(g->position[ps].mode & 0x0010))
+        return 0;
+
+    if (guild_get_alliance_count (g, 1) > 3)    // 敵対数確認
+        clif_guild_oppositionack (sd, 1);
+
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+    {                           // すでに関係を持っているか確認
+        if (g->alliance[i].guild_id == tsd->status.guild_id)
+        {
+            if (g->alliance[i].opposition == 1)
+            {                   // すでに敵対
+                clif_guild_oppositionack (sd, 2);
+                return 0;
+            }
+            else                // 同盟破棄
+                intif_guild_alliance (sd->status.guild_id,
+                                      tsd->status.guild_id,
+                                      sd->status.account_id,
+                                      tsd->status.account_id, 8);
+        }
+    }
+
+    // inter鯖に敵対要請
+    intif_guild_alliance (sd->status.guild_id, tsd->status.guild_id,
+                          sd->status.account_id, tsd->status.account_id, 1);
+    return 0;
+}
+
+// ギルド同盟/敵対通知
+int guild_allianceack (int guild_id1, int guild_id2, int account_id1,
+                       int account_id2, int flag, const char *name1,
+                       const char *name2)
+{
+    struct guild *g[2];
+    int  guild_id[2] = { guild_id1, guild_id2 };
+    const char *guild_name[2] = { name1, name2 };
+    struct map_session_data *sd[2] =
+        { map_id2sd (account_id1), map_id2sd (account_id2) };
+    int  j, i;
+
+    g[0] = guild_search (guild_id1);
+    g[1] = guild_search (guild_id2);
+
+    if (sd[0] != NULL && (flag & 0x0f) == 0)
+    {
+        sd[0]->guild_alliance = 0;
+        sd[0]->guild_alliance_account = 0;
+    }
+
+    if (flag & 0x70)
+    {                           // 失敗
+        for (i = 0; i < 2 - (flag & 1); i++)
+            if (sd[i] != NULL)
+                clif_guild_allianceack (sd[i],
+                                        ((flag >> 4) == i + 1) ? 3 : 4);
+        return 0;
+    }
+//  if(battle_config.etc_log)
+//      printf("guild alliance_ack %d %d %d %d %d %s %s\n",guild_id1,guild_id2,account_id1,account_id2,flag,name1,name2);
+
+    if (!(flag & 0x08))
+    {                           // 関係追加
+        for (i = 0; i < 2 - (flag & 1); i++)
+            if (g[i] != NULL)
+                for (j = 0; j < MAX_GUILDALLIANCE; j++)
+                    if (g[i]->alliance[j].guild_id == 0)
+                    {
+                        g[i]->alliance[j].guild_id = guild_id[1 - i];
+                        memcpy (g[i]->alliance[j].name, guild_name[1 - i],
+                                24);
+                        g[i]->alliance[j].opposition = flag & 1;
+                        break;
+                    }
+    }
+    else
+    {                           // 関係解消
+        for (i = 0; i < 2 - (flag & 1); i++)
+        {
+            if (g[i] != NULL)
+                for (j = 0; j < MAX_GUILDALLIANCE; j++)
+                    if (g[i]->alliance[j].guild_id == guild_id[1 - i] &&
+                        g[i]->alliance[j].opposition == (flag & 1))
+                    {
+                        g[i]->alliance[j].guild_id = 0;
+                        break;
+                    }
+            if (sd[i] != NULL)  // 解消通知
+                clif_guild_delalliance (sd[i], guild_id[1 - i], (flag & 1));
+        }
+    }
+
+    if ((flag & 0x0f) == 0)
+    {                           // 同盟通知
+        if (sd[1] != NULL)
+            clif_guild_allianceack (sd[1], 2);
+    }
+    else if ((flag & 0x0f) == 1)
+    {                           // 敵対通知
+        if (sd[0] != NULL)
+            clif_guild_oppositionack (sd[0], 0);
+    }
+
+    for (i = 0; i < 2 - (flag & 1); i++)
+    {                           // 同盟/敵対リストの再送信
+        struct map_session_data *sd;
+        if (g[i] != NULL)
+            for (j = 0; j < g[i]->max_member; j++)
+                if ((sd = g[i]->member[j].sd) != NULL)
+                    clif_guild_allianceinfo (sd);
+    }
+    return 0;
+}
+
+// ギルド解散通知用
+void guild_broken_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild *g = (struct guild *) data;
+    int  guild_id = va_arg (ap, int);
+    int  i, j;
+    struct map_session_data *sd = NULL;
+
+    nullpo_retv (g);
+
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+    {                           // 関係を破棄
+        if (g->alliance[i].guild_id == guild_id)
+        {
+            for (j = 0; j < g->max_member; j++)
+                if ((sd = g->member[j].sd) != NULL)
+                    clif_guild_delalliance (sd, guild_id,
+                                            g->alliance[i].opposition);
+            g->alliance[i].guild_id = 0;
+        }
+    }
+}
+
+// ギルド解散通知
+int guild_broken (int guild_id, int flag)
+{
+    struct guild *g = guild_search (guild_id);
+    struct map_session_data *sd;
+    int  i;
+    if (flag != 0 || g == NULL)
+        return 0;
+
+    for (i = 0; i < g->max_member; i++)
+    {                           // ギルド解散を通知
+        if ((sd = g->member[i].sd) != NULL)
+        {
+            if (sd->state.storage_flag == 2)
+                storage_guild_storage_quit (sd, 1);
+            sd->status.guild_id = 0;
+            sd->guild_sended = 0;
+            clif_guild_broken (g->member[i].sd, 0);
+        }
+    }
+
+    numdb_foreach (guild_db, guild_broken_sub, guild_id);
+    numdb_erase (guild_db, guild_id);
+    guild_storage_delete (guild_id);
+    free (g);
+    return 0;
+}
+
+// ギルド解散
+int guild_break (struct map_session_data *sd, char *name)
+{
+    struct guild *g;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if ((g = guild_search (sd->status.guild_id)) == NULL)
+        return 0;
+    if (strcmp (g->name, name) != 0)
+        return 0;
+    if (strcmp (sd->status.name, g->master) != 0)
+        return 0;
+    for (i = 0; i < g->max_member; i++)
+    {
+        if (g->member[i].account_id > 0
+            && (g->member[i].account_id != sd->status.account_id))
+            break;
+    }
+    if (i < g->max_member)
+    {
+        clif_guild_broken (sd, 2);
+        return 0;
+    }
+
+    intif_guild_break (g->guild_id);
+    return 0;
+}
+
+// ギルド城データ要求
+int guild_castledataload (int castle_id, int index)
+{
+    return intif_guild_castle_dataload (castle_id, index);
+}
+
+// ギルド城情報所得時イベント追加
+int guild_addcastleinfoevent (int castle_id, int index, const char *name)
+{
+    struct eventlist *ev;
+    int  code = castle_id | (index << 16);
+
+    if (name == NULL || *name == 0)
+        return 0;
+
+    CREATE (ev, struct eventlist, 1);
+    memcpy (ev->name, name, sizeof (ev->name));
+    ev->next = (struct eventlist *)numdb_search (guild_castleinfoevent_db, code);
+    numdb_insert (guild_castleinfoevent_db, code, ev);
+    return 0;
+}
+
+// ギルド城データ要求返信
+int guild_castledataloadack (int castle_id, int index, int value)
+{
+    struct guild_castle *gc = guild_castle_search (castle_id);
+    int  code = castle_id | (index << 16);
+    struct eventlist *ev, *ev2;
+
+    if (gc == NULL)
+    {
+        return 0;
+    }
+    switch (index)
+    {
+        case 1:
+            gc->guild_id = value;
+            break;
+        case 2:
+            gc->economy = value;
+            break;
+        case 3:
+            gc->defense = value;
+            break;
+        case 4:
+            gc->triggerE = value;
+            break;
+        case 5:
+            gc->triggerD = value;
+            break;
+        case 6:
+            gc->nextTime = value;
+            break;
+        case 7:
+            gc->payTime = value;
+            break;
+        case 8:
+            gc->createTime = value;
+            break;
+        case 9:
+            gc->visibleC = value;
+            break;
+        case 10:
+            gc->visibleG0 = value;
+            break;
+        case 11:
+            gc->visibleG1 = value;
+            break;
+        case 12:
+            gc->visibleG2 = value;
+            break;
+        case 13:
+            gc->visibleG3 = value;
+            break;
+        case 14:
+            gc->visibleG4 = value;
+            break;
+        case 15:
+            gc->visibleG5 = value;
+            break;
+        case 16:
+            gc->visibleG6 = value;
+            break;
+        case 17:
+            gc->visibleG7 = value;
+            break;
+        case 18:
+            gc->Ghp0 = value;
+            break;              // guardian HP [Valaris]
+        case 19:
+            gc->Ghp1 = value;
+            break;
+        case 20:
+            gc->Ghp2 = value;
+            break;
+        case 21:
+            gc->Ghp3 = value;
+            break;
+        case 22:
+            gc->Ghp4 = value;
+            break;
+        case 23:
+            gc->Ghp5 = value;
+            break;
+        case 24:
+            gc->Ghp6 = value;
+            break;
+        case 25:
+            gc->Ghp7 = value;
+            break;              // end additions [Valaris]
+        default:
+            printf ("guild_castledataloadack ERROR!! (Not found index=%d)\n",
+                    index);
+            return 0;
+    }
+    if ((ev = (struct eventlist *)numdb_search (guild_castleinfoevent_db, code)) != NULL)
+    {
+        numdb_erase (guild_castleinfoevent_db, code);
+        for (; ev; ev2 = ev->next, free (ev), ev = ev2)
+        {
+            npc_event_do (ev->name);
+        }
+    }
+    return 1;
+}
+
+// ギルド城データ変更要求
+int guild_castledatasave (int castle_id, int index, int value)
+{
+    return intif_guild_castle_datasave (castle_id, index, value);
+}
+
+// ギルド城データ変更通知
+int guild_castledatasaveack (int castle_id, int index, int value)
+{
+    struct guild_castle *gc = guild_castle_search (castle_id);
+    if (gc == NULL)
+    {
+        return 0;
+    }
+    switch (index)
+    {
+        case 1:
+            gc->guild_id = value;
+            break;
+        case 2:
+            gc->economy = value;
+            break;
+        case 3:
+            gc->defense = value;
+            break;
+        case 4:
+            gc->triggerE = value;
+            break;
+        case 5:
+            gc->triggerD = value;
+            break;
+        case 6:
+            gc->nextTime = value;
+            break;
+        case 7:
+            gc->payTime = value;
+            break;
+        case 8:
+            gc->createTime = value;
+            break;
+        case 9:
+            gc->visibleC = value;
+            break;
+        case 10:
+            gc->visibleG0 = value;
+            break;
+        case 11:
+            gc->visibleG1 = value;
+            break;
+        case 12:
+            gc->visibleG2 = value;
+            break;
+        case 13:
+            gc->visibleG3 = value;
+            break;
+        case 14:
+            gc->visibleG4 = value;
+            break;
+        case 15:
+            gc->visibleG5 = value;
+            break;
+        case 16:
+            gc->visibleG6 = value;
+            break;
+        case 17:
+            gc->visibleG7 = value;
+            break;
+        case 18:
+            gc->Ghp0 = value;
+            break;              // guardian HP [Valaris]
+        case 19:
+            gc->Ghp1 = value;
+            break;
+        case 20:
+            gc->Ghp2 = value;
+            break;
+        case 21:
+            gc->Ghp3 = value;
+            break;
+        case 22:
+            gc->Ghp4 = value;
+            break;
+        case 23:
+            gc->Ghp5 = value;
+            break;
+        case 24:
+            gc->Ghp6 = value;
+            break;
+        case 25:
+            gc->Ghp7 = value;
+            break;              // end additions [Valaris]
+        default:
+            printf ("guild_castledatasaveack ERROR!! (Not found index=%d)\n",
+                    index);
+            return 0;
+    }
+    return 1;
+}
+
+// ギルドデータ一括受信(初期化時)
+int guild_castlealldataload (int len, struct guild_castle *gc)
+{
+    int  i;
+    int  n = (len - 4) / sizeof (struct guild_castle), ev = -1;
+
+    nullpo_retr (0, gc);
+
+    // イベント付きで要求するデータ位置を探す(最後の占拠データ)
+    for (i = 0; i < n; i++)
+    {
+        if ((gc + i)->guild_id)
+            ev = i;
+    }
+
+    // 城データ格納とギルド情報要求
+    for (i = 0; i < n; i++, gc++)
+    {
+        struct guild_castle *c = guild_castle_search (gc->castle_id);
+        if (!c)
+        {
+            printf ("guild_castlealldataload ??\n");
+            continue;
+        }
+        memcpy (&c->guild_id, &gc->guild_id,
+                sizeof (struct guild_castle) - ((int) &c->guild_id -
+                                                (int) c));
+        if (c->guild_id)
+        {
+            if (i != ev)
+                guild_request_info (c->guild_id);
+            else
+                guild_npc_request_info (c->guild_id, "::OnAgitInit");
+        }
+    }
+    if (ev == -1)
+        npc_event_doall ("OnAgitInit");
+    return 0;
+}
+
+int guild_agit_start (void)
+{                               // Run All NPC_Event[OnAgitStart]
+    int  c = npc_event_doall ("OnAgitStart");
+    printf ("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n", c);
+    return 0;
+}
+
+int guild_agit_end (void)
+{                               // Run All NPC_Event[OnAgitEnd]
+    int  c = npc_event_doall ("OnAgitEnd");
+    printf ("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n", c);
+    return 0;
+}
+
+void guild_gvg_eliminate_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{                               // Run One NPC_Event[OnAgitEliminate]
+    size_t len = strlen ((const char *) data);
+    char *evname;
+    CREATE (evname, char, len + 4);
+    int  c = 0;
+
+    if (!agit_flag)
+        return;               // Agit already End
+    memcpy (evname, (const char *) data, len - 5);
+    strcpy (evname + len - 5, "Eliminate");
+    c = npc_event_do (evname);
+    printf ("NPC_Event:[%s] Run (%d) Events.\n", evname, c);
+}
+
+int guild_agit_break (struct mob_data *md)
+{                               // Run One NPC_Event[OnAgitBreak]
+    char *evname;
+
+    nullpo_retr (0, md);
+
+    CREATE (evname, char, strlen (md->npc_event) + 1);
+
+    strcpy (evname, md->npc_event);
+// Now By User to Run [OnAgitBreak] NPC Event...
+// It's a little impossible to null point with player disconnect in this!
+// But Script will be stop, so nothing...
+// Maybe will be changed in the futher..
+//      int c = npc_event_do(evname);
+    if (!agit_flag)
+        return 0;               // Agit already End
+    add_timer (gettick () + battle_config.gvg_eliminate_time,
+               guild_gvg_eliminate_timer, md->bl.m, (int) evname);
+    return 0;
+}
+
+// [MouseJstr]
+//   How many castles does this guild have?
+int guild_checkcastles (struct guild *g)
+{
+    int  i, nb_cas = 0, id, cas_id = 0;
+    struct guild_castle *gc;
+    id = g->guild_id;
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        gc = guild_castle_search (i);
+        cas_id = gc->guild_id;
+        if (g->guild_id == cas_id)
+            nb_cas = nb_cas + 1;
+    }                           //end for
+    return nb_cas;
+}
+
+// [MouseJstr]
+//    is this guild allied with this castle?
+int guild_isallied (struct guild *g, struct guild_castle *gc)
+{
+    int  i;
+
+    nullpo_retr (0, g);
+
+    if (g->guild_id == gc->guild_id)
+        return 1;
+
+    if (gc->guild_id == 0)
+        return 0;
+
+    for (i = 0; i < MAX_GUILDALLIANCE; i++)
+        if (g->alliance[i].guild_id == gc->guild_id)
+        {
+            if (g->alliance[i].opposition == 0)
+                return 1;
+            else
+                return 0;
+        }
+
+    return 0;
+}
+
+static void guild_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+static void castle_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+static void guild_expcache_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+static void guild_infoevent_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+void do_final_guild (void)
+{
+    if (guild_db)
+        numdb_final (guild_db, guild_db_final);
+    if (castle_db)
+        numdb_final (castle_db, castle_db_final);
+    if (guild_expcache_db)
+        numdb_final (guild_expcache_db, guild_expcache_db_final);
+    if (guild_infoevent_db)
+        numdb_final (guild_infoevent_db, guild_infoevent_db_final);
+    if (guild_castleinfoevent_db)
+        numdb_final (guild_castleinfoevent_db, guild_infoevent_db_final);
+}
diff --git a/src/map/guild.h b/src/map/guild.h
deleted file mode 100644
index 8e7c32e..0000000
--- a/src/map/guild.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// $Id: guild.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _GUILD_H_
-#define _GUILD_H_
-
-struct map_session_data;
-struct mob_data;
-struct guild;
-struct guild_member;
-struct guild_position;
-struct guild_castle;
-
-int  guild_skill_get_inf (int id);
-int  guild_skill_get_sp (int id, int lv);
-int  guild_skill_get_range (int id);
-int  guild_skill_get_max (int id);
-
-int  guild_checkskill (struct guild *g, int id);
-int  guild_checkcastles (struct guild *g);  // [MouseJstr]
-int  guild_isallied (struct guild *g, struct guild_castle *gc);
-
-void do_init_guild (void);
-struct guild *guild_search (int guild_id);
-struct guild *guild_searchname (char *str);
-struct guild_castle *guild_castle_search (int gcid);
-
-struct guild_castle *guild_mapname2gc (char *mapname);
-
-struct map_session_data *guild_getavailablesd (struct guild *g);
-int  guild_getindex (struct guild *g, int account_id, int char_id);
-int  guild_getposition (struct map_session_data *sd, struct guild *g);
-int  guild_payexp (struct map_session_data *sd, int exp);
-
-int  guild_create (struct map_session_data *sd, char *name);
-int  guild_created (int account_id, int guild_id);
-int  guild_request_info (int guild_id);
-int  guild_recv_noinfo (int guild_id);
-int  guild_recv_info (struct guild *sg);
-int  guild_npc_request_info (int guild_id, const char *ev);
-int  guild_invite (struct map_session_data *sd, int account_id);
-int  guild_reply_invite (struct map_session_data *sd, int guild_id, int flag);
-int  guild_member_added (int guild_id, int account_id, int char_id, int flag);
-int  guild_leave (struct map_session_data *sd, int guild_id,
-                  int account_id, int char_id, const char *mes);
-int  guild_member_leaved (int guild_id, int account_id, int char_id, int flag,
-                          const char *name, const char *mes);
-int  guild_explusion (struct map_session_data *sd, int guild_id,
-                      int account_id, int char_id, const char *mes);
-int  guild_skillup (struct map_session_data *sd, int skill_num);
-int  guild_reqalliance (struct map_session_data *sd, int account_id);
-int  guild_reply_reqalliance (struct map_session_data *sd, int account_id,
-                              int flag);
-int  guild_alliance (int guild_id1, int guild_id2, int account_id1,
-                     int account_id2);
-int  guild_allianceack (int guild_id1, int guild_id2, int account_id1,
-                        int account_id2, int flag, const char *name1,
-                        const char *name2);
-int  guild_delalliance (struct map_session_data *sd, int guild_id, int flag);
-int  guild_opposition (struct map_session_data *sd, int char_id);
-
-int  guild_send_memberinfoshort (struct map_session_data *sd, int online);
-int  guild_recv_memberinfoshort (int guild_id, int account_id, int char_id,
-                                 int online, int lv, int class_);
-int  guild_change_memberposition (int guild_id, int account_id, int char_id,
-                                  int idx);
-int  guild_memberposition_changed (struct guild *g, int idx, int pos);
-int  guild_change_position (struct map_session_data *sd, int idx,
-                            int mode, int exp_mode, const char *name);
-int  guild_position_changed (int guild_id, int idx, struct guild_position *p);
-int  guild_change_notice (struct map_session_data *sd, int guild_id,
-                          const char *mes1, const char *mes2);
-int  guild_notice_changed (int guild_id, const char *mes1, const char *mes2);
-int  guild_change_emblem (struct map_session_data *sd, int len,
-                          const char *data);
-int  guild_emblem_changed (int len, int guild_id, int emblem_id,
-                           const char *data);
-int  guild_send_message (struct map_session_data *sd, char *mes, int len);
-int  guild_recv_message (int guild_id, int account_id, char *mes, int len);
-int  guild_skillupack (int guild_id, int skill_num, int account_id);
-int  guild_break (struct map_session_data *sd, char *name);
-int  guild_broken (int guild_id, int flag);
-
-int  guild_addcastleinfoevent (int castle_id, int index, const char *name);
-int  guild_castledataload (int castle_id, int index);
-int  guild_castledataloadack (int castle_id, int index, int value);
-int  guild_castledatasave (int castle_id, int index, int value);
-int  guild_castledatasaveack (int castle_id, int index, int value);
-int  guild_castlealldataload (int len, struct guild_castle *gc);
-
-int  guild_agit_start (void);
-int  guild_agit_end (void);
-int  guild_agit_break (struct mob_data *md);
-
-void do_final_guild (void);
-
-#endif
diff --git a/src/map/guild.hpp b/src/map/guild.hpp
new file mode 100644
index 0000000..f6d1356
--- /dev/null
+++ b/src/map/guild.hpp
@@ -0,0 +1,95 @@
+// $Id: guild.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef GUILD_HPP
+#define GUILD_HPP
+
+struct map_session_data;
+struct mob_data;
+struct guild;
+struct guild_member;
+struct guild_position;
+struct guild_castle;
+
+int  guild_skill_get_inf (int id);
+int  guild_skill_get_sp (int id, int lv);
+int  guild_skill_get_range (int id);
+int  guild_skill_get_max (int id);
+
+int  guild_checkskill (struct guild *g, int id);
+int  guild_checkcastles (struct guild *g);  // [MouseJstr]
+int  guild_isallied (struct guild *g, struct guild_castle *gc);
+
+void do_init_guild (void);
+struct guild *guild_search (int guild_id);
+struct guild *guild_searchname (char *str);
+struct guild_castle *guild_castle_search (int gcid);
+
+struct guild_castle *guild_mapname2gc (char *mapname);
+
+struct map_session_data *guild_getavailablesd (struct guild *g);
+int  guild_getindex (struct guild *g, int account_id, int char_id);
+int  guild_getposition (struct map_session_data *sd, struct guild *g);
+int  guild_payexp (struct map_session_data *sd, int exp);
+
+int  guild_create (struct map_session_data *sd, char *name);
+int  guild_created (int account_id, int guild_id);
+int  guild_request_info (int guild_id);
+int  guild_recv_noinfo (int guild_id);
+int  guild_recv_info (struct guild *sg);
+int  guild_npc_request_info (int guild_id, const char *ev);
+int  guild_invite (struct map_session_data *sd, int account_id);
+int  guild_reply_invite (struct map_session_data *sd, int guild_id, int flag);
+int  guild_member_added (int guild_id, int account_id, int char_id, int flag);
+int  guild_leave (struct map_session_data *sd, int guild_id,
+                  int account_id, int char_id, const char *mes);
+int  guild_member_leaved (int guild_id, int account_id, int char_id, int flag,
+                          const char *name, const char *mes);
+int  guild_explusion (struct map_session_data *sd, int guild_id,
+                      int account_id, int char_id, const char *mes);
+int  guild_skillup (struct map_session_data *sd, int skill_num);
+int  guild_reqalliance (struct map_session_data *sd, int account_id);
+int  guild_reply_reqalliance (struct map_session_data *sd, int account_id,
+                              int flag);
+int  guild_alliance (int guild_id1, int guild_id2, int account_id1,
+                     int account_id2);
+int  guild_allianceack (int guild_id1, int guild_id2, int account_id1,
+                        int account_id2, int flag, const char *name1,
+                        const char *name2);
+int  guild_delalliance (struct map_session_data *sd, int guild_id, int flag);
+int  guild_opposition (struct map_session_data *sd, int char_id);
+
+int  guild_send_memberinfoshort (struct map_session_data *sd, int online);
+int  guild_recv_memberinfoshort (int guild_id, int account_id, int char_id,
+                                 int online, int lv, int class_);
+int  guild_change_memberposition (int guild_id, int account_id, int char_id,
+                                  int idx);
+int  guild_memberposition_changed (struct guild *g, int idx, int pos);
+int  guild_change_position (struct map_session_data *sd, int idx,
+                            int mode, int exp_mode, const char *name);
+int  guild_position_changed (int guild_id, int idx, struct guild_position *p);
+int  guild_change_notice (struct map_session_data *sd, int guild_id,
+                          const char *mes1, const char *mes2);
+int  guild_notice_changed (int guild_id, const char *mes1, const char *mes2);
+int  guild_change_emblem (struct map_session_data *sd, int len,
+                          const char *data);
+int  guild_emblem_changed (int len, int guild_id, int emblem_id,
+                           const char *data);
+int  guild_send_message (struct map_session_data *sd, char *mes, int len);
+int  guild_recv_message (int guild_id, int account_id, char *mes, int len);
+int  guild_skillupack (int guild_id, int skill_num, int account_id);
+int  guild_break (struct map_session_data *sd, char *name);
+int  guild_broken (int guild_id, int flag);
+
+int  guild_addcastleinfoevent (int castle_id, int index, const char *name);
+int  guild_castledataload (int castle_id, int index);
+int  guild_castledataloadack (int castle_id, int index, int value);
+int  guild_castledatasave (int castle_id, int index, int value);
+int  guild_castledatasaveack (int castle_id, int index, int value);
+int  guild_castlealldataload (int len, struct guild_castle *gc);
+
+int  guild_agit_start (void);
+int  guild_agit_end (void);
+int  guild_agit_break (struct mob_data *md);
+
+void do_final_guild (void);
+
+#endif
diff --git a/src/map/intif.c b/src/map/intif.c
deleted file mode 100644
index 7069e3a..0000000
--- a/src/map/intif.c
+++ /dev/null
@@ -1,1201 +0,0 @@
-// $Id: intif.c,v 1.2 2004/09/25 05:32:18 MouseJstr Exp $
-#include <sys/types.h>
-#ifdef LCCWIN32
-#include <winsock.h>
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#ifndef LCCWIN32
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#endif
-#include <signal.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "../common/nullpo.h"
-#include "../common/socket.h"
-#include "../common/timer.h"
-
-#include "battle.h"
-#include "chrif.h"
-#include "clif.h"
-#include "guild.h"
-#include "intif.h"
-#include "map.h"
-#include "party.h"
-#include "pc.h"
-#include "storage.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-static const int packet_len_table[] = {
-    -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0,
-    35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
-    10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1,
-    9, 9, -1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-extern int char_fd;             // inter serverのfdはchar_fdを使う
-#define inter_fd (char_fd)      // エイリアス
-
-//-----------------------------------------------------------------
-// inter serverへの送信
-
-// Message for all GMs on all map servers
-int intif_GMmessage (char *mes, int len, int flag)
-{
-    int  lp = (flag & 0x10) ? 8 : 4;
-    WFIFOW (inter_fd, 0) = 0x3000;
-    WFIFOW (inter_fd, 2) = lp + len;
-    WFIFOL (inter_fd, 4) = 0x65756c62;
-    memcpy (WFIFOP (inter_fd, lp), mes, len);
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-
-    return 0;
-}
-
-// The transmission of Wisp/Page to inter-server (player not found on this server)
-int intif_wis_message (struct map_session_data *sd, char *nick, char *mes,
-                       int mes_len)
-{
-    nullpo_retr (0, sd);
-
-    WFIFOW (inter_fd, 0) = 0x3001;
-    WFIFOW (inter_fd, 2) = mes_len + 52;
-    memcpy (WFIFOP (inter_fd, 4), sd->status.name, 24);
-    memcpy (WFIFOP (inter_fd, 28), nick, 24);
-    memcpy (WFIFOP (inter_fd, 52), mes, mes_len);
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-
-    if (battle_config.etc_log)
-        printf ("intif_wis_message from %s to %s (message: '%s')\n",
-                sd->status.name, nick, mes);
-
-    return 0;
-}
-
-// The reply of Wisp/page
-int intif_wis_replay (int id, int flag)
-{
-    WFIFOW (inter_fd, 0) = 0x3002;
-    WFIFOL (inter_fd, 2) = id;
-    WFIFOB (inter_fd, 6) = flag;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-    WFIFOSET (inter_fd, 7);
-
-    if (battle_config.etc_log)
-        printf ("intif_wis_replay: id: %d, flag:%d\n", id, flag);
-
-    return 0;
-}
-
-// The transmission of GM only Wisp/Page from server to inter-server
-int intif_wis_message_to_gm (char *Wisp_name, int min_gm_level, char *mes,
-                             int mes_len)
-{
-    WFIFOW (inter_fd, 0) = 0x3003;
-    WFIFOW (inter_fd, 2) = mes_len + 30;
-    memcpy (WFIFOP (inter_fd, 4), Wisp_name, 24);
-    WFIFOW (inter_fd, 28) = (short) min_gm_level;
-    memcpy (WFIFOP (inter_fd, 30), mes, mes_len);
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-
-    if (battle_config.etc_log)
-        printf
-            ("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n",
-             Wisp_name, min_gm_level, mes);
-
-    return 0;
-}
-
-// アカウント変数送信
-int intif_saveaccountreg (struct map_session_data *sd)
-{
-    int  j, p;
-
-    nullpo_retr (0, sd);
-
-    WFIFOW (inter_fd, 0) = 0x3004;
-    WFIFOL (inter_fd, 4) = sd->bl.id;
-    for (j = 0, p = 8; j < sd->status.account_reg_num; j++, p += 36)
-    {
-        memcpy (WFIFOP (inter_fd, p), sd->status.account_reg[j].str, 32);
-        WFIFOL (inter_fd, p + 32) = sd->status.account_reg[j].value;
-    }
-    WFIFOW (inter_fd, 2) = p;
-    WFIFOSET (inter_fd, p);
-    return 0;
-}
-
-// アカウント変数要求
-int intif_request_accountreg (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    WFIFOW (inter_fd, 0) = 0x3005;
-    WFIFOL (inter_fd, 2) = sd->bl.id;
-    WFIFOSET (inter_fd, 6);
-    return 0;
-}
-
-// 倉庫データ要求
-int intif_request_storage (int account_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3010;
-    WFIFOL (inter_fd, 2) = account_id;
-    WFIFOSET (inter_fd, 6);
-    return 0;
-}
-
-// 倉庫データ送信
-int intif_send_storage (struct storage *stor)
-{
-    nullpo_retr (0, stor);
-    WFIFOW (inter_fd, 0) = 0x3011;
-    WFIFOW (inter_fd, 2) = sizeof (struct storage) + 8;
-    WFIFOL (inter_fd, 4) = stor->account_id;
-    memcpy (WFIFOP (inter_fd, 8), stor, sizeof (struct storage));
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-    return 0;
-}
-
-int intif_request_guild_storage (int account_id, int guild_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3018;
-    WFIFOL (inter_fd, 2) = account_id;
-    WFIFOL (inter_fd, 6) = guild_id;
-    WFIFOSET (inter_fd, 10);
-    return 0;
-}
-
-int intif_send_guild_storage (int account_id, struct guild_storage *gstor)
-{
-    WFIFOW (inter_fd, 0) = 0x3019;
-    WFIFOW (inter_fd, 2) = sizeof (struct guild_storage) + 12;
-    WFIFOL (inter_fd, 4) = account_id;
-    WFIFOL (inter_fd, 8) = gstor->guild_id;
-    memcpy (WFIFOP (inter_fd, 12), gstor, sizeof (struct guild_storage));
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-    return 0;
-}
-
-// パーティ作成要求
-int intif_create_party (struct map_session_data *sd, char *name)
-{
-    nullpo_retr (0, sd);
-
-    WFIFOW (inter_fd, 0) = 0x3020;
-    WFIFOL (inter_fd, 2) = sd->status.account_id;
-    memcpy (WFIFOP (inter_fd, 6), name, 24);
-    memcpy (WFIFOP (inter_fd, 30), sd->status.name, 24);
-    memcpy (WFIFOP (inter_fd, 54), map[sd->bl.m].name, 16);
-    WFIFOW (inter_fd, 70) = sd->status.base_level;
-    WFIFOSET (inter_fd, 72);
-//  if(battle_config.etc_log)
-//      printf("intif: create party\n");
-    return 0;
-}
-
-// パーティ情報要求
-int intif_request_partyinfo (int party_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3021;
-    WFIFOL (inter_fd, 2) = party_id;
-    WFIFOSET (inter_fd, 6);
-//  if(battle_config.etc_log)
-//      printf("intif: request party info\n");
-    return 0;
-}
-
-// パーティ追加要求
-int intif_party_addmember (int party_id, int account_id)
-{
-    struct map_session_data *sd;
-    sd = map_id2sd (account_id);
-//  if(battle_config.etc_log)
-//      printf("intif: party add member %d %d\n",party_id,account_id);
-    if (sd != NULL)
-    {
-        WFIFOW (inter_fd, 0) = 0x3022;
-        WFIFOL (inter_fd, 2) = party_id;
-        WFIFOL (inter_fd, 6) = account_id;
-        memcpy (WFIFOP (inter_fd, 10), sd->status.name, 24);
-        memcpy (WFIFOP (inter_fd, 34), map[sd->bl.m].name, 16);
-        WFIFOW (inter_fd, 50) = sd->status.base_level;
-        WFIFOSET (inter_fd, 52);
-    }
-    return 0;
-}
-
-// パーティ設定変更
-int intif_party_changeoption (int party_id, int account_id, int exp, int item)
-{
-    WFIFOW (inter_fd, 0) = 0x3023;
-    WFIFOL (inter_fd, 2) = party_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    WFIFOW (inter_fd, 10) = exp;
-    WFIFOW (inter_fd, 12) = item;
-    WFIFOSET (inter_fd, 14);
-    return 0;
-}
-
-// パーティ脱退要求
-int intif_party_leave (int party_id, int account_id)
-{
-//  if(battle_config.etc_log)
-//      printf("intif: party leave %d %d\n",party_id,account_id);
-    WFIFOW (inter_fd, 0) = 0x3024;
-    WFIFOL (inter_fd, 2) = party_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    WFIFOSET (inter_fd, 10);
-    return 0;
-}
-
-// パーティ移動要求
-int intif_party_changemap (struct map_session_data *sd, int online)
-{
-    if (sd != NULL)
-    {
-        WFIFOW (inter_fd, 0) = 0x3025;
-        WFIFOL (inter_fd, 2) = sd->status.party_id;
-        WFIFOL (inter_fd, 6) = sd->status.account_id;
-        memcpy (WFIFOP (inter_fd, 10), map[sd->bl.m].name, 16);
-        WFIFOB (inter_fd, 26) = online;
-        WFIFOW (inter_fd, 27) = sd->status.base_level;
-        WFIFOSET (inter_fd, 29);
-    }
-//  if(battle_config.etc_log)
-//      printf("party: change map\n");
-    return 0;
-}
-
-// パーティー解散要求
-int intif_break_party (int party_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3026;
-    WFIFOL (inter_fd, 2) = party_id;
-    WFIFOSET (inter_fd, 6);
-    return 0;
-}
-
-// パーティ会話送信
-int intif_party_message (int party_id, int account_id, char *mes, int len)
-{
-//  if(battle_config.etc_log)
-//      printf("intif_party_message: %s\n",mes);
-    WFIFOW (inter_fd, 0) = 0x3027;
-    WFIFOW (inter_fd, 2) = len + 12;
-    WFIFOL (inter_fd, 4) = party_id;
-    WFIFOL (inter_fd, 8) = account_id;
-    memcpy (WFIFOP (inter_fd, 12), mes, len);
-    WFIFOSET (inter_fd, len + 12);
-    return 0;
-}
-
-// パーティ競合チェック要求
-int intif_party_checkconflict (int party_id, int account_id, char *nick)
-{
-    WFIFOW (inter_fd, 0) = 0x3028;
-    WFIFOL (inter_fd, 2) = party_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    memcpy (WFIFOP (inter_fd, 10), nick, 24);
-    WFIFOSET (inter_fd, 34);
-    return 0;
-}
-
-// ギルド作成要求
-int intif_guild_create (const char *name, const struct guild_member *master)
-{
-    nullpo_retr (0, master);
-
-    WFIFOW (inter_fd, 0) = 0x3030;
-    WFIFOW (inter_fd, 2) = sizeof (struct guild_member) + 32;
-    WFIFOL (inter_fd, 4) = master->account_id;
-    memcpy (WFIFOP (inter_fd, 8), name, 24);
-    memcpy (WFIFOP (inter_fd, 32), master, sizeof (struct guild_member));
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-    return 0;
-}
-
-// ギルド情報要求
-int intif_guild_request_info (int guild_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3031;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOSET (inter_fd, 6);
-    return 0;
-}
-
-// ギルドメンバ追加要求
-int intif_guild_addmember (int guild_id, struct guild_member *m)
-{
-    WFIFOW (inter_fd, 0) = 0x3032;
-    WFIFOW (inter_fd, 2) = sizeof (struct guild_member) + 8;
-    WFIFOL (inter_fd, 4) = guild_id;
-    memcpy (WFIFOP (inter_fd, 8), m, sizeof (struct guild_member));
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-    return 0;
-}
-
-// ギルドメンバ脱退/追放要求
-int intif_guild_leave (int guild_id, int account_id, int char_id, int flag,
-                       const char *mes)
-{
-    WFIFOW (inter_fd, 0) = 0x3034;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    WFIFOL (inter_fd, 10) = char_id;
-    WFIFOB (inter_fd, 14) = flag;
-    memcpy (WFIFOP (inter_fd, 15), mes, 40);
-    WFIFOSET (inter_fd, 55);
-    return 0;
-}
-
-// ギルドメンバのオンライン状況/Lv更新要求
-int intif_guild_memberinfoshort (int guild_id,
-                                 int account_id, int char_id, int online,
-                                 int lv, int class_)
-{
-    WFIFOW (inter_fd, 0) = 0x3035;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    WFIFOL (inter_fd, 10) = char_id;
-    WFIFOB (inter_fd, 14) = online;
-    WFIFOW (inter_fd, 15) = lv;
-    WFIFOW (inter_fd, 17) = class_;
-    WFIFOSET (inter_fd, 19);
-    return 0;
-}
-
-// ギルド解散通知
-int intif_guild_break (int guild_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3036;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOSET (inter_fd, 6);
-    return 0;
-}
-
-// ギルド会話送信
-int intif_guild_message (int guild_id, int account_id, char *mes, int len)
-{
-    WFIFOW (inter_fd, 0) = 0x3037;
-    WFIFOW (inter_fd, 2) = len + 12;
-    WFIFOL (inter_fd, 4) = guild_id;
-    WFIFOL (inter_fd, 8) = account_id;
-    memcpy (WFIFOP (inter_fd, 12), mes, len);
-    WFIFOSET (inter_fd, len + 12);
-    return 0;
-}
-
-// ギルド競合チェック要求
-int intif_guild_checkconflict (int guild_id, int account_id, int char_id)
-{
-    WFIFOW (inter_fd, 0) = 0x3038;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOL (inter_fd, 6) = account_id;
-    WFIFOL (inter_fd, 10) = char_id;
-    WFIFOSET (inter_fd, 14);
-    return 0;
-}
-
-// ギルド基本情報変更要求
-int intif_guild_change_basicinfo (int guild_id, int type, const void *data,
-                                  int len)
-{
-    WFIFOW (inter_fd, 0) = 0x3039;
-    WFIFOW (inter_fd, 2) = len + 10;
-    WFIFOL (inter_fd, 4) = guild_id;
-    WFIFOW (inter_fd, 8) = type;
-    memcpy (WFIFOP (inter_fd, 10), data, len);
-    WFIFOSET (inter_fd, len + 10);
-    return 0;
-}
-
-// ギルドメンバ情報変更要求
-int intif_guild_change_memberinfo (int guild_id, int account_id, int char_id,
-                                   int type, const void *data, int len)
-{
-    WFIFOW (inter_fd, 0) = 0x303a;
-    WFIFOW (inter_fd, 2) = len + 18;
-    WFIFOL (inter_fd, 4) = guild_id;
-    WFIFOL (inter_fd, 8) = account_id;
-    WFIFOL (inter_fd, 12) = char_id;
-    WFIFOW (inter_fd, 16) = type;
-    memcpy (WFIFOP (inter_fd, 18), data, len);
-    WFIFOSET (inter_fd, len + 18);
-    return 0;
-}
-
-// ギルド役職変更要求
-int intif_guild_position (int guild_id, int idx, struct guild_position *p)
-{
-    WFIFOW (inter_fd, 0) = 0x303b;
-    WFIFOW (inter_fd, 2) = sizeof (struct guild_position) + 12;
-    WFIFOL (inter_fd, 4) = guild_id;
-    WFIFOL (inter_fd, 8) = idx;
-    memcpy (WFIFOP (inter_fd, 12), p, sizeof (struct guild_position));
-    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
-    return 0;
-}
-
-// ギルドスキルアップ要求
-int intif_guild_skillup (int guild_id, int skill_num, int account_id)
-{
-    WFIFOW (inter_fd, 0) = 0x303c;
-    WFIFOL (inter_fd, 2) = guild_id;
-    WFIFOL (inter_fd, 6) = skill_num;
-    WFIFOL (inter_fd, 10) = account_id;
-    WFIFOSET (inter_fd, 14);
-    return 0;
-}
-
-// ギルド同盟/敵対要求
-int intif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
-                          int account_id2, int flag)
-{
-    WFIFOW (inter_fd, 0) = 0x303d;
-    WFIFOL (inter_fd, 2) = guild_id1;
-    WFIFOL (inter_fd, 6) = guild_id2;
-    WFIFOL (inter_fd, 10) = account_id1;
-    WFIFOL (inter_fd, 14) = account_id2;
-    WFIFOB (inter_fd, 18) = flag;
-    WFIFOSET (inter_fd, 19);
-    return 0;
-}
-
-// ギルド告知変更要求
-int intif_guild_notice (int guild_id, const char *mes1, const char *mes2)
-{
-    WFIFOW (inter_fd, 0) = 0x303e;
-    WFIFOL (inter_fd, 2) = guild_id;
-    memcpy (WFIFOP (inter_fd, 6), mes1, 60);
-    memcpy (WFIFOP (inter_fd, 66), mes2, 120);
-    WFIFOSET (inter_fd, 186);
-    return 0;
-}
-
-// ギルドエンブレム変更要求
-int intif_guild_emblem (int guild_id, int len, const char *data)
-{
-    if (guild_id <= 0 || len < 0 || len > 2000)
-        return 0;
-    WFIFOW (inter_fd, 0) = 0x303f;
-    WFIFOW (inter_fd, 2) = len + 12;
-    WFIFOL (inter_fd, 4) = guild_id;
-    WFIFOL (inter_fd, 8) = 0;
-    memcpy (WFIFOP (inter_fd, 12), data, len);
-    WFIFOSET (inter_fd, len + 12);
-    return 0;
-}
-
-//現在のギルド城占領ギルドを調べる
-int intif_guild_castle_dataload (int castle_id, int index)
-{
-    WFIFOW (inter_fd, 0) = 0x3040;
-    WFIFOW (inter_fd, 2) = castle_id;
-    WFIFOB (inter_fd, 4) = index;
-    WFIFOSET (inter_fd, 5);
-    return 0;
-}
-
-//ギルド城占領ギルド変更要求
-int intif_guild_castle_datasave (int castle_id, int index, int value)
-{
-    WFIFOW (inter_fd, 0) = 0x3041;
-    WFIFOW (inter_fd, 2) = castle_id;
-    WFIFOB (inter_fd, 4) = index;
-    WFIFOL (inter_fd, 5) = value;
-    WFIFOSET (inter_fd, 9);
-    return 0;
-}
-
-//-----------------------------------------------------------------
-// Packets receive from inter server
-
-// Wisp/Page reception
-int intif_parse_WisMessage (int fd)
-{                               // rewritten by [Yor]
-    struct map_session_data *sd;
-    int  i;
-    char *wisp_source;
-
-    if (battle_config.etc_log)
-        printf
-            ("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n",
-             RFIFOL (fd, 4), RFIFOP (fd, 8), RFIFOP (fd, 32), RFIFOP (fd,
-                                                                      56));
-    sd = map_nick2sd (RFIFOP (fd, 32)); // Searching destination player
-    if (sd != NULL && strcmp (sd->status.name, RFIFOP (fd, 32)) == 0)
-    {                           // exactly same name (inter-server have checked the name before)
-        // if player ignore all
-        if (sd->ignoreAll == 1)
-            intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-        else
-        {
-            wisp_source = RFIFOP (fd, 8);   // speed up
-            // if player ignore the source character
-            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
-                 i++)
-                if (strcmp (sd->ignore[i].name, wisp_source) == 0)
-                {
-                    intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-                    break;
-                }
-            // if source player not found in ignore list
-            if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
-            {
-                clif_wis_message (sd->fd, RFIFOP (fd, 8), RFIFOP (fd, 56),
-                                  RFIFOW (fd, 2) - 56);
-                intif_wis_replay (RFIFOL (fd, 4), 0);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-            }
-        }
-    }
-    else
-        intif_wis_replay (RFIFOL (fd, 4), 1);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-    return 0;
-}
-
-// Wisp/page transmission result reception
-int intif_parse_WisEnd (int fd)
-{
-    struct map_session_data *sd;
-
-    if (battle_config.etc_log)
-        printf ("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP (fd, 2), RFIFOB (fd, 26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
-    sd = map_nick2sd (RFIFOP (fd, 2));
-    if (sd != NULL)
-        clif_wis_end (sd->fd, RFIFOB (fd, 26));
-
-    return 0;
-}
-
-// Received wisp message from map-server via char-server for ALL gm
-int mapif_parse_WisToGM (int fd)
-{                               // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
-    int  i, min_gm_level, len;
-    struct map_session_data *pl_sd;
-    char Wisp_name[24];
-    char mbuf[255];
-
-    if (RFIFOW (fd, 2) - 30 <= 0)
-        return 0;
-
-    len = RFIFOW (fd, 2) - 30;
-    char *message = ((len) >= 255) ? (char *) malloc (len) : mbuf;
-
-    min_gm_level = (int) RFIFOW (fd, 28);
-    memcpy (Wisp_name, RFIFOP (fd, 4), 24);
-    Wisp_name[23] = '\0';
-    memcpy (message, RFIFOP (fd, 30), len);
-    message[len - 1] = '\0';
-    // information is sended to all online GM
-    for (i = 0; i < fd_max; i++)
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-            if (pc_isGM (pl_sd) >= min_gm_level)
-                clif_wis_message (i, Wisp_name, message,
-                                  strlen (message) + 1);
-
-    if (message != mbuf)
-        free (message);
-
-    return 0;
-}
-
-// アカウント変数通知
-int intif_parse_AccountReg (int fd)
-{
-    int  j, p;
-    struct map_session_data *sd;
-
-    if ((sd = map_id2sd (RFIFOL (fd, 4))) == NULL)
-        return 1;
-    for (p = 8, j = 0; p < RFIFOW (fd, 2) && j < ACCOUNT_REG_NUM;
-         p += 36, j++)
-    {
-        memcpy (sd->status.account_reg[j].str, RFIFOP (fd, p), 32);
-        sd->status.account_reg[j].value = RFIFOL (fd, p + 32);
-    }
-    sd->status.account_reg_num = j;
-//  printf("intif: accountreg\n");
-
-    return 0;
-}
-
-// 倉庫データ受信
-int intif_parse_LoadStorage (int fd)
-{
-    struct storage *stor;
-    struct map_session_data *sd;
-
-    sd = map_id2sd (RFIFOL (fd, 4));
-    if (sd == NULL)
-    {
-        if (battle_config.error_log)
-            printf ("intif_parse_LoadStorage: user not found %d\n",
-                    RFIFOL (fd, 4));
-        return 1;
-    }
-    stor = account2storage (RFIFOL (fd, 4));
-    if (stor->storage_status == 1)
-    {                           // Already open.. lets ignore this update
-        if (battle_config.error_log)
-            printf
-                ("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n",
-                 sd->status.account_id, sd->status.char_id);
-        return 1;
-    }
-    if (stor->dirty)
-    {                           // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
-        if (battle_config.error_log)
-            printf
-                ("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n",
-                 sd->status.account_id, sd->status.char_id);
-        return 1;
-    }
-
-    if (RFIFOW (fd, 2) - 8 != sizeof (struct storage))
-    {
-        if (battle_config.error_log)
-            printf ("intif_parse_LoadStorage: data size error %d %d\n",
-                    RFIFOW (fd, 2) - 8, sizeof (struct storage));
-        return 1;
-    }
-    if (battle_config.save_log)
-        printf ("intif_openstorage: %d\n", RFIFOL (fd, 4));
-    memcpy (stor, RFIFOP (fd, 8), sizeof (struct storage));
-    stor->dirty = 0;
-    stor->storage_status = 1;
-    sd->state.storage_flag = 1;
-    clif_storageitemlist (sd, stor);
-    clif_storageequiplist (sd, stor);
-    clif_updatestorageamount (sd, stor);
-
-    return 0;
-}
-
-// 倉庫データ送信成功
-int intif_parse_SaveStorage (int fd)
-{
-    if (battle_config.save_log)
-        printf ("intif_savestorage: done %d %d\n", RFIFOL (fd, 2),
-                RFIFOB (fd, 6));
-    storage_storage_saved (RFIFOL (fd, 2));
-    return 0;
-}
-
-int intif_parse_LoadGuildStorage (int fd)
-{
-    struct guild_storage *gstor;
-    struct map_session_data *sd;
-    int  guild_id;
-
-    guild_id = RFIFOL (fd, 8);
-    if (guild_id > 0)
-    {
-        gstor = guild2storage (guild_id);
-        if (!gstor)
-        {
-            if (battle_config.error_log)
-                printf
-                    ("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",
-                     guild_id);
-            return 1;
-        }
-        if (RFIFOW (fd, 2) - 12 != sizeof (struct guild_storage))
-        {
-            gstor->storage_status = 0;
-            if (battle_config.error_log)
-                printf
-                    ("intif_parse_LoadGuildStorage: data size error %d %d\n",
-                     RFIFOW (fd, 2) - 12, sizeof (struct guild_storage));
-            return 1;
-        }
-        sd = map_id2sd (RFIFOL (fd, 4));
-        if (sd == NULL)
-        {
-            if (battle_config.error_log)
-                printf ("intif_parse_LoadGuildStorage: user not found %d\n",
-                        RFIFOL (fd, 4));
-            return 1;
-        }
-        if (gstor->storage_status == 1)
-        {                       // Already open.. lets ignore this update
-            if (battle_config.error_log)
-                printf
-                    ("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n",
-                     sd->status.account_id, sd->status.char_id);
-            return 1;
-        }
-        if (gstor->dirty)
-        {                       // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
-            if (battle_config.error_log)
-                printf
-                    ("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n",
-                     sd->status.account_id, sd->status.char_id);
-            return 1;
-        }
-        if (battle_config.save_log)
-            printf ("intif_open_guild_storage: %d\n", RFIFOL (fd, 4));
-        memcpy (gstor, RFIFOP (fd, 12), sizeof (struct guild_storage));
-        gstor->storage_status = 1;
-        sd->state.storage_flag = 2;
-        clif_guildstorageitemlist (sd, gstor);
-        clif_guildstorageequiplist (sd, gstor);
-        clif_updateguildstorageamount (sd, gstor);
-    }
-    return 0;
-}
-
-int intif_parse_SaveGuildStorage (int fd)
-{
-    if (battle_config.save_log)
-    {
-        printf ("intif_save_guild_storage: done %d %d %d\n", RFIFOL (fd, 2),
-                RFIFOL (fd, 6), RFIFOB (fd, 10));
-    }
-    storage_guild_storagesaved ( /*RFIFOL(fd,2), */ RFIFOL (fd, 6));
-    return 0;
-}
-
-// パーティ作成可否
-int intif_parse_PartyCreated (int fd)
-{
-    if (battle_config.etc_log)
-        printf ("intif: party created\n");
-    party_created (RFIFOL (fd, 2), RFIFOB (fd, 6), RFIFOL (fd, 7),
-                   RFIFOP (fd, 11));
-    return 0;
-}
-
-// パーティ情報
-int intif_parse_PartyInfo (int fd)
-{
-    if (RFIFOW (fd, 2) == 8)
-    {
-        if (battle_config.error_log)
-            printf ("intif: party noinfo %d\n", RFIFOL (fd, 4));
-        party_recv_noinfo (RFIFOL (fd, 4));
-        return 0;
-    }
-
-//  printf("intif: party info %d\n",RFIFOL(fd,4));
-    if (RFIFOW (fd, 2) != sizeof (struct party) + 4)
-    {
-        if (battle_config.error_log)
-            printf ("intif: party info : data size error %d %d %d\n",
-                    RFIFOL (fd, 4), RFIFOW (fd, 2),
-                    sizeof (struct party) + 4);
-    }
-    party_recv_info ((struct party *) RFIFOP (fd, 4));
-    return 0;
-}
-
-// パーティ追加通知
-int intif_parse_PartyMemberAdded (int fd)
-{
-    if (battle_config.etc_log)
-        printf ("intif: party member added %d %d %d\n", RFIFOL (fd, 2),
-                RFIFOL (fd, 6), RFIFOB (fd, 10));
-    party_member_added (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOB (fd, 10));
-    return 0;
-}
-
-// パーティ設定変更通知
-int intif_parse_PartyOptionChanged (int fd)
-{
-    party_optionchanged (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOW (fd, 10),
-                         RFIFOW (fd, 12), RFIFOB (fd, 14));
-    return 0;
-}
-
-// パーティ脱退通知
-int intif_parse_PartyMemberLeaved (int fd)
-{
-    if (battle_config.etc_log)
-        printf ("intif: party member leaved %d %d %s\n", RFIFOL (fd, 2),
-                RFIFOL (fd, 6), RFIFOP (fd, 10));
-    party_member_leaved (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOP (fd, 10));
-    return 0;
-}
-
-// パーティ解散通知
-int intif_parse_PartyBroken (int fd)
-{
-    party_broken (RFIFOL (fd, 2));
-    return 0;
-}
-
-// パーティ移動通知
-int intif_parse_PartyMove (int fd)
-{
-//  if(battle_config.etc_log)
-//      printf("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27));
-    party_recv_movemap (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOP (fd, 10),
-                        RFIFOB (fd, 26), RFIFOW (fd, 27));
-    return 0;
-}
-
-// パーティメッセージ
-int intif_parse_PartyMessage (int fd)
-{
-//  if(battle_config.etc_log)
-//      printf("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12));
-    party_recv_message (RFIFOL (fd, 4), RFIFOL (fd, 8), RFIFOP (fd, 12),
-                        RFIFOW (fd, 2) - 12);
-    return 0;
-}
-
-// ギルド作成可否
-int intif_parse_GuildCreated (int fd)
-{
-    guild_created (RFIFOL (fd, 2), RFIFOL (fd, 6));
-    return 0;
-}
-
-// ギルド情報
-int intif_parse_GuildInfo (int fd)
-{
-    if (RFIFOW (fd, 2) == 8)
-    {
-        if (battle_config.error_log)
-            printf ("intif: guild noinfo %d\n", RFIFOL (fd, 4));
-        guild_recv_noinfo (RFIFOL (fd, 4));
-        return 0;
-    }
-
-//  if(battle_config.etc_log)
-//      printf("intif: guild info %d\n",RFIFOL(fd,4));
-    if (RFIFOW (fd, 2) != sizeof (struct guild) + 4)
-    {
-        if (battle_config.error_log)
-            printf ("intif: guild info : data size error\n %d %d %d",
-                    RFIFOL (fd, 4), RFIFOW (fd, 2),
-                    sizeof (struct guild) + 4);
-    }
-    guild_recv_info ((struct guild *) RFIFOP (fd, 4));
-    return 0;
-}
-
-// ギルドメンバ追加通知
-int intif_parse_GuildMemberAdded (int fd)
-{
-    if (battle_config.etc_log)
-        printf ("intif: guild member added %d %d %d %d\n", RFIFOL (fd, 2),
-                RFIFOL (fd, 6), RFIFOL (fd, 10), RFIFOB (fd, 14));
-    guild_member_added (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
-                        RFIFOB (fd, 14));
-    return 0;
-}
-
-// ギルドメンバ脱退/追放通知
-int intif_parse_GuildMemberLeaved (int fd)
-{
-    guild_member_leaved (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
-                         RFIFOB (fd, 14), RFIFOP (fd, 55), RFIFOP (fd, 15));
-    return 0;
-}
-
-// ギルドメンバオンライン状態/Lv変更通知
-int intif_parse_GuildMemberInfoShort (int fd)
-{
-    guild_recv_memberinfoshort (RFIFOL (fd, 2), RFIFOL (fd, 6),
-                                RFIFOL (fd, 10), RFIFOB (fd, 14), RFIFOW (fd,
-                                                                          15),
-                                RFIFOW (fd, 17));
-    return 0;
-}
-
-// ギルド解散通知
-int intif_parse_GuildBroken (int fd)
-{
-    guild_broken (RFIFOL (fd, 2), RFIFOB (fd, 6));
-    return 0;
-}
-
-// ギルド基本情報変更通知
-int intif_parse_GuildBasicInfoChanged (int fd)
-{
-    int  type = RFIFOW (fd, 8), guild_id = RFIFOL (fd, 4);
-    void *data = RFIFOP (fd, 10);
-    struct guild *g = guild_search (guild_id);
-    short dw = *((short *) data);
-    int  dd = *((int *) data);
-    if (g == NULL)
-        return 0;
-    switch (type)
-    {
-        case GBI_EXP:
-            g->exp = dd;
-            break;
-        case GBI_GUILDLV:
-            g->guild_lv = dw;
-            break;
-        case GBI_SKILLPOINT:
-            g->skill_point = dd;
-            break;
-    }
-    return 0;
-}
-
-// ギルドメンバ情報変更通知
-int intif_parse_GuildMemberInfoChanged (int fd)
-{
-    int  type = RFIFOW (fd, 16), guild_id = RFIFOL (fd, 4);
-    int  account_id = RFIFOL (fd, 8), char_id = RFIFOL (fd, 12);
-    void *data = RFIFOP (fd, 18);
-    struct guild *g = guild_search (guild_id);
-    int  idx, dd = *((int *) data);
-    if (g == NULL)
-        return 0;
-    idx = guild_getindex (g, account_id, char_id);
-    switch (type)
-    {
-        case GMI_POSITION:
-            g->member[idx].position = dd;
-            guild_memberposition_changed (g, idx, dd);
-            break;
-        case GMI_EXP:
-            g->member[idx].exp = dd;
-            break;
-    }
-    return 0;
-}
-
-// ギルド役職変更通知
-int intif_parse_GuildPosition (int fd)
-{
-    if (RFIFOW (fd, 2) != sizeof (struct guild_position) + 12)
-    {
-        if (battle_config.error_log)
-            printf ("intif: guild info : data size error\n %d %d %d",
-                    RFIFOL (fd, 4), RFIFOW (fd, 2),
-                    sizeof (struct guild_position) + 12);
-    }
-    guild_position_changed (RFIFOL (fd, 4), RFIFOL (fd, 8),
-                            (struct guild_position *) RFIFOP (fd, 12));
-    return 0;
-}
-
-// ギルドスキル割り振り通知
-int intif_parse_GuildSkillUp (int fd)
-{
-    guild_skillupack (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10));
-    return 0;
-}
-
-// ギルド同盟/敵対通知
-int intif_parse_GuildAlliance (int fd)
-{
-    guild_allianceack (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
-                       RFIFOL (fd, 14), RFIFOB (fd, 18), RFIFOP (fd, 19),
-                       RFIFOP (fd, 43));
-    return 0;
-}
-
-// ギルド告知変更通知
-int intif_parse_GuildNotice (int fd)
-{
-    guild_notice_changed (RFIFOL (fd, 2), RFIFOP (fd, 6), RFIFOP (fd, 66));
-    return 0;
-}
-
-// ギルドエンブレム変更通知
-int intif_parse_GuildEmblem (int fd)
-{
-    guild_emblem_changed (RFIFOW (fd, 2) - 12, RFIFOL (fd, 4), RFIFOL (fd, 8),
-                          RFIFOP (fd, 12));
-    return 0;
-}
-
-// ギルド会話受信
-int intif_parse_GuildMessage (int fd)
-{
-    guild_recv_message (RFIFOL (fd, 4), RFIFOL (fd, 8), RFIFOP (fd, 12),
-                        RFIFOW (fd, 2) - 12);
-    return 0;
-}
-
-// ギルド城データ要求返信
-int intif_parse_GuildCastleDataLoad (int fd)
-{
-    return guild_castledataloadack (RFIFOW (fd, 2), RFIFOB (fd, 4),
-                                    RFIFOL (fd, 5));
-}
-
-// ギルド城データ変更通知
-int intif_parse_GuildCastleDataSave (int fd)
-{
-    return guild_castledatasaveack (RFIFOW (fd, 2), RFIFOB (fd, 4),
-                                    RFIFOL (fd, 5));
-}
-
-// ギルド城データ一括受信(初期化時)
-int intif_parse_GuildCastleAllDataLoad (int fd)
-{
-    return guild_castlealldataload (RFIFOW (fd, 2),
-                                    (struct guild_castle *) RFIFOP (fd, 4));
-}
-
-//-----------------------------------------------------------------
-// inter serverからの通信
-// エラーがあれば0(false)を返すこと
-// パケットが処理できれば1,パケット長が足りなければ2を返すこと
-int intif_parse (int fd)
-{
-    int  packet_len;
-    int  cmd = RFIFOW (fd, 0);
-    // パケットのID確認
-    if (cmd < 0x3800
-        || cmd >=
-        0x3800 + (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
-        || packet_len_table[cmd - 0x3800] == 0)
-    {
-        return 0;
-    }
-    // パケットの長さ確認
-    packet_len = packet_len_table[cmd - 0x3800];
-    if (packet_len == -1)
-    {
-        if (RFIFOREST (fd) < 4)
-            return 2;
-        packet_len = RFIFOW (fd, 2);
-    }
-//  if(battle_config.etc_log)
-//      printf("intif_parse %d %x %d %d\n",fd,cmd,packet_len,RFIFOREST(fd));
-    if (RFIFOREST (fd) < packet_len)
-    {
-        return 2;
-    }
-    // 処理分岐
-    switch (cmd)
-    {
-        case 0x3800:
-            clif_GMmessage (NULL, RFIFOP (fd, 4), packet_len - 4, 0);
-            break;
-        case 0x3801:
-            intif_parse_WisMessage (fd);
-            break;
-        case 0x3802:
-            intif_parse_WisEnd (fd);
-            break;
-        case 0x3803:
-            mapif_parse_WisToGM (fd);
-            break;
-        case 0x3804:
-            intif_parse_AccountReg (fd);
-            break;
-        case 0x3810:
-            intif_parse_LoadStorage (fd);
-            break;
-        case 0x3811:
-            intif_parse_SaveStorage (fd);
-            break;
-        case 0x3818:
-            intif_parse_LoadGuildStorage (fd);
-            break;
-        case 0x3819:
-            intif_parse_SaveGuildStorage (fd);
-            break;
-        case 0x3820:
-            intif_parse_PartyCreated (fd);
-            break;
-        case 0x3821:
-            intif_parse_PartyInfo (fd);
-            break;
-        case 0x3822:
-            intif_parse_PartyMemberAdded (fd);
-            break;
-        case 0x3823:
-            intif_parse_PartyOptionChanged (fd);
-            break;
-        case 0x3824:
-            intif_parse_PartyMemberLeaved (fd);
-            break;
-        case 0x3825:
-            intif_parse_PartyMove (fd);
-            break;
-        case 0x3826:
-            intif_parse_PartyBroken (fd);
-            break;
-        case 0x3827:
-            intif_parse_PartyMessage (fd);
-            break;
-        case 0x3830:
-            intif_parse_GuildCreated (fd);
-            break;
-        case 0x3831:
-            intif_parse_GuildInfo (fd);
-            break;
-        case 0x3832:
-            intif_parse_GuildMemberAdded (fd);
-            break;
-        case 0x3834:
-            intif_parse_GuildMemberLeaved (fd);
-            break;
-        case 0x3835:
-            intif_parse_GuildMemberInfoShort (fd);
-            break;
-        case 0x3836:
-            intif_parse_GuildBroken (fd);
-            break;
-        case 0x3837:
-            intif_parse_GuildMessage (fd);
-            break;
-        case 0x3839:
-            intif_parse_GuildBasicInfoChanged (fd);
-            break;
-        case 0x383a:
-            intif_parse_GuildMemberInfoChanged (fd);
-            break;
-        case 0x383b:
-            intif_parse_GuildPosition (fd);
-            break;
-        case 0x383c:
-            intif_parse_GuildSkillUp (fd);
-            break;
-        case 0x383d:
-            intif_parse_GuildAlliance (fd);
-            break;
-        case 0x383e:
-            intif_parse_GuildNotice (fd);
-            break;
-        case 0x383f:
-            intif_parse_GuildEmblem (fd);
-            break;
-        case 0x3840:
-            intif_parse_GuildCastleDataLoad (fd);
-            break;
-        case 0x3841:
-            intif_parse_GuildCastleDataSave (fd);
-            break;
-        case 0x3842:
-            intif_parse_GuildCastleAllDataLoad (fd);
-            break;
-            //case 0x3880:  intif_parse_CreateP.et(fd); break;
-            //case 0x3881:  intif_parse_RecvP.etData(fd); break;
-            //case 0x3882:  intif_parse_SaveP.etOk(fd); break;
-            //case 0x3883:  intif_parse_DeleteP.etOk(fd); break;
-        default:
-            if (battle_config.error_log)
-                printf ("intif_parse : unknown packet %d %x\n", fd,
-                        RFIFOW (fd, 0));
-            return 0;
-    }
-    // パケット読み飛ばし
-    RFIFOSKIP (fd, packet_len);
-    return 1;
-}
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
new file mode 100644
index 0000000..3ccb13a
--- /dev/null
+++ b/src/map/intif.cpp
@@ -0,0 +1,1201 @@
+// $Id: intif.c,v 1.2 2004/09/25 05:32:18 MouseJstr Exp $
+#include <sys/types.h>
+#ifdef LCCWIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef LCCWIN32
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#endif
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "../common/nullpo.hpp"
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+
+#include "battle.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "map.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "storage.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+static const int packet_len_table[] = {
+    -1, -1, 27, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    -1, 7, 0, 0, 0, 0, 0, 0, -1, 11, 0, 0, 0, 0, 0, 0,
+    35, -1, 11, 15, 34, 29, 7, -1, 0, 0, 0, 0, 0, 0, 0, 0,
+    10, -1, 15, 0, 79, 19, 7, -1, 0, -1, -1, -1, 14, 67, 186, -1,
+    9, 9, -1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    11, -1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+extern int char_fd;             // inter serverのfdはchar_fdを使う
+#define inter_fd (char_fd)      // エイリアス
+
+//-----------------------------------------------------------------
+// inter serverへの送信
+
+// Message for all GMs on all map servers
+int intif_GMmessage (char *mes, int len, int flag)
+{
+    int  lp = (flag & 0x10) ? 8 : 4;
+    WFIFOW (inter_fd, 0) = 0x3000;
+    WFIFOW (inter_fd, 2) = lp + len;
+    WFIFOL (inter_fd, 4) = 0x65756c62;
+    memcpy (WFIFOP (inter_fd, lp), mes, len);
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+
+    return 0;
+}
+
+// The transmission of Wisp/Page to inter-server (player not found on this server)
+int intif_wis_message (struct map_session_data *sd, char *nick, char *mes,
+                       int mes_len)
+{
+    nullpo_retr (0, sd);
+
+    WFIFOW (inter_fd, 0) = 0x3001;
+    WFIFOW (inter_fd, 2) = mes_len + 52;
+    memcpy (WFIFOP (inter_fd, 4), sd->status.name, 24);
+    memcpy (WFIFOP (inter_fd, 28), nick, 24);
+    memcpy (WFIFOP (inter_fd, 52), mes, mes_len);
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+
+    if (battle_config.etc_log)
+        printf ("intif_wis_message from %s to %s (message: '%s')\n",
+                sd->status.name, nick, mes);
+
+    return 0;
+}
+
+// The reply of Wisp/page
+int intif_wis_replay (int id, int flag)
+{
+    WFIFOW (inter_fd, 0) = 0x3002;
+    WFIFOL (inter_fd, 2) = id;
+    WFIFOB (inter_fd, 6) = flag;    // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+    WFIFOSET (inter_fd, 7);
+
+    if (battle_config.etc_log)
+        printf ("intif_wis_replay: id: %d, flag:%d\n", id, flag);
+
+    return 0;
+}
+
+// The transmission of GM only Wisp/Page from server to inter-server
+int intif_wis_message_to_gm (char *Wisp_name, int min_gm_level, char *mes,
+                             int mes_len)
+{
+    WFIFOW (inter_fd, 0) = 0x3003;
+    WFIFOW (inter_fd, 2) = mes_len + 30;
+    memcpy (WFIFOP (inter_fd, 4), Wisp_name, 24);
+    WFIFOW (inter_fd, 28) = (short) min_gm_level;
+    memcpy (WFIFOP (inter_fd, 30), mes, mes_len);
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+
+    if (battle_config.etc_log)
+        printf
+            ("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n",
+             Wisp_name, min_gm_level, mes);
+
+    return 0;
+}
+
+// アカウント変数送信
+int intif_saveaccountreg (struct map_session_data *sd)
+{
+    int  j, p;
+
+    nullpo_retr (0, sd);
+
+    WFIFOW (inter_fd, 0) = 0x3004;
+    WFIFOL (inter_fd, 4) = sd->bl.id;
+    for (j = 0, p = 8; j < sd->status.account_reg_num; j++, p += 36)
+    {
+        memcpy (WFIFOP (inter_fd, p), sd->status.account_reg[j].str, 32);
+        WFIFOL (inter_fd, p + 32) = sd->status.account_reg[j].value;
+    }
+    WFIFOW (inter_fd, 2) = p;
+    WFIFOSET (inter_fd, p);
+    return 0;
+}
+
+// アカウント変数要求
+int intif_request_accountreg (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    WFIFOW (inter_fd, 0) = 0x3005;
+    WFIFOL (inter_fd, 2) = sd->bl.id;
+    WFIFOSET (inter_fd, 6);
+    return 0;
+}
+
+// 倉庫データ要求
+int intif_request_storage (int account_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3010;
+    WFIFOL (inter_fd, 2) = account_id;
+    WFIFOSET (inter_fd, 6);
+    return 0;
+}
+
+// 倉庫データ送信
+int intif_send_storage (struct storage *stor)
+{
+    nullpo_retr (0, stor);
+    WFIFOW (inter_fd, 0) = 0x3011;
+    WFIFOW (inter_fd, 2) = sizeof (struct storage) + 8;
+    WFIFOL (inter_fd, 4) = stor->account_id;
+    memcpy (WFIFOP (inter_fd, 8), stor, sizeof (struct storage));
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+    return 0;
+}
+
+int intif_request_guild_storage (int account_id, int guild_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3018;
+    WFIFOL (inter_fd, 2) = account_id;
+    WFIFOL (inter_fd, 6) = guild_id;
+    WFIFOSET (inter_fd, 10);
+    return 0;
+}
+
+int intif_send_guild_storage (int account_id, struct guild_storage *gstor)
+{
+    WFIFOW (inter_fd, 0) = 0x3019;
+    WFIFOW (inter_fd, 2) = sizeof (struct guild_storage) + 12;
+    WFIFOL (inter_fd, 4) = account_id;
+    WFIFOL (inter_fd, 8) = gstor->guild_id;
+    memcpy (WFIFOP (inter_fd, 12), gstor, sizeof (struct guild_storage));
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+    return 0;
+}
+
+// パーティ作成要求
+int intif_create_party (struct map_session_data *sd, char *name)
+{
+    nullpo_retr (0, sd);
+
+    WFIFOW (inter_fd, 0) = 0x3020;
+    WFIFOL (inter_fd, 2) = sd->status.account_id;
+    memcpy (WFIFOP (inter_fd, 6), name, 24);
+    memcpy (WFIFOP (inter_fd, 30), sd->status.name, 24);
+    memcpy (WFIFOP (inter_fd, 54), map[sd->bl.m].name, 16);
+    WFIFOW (inter_fd, 70) = sd->status.base_level;
+    WFIFOSET (inter_fd, 72);
+//  if(battle_config.etc_log)
+//      printf("intif: create party\n");
+    return 0;
+}
+
+// パーティ情報要求
+int intif_request_partyinfo (int party_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3021;
+    WFIFOL (inter_fd, 2) = party_id;
+    WFIFOSET (inter_fd, 6);
+//  if(battle_config.etc_log)
+//      printf("intif: request party info\n");
+    return 0;
+}
+
+// パーティ追加要求
+int intif_party_addmember (int party_id, int account_id)
+{
+    struct map_session_data *sd;
+    sd = map_id2sd (account_id);
+//  if(battle_config.etc_log)
+//      printf("intif: party add member %d %d\n",party_id,account_id);
+    if (sd != NULL)
+    {
+        WFIFOW (inter_fd, 0) = 0x3022;
+        WFIFOL (inter_fd, 2) = party_id;
+        WFIFOL (inter_fd, 6) = account_id;
+        memcpy (WFIFOP (inter_fd, 10), sd->status.name, 24);
+        memcpy (WFIFOP (inter_fd, 34), map[sd->bl.m].name, 16);
+        WFIFOW (inter_fd, 50) = sd->status.base_level;
+        WFIFOSET (inter_fd, 52);
+    }
+    return 0;
+}
+
+// パーティ設定変更
+int intif_party_changeoption (int party_id, int account_id, int exp, int item)
+{
+    WFIFOW (inter_fd, 0) = 0x3023;
+    WFIFOL (inter_fd, 2) = party_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    WFIFOW (inter_fd, 10) = exp;
+    WFIFOW (inter_fd, 12) = item;
+    WFIFOSET (inter_fd, 14);
+    return 0;
+}
+
+// パーティ脱退要求
+int intif_party_leave (int party_id, int account_id)
+{
+//  if(battle_config.etc_log)
+//      printf("intif: party leave %d %d\n",party_id,account_id);
+    WFIFOW (inter_fd, 0) = 0x3024;
+    WFIFOL (inter_fd, 2) = party_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    WFIFOSET (inter_fd, 10);
+    return 0;
+}
+
+// パーティ移動要求
+int intif_party_changemap (struct map_session_data *sd, int online)
+{
+    if (sd != NULL)
+    {
+        WFIFOW (inter_fd, 0) = 0x3025;
+        WFIFOL (inter_fd, 2) = sd->status.party_id;
+        WFIFOL (inter_fd, 6) = sd->status.account_id;
+        memcpy (WFIFOP (inter_fd, 10), map[sd->bl.m].name, 16);
+        WFIFOB (inter_fd, 26) = online;
+        WFIFOW (inter_fd, 27) = sd->status.base_level;
+        WFIFOSET (inter_fd, 29);
+    }
+//  if(battle_config.etc_log)
+//      printf("party: change map\n");
+    return 0;
+}
+
+// パーティー解散要求
+int intif_break_party (int party_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3026;
+    WFIFOL (inter_fd, 2) = party_id;
+    WFIFOSET (inter_fd, 6);
+    return 0;
+}
+
+// パーティ会話送信
+int intif_party_message (int party_id, int account_id, char *mes, int len)
+{
+//  if(battle_config.etc_log)
+//      printf("intif_party_message: %s\n",mes);
+    WFIFOW (inter_fd, 0) = 0x3027;
+    WFIFOW (inter_fd, 2) = len + 12;
+    WFIFOL (inter_fd, 4) = party_id;
+    WFIFOL (inter_fd, 8) = account_id;
+    memcpy (WFIFOP (inter_fd, 12), mes, len);
+    WFIFOSET (inter_fd, len + 12);
+    return 0;
+}
+
+// パーティ競合チェック要求
+int intif_party_checkconflict (int party_id, int account_id, char *nick)
+{
+    WFIFOW (inter_fd, 0) = 0x3028;
+    WFIFOL (inter_fd, 2) = party_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    memcpy (WFIFOP (inter_fd, 10), nick, 24);
+    WFIFOSET (inter_fd, 34);
+    return 0;
+}
+
+// ギルド作成要求
+int intif_guild_create (const char *name, const struct guild_member *master)
+{
+    nullpo_retr (0, master);
+
+    WFIFOW (inter_fd, 0) = 0x3030;
+    WFIFOW (inter_fd, 2) = sizeof (struct guild_member) + 32;
+    WFIFOL (inter_fd, 4) = master->account_id;
+    memcpy (WFIFOP (inter_fd, 8), name, 24);
+    memcpy (WFIFOP (inter_fd, 32), master, sizeof (struct guild_member));
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+    return 0;
+}
+
+// ギルド情報要求
+int intif_guild_request_info (int guild_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3031;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOSET (inter_fd, 6);
+    return 0;
+}
+
+// ギルドメンバ追加要求
+int intif_guild_addmember (int guild_id, struct guild_member *m)
+{
+    WFIFOW (inter_fd, 0) = 0x3032;
+    WFIFOW (inter_fd, 2) = sizeof (struct guild_member) + 8;
+    WFIFOL (inter_fd, 4) = guild_id;
+    memcpy (WFIFOP (inter_fd, 8), m, sizeof (struct guild_member));
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+    return 0;
+}
+
+// ギルドメンバ脱退/追放要求
+int intif_guild_leave (int guild_id, int account_id, int char_id, int flag,
+                       const char *mes)
+{
+    WFIFOW (inter_fd, 0) = 0x3034;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    WFIFOL (inter_fd, 10) = char_id;
+    WFIFOB (inter_fd, 14) = flag;
+    memcpy (WFIFOP (inter_fd, 15), mes, 40);
+    WFIFOSET (inter_fd, 55);
+    return 0;
+}
+
+// ギルドメンバのオンライン状況/Lv更新要求
+int intif_guild_memberinfoshort (int guild_id,
+                                 int account_id, int char_id, int online,
+                                 int lv, int class_)
+{
+    WFIFOW (inter_fd, 0) = 0x3035;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    WFIFOL (inter_fd, 10) = char_id;
+    WFIFOB (inter_fd, 14) = online;
+    WFIFOW (inter_fd, 15) = lv;
+    WFIFOW (inter_fd, 17) = class_;
+    WFIFOSET (inter_fd, 19);
+    return 0;
+}
+
+// ギルド解散通知
+int intif_guild_break (int guild_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3036;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOSET (inter_fd, 6);
+    return 0;
+}
+
+// ギルド会話送信
+int intif_guild_message (int guild_id, int account_id, char *mes, int len)
+{
+    WFIFOW (inter_fd, 0) = 0x3037;
+    WFIFOW (inter_fd, 2) = len + 12;
+    WFIFOL (inter_fd, 4) = guild_id;
+    WFIFOL (inter_fd, 8) = account_id;
+    memcpy (WFIFOP (inter_fd, 12), mes, len);
+    WFIFOSET (inter_fd, len + 12);
+    return 0;
+}
+
+// ギルド競合チェック要求
+int intif_guild_checkconflict (int guild_id, int account_id, int char_id)
+{
+    WFIFOW (inter_fd, 0) = 0x3038;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOL (inter_fd, 6) = account_id;
+    WFIFOL (inter_fd, 10) = char_id;
+    WFIFOSET (inter_fd, 14);
+    return 0;
+}
+
+// ギルド基本情報変更要求
+int intif_guild_change_basicinfo (int guild_id, int type, const void *data,
+                                  int len)
+{
+    WFIFOW (inter_fd, 0) = 0x3039;
+    WFIFOW (inter_fd, 2) = len + 10;
+    WFIFOL (inter_fd, 4) = guild_id;
+    WFIFOW (inter_fd, 8) = type;
+    memcpy (WFIFOP (inter_fd, 10), data, len);
+    WFIFOSET (inter_fd, len + 10);
+    return 0;
+}
+
+// ギルドメンバ情報変更要求
+int intif_guild_change_memberinfo (int guild_id, int account_id, int char_id,
+                                   int type, const void *data, int len)
+{
+    WFIFOW (inter_fd, 0) = 0x303a;
+    WFIFOW (inter_fd, 2) = len + 18;
+    WFIFOL (inter_fd, 4) = guild_id;
+    WFIFOL (inter_fd, 8) = account_id;
+    WFIFOL (inter_fd, 12) = char_id;
+    WFIFOW (inter_fd, 16) = type;
+    memcpy (WFIFOP (inter_fd, 18), data, len);
+    WFIFOSET (inter_fd, len + 18);
+    return 0;
+}
+
+// ギルド役職変更要求
+int intif_guild_position (int guild_id, int idx, struct guild_position *p)
+{
+    WFIFOW (inter_fd, 0) = 0x303b;
+    WFIFOW (inter_fd, 2) = sizeof (struct guild_position) + 12;
+    WFIFOL (inter_fd, 4) = guild_id;
+    WFIFOL (inter_fd, 8) = idx;
+    memcpy (WFIFOP (inter_fd, 12), p, sizeof (struct guild_position));
+    WFIFOSET (inter_fd, WFIFOW (inter_fd, 2));
+    return 0;
+}
+
+// ギルドスキルアップ要求
+int intif_guild_skillup (int guild_id, int skill_num, int account_id)
+{
+    WFIFOW (inter_fd, 0) = 0x303c;
+    WFIFOL (inter_fd, 2) = guild_id;
+    WFIFOL (inter_fd, 6) = skill_num;
+    WFIFOL (inter_fd, 10) = account_id;
+    WFIFOSET (inter_fd, 14);
+    return 0;
+}
+
+// ギルド同盟/敵対要求
+int intif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
+                          int account_id2, int flag)
+{
+    WFIFOW (inter_fd, 0) = 0x303d;
+    WFIFOL (inter_fd, 2) = guild_id1;
+    WFIFOL (inter_fd, 6) = guild_id2;
+    WFIFOL (inter_fd, 10) = account_id1;
+    WFIFOL (inter_fd, 14) = account_id2;
+    WFIFOB (inter_fd, 18) = flag;
+    WFIFOSET (inter_fd, 19);
+    return 0;
+}
+
+// ギルド告知変更要求
+int intif_guild_notice (int guild_id, const char *mes1, const char *mes2)
+{
+    WFIFOW (inter_fd, 0) = 0x303e;
+    WFIFOL (inter_fd, 2) = guild_id;
+    memcpy (WFIFOP (inter_fd, 6), mes1, 60);
+    memcpy (WFIFOP (inter_fd, 66), mes2, 120);
+    WFIFOSET (inter_fd, 186);
+    return 0;
+}
+
+// ギルドエンブレム変更要求
+int intif_guild_emblem (int guild_id, int len, const char *data)
+{
+    if (guild_id <= 0 || len < 0 || len > 2000)
+        return 0;
+    WFIFOW (inter_fd, 0) = 0x303f;
+    WFIFOW (inter_fd, 2) = len + 12;
+    WFIFOL (inter_fd, 4) = guild_id;
+    WFIFOL (inter_fd, 8) = 0;
+    memcpy (WFIFOP (inter_fd, 12), data, len);
+    WFIFOSET (inter_fd, len + 12);
+    return 0;
+}
+
+//現在のギルド城占領ギルドを調べる
+int intif_guild_castle_dataload (int castle_id, int index)
+{
+    WFIFOW (inter_fd, 0) = 0x3040;
+    WFIFOW (inter_fd, 2) = castle_id;
+    WFIFOB (inter_fd, 4) = index;
+    WFIFOSET (inter_fd, 5);
+    return 0;
+}
+
+//ギルド城占領ギルド変更要求
+int intif_guild_castle_datasave (int castle_id, int index, int value)
+{
+    WFIFOW (inter_fd, 0) = 0x3041;
+    WFIFOW (inter_fd, 2) = castle_id;
+    WFIFOB (inter_fd, 4) = index;
+    WFIFOL (inter_fd, 5) = value;
+    WFIFOSET (inter_fd, 9);
+    return 0;
+}
+
+//-----------------------------------------------------------------
+// Packets receive from inter server
+
+// Wisp/Page reception
+int intif_parse_WisMessage (int fd)
+{                               // rewritten by [Yor]
+    struct map_session_data *sd;
+    int  i;
+    char *wisp_source;
+
+    if (battle_config.etc_log)
+        printf
+            ("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n",
+             RFIFOL (fd, 4), RFIFOP (fd, 8), RFIFOP (fd, 32), RFIFOP (fd,
+                                                                      56));
+    sd = map_nick2sd (RFIFOP (fd, 32)); // Searching destination player
+    if (sd != NULL && strcmp (sd->status.name, RFIFOP (fd, 32)) == 0)
+    {                           // exactly same name (inter-server have checked the name before)
+        // if player ignore all
+        if (sd->ignoreAll == 1)
+            intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+        else
+        {
+            wisp_source = RFIFOP (fd, 8);   // speed up
+            // if player ignore the source character
+            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
+                 i++)
+                if (strcmp (sd->ignore[i].name, wisp_source) == 0)
+                {
+                    intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+                    break;
+                }
+            // if source player not found in ignore list
+            if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
+            {
+                clif_wis_message (sd->fd, RFIFOP (fd, 8), RFIFOP (fd, 56),
+                                  RFIFOW (fd, 2) - 56);
+                intif_wis_replay (RFIFOL (fd, 4), 0);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+            }
+        }
+    }
+    else
+        intif_wis_replay (RFIFOL (fd, 4), 1);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+    return 0;
+}
+
+// Wisp/page transmission result reception
+int intif_parse_WisEnd (int fd)
+{
+    struct map_session_data *sd;
+
+    if (battle_config.etc_log)
+        printf ("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP (fd, 2), RFIFOB (fd, 26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
+    sd = map_nick2sd (RFIFOP (fd, 2));
+    if (sd != NULL)
+        clif_wis_end (sd->fd, RFIFOB (fd, 26));
+
+    return 0;
+}
+
+// Received wisp message from map-server via char-server for ALL gm
+int mapif_parse_WisToGM (int fd)
+{                               // 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B
+    int  i, min_gm_level, len;
+    struct map_session_data *pl_sd;
+    char Wisp_name[24];
+    char mbuf[255];
+
+    if (RFIFOW (fd, 2) - 30 <= 0)
+        return 0;
+
+    len = RFIFOW (fd, 2) - 30;
+    char *message = ((len) >= 255) ? (char *) malloc (len) : mbuf;
+
+    min_gm_level = (int) RFIFOW (fd, 28);
+    memcpy (Wisp_name, RFIFOP (fd, 4), 24);
+    Wisp_name[23] = '\0';
+    memcpy (message, RFIFOP (fd, 30), len);
+    message[len - 1] = '\0';
+    // information is sended to all online GM
+    for (i = 0; i < fd_max; i++)
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+            if (pc_isGM (pl_sd) >= min_gm_level)
+                clif_wis_message (i, Wisp_name, message,
+                                  strlen (message) + 1);
+
+    if (message != mbuf)
+        free (message);
+
+    return 0;
+}
+
+// アカウント変数通知
+int intif_parse_AccountReg (int fd)
+{
+    int  j, p;
+    struct map_session_data *sd;
+
+    if ((sd = map_id2sd (RFIFOL (fd, 4))) == NULL)
+        return 1;
+    for (p = 8, j = 0; p < RFIFOW (fd, 2) && j < ACCOUNT_REG_NUM;
+         p += 36, j++)
+    {
+        memcpy (sd->status.account_reg[j].str, RFIFOP (fd, p), 32);
+        sd->status.account_reg[j].value = RFIFOL (fd, p + 32);
+    }
+    sd->status.account_reg_num = j;
+//  printf("intif: accountreg\n");
+
+    return 0;
+}
+
+// 倉庫データ受信
+int intif_parse_LoadStorage (int fd)
+{
+    struct storage *stor;
+    struct map_session_data *sd;
+
+    sd = map_id2sd (RFIFOL (fd, 4));
+    if (sd == NULL)
+    {
+        if (battle_config.error_log)
+            printf ("intif_parse_LoadStorage: user not found %d\n",
+                    RFIFOL (fd, 4));
+        return 1;
+    }
+    stor = account2storage (RFIFOL (fd, 4));
+    if (stor->storage_status == 1)
+    {                           // Already open.. lets ignore this update
+        if (battle_config.error_log)
+            printf
+                ("intif_parse_LoadStorage: storage received for a client already open (User %d:%d)\n",
+                 sd->status.account_id, sd->status.char_id);
+        return 1;
+    }
+    if (stor->dirty)
+    {                           // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
+        if (battle_config.error_log)
+            printf
+                ("intif_parse_LoadStorage: received storage for an already modified non-saved storage! (User %d:%d)\n",
+                 sd->status.account_id, sd->status.char_id);
+        return 1;
+    }
+
+    if (RFIFOW (fd, 2) - 8 != sizeof (struct storage))
+    {
+        if (battle_config.error_log)
+            printf ("intif_parse_LoadStorage: data size error %d %d\n",
+                    RFIFOW (fd, 2) - 8, sizeof (struct storage));
+        return 1;
+    }
+    if (battle_config.save_log)
+        printf ("intif_openstorage: %d\n", RFIFOL (fd, 4));
+    memcpy (stor, RFIFOP (fd, 8), sizeof (struct storage));
+    stor->dirty = 0;
+    stor->storage_status = 1;
+    sd->state.storage_flag = 1;
+    clif_storageitemlist (sd, stor);
+    clif_storageequiplist (sd, stor);
+    clif_updatestorageamount (sd, stor);
+
+    return 0;
+}
+
+// 倉庫データ送信成功
+int intif_parse_SaveStorage (int fd)
+{
+    if (battle_config.save_log)
+        printf ("intif_savestorage: done %d %d\n", RFIFOL (fd, 2),
+                RFIFOB (fd, 6));
+    storage_storage_saved (RFIFOL (fd, 2));
+    return 0;
+}
+
+int intif_parse_LoadGuildStorage (int fd)
+{
+    struct guild_storage *gstor;
+    struct map_session_data *sd;
+    int  guild_id;
+
+    guild_id = RFIFOL (fd, 8);
+    if (guild_id > 0)
+    {
+        gstor = guild2storage (guild_id);
+        if (!gstor)
+        {
+            if (battle_config.error_log)
+                printf
+                    ("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",
+                     guild_id);
+            return 1;
+        }
+        if (RFIFOW (fd, 2) - 12 != sizeof (struct guild_storage))
+        {
+            gstor->storage_status = 0;
+            if (battle_config.error_log)
+                printf
+                    ("intif_parse_LoadGuildStorage: data size error %d %d\n",
+                     RFIFOW (fd, 2) - 12, sizeof (struct guild_storage));
+            return 1;
+        }
+        sd = map_id2sd (RFIFOL (fd, 4));
+        if (sd == NULL)
+        {
+            if (battle_config.error_log)
+                printf ("intif_parse_LoadGuildStorage: user not found %d\n",
+                        RFIFOL (fd, 4));
+            return 1;
+        }
+        if (gstor->storage_status == 1)
+        {                       // Already open.. lets ignore this update
+            if (battle_config.error_log)
+                printf
+                    ("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n",
+                     sd->status.account_id, sd->status.char_id);
+            return 1;
+        }
+        if (gstor->dirty)
+        {                       // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
+            if (battle_config.error_log)
+                printf
+                    ("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n",
+                     sd->status.account_id, sd->status.char_id);
+            return 1;
+        }
+        if (battle_config.save_log)
+            printf ("intif_open_guild_storage: %d\n", RFIFOL (fd, 4));
+        memcpy (gstor, RFIFOP (fd, 12), sizeof (struct guild_storage));
+        gstor->storage_status = 1;
+        sd->state.storage_flag = 2;
+        clif_guildstorageitemlist (sd, gstor);
+        clif_guildstorageequiplist (sd, gstor);
+        clif_updateguildstorageamount (sd, gstor);
+    }
+    return 0;
+}
+
+int intif_parse_SaveGuildStorage (int fd)
+{
+    if (battle_config.save_log)
+    {
+        printf ("intif_save_guild_storage: done %d %d %d\n", RFIFOL (fd, 2),
+                RFIFOL (fd, 6), RFIFOB (fd, 10));
+    }
+    storage_guild_storagesaved ( /*RFIFOL(fd,2), */ RFIFOL (fd, 6));
+    return 0;
+}
+
+// パーティ作成可否
+int intif_parse_PartyCreated (int fd)
+{
+    if (battle_config.etc_log)
+        printf ("intif: party created\n");
+    party_created (RFIFOL (fd, 2), RFIFOB (fd, 6), RFIFOL (fd, 7),
+                   RFIFOP (fd, 11));
+    return 0;
+}
+
+// パーティ情報
+int intif_parse_PartyInfo (int fd)
+{
+    if (RFIFOW (fd, 2) == 8)
+    {
+        if (battle_config.error_log)
+            printf ("intif: party noinfo %d\n", RFIFOL (fd, 4));
+        party_recv_noinfo (RFIFOL (fd, 4));
+        return 0;
+    }
+
+//  printf("intif: party info %d\n",RFIFOL(fd,4));
+    if (RFIFOW (fd, 2) != sizeof (struct party) + 4)
+    {
+        if (battle_config.error_log)
+            printf ("intif: party info : data size error %d %d %d\n",
+                    RFIFOL (fd, 4), RFIFOW (fd, 2),
+                    sizeof (struct party) + 4);
+    }
+    party_recv_info ((struct party *) RFIFOP (fd, 4));
+    return 0;
+}
+
+// パーティ追加通知
+int intif_parse_PartyMemberAdded (int fd)
+{
+    if (battle_config.etc_log)
+        printf ("intif: party member added %d %d %d\n", RFIFOL (fd, 2),
+                RFIFOL (fd, 6), RFIFOB (fd, 10));
+    party_member_added (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOB (fd, 10));
+    return 0;
+}
+
+// パーティ設定変更通知
+int intif_parse_PartyOptionChanged (int fd)
+{
+    party_optionchanged (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOW (fd, 10),
+                         RFIFOW (fd, 12), RFIFOB (fd, 14));
+    return 0;
+}
+
+// パーティ脱退通知
+int intif_parse_PartyMemberLeaved (int fd)
+{
+    if (battle_config.etc_log)
+        printf ("intif: party member leaved %d %d %s\n", RFIFOL (fd, 2),
+                RFIFOL (fd, 6), RFIFOP (fd, 10));
+    party_member_leaved (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOP (fd, 10));
+    return 0;
+}
+
+// パーティ解散通知
+int intif_parse_PartyBroken (int fd)
+{
+    party_broken (RFIFOL (fd, 2));
+    return 0;
+}
+
+// パーティ移動通知
+int intif_parse_PartyMove (int fd)
+{
+//  if(battle_config.etc_log)
+//      printf("intif: party move %d %d %s %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27));
+    party_recv_movemap (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOP (fd, 10),
+                        RFIFOB (fd, 26), RFIFOW (fd, 27));
+    return 0;
+}
+
+// パーティメッセージ
+int intif_parse_PartyMessage (int fd)
+{
+//  if(battle_config.etc_log)
+//      printf("intif_parse_PartyMessage: %s\n",RFIFOP(fd,12));
+    party_recv_message (RFIFOL (fd, 4), RFIFOL (fd, 8), RFIFOP (fd, 12),
+                        RFIFOW (fd, 2) - 12);
+    return 0;
+}
+
+// ギルド作成可否
+int intif_parse_GuildCreated (int fd)
+{
+    guild_created (RFIFOL (fd, 2), RFIFOL (fd, 6));
+    return 0;
+}
+
+// ギルド情報
+int intif_parse_GuildInfo (int fd)
+{
+    if (RFIFOW (fd, 2) == 8)
+    {
+        if (battle_config.error_log)
+            printf ("intif: guild noinfo %d\n", RFIFOL (fd, 4));
+        guild_recv_noinfo (RFIFOL (fd, 4));
+        return 0;
+    }
+
+//  if(battle_config.etc_log)
+//      printf("intif: guild info %d\n",RFIFOL(fd,4));
+    if (RFIFOW (fd, 2) != sizeof (struct guild) + 4)
+    {
+        if (battle_config.error_log)
+            printf ("intif: guild info : data size error\n %d %d %d",
+                    RFIFOL (fd, 4), RFIFOW (fd, 2),
+                    sizeof (struct guild) + 4);
+    }
+    guild_recv_info ((struct guild *) RFIFOP (fd, 4));
+    return 0;
+}
+
+// ギルドメンバ追加通知
+int intif_parse_GuildMemberAdded (int fd)
+{
+    if (battle_config.etc_log)
+        printf ("intif: guild member added %d %d %d %d\n", RFIFOL (fd, 2),
+                RFIFOL (fd, 6), RFIFOL (fd, 10), RFIFOB (fd, 14));
+    guild_member_added (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
+                        RFIFOB (fd, 14));
+    return 0;
+}
+
+// ギルドメンバ脱退/追放通知
+int intif_parse_GuildMemberLeaved (int fd)
+{
+    guild_member_leaved (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
+                         RFIFOB (fd, 14), RFIFOP (fd, 55), RFIFOP (fd, 15));
+    return 0;
+}
+
+// ギルドメンバオンライン状態/Lv変更通知
+int intif_parse_GuildMemberInfoShort (int fd)
+{
+    guild_recv_memberinfoshort (RFIFOL (fd, 2), RFIFOL (fd, 6),
+                                RFIFOL (fd, 10), RFIFOB (fd, 14), RFIFOW (fd,
+                                                                          15),
+                                RFIFOW (fd, 17));
+    return 0;
+}
+
+// ギルド解散通知
+int intif_parse_GuildBroken (int fd)
+{
+    guild_broken (RFIFOL (fd, 2), RFIFOB (fd, 6));
+    return 0;
+}
+
+// ギルド基本情報変更通知
+int intif_parse_GuildBasicInfoChanged (int fd)
+{
+    int  type = RFIFOW (fd, 8), guild_id = RFIFOL (fd, 4);
+    void *data = RFIFOP (fd, 10);
+    struct guild *g = guild_search (guild_id);
+    short dw = *((short *) data);
+    int  dd = *((int *) data);
+    if (g == NULL)
+        return 0;
+    switch (type)
+    {
+        case GBI_EXP:
+            g->exp = dd;
+            break;
+        case GBI_GUILDLV:
+            g->guild_lv = dw;
+            break;
+        case GBI_SKILLPOINT:
+            g->skill_point = dd;
+            break;
+    }
+    return 0;
+}
+
+// ギルドメンバ情報変更通知
+int intif_parse_GuildMemberInfoChanged (int fd)
+{
+    int  type = RFIFOW (fd, 16), guild_id = RFIFOL (fd, 4);
+    int  account_id = RFIFOL (fd, 8), char_id = RFIFOL (fd, 12);
+    void *data = RFIFOP (fd, 18);
+    struct guild *g = guild_search (guild_id);
+    int  idx, dd = *((int *) data);
+    if (g == NULL)
+        return 0;
+    idx = guild_getindex (g, account_id, char_id);
+    switch (type)
+    {
+        case GMI_POSITION:
+            g->member[idx].position = dd;
+            guild_memberposition_changed (g, idx, dd);
+            break;
+        case GMI_EXP:
+            g->member[idx].exp = dd;
+            break;
+    }
+    return 0;
+}
+
+// ギルド役職変更通知
+int intif_parse_GuildPosition (int fd)
+{
+    if (RFIFOW (fd, 2) != sizeof (struct guild_position) + 12)
+    {
+        if (battle_config.error_log)
+            printf ("intif: guild info : data size error\n %d %d %d",
+                    RFIFOL (fd, 4), RFIFOW (fd, 2),
+                    sizeof (struct guild_position) + 12);
+    }
+    guild_position_changed (RFIFOL (fd, 4), RFIFOL (fd, 8),
+                            (struct guild_position *) RFIFOP (fd, 12));
+    return 0;
+}
+
+// ギルドスキル割り振り通知
+int intif_parse_GuildSkillUp (int fd)
+{
+    guild_skillupack (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10));
+    return 0;
+}
+
+// ギルド同盟/敵対通知
+int intif_parse_GuildAlliance (int fd)
+{
+    guild_allianceack (RFIFOL (fd, 2), RFIFOL (fd, 6), RFIFOL (fd, 10),
+                       RFIFOL (fd, 14), RFIFOB (fd, 18), RFIFOP (fd, 19),
+                       RFIFOP (fd, 43));
+    return 0;
+}
+
+// ギルド告知変更通知
+int intif_parse_GuildNotice (int fd)
+{
+    guild_notice_changed (RFIFOL (fd, 2), RFIFOP (fd, 6), RFIFOP (fd, 66));
+    return 0;
+}
+
+// ギルドエンブレム変更通知
+int intif_parse_GuildEmblem (int fd)
+{
+    guild_emblem_changed (RFIFOW (fd, 2) - 12, RFIFOL (fd, 4), RFIFOL (fd, 8),
+                          RFIFOP (fd, 12));
+    return 0;
+}
+
+// ギルド会話受信
+int intif_parse_GuildMessage (int fd)
+{
+    guild_recv_message (RFIFOL (fd, 4), RFIFOL (fd, 8), RFIFOP (fd, 12),
+                        RFIFOW (fd, 2) - 12);
+    return 0;
+}
+
+// ギルド城データ要求返信
+int intif_parse_GuildCastleDataLoad (int fd)
+{
+    return guild_castledataloadack (RFIFOW (fd, 2), RFIFOB (fd, 4),
+                                    RFIFOL (fd, 5));
+}
+
+// ギルド城データ変更通知
+int intif_parse_GuildCastleDataSave (int fd)
+{
+    return guild_castledatasaveack (RFIFOW (fd, 2), RFIFOB (fd, 4),
+                                    RFIFOL (fd, 5));
+}
+
+// ギルド城データ一括受信(初期化時)
+int intif_parse_GuildCastleAllDataLoad (int fd)
+{
+    return guild_castlealldataload (RFIFOW (fd, 2),
+                                    (struct guild_castle *) RFIFOP (fd, 4));
+}
+
+//-----------------------------------------------------------------
+// inter serverからの通信
+// エラーがあれば0(false)を返すこと
+// パケットが処理できれば1,パケット長が足りなければ2を返すこと
+int intif_parse (int fd)
+{
+    int  packet_len;
+    int  cmd = RFIFOW (fd, 0);
+    // パケットのID確認
+    if (cmd < 0x3800
+        || cmd >=
+        0x3800 + (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
+        || packet_len_table[cmd - 0x3800] == 0)
+    {
+        return 0;
+    }
+    // パケットの長さ確認
+    packet_len = packet_len_table[cmd - 0x3800];
+    if (packet_len == -1)
+    {
+        if (RFIFOREST (fd) < 4)
+            return 2;
+        packet_len = RFIFOW (fd, 2);
+    }
+//  if(battle_config.etc_log)
+//      printf("intif_parse %d %x %d %d\n",fd,cmd,packet_len,RFIFOREST(fd));
+    if (RFIFOREST (fd) < packet_len)
+    {
+        return 2;
+    }
+    // 処理分岐
+    switch (cmd)
+    {
+        case 0x3800:
+            clif_GMmessage (NULL, RFIFOP (fd, 4), packet_len - 4, 0);
+            break;
+        case 0x3801:
+            intif_parse_WisMessage (fd);
+            break;
+        case 0x3802:
+            intif_parse_WisEnd (fd);
+            break;
+        case 0x3803:
+            mapif_parse_WisToGM (fd);
+            break;
+        case 0x3804:
+            intif_parse_AccountReg (fd);
+            break;
+        case 0x3810:
+            intif_parse_LoadStorage (fd);
+            break;
+        case 0x3811:
+            intif_parse_SaveStorage (fd);
+            break;
+        case 0x3818:
+            intif_parse_LoadGuildStorage (fd);
+            break;
+        case 0x3819:
+            intif_parse_SaveGuildStorage (fd);
+            break;
+        case 0x3820:
+            intif_parse_PartyCreated (fd);
+            break;
+        case 0x3821:
+            intif_parse_PartyInfo (fd);
+            break;
+        case 0x3822:
+            intif_parse_PartyMemberAdded (fd);
+            break;
+        case 0x3823:
+            intif_parse_PartyOptionChanged (fd);
+            break;
+        case 0x3824:
+            intif_parse_PartyMemberLeaved (fd);
+            break;
+        case 0x3825:
+            intif_parse_PartyMove (fd);
+            break;
+        case 0x3826:
+            intif_parse_PartyBroken (fd);
+            break;
+        case 0x3827:
+            intif_parse_PartyMessage (fd);
+            break;
+        case 0x3830:
+            intif_parse_GuildCreated (fd);
+            break;
+        case 0x3831:
+            intif_parse_GuildInfo (fd);
+            break;
+        case 0x3832:
+            intif_parse_GuildMemberAdded (fd);
+            break;
+        case 0x3834:
+            intif_parse_GuildMemberLeaved (fd);
+            break;
+        case 0x3835:
+            intif_parse_GuildMemberInfoShort (fd);
+            break;
+        case 0x3836:
+            intif_parse_GuildBroken (fd);
+            break;
+        case 0x3837:
+            intif_parse_GuildMessage (fd);
+            break;
+        case 0x3839:
+            intif_parse_GuildBasicInfoChanged (fd);
+            break;
+        case 0x383a:
+            intif_parse_GuildMemberInfoChanged (fd);
+            break;
+        case 0x383b:
+            intif_parse_GuildPosition (fd);
+            break;
+        case 0x383c:
+            intif_parse_GuildSkillUp (fd);
+            break;
+        case 0x383d:
+            intif_parse_GuildAlliance (fd);
+            break;
+        case 0x383e:
+            intif_parse_GuildNotice (fd);
+            break;
+        case 0x383f:
+            intif_parse_GuildEmblem (fd);
+            break;
+        case 0x3840:
+            intif_parse_GuildCastleDataLoad (fd);
+            break;
+        case 0x3841:
+            intif_parse_GuildCastleDataSave (fd);
+            break;
+        case 0x3842:
+            intif_parse_GuildCastleAllDataLoad (fd);
+            break;
+            //case 0x3880:  intif_parse_CreateP.et(fd); break;
+            //case 0x3881:  intif_parse_RecvP.etData(fd); break;
+            //case 0x3882:  intif_parse_SaveP.etOk(fd); break;
+            //case 0x3883:  intif_parse_DeleteP.etOk(fd); break;
+        default:
+            if (battle_config.error_log)
+                printf ("intif_parse : unknown packet %d %x\n", fd,
+                        RFIFOW (fd, 0));
+            return 0;
+    }
+    // パケット読み飛ばし
+    RFIFOSKIP (fd, packet_len);
+    return 1;
+}
diff --git a/src/map/intif.h b/src/map/intif.h
deleted file mode 100644
index 374c95a..0000000
--- a/src/map/intif.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// $Id: intif.h,v 1.2 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _INTIF_H_
-#define _INFIF_H_
-
-int  intif_parse (int fd);
-
-int  intif_GMmessage (char *mes, int len, int flag);
-
-int  intif_wis_message (struct map_session_data *sd, char *nick, char *mes,
-                        int mes_len);
-int  intif_wis_message_to_gm (char *Wisp_name, int min_gm_level, char *mes,
-                              int mes_len);
-
-int  intif_saveaccountreg (struct map_session_data *sd);
-int  intif_request_accountreg (struct map_session_data *sd);
-
-int  intif_request_storage (int account_id);
-int  intif_send_storage (struct storage *stor);
-int  intif_request_guild_storage (int account_id, int guild_id);
-int  intif_send_guild_storage (int account_id, struct guild_storage *gstor);
-
-int  intif_create_party (struct map_session_data *sd, char *name);
-int  intif_request_partyinfo (int party_id);
-int  intif_party_addmember (int party_id, int account_id);
-int  intif_party_changeoption (int party_id, int account_id, int exp,
-                               int item);
-int  intif_party_leave (int party_id, int accound_id);
-int  intif_party_changemap (struct map_session_data *sd, int online);
-int  intif_break_party (int party_id);
-int  intif_party_message (int party_id, int account_id, char *mes, int len);
-int  intif_party_checkconflict (int party_id, int account_id, char *nick);
-
-int  intif_guild_create (const char *name, const struct guild_member *master);
-int  intif_guild_request_info (int guild_id);
-int  intif_guild_addmember (int guild_id, struct guild_member *m);
-int  intif_guild_leave (int guild_id, int account_id, int char_id, int flag,
-                        const char *mes);
-int  intif_guild_memberinfoshort (int guild_id, int account_id, int char_id,
-                                  int online, int lv, int class_);
-int  intif_guild_break (int guild_id);
-int  intif_guild_message (int guild_id, int account_id, char *mes, int len);
-int  intif_guild_checkconflict (int guild_id, int account_id, int char_id);
-int  intif_guild_change_basicinfo (int guild_id, int type, const void *data,
-                                   int len);
-int  intif_guild_change_memberinfo (int guild_id, int account_id, int char_id,
-                                    int type, const void *data, int len);
-int  intif_guild_position (int guild_id, int idx, struct guild_position *p);
-int  intif_guild_skillup (int guild_id, int skill_num, int account_id);
-int  intif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
-                           int account_id2, int flag);
-int  intif_guild_notice (int guild_id, const char *mes1, const char *mes2);
-int  intif_guild_emblem (int guild_id, int len, const char *data);
-int  intif_guild_castle_dataload (int castle_id, int index);
-int  intif_guild_castle_datasave (int castle_id, int index, int value);
-
-#endif
diff --git a/src/map/intif.hpp b/src/map/intif.hpp
new file mode 100644
index 0000000..dc002e5
--- /dev/null
+++ b/src/map/intif.hpp
@@ -0,0 +1,56 @@
+// $Id: intif.h,v 1.2 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef INTIF_HPP
+#define INFIF_HPP
+
+int  intif_parse (int fd);
+
+int  intif_GMmessage (char *mes, int len, int flag);
+
+int  intif_wis_message (struct map_session_data *sd, char *nick, char *mes,
+                        int mes_len);
+int  intif_wis_message_to_gm (char *Wisp_name, int min_gm_level, char *mes,
+                              int mes_len);
+
+int  intif_saveaccountreg (struct map_session_data *sd);
+int  intif_request_accountreg (struct map_session_data *sd);
+
+int  intif_request_storage (int account_id);
+int  intif_send_storage (struct storage *stor);
+int  intif_request_guild_storage (int account_id, int guild_id);
+int  intif_send_guild_storage (int account_id, struct guild_storage *gstor);
+
+int  intif_create_party (struct map_session_data *sd, char *name);
+int  intif_request_partyinfo (int party_id);
+int  intif_party_addmember (int party_id, int account_id);
+int  intif_party_changeoption (int party_id, int account_id, int exp,
+                               int item);
+int  intif_party_leave (int party_id, int accound_id);
+int  intif_party_changemap (struct map_session_data *sd, int online);
+int  intif_break_party (int party_id);
+int  intif_party_message (int party_id, int account_id, char *mes, int len);
+int  intif_party_checkconflict (int party_id, int account_id, char *nick);
+
+int  intif_guild_create (const char *name, const struct guild_member *master);
+int  intif_guild_request_info (int guild_id);
+int  intif_guild_addmember (int guild_id, struct guild_member *m);
+int  intif_guild_leave (int guild_id, int account_id, int char_id, int flag,
+                        const char *mes);
+int  intif_guild_memberinfoshort (int guild_id, int account_id, int char_id,
+                                  int online, int lv, int class_);
+int  intif_guild_break (int guild_id);
+int  intif_guild_message (int guild_id, int account_id, char *mes, int len);
+int  intif_guild_checkconflict (int guild_id, int account_id, int char_id);
+int  intif_guild_change_basicinfo (int guild_id, int type, const void *data,
+                                   int len);
+int  intif_guild_change_memberinfo (int guild_id, int account_id, int char_id,
+                                    int type, const void *data, int len);
+int  intif_guild_position (int guild_id, int idx, struct guild_position *p);
+int  intif_guild_skillup (int guild_id, int skill_num, int account_id);
+int  intif_guild_alliance (int guild_id1, int guild_id2, int account_id1,
+                           int account_id2, int flag);
+int  intif_guild_notice (int guild_id, const char *mes1, const char *mes2);
+int  intif_guild_emblem (int guild_id, int len, const char *data);
+int  intif_guild_castle_dataload (int castle_id, int index);
+int  intif_guild_castle_datasave (int castle_id, int index, int value);
+
+#endif
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
deleted file mode 100644
index f89446b..0000000
--- a/src/map/itemdb.c
+++ /dev/null
@@ -1,753 +0,0 @@
-// $Id: itemdb.c,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/db.h"
-#include "../common/grfio.h"
-#include "../common/nullpo.h"
-#include "map.h"
-#include "battle.h"
-#include "itemdb.h"
-#include "script.h"
-#include "pc.h"
-#include "../common/socket.h"
-#include "../common/mt_rand.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define MAX_RANDITEM	2000
-
-// ** ITEMDB_OVERRIDE_NAME_VERBOSE **
-//   定義すると、itemdb.txtとgrfで名前が異なる場合、表示します.
-//#define ITEMDB_OVERRIDE_NAME_VERBOSE  1
-
-static struct dbt *item_db;
-
-static struct random_item_data blue_box[MAX_RANDITEM],
-    violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM],
-    gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM];
-static int blue_box_count = 0, violet_box_count = 0, card_album_count =
-    0, gift_box_count = 0, scroll_count = 0;
-static int blue_box_default = 0, violet_box_default = 0, card_album_default =
-    0, gift_box_default = 0, scroll_default = 0;
-
-// Function declarations
-
-static void itemdb_read (void);
-static int itemdb_readdb (void);
-static int itemdb_read_randomitem (void);
-static int itemdb_read_itemavail (void);
-static int itemdb_read_itemnametable (void);
-static int itemdb_read_noequip (void);
-void itemdb_reload (void);
-
-/*==========================================
- * 名前で検索用
- *------------------------------------------
- */
-// name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
-void itemdb_searchname_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct item_data *item = (struct item_data *) data, **dst;
-    char *str;
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct item_data **);
-//  if( strcasecmp(item->name,str)==0 || strcmp(item->jname,str)==0 ||
-//      memcmp(item->name,str,24)==0 || memcmp(item->jname,str,24)==0 )
-    if (strcasecmp (item->name, str) == 0) //by lupus
-        *dst = item;
-}
-
-/*==========================================
- * 名前で検索用
- *------------------------------------------
- */
-int itemdb_searchjname_sub (void *key, void *data, va_list ap)
-{
-    struct item_data *item = (struct item_data *) data, **dst;
-    char *str;
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct item_data **);
-    if (strcasecmp (item->jname, str) == 0)
-        *dst = item;
-    return 0;
-}
-
-/*==========================================
- * 名前で検索
- *------------------------------------------
- */
-struct item_data *itemdb_searchname (const char *str)
-{
-    struct item_data *item = NULL;
-    numdb_foreach (item_db, itemdb_searchname_sub, str, &item);
-    return item;
-}
-
-/*==========================================
- * 箱系アイテム検索
- *------------------------------------------
- */
-int itemdb_searchrandomid (int flags)
-{
-    int  nameid = 0, i, index, count;
-    struct random_item_data *list = NULL;
-
-    struct
-    {
-        int  nameid, count;
-        struct random_item_data *list;
-    } data[] =
-    {
-        {
-        0, 0, NULL},
-        {
-        blue_box_default, blue_box_count, blue_box},
-        {
-        violet_box_default, violet_box_count, violet_box},
-        {
-        card_album_default, card_album_count, card_album},
-        {
-        gift_box_default, gift_box_count, gift_box},
-        {
-    scroll_default, scroll_count, scroll},};
-
-    if (flags >= 1 && flags <= 5)
-    {
-        nameid = data[flags].nameid;
-        count = data[flags].count;
-        list = data[flags].list;
-
-        if (count > 0)
-        {
-            for (i = 0; i < 1000; i++)
-            {
-                index = MRAND (count);
-                if (MRAND (1000000) < list[index].per)
-                {
-                    nameid = list[index].nameid;
-                    break;
-                }
-            }
-        }
-    }
-    return nameid;
-}
-
-/*==========================================
- * DBの存在確認
- *------------------------------------------
- */
-struct item_data *itemdb_exists (int nameid)
-{
-    return (struct item_data *)numdb_search (item_db, nameid);
-}
-
-/*==========================================
- * DBの検索
- *------------------------------------------
- */
-struct item_data *itemdb_search (int nameid)
-{
-    struct item_data *id = (struct item_data *)numdb_search (item_db, nameid);
-    if (id)
-        return id;
-
-    id = (struct item_data *) calloc (1, sizeof (struct item_data));
-    numdb_insert (item_db, nameid, id);
-
-    id->nameid = nameid;
-    id->value_buy = 10;
-    id->value_sell = id->value_buy / 2;
-    id->weight = 10;
-    id->sex = 2;
-    id->elv = 0;
-    id->flag.available = 0;
-    id->flag.value_notdc = 0;   //一応・・・
-    id->flag.value_notoc = 0;
-    id->flag.no_equip = 0;
-    id->view_id = 0;
-
-    if (nameid > 500 && nameid < 600)
-        id->type = 0;           //heal item
-    else if (nameid > 600 && nameid < 700)
-        id->type = 2;           //use item
-    else if ((nameid > 700 && nameid < 1100) ||
-             (nameid > 7000 && nameid < 8000))
-        id->type = 3;           //correction
-    else if (nameid >= 1750 && nameid < 1771)
-        id->type = 10;          //arrow
-    else if (nameid > 1100 && nameid < 2000)
-        id->type = 4;           //weapon
-    else if ((nameid > 2100 && nameid < 3000) ||
-             (nameid > 5000 && nameid < 6000))
-        id->type = 5;           //armor
-    else if (nameid > 4000 && nameid < 5000)
-        id->type = 6;           //card
-
-    return id;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int itemdb_isequip (int nameid)
-{
-    int  type = itemdb_type (nameid);
-    if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10)
-        return 0;
-    return 1;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int itemdb_isequip2 (struct item_data *data)
-{
-    if (data)
-    {
-        int  type = data->type;
-        if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10)
-            return 0;
-        else
-            return 1;
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int itemdb_isequip3 (int nameid)
-{
-    int  type = itemdb_type (nameid);
-    if (type == 4 || type == 5 || type == 8)
-        return 1;
-    return 0;
-}
-
-/*==========================================
- * 捨てられるアイテムは1、そうでないアイテムは0
- *------------------------------------------
- */
-int itemdb_isdropable (int nameid)
-{
-    //結婚指輪は捨てられない
-    switch (nameid)
-    {
-        case 2634:             //結婚指輪
-        case 2635:             //結婚指輪
-            return 0;
-    }
-
-    return 1;
-}
-
-//
-// 初期化
-//
-/*==========================================
- *
- *------------------------------------------
- */
-static int itemdb_read_itemslottable (void)
-{
-    char *buf, *p;
-    int  s;
-
-    buf = (char *)grfio_reads ("data\\itemslottable.txt", &s);
-    if (buf == NULL)
-        return -1;
-    buf[s] = 0;
-    for (p = buf; p - buf < s;)
-    {
-        int  nameid, equip;
-        sscanf (p, "%d#%d#", &nameid, &equip);
-        itemdb_search (nameid)->equip = equip;
-        p = strchr (p, 10);
-        if (!p)
-            break;
-        p++;
-        p = strchr (p, 10);
-        if (!p)
-            break;
-        p++;
-    }
-    free (buf);
-
-    return 0;
-}
-
-/*==========================================
- * アイテムデータベースの読み込み
- *------------------------------------------
- */
-static int itemdb_readdb (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  ln = 0, lines = 0;
-    int  nameid, j;
-    char *str[32], *p, *np;
-    struct item_data *id;
-    int  i = 0;
-    char *filename[] = { "db/item_db.txt", "db/item_db2.txt" };
-
-    for (i = 0; i < 2; i++)
-    {
-
-        fp = fopen_ (filename[i], "r");
-        if (fp == NULL)
-        {
-            if (i > 0)
-                continue;
-            printf ("can't read %s\n", filename[i]);
-            exit (1);
-        }
-
-        lines = 0;
-        while (fgets (line, 1020, fp))
-        {
-            lines++;
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-            memset (str, 0, sizeof (str));
-            for (j = 0, np = p = line; j < 17 && p; j++)
-            {
-                while (*p == '\t' || *p == ' ')
-                    p++;
-                str[j] = p;
-                p = strchr (p, ',');
-                if (p)
-                {
-                    *p++ = 0;
-                    np = p;
-                }
-            }
-            if (str[0] == NULL)
-                continue;
-
-            nameid = atoi (str[0]);
-            if (nameid <= 0 || nameid >= 20000)
-                continue;
-            ln++;
-
-            //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Gender,Loc,wLV,eLV,View
-            id = itemdb_search (nameid);
-            memcpy (id->name, str[1], 24);
-            memcpy (id->jname, str[2], 24);
-            id->type = atoi (str[3]);
-            id->value_buy = atoi (str[4]);
-            id->value_sell = atoi (str[5]);
-            if (id->value_buy == 0 && id->value_sell == 0)
-            {
-            }
-            else if (id->value_buy == 0)
-            {
-                id->value_buy = id->value_sell * 2;
-            }
-            else if (id->value_sell == 0)
-            {
-                id->value_sell = id->value_buy / 2;
-            }
-            id->weight = atoi (str[6]);
-            id->atk = atoi (str[7]);
-            id->def = atoi (str[8]);
-            id->range = atoi (str[9]);
-            id->magic_bonus = atoi (str[10]);
-            id->slot = atoi (str[11]);
-            id->sex = atoi (str[12]);
-            id->equip = atoi (str[13]);
-            id->wlv = atoi (str[14]);
-            id->elv = atoi (str[15]);
-            id->look = atoi (str[16]);
-            id->flag.available = 1;
-            id->flag.value_notdc = 0;
-            id->flag.value_notoc = 0;
-            id->view_id = 0;
-
-            id->use_script = NULL;
-            id->equip_script = NULL;
-
-            if ((p = strchr (np, '{')) == NULL)
-                continue;
-            id->use_script = parse_script (p, lines);
-
-            if ((p = strchr (p + 1, '{')) == NULL)
-                continue;
-            id->equip_script = parse_script (p, lines);
-        }
-        fclose_ (fp);
-        printf ("read %s done (count=%d)\n", filename[i], ln);
-    }
-    return 0;
-}
-
-// Removed item_value_db, don't re-add!
-
-/*==========================================
- * ランダムアイテム出現データの読み込み
- *------------------------------------------
- */
-static int itemdb_read_randomitem (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  ln = 0;
-    int  nameid, i, j;
-    char *str[10], *p;
-
-    const struct
-    {
-        char filename[64];
-        struct random_item_data *pdata;
-        int *pcount, *pdefault;
-    } data[] =
-    {
-        {
-        "db/item_bluebox.txt", blue_box, &blue_box_count,
-                &blue_box_default},
-        {
-        "db/item_violetbox.txt", violet_box, &violet_box_count,
-                &violet_box_default},
-        {
-        "db/item_cardalbum.txt", card_album, &card_album_count,
-                &card_album_default},
-        {
-        "db/item_giftbox.txt", gift_box, &gift_box_count,
-                &gift_box_default},
-        {
-    "db/item_scroll.txt", scroll, &scroll_count, &scroll_default},};
-
-    for (i = 0; i < sizeof (data) / sizeof (data[0]); i++)
-    {
-        struct random_item_data *pd = data[i].pdata;
-        int *pc = data[i].pcount;
-        int *pdefault = data[i].pdefault;
-        const char *fn = data[i].filename;
-
-        *pdefault = 0;
-        if ((fp = fopen_ (fn, "r")) == NULL)
-        {
-            printf ("can't read %s\n", fn);
-            continue;
-        }
-
-        while (fgets (line, 1020, fp))
-        {
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-            memset (str, 0, sizeof (str));
-            for (j = 0, p = line; j < 3 && p; j++)
-            {
-                str[j] = p;
-                p = strchr (p, ',');
-                if (p)
-                    *p++ = 0;
-            }
-
-            if (str[0] == NULL)
-                continue;
-
-            nameid = atoi (str[0]);
-            if (nameid < 0 || nameid >= 20000)
-                continue;
-            if (nameid == 0)
-            {
-                if (str[2])
-                    *pdefault = atoi (str[2]);
-                continue;
-            }
-
-            if (str[2])
-            {
-                pd[*pc].nameid = nameid;
-                pd[(*pc)++].per = atoi (str[2]);
-            }
-
-            if (ln >= MAX_RANDITEM)
-                break;
-            ln++;
-        }
-        fclose_ (fp);
-        printf ("read %s done (count=%d)\n", fn, *pc);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * アイテム使用可能フラグのオーバーライド
- *------------------------------------------
- */
-static int itemdb_read_itemavail (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  ln = 0;
-    int  nameid, j, k;
-    char *str[10], *p;
-
-    if ((fp = fopen_ ("db/item_avail.txt", "r")) == NULL)
-    {
-        printf ("can't read db/item_avail.txt\n");
-        return -1;
-    }
-
-    while (fgets (line, 1020, fp))
-    {
-        struct item_data *id;
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        memset (str, 0, sizeof (str));
-        for (j = 0, p = line; j < 2 && p; j++)
-        {
-            str[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-
-        if (str[0] == NULL)
-            continue;
-
-        nameid = atoi (str[0]);
-        if (nameid < 0 || nameid >= 20000 || !(id = itemdb_exists (nameid)))
-            continue;
-        k = atoi (str[1]);
-        if (k > 0)
-        {
-            id->flag.available = 1;
-            id->view_id = k;
-        }
-        else
-            id->flag.available = 0;
-        ln++;
-    }
-    fclose_ (fp);
-    printf ("read db/item_avail.txt done (count=%d)\n", ln);
-    return 0;
-}
-
-/*==========================================
- * アイテムの名前テーブルを読み込む
- *------------------------------------------
- */
-static int itemdb_read_itemnametable (void)
-{
-    char *buf, *p;
-    int  s;
-
-    buf = (char *)grfio_reads ("data\\idnum2itemdisplaynametable.txt", &s);
-
-    if (buf == NULL)
-        return -1;
-
-    buf[s] = 0;
-    for (p = buf; p - buf < s;)
-    {
-        int  nameid;
-        char buf2[64];
-
-        if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2)
-        {
-
-#ifdef ITEMDB_OVERRIDE_NAME_VERBOSE
-            if (itemdb_exists (nameid) &&
-                strncmp (itemdb_search (nameid)->jname, buf2, 24) != 0)
-            {
-                printf ("[override] %d %s => %s\n", nameid,
-                        itemdb_search (nameid)->jname, buf2);
-            }
-#endif
-
-            memcpy (itemdb_search (nameid)->jname, buf2, 24);
-        }
-
-        p = strchr (p, 10);
-        if (!p)
-            break;
-        p++;
-    }
-    free (buf);
-    printf ("read data\\idnum2itemdisplaynametable.txt done.\n");
-
-    return 0;
-}
-
-/*==========================================
- * カードイラストのリソース名前テーブルを読み込む
- *------------------------------------------
- */
-static int itemdb_read_cardillustnametable (void)
-{
-    char *buf, *p;
-    int  s;
-
-    buf = (char *)grfio_reads ("data\\num2cardillustnametable.txt", &s);
-
-    if (buf == NULL)
-        return -1;
-
-    buf[s] = 0;
-    for (p = buf; p - buf < s;)
-    {
-        int  nameid;
-        char buf2[64];
-
-        if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2)
-        {
-            strcat (buf2, ".bmp");
-            memcpy (itemdb_search (nameid)->cardillustname, buf2, 64);
-//          printf("%d %s\n",nameid,itemdb_search(nameid)->cardillustname);
-        }
-
-        p = strchr (p, 10);
-        if (!p)
-            break;
-        p++;
-    }
-    free (buf);
-    printf ("read data\\num2cardillustnametable.txt done.\n");
-
-    return 0;
-}
-
-/*==========================================
- * 装備制限ファイル読み出し
- *------------------------------------------
- */
-static int itemdb_read_noequip (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  ln = 0;
-    int  nameid, j;
-    char *str[32], *p;
-    struct item_data *id;
-
-    if ((fp = fopen_ ("db/item_noequip.txt", "r")) == NULL)
-    {
-        printf ("can't read db/item_noequip.txt\n");
-        return -1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        memset (str, 0, sizeof (str));
-        for (j = 0, p = line; j < 2 && p; j++)
-        {
-            str[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (str[0] == NULL)
-            continue;
-
-        nameid = atoi (str[0]);
-        if (nameid <= 0 || nameid >= 20000 || !(id = itemdb_exists (nameid)))
-            continue;
-
-        id->flag.no_equip = atoi (str[1]);
-
-        ln++;
-
-    }
-    fclose_ (fp);
-    printf ("read db/item_noequip.txt done (count=%d)\n", ln);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static void itemdb_final (db_key_t key, db_val_t data, va_list ap)
-{
-    struct item_data *id;
-
-    nullpo_retv (id = (struct item_data *)data);
-
-    if (id->use_script)
-        free (id->use_script);
-    if (id->equip_script)
-        free (id->equip_script);
-    free (id);
-}
-
-void itemdb_reload (void)
-{
-    /*
-     *
-     * <empty item databases>
-     * itemdb_read();
-     *
-     */
-
-    do_init_itemdb ();
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-void do_final_itemdb (void)
-{
-    if (item_db)
-    {
-        numdb_final (item_db, itemdb_final);
-        item_db = NULL;
-    }
-}
-
-/*
-static FILE *dfp;
-static int itemdebug(void *key,void *data,va_list ap){
-//	struct item_data *id=(struct item_data *)data;
-	fprintf(dfp,"%6d",(int)key);
-	return 0;
-}
-void itemdebugtxt()
-{
-	dfp=fopen_("itemdebug.txt","wt");
-	numdb_foreach(item_db,itemdebug);
-	fclose_(dfp);
-}
-*/
-
-/*====================================
- * Removed item_value_db, don't re-add
- *------------------------------------
- */
-static void itemdb_read (void)
-{
-    itemdb_read_itemslottable ();
-    itemdb_readdb ();
-    itemdb_read_randomitem ();
-    itemdb_read_itemavail ();
-    itemdb_read_noequip ();
-    itemdb_read_cardillustnametable ();
-    if (!battle_config.item_name_override_grffile)
-        itemdb_read_itemnametable ();
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int do_init_itemdb (void)
-{
-    item_db = numdb_init ();
-
-    itemdb_read ();
-
-    return 0;
-}
diff --git a/src/map/itemdb.cpp b/src/map/itemdb.cpp
new file mode 100644
index 0000000..c1255bd
--- /dev/null
+++ b/src/map/itemdb.cpp
@@ -0,0 +1,753 @@
+// $Id: itemdb.c,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/db.hpp"
+#include "../common/grfio.hpp"
+#include "../common/nullpo.hpp"
+#include "map.hpp"
+#include "battle.hpp"
+#include "itemdb.hpp"
+#include "script.hpp"
+#include "pc.hpp"
+#include "../common/socket.hpp"
+#include "../common/mt_rand.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define MAX_RANDITEM	2000
+
+// ** ITEMDB_OVERRIDE_NAME_VERBOSE **
+//   定義すると、itemdb.txtとgrfで名前が異なる場合、表示します.
+//#define ITEMDB_OVERRIDE_NAME_VERBOSE  1
+
+static struct dbt *item_db;
+
+static struct random_item_data blue_box[MAX_RANDITEM],
+    violet_box[MAX_RANDITEM], card_album[MAX_RANDITEM],
+    gift_box[MAX_RANDITEM], scroll[MAX_RANDITEM];
+static int blue_box_count = 0, violet_box_count = 0, card_album_count =
+    0, gift_box_count = 0, scroll_count = 0;
+static int blue_box_default = 0, violet_box_default = 0, card_album_default =
+    0, gift_box_default = 0, scroll_default = 0;
+
+// Function declarations
+
+static void itemdb_read (void);
+static int itemdb_readdb (void);
+static int itemdb_read_randomitem (void);
+static int itemdb_read_itemavail (void);
+static int itemdb_read_itemnametable (void);
+static int itemdb_read_noequip (void);
+void itemdb_reload (void);
+
+/*==========================================
+ * 名前で検索用
+ *------------------------------------------
+ */
+// name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
+void itemdb_searchname_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct item_data *item = (struct item_data *) data, **dst;
+    char *str;
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct item_data **);
+//  if( strcasecmp(item->name,str)==0 || strcmp(item->jname,str)==0 ||
+//      memcmp(item->name,str,24)==0 || memcmp(item->jname,str,24)==0 )
+    if (strcasecmp (item->name, str) == 0) //by lupus
+        *dst = item;
+}
+
+/*==========================================
+ * 名前で検索用
+ *------------------------------------------
+ */
+int itemdb_searchjname_sub (void *key, void *data, va_list ap)
+{
+    struct item_data *item = (struct item_data *) data, **dst;
+    char *str;
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct item_data **);
+    if (strcasecmp (item->jname, str) == 0)
+        *dst = item;
+    return 0;
+}
+
+/*==========================================
+ * 名前で検索
+ *------------------------------------------
+ */
+struct item_data *itemdb_searchname (const char *str)
+{
+    struct item_data *item = NULL;
+    numdb_foreach (item_db, itemdb_searchname_sub, str, &item);
+    return item;
+}
+
+/*==========================================
+ * 箱系アイテム検索
+ *------------------------------------------
+ */
+int itemdb_searchrandomid (int flags)
+{
+    int  nameid = 0, i, index, count;
+    struct random_item_data *list = NULL;
+
+    struct
+    {
+        int  nameid, count;
+        struct random_item_data *list;
+    } data[] =
+    {
+        {
+        0, 0, NULL},
+        {
+        blue_box_default, blue_box_count, blue_box},
+        {
+        violet_box_default, violet_box_count, violet_box},
+        {
+        card_album_default, card_album_count, card_album},
+        {
+        gift_box_default, gift_box_count, gift_box},
+        {
+    scroll_default, scroll_count, scroll},};
+
+    if (flags >= 1 && flags <= 5)
+    {
+        nameid = data[flags].nameid;
+        count = data[flags].count;
+        list = data[flags].list;
+
+        if (count > 0)
+        {
+            for (i = 0; i < 1000; i++)
+            {
+                index = MRAND (count);
+                if (MRAND (1000000) < list[index].per)
+                {
+                    nameid = list[index].nameid;
+                    break;
+                }
+            }
+        }
+    }
+    return nameid;
+}
+
+/*==========================================
+ * DBの存在確認
+ *------------------------------------------
+ */
+struct item_data *itemdb_exists (int nameid)
+{
+    return (struct item_data *)numdb_search (item_db, nameid);
+}
+
+/*==========================================
+ * DBの検索
+ *------------------------------------------
+ */
+struct item_data *itemdb_search (int nameid)
+{
+    struct item_data *id = (struct item_data *)numdb_search (item_db, nameid);
+    if (id)
+        return id;
+
+    id = (struct item_data *) calloc (1, sizeof (struct item_data));
+    numdb_insert (item_db, nameid, id);
+
+    id->nameid = nameid;
+    id->value_buy = 10;
+    id->value_sell = id->value_buy / 2;
+    id->weight = 10;
+    id->sex = 2;
+    id->elv = 0;
+    id->flag.available = 0;
+    id->flag.value_notdc = 0;   //一応・・・
+    id->flag.value_notoc = 0;
+    id->flag.no_equip = 0;
+    id->view_id = 0;
+
+    if (nameid > 500 && nameid < 600)
+        id->type = 0;           //heal item
+    else if (nameid > 600 && nameid < 700)
+        id->type = 2;           //use item
+    else if ((nameid > 700 && nameid < 1100) ||
+             (nameid > 7000 && nameid < 8000))
+        id->type = 3;           //correction
+    else if (nameid >= 1750 && nameid < 1771)
+        id->type = 10;          //arrow
+    else if (nameid > 1100 && nameid < 2000)
+        id->type = 4;           //weapon
+    else if ((nameid > 2100 && nameid < 3000) ||
+             (nameid > 5000 && nameid < 6000))
+        id->type = 5;           //armor
+    else if (nameid > 4000 && nameid < 5000)
+        id->type = 6;           //card
+
+    return id;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int itemdb_isequip (int nameid)
+{
+    int  type = itemdb_type (nameid);
+    if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10)
+        return 0;
+    return 1;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int itemdb_isequip2 (struct item_data *data)
+{
+    if (data)
+    {
+        int  type = data->type;
+        if (type == 0 || type == 2 || type == 3 || type == 6 || type == 10)
+            return 0;
+        else
+            return 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int itemdb_isequip3 (int nameid)
+{
+    int  type = itemdb_type (nameid);
+    if (type == 4 || type == 5 || type == 8)
+        return 1;
+    return 0;
+}
+
+/*==========================================
+ * 捨てられるアイテムは1、そうでないアイテムは0
+ *------------------------------------------
+ */
+int itemdb_isdropable (int nameid)
+{
+    //結婚指輪は捨てられない
+    switch (nameid)
+    {
+        case 2634:             //結婚指輪
+        case 2635:             //結婚指輪
+            return 0;
+    }
+
+    return 1;
+}
+
+//
+// 初期化
+//
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int itemdb_read_itemslottable (void)
+{
+    char *buf, *p;
+    int  s;
+
+    buf = (char *)grfio_reads ("data\\itemslottable.txt", &s);
+    if (buf == NULL)
+        return -1;
+    buf[s] = 0;
+    for (p = buf; p - buf < s;)
+    {
+        int  nameid, equip;
+        sscanf (p, "%d#%d#", &nameid, &equip);
+        itemdb_search (nameid)->equip = equip;
+        p = strchr (p, 10);
+        if (!p)
+            break;
+        p++;
+        p = strchr (p, 10);
+        if (!p)
+            break;
+        p++;
+    }
+    free (buf);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムデータベースの読み込み
+ *------------------------------------------
+ */
+static int itemdb_readdb (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  ln = 0, lines = 0;
+    int  nameid, j;
+    char *str[32], *p, *np;
+    struct item_data *id;
+    int  i = 0;
+    char *filename[] = { "db/item_db.txt", "db/item_db2.txt" };
+
+    for (i = 0; i < 2; i++)
+    {
+
+        fp = fopen_ (filename[i], "r");
+        if (fp == NULL)
+        {
+            if (i > 0)
+                continue;
+            printf ("can't read %s\n", filename[i]);
+            exit (1);
+        }
+
+        lines = 0;
+        while (fgets (line, 1020, fp))
+        {
+            lines++;
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+            memset (str, 0, sizeof (str));
+            for (j = 0, np = p = line; j < 17 && p; j++)
+            {
+                while (*p == '\t' || *p == ' ')
+                    p++;
+                str[j] = p;
+                p = strchr (p, ',');
+                if (p)
+                {
+                    *p++ = 0;
+                    np = p;
+                }
+            }
+            if (str[0] == NULL)
+                continue;
+
+            nameid = atoi (str[0]);
+            if (nameid <= 0 || nameid >= 20000)
+                continue;
+            ln++;
+
+            //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Gender,Loc,wLV,eLV,View
+            id = itemdb_search (nameid);
+            memcpy (id->name, str[1], 24);
+            memcpy (id->jname, str[2], 24);
+            id->type = atoi (str[3]);
+            id->value_buy = atoi (str[4]);
+            id->value_sell = atoi (str[5]);
+            if (id->value_buy == 0 && id->value_sell == 0)
+            {
+            }
+            else if (id->value_buy == 0)
+            {
+                id->value_buy = id->value_sell * 2;
+            }
+            else if (id->value_sell == 0)
+            {
+                id->value_sell = id->value_buy / 2;
+            }
+            id->weight = atoi (str[6]);
+            id->atk = atoi (str[7]);
+            id->def = atoi (str[8]);
+            id->range = atoi (str[9]);
+            id->magic_bonus = atoi (str[10]);
+            id->slot = atoi (str[11]);
+            id->sex = atoi (str[12]);
+            id->equip = atoi (str[13]);
+            id->wlv = atoi (str[14]);
+            id->elv = atoi (str[15]);
+            id->look = atoi (str[16]);
+            id->flag.available = 1;
+            id->flag.value_notdc = 0;
+            id->flag.value_notoc = 0;
+            id->view_id = 0;
+
+            id->use_script = NULL;
+            id->equip_script = NULL;
+
+            if ((p = strchr (np, '{')) == NULL)
+                continue;
+            id->use_script = parse_script (p, lines);
+
+            if ((p = strchr (p + 1, '{')) == NULL)
+                continue;
+            id->equip_script = parse_script (p, lines);
+        }
+        fclose_ (fp);
+        printf ("read %s done (count=%d)\n", filename[i], ln);
+    }
+    return 0;
+}
+
+// Removed item_value_db, don't re-add!
+
+/*==========================================
+ * ランダムアイテム出現データの読み込み
+ *------------------------------------------
+ */
+static int itemdb_read_randomitem (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  ln = 0;
+    int  nameid, i, j;
+    char *str[10], *p;
+
+    const struct
+    {
+        char filename[64];
+        struct random_item_data *pdata;
+        int *pcount, *pdefault;
+    } data[] =
+    {
+        {
+        "db/item_bluebox.txt", blue_box, &blue_box_count,
+                &blue_box_default},
+        {
+        "db/item_violetbox.txt", violet_box, &violet_box_count,
+                &violet_box_default},
+        {
+        "db/item_cardalbum.txt", card_album, &card_album_count,
+                &card_album_default},
+        {
+        "db/item_giftbox.txt", gift_box, &gift_box_count,
+                &gift_box_default},
+        {
+    "db/item_scroll.txt", scroll, &scroll_count, &scroll_default},};
+
+    for (i = 0; i < sizeof (data) / sizeof (data[0]); i++)
+    {
+        struct random_item_data *pd = data[i].pdata;
+        int *pc = data[i].pcount;
+        int *pdefault = data[i].pdefault;
+        const char *fn = data[i].filename;
+
+        *pdefault = 0;
+        if ((fp = fopen_ (fn, "r")) == NULL)
+        {
+            printf ("can't read %s\n", fn);
+            continue;
+        }
+
+        while (fgets (line, 1020, fp))
+        {
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+            memset (str, 0, sizeof (str));
+            for (j = 0, p = line; j < 3 && p; j++)
+            {
+                str[j] = p;
+                p = strchr (p, ',');
+                if (p)
+                    *p++ = 0;
+            }
+
+            if (str[0] == NULL)
+                continue;
+
+            nameid = atoi (str[0]);
+            if (nameid < 0 || nameid >= 20000)
+                continue;
+            if (nameid == 0)
+            {
+                if (str[2])
+                    *pdefault = atoi (str[2]);
+                continue;
+            }
+
+            if (str[2])
+            {
+                pd[*pc].nameid = nameid;
+                pd[(*pc)++].per = atoi (str[2]);
+            }
+
+            if (ln >= MAX_RANDITEM)
+                break;
+            ln++;
+        }
+        fclose_ (fp);
+        printf ("read %s done (count=%d)\n", fn, *pc);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * アイテム使用可能フラグのオーバーライド
+ *------------------------------------------
+ */
+static int itemdb_read_itemavail (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  ln = 0;
+    int  nameid, j, k;
+    char *str[10], *p;
+
+    if ((fp = fopen_ ("db/item_avail.txt", "r")) == NULL)
+    {
+        printf ("can't read db/item_avail.txt\n");
+        return -1;
+    }
+
+    while (fgets (line, 1020, fp))
+    {
+        struct item_data *id;
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        memset (str, 0, sizeof (str));
+        for (j = 0, p = line; j < 2 && p; j++)
+        {
+            str[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+
+        if (str[0] == NULL)
+            continue;
+
+        nameid = atoi (str[0]);
+        if (nameid < 0 || nameid >= 20000 || !(id = itemdb_exists (nameid)))
+            continue;
+        k = atoi (str[1]);
+        if (k > 0)
+        {
+            id->flag.available = 1;
+            id->view_id = k;
+        }
+        else
+            id->flag.available = 0;
+        ln++;
+    }
+    fclose_ (fp);
+    printf ("read db/item_avail.txt done (count=%d)\n", ln);
+    return 0;
+}
+
+/*==========================================
+ * アイテムの名前テーブルを読み込む
+ *------------------------------------------
+ */
+static int itemdb_read_itemnametable (void)
+{
+    char *buf, *p;
+    int  s;
+
+    buf = (char *)grfio_reads ("data\\idnum2itemdisplaynametable.txt", &s);
+
+    if (buf == NULL)
+        return -1;
+
+    buf[s] = 0;
+    for (p = buf; p - buf < s;)
+    {
+        int  nameid;
+        char buf2[64];
+
+        if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2)
+        {
+
+#ifdef ITEMDB_OVERRIDE_NAME_VERBOSE
+            if (itemdb_exists (nameid) &&
+                strncmp (itemdb_search (nameid)->jname, buf2, 24) != 0)
+            {
+                printf ("[override] %d %s => %s\n", nameid,
+                        itemdb_search (nameid)->jname, buf2);
+            }
+#endif
+
+            memcpy (itemdb_search (nameid)->jname, buf2, 24);
+        }
+
+        p = strchr (p, 10);
+        if (!p)
+            break;
+        p++;
+    }
+    free (buf);
+    printf ("read data\\idnum2itemdisplaynametable.txt done.\n");
+
+    return 0;
+}
+
+/*==========================================
+ * カードイラストのリソース名前テーブルを読み込む
+ *------------------------------------------
+ */
+static int itemdb_read_cardillustnametable (void)
+{
+    char *buf, *p;
+    int  s;
+
+    buf = (char *)grfio_reads ("data\\num2cardillustnametable.txt", &s);
+
+    if (buf == NULL)
+        return -1;
+
+    buf[s] = 0;
+    for (p = buf; p - buf < s;)
+    {
+        int  nameid;
+        char buf2[64];
+
+        if (sscanf (p, "%d#%[^#]#", &nameid, buf2) == 2)
+        {
+            strcat (buf2, ".bmp");
+            memcpy (itemdb_search (nameid)->cardillustname, buf2, 64);
+//          printf("%d %s\n",nameid,itemdb_search(nameid)->cardillustname);
+        }
+
+        p = strchr (p, 10);
+        if (!p)
+            break;
+        p++;
+    }
+    free (buf);
+    printf ("read data\\num2cardillustnametable.txt done.\n");
+
+    return 0;
+}
+
+/*==========================================
+ * 装備制限ファイル読み出し
+ *------------------------------------------
+ */
+static int itemdb_read_noequip (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  ln = 0;
+    int  nameid, j;
+    char *str[32], *p;
+    struct item_data *id;
+
+    if ((fp = fopen_ ("db/item_noequip.txt", "r")) == NULL)
+    {
+        printf ("can't read db/item_noequip.txt\n");
+        return -1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        memset (str, 0, sizeof (str));
+        for (j = 0, p = line; j < 2 && p; j++)
+        {
+            str[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (str[0] == NULL)
+            continue;
+
+        nameid = atoi (str[0]);
+        if (nameid <= 0 || nameid >= 20000 || !(id = itemdb_exists (nameid)))
+            continue;
+
+        id->flag.no_equip = atoi (str[1]);
+
+        ln++;
+
+    }
+    fclose_ (fp);
+    printf ("read db/item_noequip.txt done (count=%d)\n", ln);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static void itemdb_final (db_key_t key, db_val_t data, va_list ap)
+{
+    struct item_data *id;
+
+    nullpo_retv (id = (struct item_data *)data);
+
+    if (id->use_script)
+        free (id->use_script);
+    if (id->equip_script)
+        free (id->equip_script);
+    free (id);
+}
+
+void itemdb_reload (void)
+{
+    /*
+     *
+     * <empty item databases>
+     * itemdb_read();
+     *
+     */
+
+    do_init_itemdb ();
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+void do_final_itemdb (void)
+{
+    if (item_db)
+    {
+        numdb_final (item_db, itemdb_final);
+        item_db = NULL;
+    }
+}
+
+/*
+static FILE *dfp;
+static int itemdebug(void *key,void *data,va_list ap){
+//	struct item_data *id=(struct item_data *)data;
+	fprintf(dfp,"%6d",(int)key);
+	return 0;
+}
+void itemdebugtxt()
+{
+	dfp=fopen_("itemdebug.txt","wt");
+	numdb_foreach(item_db,itemdebug);
+	fclose_(dfp);
+}
+*/
+
+/*====================================
+ * Removed item_value_db, don't re-add
+ *------------------------------------
+ */
+static void itemdb_read (void)
+{
+    itemdb_read_itemslottable ();
+    itemdb_readdb ();
+    itemdb_read_randomitem ();
+    itemdb_read_itemavail ();
+    itemdb_read_noequip ();
+    itemdb_read_cardillustnametable ();
+    if (!battle_config.item_name_override_grffile)
+        itemdb_read_itemnametable ();
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int do_init_itemdb (void)
+{
+    item_db = numdb_init ();
+
+    itemdb_read ();
+
+    return 0;
+}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
deleted file mode 100644
index de07822..0000000
--- a/src/map/itemdb.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// $Id: itemdb.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _ITEMDB_H_
-#define _ITEMDB_H_
-
-#include "map.h"
-
-struct item_data
-{
-    int  nameid;
-    char name[24], jname[24];
-    char prefix[24], suffix[24];
-    char cardillustname[64];
-    int  value_buy;
-    int  value_sell;
-    int  type;
-    int  sex;
-    int  equip;
-    int  weight;
-    int  atk;
-    int  def;
-    int  range;
-    int  magic_bonus;
-    int  slot;
-    int  look;
-    int  elv;
-    int  wlv;
-    int  refine;
-    char *use_script;
-    char *equip_script;
-    struct
-    {
-        unsigned available:1;
-        unsigned value_notdc:1;
-        unsigned value_notoc:1;
-        unsigned no_equip:3;
-        unsigned no_drop:1;
-        unsigned no_use:1;
-    } flag;
-    int  view_id;
-};
-
-struct random_item_data
-{
-    int  nameid;
-    int  per;
-};
-
-struct item_data *itemdb_searchname (const char *name);
-struct item_data *itemdb_search (int nameid);
-struct item_data *itemdb_exists (int nameid);
-#define itemdb_type(n) itemdb_search(n)->type
-#define itemdb_atk(n) itemdb_search(n)->atk
-#define itemdb_def(n) itemdb_search(n)->def
-#define itemdb_look(n) itemdb_search(n)->look
-#define itemdb_weight(n) itemdb_search(n)->weight
-#define itemdb_equip(n) itemdb_search(n)->equip
-#define itemdb_usescript(n) itemdb_search(n)->use_script
-#define itemdb_equipscript(n) itemdb_search(n)->equip_script
-#define itemdb_wlv(n) itemdb_search(n)->wlv
-#define itemdb_range(n) itemdb_search(n)->range
-#define itemdb_slot(n) itemdb_search(n)->slot
-#define	itemdb_available(n) (itemdb_exists(n) && itemdb_search(n)->flag.available)
-#define	itemdb_viewid(n) (itemdb_search(n)->view_id)
-
-int  itemdb_searchrandomid (int flags);
-
-#define itemdb_value_buy(n) itemdb_search(n)->value_buy
-#define itemdb_value_sell(n) itemdb_search(n)->value_sell
-#define itemdb_value_notdc(n) itemdb_search(n)->flag.value_notdc
-#define itemdb_value_notoc(n) itemdb_search(n)->flag.value_notoc
-
-int  itemdb_isequip (int);
-int  itemdb_isequip2 (struct item_data *);
-int  itemdb_isequip3 (int);
-int  itemdb_isdropable (int nameid);
-
-void itemdb_reload (void);
-
-void do_final_itemdb (void);
-int  do_init_itemdb (void);
-
-#endif
diff --git a/src/map/itemdb.hpp b/src/map/itemdb.hpp
new file mode 100644
index 0000000..ef5eab2
--- /dev/null
+++ b/src/map/itemdb.hpp
@@ -0,0 +1,82 @@
+// $Id: itemdb.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef ITEMDB_HPP
+#define ITEMDB_HPP
+
+#include "map.hpp"
+
+struct item_data
+{
+    int  nameid;
+    char name[24], jname[24];
+    char prefix[24], suffix[24];
+    char cardillustname[64];
+    int  value_buy;
+    int  value_sell;
+    int  type;
+    int  sex;
+    int  equip;
+    int  weight;
+    int  atk;
+    int  def;
+    int  range;
+    int  magic_bonus;
+    int  slot;
+    int  look;
+    int  elv;
+    int  wlv;
+    int  refine;
+    char *use_script;
+    char *equip_script;
+    struct
+    {
+        unsigned available:1;
+        unsigned value_notdc:1;
+        unsigned value_notoc:1;
+        unsigned no_equip:3;
+        unsigned no_drop:1;
+        unsigned no_use:1;
+    } flag;
+    int  view_id;
+};
+
+struct random_item_data
+{
+    int  nameid;
+    int  per;
+};
+
+struct item_data *itemdb_searchname (const char *name);
+struct item_data *itemdb_search (int nameid);
+struct item_data *itemdb_exists (int nameid);
+#define itemdb_type(n) itemdb_search(n)->type
+#define itemdb_atk(n) itemdb_search(n)->atk
+#define itemdb_def(n) itemdb_search(n)->def
+#define itemdb_look(n) itemdb_search(n)->look
+#define itemdb_weight(n) itemdb_search(n)->weight
+#define itemdb_equip(n) itemdb_search(n)->equip
+#define itemdb_usescript(n) itemdb_search(n)->use_script
+#define itemdb_equipscript(n) itemdb_search(n)->equip_script
+#define itemdb_wlv(n) itemdb_search(n)->wlv
+#define itemdb_range(n) itemdb_search(n)->range
+#define itemdb_slot(n) itemdb_search(n)->slot
+#define	itemdb_available(n) (itemdb_exists(n) && itemdb_search(n)->flag.available)
+#define	itemdb_viewid(n) (itemdb_search(n)->view_id)
+
+int  itemdb_searchrandomid (int flags);
+
+#define itemdb_value_buy(n) itemdb_search(n)->value_buy
+#define itemdb_value_sell(n) itemdb_search(n)->value_sell
+#define itemdb_value_notdc(n) itemdb_search(n)->flag.value_notdc
+#define itemdb_value_notoc(n) itemdb_search(n)->flag.value_notoc
+
+int  itemdb_isequip (int);
+int  itemdb_isequip2 (struct item_data *);
+int  itemdb_isequip3 (int);
+int  itemdb_isdropable (int nameid);
+
+void itemdb_reload (void);
+
+void do_final_itemdb (void);
+int  do_init_itemdb (void);
+
+#endif
diff --git a/src/map/magic-expr-eval.h b/src/map/magic-expr-eval.h
deleted file mode 100644
index 71c1d86..0000000
--- a/src/map/magic-expr-eval.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef MAGIC_EXPR_EVAL
-#define MAGIC_EXPR_EVAL
-
-/* Helper definitions for dealing with functions and operations */
-
-static int heading_x[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-static int heading_y[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-
-int
- magic_signature_check (char *opname, char *funname, char *signature,
-                        int args_nr, val_t * args, int line, int column);
-
-void
-magic_area_rect (int *m, int *x, int *y, int *width, int *height,
-                 area_t * area);
-
-#define ARGINT(x) args[x].v.v_int
-#define ARGDIR(x) args[x].v.v_int
-#define ARGSTR(x) args[x].v.v_string
-#define ARGENTITY(x) args[x].v.v_entity
-#define ARGLOCATION(x) args[x].v.v_location
-#define ARGAREA(x) args[x].v.v_area
-#define ARGSPELL(x) args[x].v.v_spell
-#define ARGINVOCATION(x) args[x].v.v_invocation
-
-#define RESULTINT result->v.v_int
-#define RESULTDIR result->v.v_int
-#define RESULTSTR result->v.v_string
-#define RESULTENTITY result->v.v_entity
-#define RESULTLOCATION result->v.v_location
-#define RESULTAREA result->v.v_area
-#define RESULTSPELL result->v.v_spell
-#define RESULTINVOCATION result->v.v_invocation
-
-#define TY(x) args[x].ty
-#define ETY(x) ARGENTITY(x)->type
-
-#define ARGPC(x)  ((struct map_session_data *)ARGENTITY(x))
-#define ARGNPC(x)  ((struct map_session_data *)ARGENTITY(x))
-#define ARGMOB(x)  ((struct map_session_data *)ARGENTITY(x))
-
-#define ARG_MAY_BE_AREA(x) (TY(x) == TY_AREA || TY(x) == TY_LOCATION)
-
-#endif /* !defined(MAGIC_EXPR_EVAL) */
diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp
new file mode 100644
index 0000000..71c1d86
--- /dev/null
+++ b/src/map/magic-expr-eval.hpp
@@ -0,0 +1,44 @@
+#ifndef MAGIC_EXPR_EVAL
+#define MAGIC_EXPR_EVAL
+
+/* Helper definitions for dealing with functions and operations */
+
+static int heading_x[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+static int heading_y[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+
+int
+ magic_signature_check (char *opname, char *funname, char *signature,
+                        int args_nr, val_t * args, int line, int column);
+
+void
+magic_area_rect (int *m, int *x, int *y, int *width, int *height,
+                 area_t * area);
+
+#define ARGINT(x) args[x].v.v_int
+#define ARGDIR(x) args[x].v.v_int
+#define ARGSTR(x) args[x].v.v_string
+#define ARGENTITY(x) args[x].v.v_entity
+#define ARGLOCATION(x) args[x].v.v_location
+#define ARGAREA(x) args[x].v.v_area
+#define ARGSPELL(x) args[x].v.v_spell
+#define ARGINVOCATION(x) args[x].v.v_invocation
+
+#define RESULTINT result->v.v_int
+#define RESULTDIR result->v.v_int
+#define RESULTSTR result->v.v_string
+#define RESULTENTITY result->v.v_entity
+#define RESULTLOCATION result->v.v_location
+#define RESULTAREA result->v.v_area
+#define RESULTSPELL result->v.v_spell
+#define RESULTINVOCATION result->v.v_invocation
+
+#define TY(x) args[x].ty
+#define ETY(x) ARGENTITY(x)->type
+
+#define ARGPC(x)  ((struct map_session_data *)ARGENTITY(x))
+#define ARGNPC(x)  ((struct map_session_data *)ARGENTITY(x))
+#define ARGMOB(x)  ((struct map_session_data *)ARGENTITY(x))
+
+#define ARG_MAY_BE_AREA(x) (TY(x) == TY_AREA || TY(x) == TY_LOCATION)
+
+#endif /* !defined(MAGIC_EXPR_EVAL) */
diff --git a/src/map/magic-expr.c b/src/map/magic-expr.c
deleted file mode 100644
index a0a4935..0000000
--- a/src/map/magic-expr.c
+++ /dev/null
@@ -1,1655 +0,0 @@
-#include "magic-expr.h"
-#include "magic-expr-eval.h"
-#include "itemdb.h"
-#include <math.h>
-
-#include "../common/mt_rand.h"
-
-#define IS_SOLID(c) ((c) == 1 || (c) == 5)
-
-int map_is_solid (int m, int x, int y)
-{
-    return (IS_SOLID (map_getcell (m, x, y)));
-}
-
-#undef IS_SOLID
-
-static void free_area (area_t * area)
-{
-    if (!area)
-        return;
-
-    switch (area->ty)
-    {
-        case AREA_UNION:
-            free_area (area->a.a_union[0]);
-            free_area (area->a.a_union[1]);
-            break;
-        default:
-            break;
-    }
-
-    free (area);
-}
-
-static area_t *dup_area (area_t * area)
-{
-    area_t *retval = (area_t *)malloc (sizeof (area_t));
-    *retval = *area;
-
-    switch (area->ty)
-    {
-        case AREA_UNION:
-            retval->a.a_union[0] = dup_area (retval->a.a_union[0]);
-            retval->a.a_union[1] = dup_area (retval->a.a_union[1]);
-            break;
-        default:
-            break;
-    }
-
-    return retval;
-}
-
-void magic_copy_var (val_t * dest, val_t * src)
-{
-    *dest = *src;
-
-    switch (dest->ty)
-    {
-        case TY_STRING:
-            dest->v.v_string = strdup (dest->v.v_string);
-            break;
-        case TY_AREA:
-            dest->v.v_area = dup_area (dest->v.v_area);
-            break;
-        default:
-            break;
-    }
-
-}
-
-void magic_clear_var (val_t * v)
-{
-    switch (v->ty)
-    {
-        case TY_STRING:
-            free (v->v.v_string);
-            break;
-        case TY_AREA:
-            free_area (v->v.v_area);
-            break;
-        default:
-            break;
-    }
-}
-
-static char *show_entity (entity_t * entity)
-{
-    switch (entity->type)
-    {
-        case BL_PC:
-            return ((struct map_session_data *) entity)->status.name;
-        case BL_NPC:
-            return ((struct npc_data *) entity)->name;
-        case BL_MOB:
-            return ((struct mob_data *) entity)->name;
-        case BL_ITEM:
-            /* Sorry about this one... */
-            return ((struct item_data
-                     *) (&((struct flooritem_data *) entity)->
-                         item_data))->name;
-        case BL_SKILL:
-            return "%skill";
-        case BL_SPELL:
-            return "%invocation(ERROR:this-should-not-be-an-entity)";
-        default:
-            return "%unknown-entity";
-    }
-}
-
-static void stringify (val_t * v, int within_op)
-{
-    static char *dirs[8] =
-        { "south", "south-west", "west", "north-west", "north", "north-east",
-        "east", "south-east"
-    };
-    char *buf;
-
-    switch (v->ty)
-    {
-        case TY_UNDEF:
-            buf = strdup ("UNDEF");
-            break;
-
-        case TY_INT:
-            buf = (char *)malloc (32);
-            sprintf (buf, "%i", v->v.v_int);
-            break;
-
-        case TY_STRING:
-            return;
-
-        case TY_DIR:
-            buf = strdup (dirs[v->v.v_int]);
-            break;
-
-        case TY_ENTITY:
-            buf = strdup (show_entity (v->v.v_entity));
-            break;
-
-        case TY_LOCATION:
-            buf = (char *) malloc (128);
-            sprintf (buf, "<\"%s\", %d, %d>", map[v->v.v_location.m].name,
-                     v->v.v_location.x, v->v.v_location.y);
-            break;
-
-        case TY_AREA:
-            buf = strdup ("%area");
-            free_area (v->v.v_area);
-            break;
-
-        case TY_SPELL:
-            buf = strdup (v->v.v_spell->name);
-            break;
-
-        case TY_INVOCATION:
-        {
-            invocation_t *invocation = within_op
-                ? v->v.v_invocation : (invocation_t *) map_id2bl (v->v.v_int);
-            buf = strdup (invocation->spell->name);
-        }
-            break;
-
-        default:
-            fprintf (stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n",
-                     v->ty);
-            return;
-    }
-
-    v->v.v_string = buf;
-    v->ty = TY_STRING;
-}
-
-static void intify (val_t * v)
-{
-    if (v->ty == TY_INT)
-        return;
-
-    magic_clear_var (v);
-    v->ty = TY_INT;
-    v->v.v_int = 1;
-}
-
-area_t *area_new (int ty)
-{
-    area_t *retval;
-    CREATE (retval, area_t, 1);
-    retval->ty = ty;
-    return retval;
-}
-
-area_t *area_union (area_t * area, area_t * other_area)
-{
-    area_t *retval = area_new (AREA_UNION);
-    retval->a.a_union[0] = area;
-    retval->a.a_union[1] = other_area;
-    retval->size = area->size + other_area->size;   /* Assume no overlap */
-    return retval;
-}
-
-/**
- * Turns location into area, leaves other types untouched
- */
-static void make_area (val_t * v)
-{
-    if (v->ty == TY_LOCATION)
-    {
-        area_t *a = (char *)malloc (sizeof (area_t));
-        v->ty = TY_AREA;
-        a->ty = AREA_LOCATION;
-        a->a.a_loc = v->v.v_location;
-        v->v.v_area = a;
-    }
-}
-
-static void make_location (val_t * v)
-{
-    if (v->ty == TY_AREA && v->v.v_area->ty == AREA_LOCATION)
-    {
-        location_t location = v->v.v_area->a.a_loc;
-        free_area (v->v.v_area);
-        v->ty = TY_LOCATION;
-        v->v.v_location = location;
-    }
-}
-
-static void make_spell (val_t * v)
-{
-    if (v->ty == TY_INVOCATION)
-    {
-        invocation_t *invoc = v->v.v_invocation;    //(invocation_t *) map_id2bl(v->v.v_int);
-        if (!invoc)
-            v->ty = TY_FAIL;
-        else
-        {
-            v->ty = TY_SPELL;
-            v->v.v_spell = invoc->spell;
-        }
-    }
-}
-
-static int fun_add (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (TY (0) == TY_INT && TY (1) == TY_INT)
-    {
-        /* Integer addition */
-        RESULTINT = ARGINT (0) + ARGINT (1);
-        result->ty = TY_INT;
-    }
-    else if (ARG_MAY_BE_AREA (0) && ARG_MAY_BE_AREA (1))
-    {
-        /* Area union */
-        make_area (&args[0]);
-        make_area (&args[1]);
-        RESULTAREA = area_union (ARGAREA (0), ARGAREA (1));
-        ARGAREA (0) = NULL;
-        ARGAREA (1) = NULL;
-        result->ty = TY_AREA;
-    }
-    else
-    {
-        /* Anything else -> string concatenation */
-        stringify (&args[0], 1);
-        stringify (&args[1], 1);
-        /* Yes, we could speed this up. */
-        RESULTSTR =
-            (char *) malloc (1 + strlen (ARGSTR (0)) + strlen (ARGSTR (1)));
-        strcpy (RESULTSTR, ARGSTR (0));
-        strcat (RESULTSTR, ARGSTR (1));
-        result->ty = TY_STRING;
-    }
-    return 0;
-}
-
-static int fun_sub (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) - ARGINT (1);
-    return 0;
-}
-
-static int fun_mul (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) * ARGINT (1);
-    return 0;
-}
-
-static int fun_div (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (!ARGINT (1))
-        return 1;               /* division by zero */
-    RESULTINT = ARGINT (0) / ARGINT (1);
-    return 0;
-}
-
-static int fun_mod (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (!ARGINT (1))
-        return 1;               /* division by zero */
-    RESULTINT = ARGINT (0) % ARGINT (1);
-    return 0;
-}
-
-static int fun_or (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) || ARGINT (1);
-    return 0;
-}
-
-static int fun_and (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) && ARGINT (1);
-    return 0;
-}
-
-static int fun_not (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = !ARGINT (0);
-    return 0;
-}
-
-static int fun_neg (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ~ARGINT (0);
-    return 0;
-}
-
-static int fun_gte (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
-    {
-        stringify (&args[0], 1);
-        stringify (&args[1], 1);
-        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) >= 0;
-    }
-    else
-    {
-        intify (&args[0]);
-        intify (&args[1]);
-        RESULTINT = ARGINT (0) >= ARGINT (1);
-    }
-    return 0;
-}
-
-static int fun_gt (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
-    {
-        stringify (&args[0], 1);
-        stringify (&args[1], 1);
-        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) > 0;
-    }
-    else
-    {
-        intify (&args[0]);
-        intify (&args[1]);
-        RESULTINT = ARGINT (0) > ARGINT (1);
-    }
-    return 0;
-}
-
-static int fun_eq (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
-    {
-        stringify (&args[0], 1);
-        stringify (&args[1], 1);
-        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) == 0;
-    }
-    else if (TY (0) == TY_DIR && TY (1) == TY_DIR)
-        RESULTINT = ARGDIR (0) == ARGDIR (1);
-    else if (TY (0) == TY_ENTITY && TY (1) == TY_ENTITY)
-        RESULTINT = ARGENTITY (0) == ARGENTITY (1);
-    else if (TY (0) == TY_LOCATION && TY (1) == TY_LOCATION)
-        RESULTINT = (ARGLOCATION (0).x == ARGLOCATION (1).x
-                     && ARGLOCATION (0).y == ARGLOCATION (1).y
-                     && ARGLOCATION (0).m == ARGLOCATION (1).m);
-    else if (TY (0) == TY_AREA && TY (1) == TY_AREA)
-        RESULTINT = ARGAREA (0) == ARGAREA (1); /* Probably not that great an idea... */
-    else if (TY (0) == TY_SPELL && TY (1) == TY_SPELL)
-        RESULTINT = ARGSPELL (0) == ARGSPELL (1);
-    else if (TY (0) == TY_INVOCATION && TY (1) == TY_INVOCATION)
-        RESULTINT = ARGINVOCATION (0) == ARGINVOCATION (1);
-    else
-    {
-        intify (&args[0]);
-        intify (&args[1]);
-        RESULTINT = ARGINT (0) == ARGINT (1);
-    }
-    return 0;
-}
-
-static int fun_bitand (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) & ARGINT (1);
-    return 0;
-}
-
-static int fun_bitor (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) | ARGINT (1);
-    return 0;
-}
-
-static int fun_bitxor (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) ^ ARGINT (1);
-    return 0;
-}
-
-static int fun_bitshl (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) << ARGINT (1);
-    return 0;
-}
-
-static int fun_bitshr (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGINT (0) >> ARGINT (1);
-    return 0;
-}
-
-static int fun_max (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = MAX (ARGINT (0), ARGINT (1));
-    return 0;
-}
-
-static int fun_min (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = MIN (ARGINT (0), ARGINT (1));
-    return 0;
-}
-
-static int
-fun_if_then_else (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ARGINT (0))
-        magic_copy_var (result, &args[1]);
-    else
-        magic_copy_var (result, &args[2]);
-    return 0;
-}
-
-void
-magic_area_rect (int *m, int *x, int *y, int *width, int *height,
-                 area_t * area)
-{
-    switch (area->ty)
-    {
-        case AREA_UNION:
-            break;
-
-        case AREA_LOCATION:
-            *m = area->a.a_loc.m;
-            *x = area->a.a_loc.x;
-            *y = area->a.a_loc.y;
-            *width = 1;
-            *height = 1;
-            break;
-
-        case AREA_RECT:
-            *m = area->a.a_rect.loc.m;
-            *x = area->a.a_rect.loc.x;
-            *y = area->a.a_rect.loc.y;
-            *width = area->a.a_rect.width;
-            *height = area->a.a_rect.height;
-            break;
-
-        case AREA_BAR:
-        {
-            int  tx = area->a.a_bar.loc.x;
-            int  ty = area->a.a_bar.loc.y;
-            int  twidth = area->a.a_bar.width;
-            int  tdepth = area->a.a_bar.width;
-            *m = area->a.a_bar.loc.m;
-
-            switch (area->a.a_bar.dir)
-            {
-                case DIR_S:
-                    *x = tx - twidth;
-                    *y = ty;
-                    *width = twidth * 2 + 1;
-                    *height = tdepth;
-                    break;
-
-                case DIR_W:
-                    *x = tx - tdepth;
-                    *y = ty - twidth;
-                    *width = tdepth;
-                    *height = twidth * 2 + 1;
-                    break;
-
-                case DIR_N:
-                    *x = tx - twidth;
-                    *y = ty - tdepth;
-                    *width = twidth * 2 + 1;
-                    *height = tdepth;
-                    break;
-
-                case DIR_E:
-                    *x = tx;
-                    *y = ty - twidth;
-                    *width = tdepth;
-                    *height = twidth * 2 + 1;
-                    break;
-
-                default:
-                    fprintf (stderr,
-                             "Error: Trying to compute area of NE/SE/NW/SW-facing bar");
-                    *x = tx;
-                    *y = ty;
-                    *width = *height = 1;
-            }
-            break;
-        }
-    }
-}
-
-int magic_location_in_area (int m, int x, int y, area_t * area)
-{
-    switch (area->ty)
-    {
-        case AREA_UNION:
-            return magic_location_in_area (m, x, y, area->a.a_union[0])
-                || magic_location_in_area (m, x, y, area->a.a_union[1]);
-        case AREA_LOCATION:
-        case AREA_RECT:
-        case AREA_BAR:
-        {
-            int  am;
-            int  ax, ay, awidth, aheight;
-            magic_area_rect (&am, &ax, &ay, &awidth, &aheight, area);
-            return (am == m
-                    && (x >= ax) && (y >= ay)
-                    && (x < ax + awidth) && (y < ay + aheight));
-        }
-        default:
-            fprintf (stderr, "INTERNAL ERROR: Invalid area\n");
-            return 0;
-    }
-}
-
-static int fun_is_in (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = magic_location_in_area (ARGLOCATION (0).m,
-                                        ARGLOCATION (0).x,
-                                        ARGLOCATION (0).y, ARGAREA (1));
-    return 0;
-}
-
-static int fun_skill (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ETY (0) != BL_PC
-        || ARGINT (1) < 0
-        || ARGINT (1) >= MAX_SKILL
-        || ARGPC (0)->status.skill[ARGINT (1)].id != ARGINT (1))
-        RESULTINT = 0;
-    else
-        RESULTINT = ARGPC (0)->status.skill[ARGINT (1)].lv;
-    return 0;
-}
-
-static int
-fun_has_shroud (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = (ETY (0) == BL_PC && ARGPC (0)->state.shroud_active);
-    return 0;
-}
-
-#define BATTLE_GETTER(name) static int fun_get_##name(env_t *env, int args_nr, val_t *result, val_t *args) { RESULTINT = battle_get_##name(ARGENTITY(0)); return 0; }
-
-BATTLE_GETTER (str);
-BATTLE_GETTER (agi);
-BATTLE_GETTER (vit);
-BATTLE_GETTER (dex);
-BATTLE_GETTER (luk);
-BATTLE_GETTER (int);
-BATTLE_GETTER (lv);
-BATTLE_GETTER (hp);
-BATTLE_GETTER (mdef);
-BATTLE_GETTER (def);
-BATTLE_GETTER (max_hp);
-BATTLE_GETTER (dir);
-
-#define MMO_GETTER(name) static int fun_get_##name(env_t *env, int args_nr, val_t *result, val_t *args) {	\
-                if (ETY(0) == BL_PC)								\
-                	RESULTINT = ARGPC(0)->status.name;					\
-		else										\
-		        RESULTINT = 0;								\
-		return 0; }
-
-MMO_GETTER (sp);
-MMO_GETTER (max_sp);
-
-static int
-fun_name_of (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (TY (0) == TY_ENTITY)
-    {
-        RESULTSTR = strdup (show_entity (ARGENTITY (0)));
-        return 0;
-    }
-    else if (TY (0) == TY_SPELL)
-    {
-        RESULTSTR = strdup (ARGSPELL (0)->name);
-        return 0;
-    }
-    else if (TY (0) == TY_INVOCATION)
-    {
-        RESULTSTR = strdup (ARGINVOCATION (0)->spell->name);
-        return 0;
-    }
-    return 1;
-}
-
-/* [Freeyorp] I'm putting this one in as name_of seems to have issues with summoned or spawned mobs. */
-static int
-fun_mob_id (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ETY (0) != BL_MOB) return 1;
-    RESULTINT = ((struct mob_data *) (ARGENTITY(0)))->mob_class;
-    return 0;
-}
-
-#define COPY_LOCATION(dest, src) (dest).x = (src).x; (dest).y = (src).y; (dest).m = (src).m;
-
-static int
-fun_location (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    COPY_LOCATION (RESULTLOCATION, *(ARGENTITY (0)));
-    return 0;
-}
-
-static int fun_random (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    int  delta = ARGINT (0);
-    if (delta < 0)
-        delta = -delta;
-    if (delta == 0)
-    {
-        RESULTINT = 0;
-        return 0;
-    }
-    RESULTINT = MRAND (delta);
-
-    if (ARGINT (0) < 0)
-        RESULTINT = -RESULTINT;
-    return 0;
-}
-
-static int
-fun_random_dir (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ARGINT (0))
-        RESULTDIR = mt_random () & 0x7;
-    else
-        RESULTDIR = (mt_random () & 0x3) * 2;
-    return 0;
-}
-
-static int
-fun_hash_entity (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGENTITY (0)->id;
-    return 0;
-}
-
-int                             // ret -1: not a string, ret 1: no such item, ret 0: OK
-magic_find_item (val_t * args, int index, struct item *item, int *stackable)
-{
-    struct item_data *item_data;
-    int  must_add_sequentially;
-
-    if (TY (index) == TY_INT)
-        item_data = itemdb_exists (ARGINT (index));
-    else if (TY (index) == TY_STRING)
-        item_data = itemdb_searchname (ARGSTR (index));
-    else
-        return -1;
-
-    if (!item_data)
-        return 1;
-
-    must_add_sequentially = (item_data->type == 4 || item_data->type == 5 || item_data->type == 7 || item_data->type == 8); /* Very elegant. */
-
-    if (stackable)
-        *stackable = !must_add_sequentially;
-
-    memset (item, 0, sizeof (struct item));
-    item->nameid = item_data->nameid;
-    item->identify = 1;
-
-    return 0;
-}
-
-static int
-fun_count_item (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    character_t *chr = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-    int  stackable;
-    struct item item;
-
-    GET_ARG_ITEM (1, item, stackable);
-
-    if (!chr)
-        return 1;
-
-    RESULTINT = pc_count_all_items (chr, item.nameid);
-    return 0;
-}
-
-static int
-fun_is_equipped (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    character_t *chr = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-    int  stackable;
-    struct item item;
-    int  i;
-    int  retval = 0;
-
-    GET_ARG_ITEM (1, item, stackable);
-
-    if (!chr)
-        return 1;
-
-    for (i = 0; i < 11; i++)
-        if (chr->equip_index[i] >= 0
-            && chr->status.inventory[chr->equip_index[i]].nameid ==
-            item.nameid)
-        {
-            retval = i + 1;
-            break;
-        }
-
-    RESULTINT = retval;
-    return 0;
-}
-
-static int
-fun_is_married (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = (ETY (0) == BL_PC && ARGPC (0)->status.partner_id);
-    return 0;
-}
-
-static int
-fun_is_dead (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = (ETY (0) == BL_PC && pc_isdead (ARGPC (0)));
-    return 0;
-}
-
-static int fun_is_pc (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = (ETY (0) == BL_PC);
-    return 0;
-}
-
-static int
-fun_partner (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ETY (0) == BL_PC && ARGPC (0)->status.partner_id)
-    {
-        RESULTENTITY =
-            (entity_t *)
-            map_nick2sd (map_charid2nick (ARGPC (0)->status.partner_id));
-        return 0;
-    }
-    else
-        return 1;
-}
-
-static int
-fun_awayfrom (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    location_t *loc = &ARGLOCATION (0);
-    int  dx = heading_x[ARGDIR (1)];
-    int  dy = heading_y[ARGDIR (1)];
-    int  distance = ARGINT (2);
-    while (distance-- && !map_is_solid (loc->m, loc->x + dx, loc->y + dy))
-    {
-        loc->x += dx;
-        loc->y += dy;
-    }
-
-    RESULTLOCATION = *loc;
-    return 0;
-}
-
-static int fun_failed (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = TY (0) == TY_FAIL;
-    return 0;
-}
-
-static int fun_npc (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTENTITY = (entity_t *) npc_name2id (ARGSTR (0));
-    return RESULTENTITY == NULL;
-}
-
-static int fun_pc (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTENTITY = (entity_t *) map_nick2sd (ARGSTR (0));
-    return RESULTENTITY == NULL;
-}
-
-static int
-fun_distance (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
-        RESULTINT = INT_MAX;
-    else
-        RESULTINT = MAX (abs (ARGLOCATION (0).x - ARGLOCATION (1).x),
-                         abs (ARGLOCATION (0).y - ARGLOCATION (1).y));
-    return 0;
-}
-
-static int
-fun_rdistance (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
-        RESULTINT = INT_MAX;
-    else
-    {
-        int  dx = ARGLOCATION (0).x - ARGLOCATION (1).x;
-        int  dy = ARGLOCATION (0).y - ARGLOCATION (1).y;
-        RESULTINT = (int) (sqrt ((dx * dx) + (dy * dy)));
-    }
-    return 0;
-}
-
-static int fun_anchor (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    teleport_anchor_t *anchor = magic_find_anchor (ARGSTR (0));
-
-    if (!anchor)
-        return 1;
-
-    magic_eval (env, result, anchor->location);
-
-    make_area (result);
-    if (result->ty != TY_AREA)
-    {
-        magic_clear_var (result);
-        return 1;
-    }
-
-    return 0;
-}
-
-static int
-fun_line_of_sight (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    entity_t e1, e2;
-
-    COPY_LOCATION (e1, ARGLOCATION (0));
-    COPY_LOCATION (e2, ARGLOCATION (1));
-
-    RESULTINT = battle_check_range (&e1, &e2, 0);
-
-    return 0;
-}
-
-void magic_random_location (location_t * dest, area_t * area)
-{
-    switch (area->ty)
-    {
-        case AREA_UNION:
-        {
-            int  rv = MRAND (area->size);
-            if (rv < area->a.a_union[0]->size)
-                magic_random_location (dest, area->a.a_union[0]);
-            else
-                magic_random_location (dest, area->a.a_union[1]);
-            break;
-        }
-
-        case AREA_LOCATION:
-        case AREA_RECT:
-        case AREA_BAR:
-        {
-            int  m, x, y, w, h;
-            magic_area_rect (&m, &x, &y, &w, &h, area);
-
-            if (w <= 1)
-                w = 1;
-
-            if (h <= 1)
-                h = 1;
-
-            x += MRAND (w);
-            y += MRAND (h);
-
-            if (!map_is_solid (m, x, y))
-            {
-                int  start_x = x;
-                int  start_y = y;
-                int  i;
-                int  initial_dir = mt_random () & 0x7;
-                int  dir = initial_dir;
-
-                /* try all directions, up to a distance to 10, for a free slot */
-                do
-                {
-                    x = start_x;
-                    y = start_y;
-
-                    for (i = 0; i < 10 && map_is_solid (m, x, y); i++)
-                    {
-                        x += heading_x[dir];
-                        y += heading_y[dir];
-                    }
-
-                    dir = (dir + 1) & 0x7;
-                }
-                while (map_is_solid (m, x, y) && dir != initial_dir);
-
-            }
-            /* We've tried our best.  If the map is still solid, the engine will automatically randomise the target location if we try to warp. */
-
-            dest->m = m;
-            dest->x = x;
-            dest->y = y;
-            break;
-        }
-
-        default:
-            fprintf (stderr, "Unknown area type %d\n", area->ty);
-    }
-}
-
-static int
-fun_pick_location (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    magic_random_location (&result->v.v_location, ARGAREA (0));
-    return 0;
-}
-
-static int
-fun_read_script_int (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    entity_t *subject_p = ARGENTITY (0);
-    char *var_name = ARGSTR (1);
-
-    if (subject_p->type != BL_PC)
-        return 1;
-
-    RESULTINT = pc_readglobalreg ((character_t *) subject_p, var_name);
-    return 0;
-}
-
-static int fun_rbox (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    location_t loc = ARGLOCATION (0);
-    int  radius = ARGINT (1);
-
-    RESULTAREA = area_new (AREA_RECT);
-    RESULTAREA->a.a_rect.loc.m = loc.m;
-    RESULTAREA->a.a_rect.loc.x = loc.x - radius;
-    RESULTAREA->a.a_rect.loc.y = loc.y - radius;
-    RESULTAREA->a.a_rect.width = radius * 2 + 1;
-    RESULTAREA->a.a_rect.height = radius * 2 + 1;
-
-    return 0;
-}
-
-static int
-fun_running_status_update (env_t * env, int args_nr, val_t * result,
-                           val_t * args)
-{
-    if (ETY (0) != BL_PC && ETY (0) != BL_MOB)
-        return 1;
-
-    RESULTINT = battle_get_sc_data (ARGENTITY (0))[ARGINT (1)].timer != -1;
-    return 0;
-}
-
-static int
-fun_status_option (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT =
-        ((((struct map_session_data *) ARGENTITY (0))->
-          status.option & ARGINT (0)) != 0);
-    return 0;
-}
-
-static int
-fun_element (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = battle_get_element (ARGENTITY (0)) % 10;
-    return 0;
-}
-
-static int
-fun_element_level (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = battle_get_element (ARGENTITY (0)) / 10;
-    return 0;
-}
-
-static int fun_index (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = ARGSPELL (0)->index;
-    return 0;
-}
-
-static int
-fun_is_exterior (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = map[ARGLOCATION (0).m].name[4] == '1';
-    return 0;
-}
-
-static int
-fun_contains_string (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = NULL != strstr (ARGSTR (0), ARGSTR (1));
-    return 0;
-}
-
-static int fun_strstr (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    char *offset = strstr (ARGSTR (0), ARGSTR (1));
-    RESULTINT = offset - ARGSTR (0);
-    return offset == NULL;
-}
-
-static int fun_strlen (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = strlen (ARGSTR (0));
-    return 0;
-}
-
-static int fun_substr (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    const char *src = ARGSTR (0);
-    const int slen = strlen (src);
-    int  offset = ARGINT (1);
-    int  len = ARGINT (2);
-
-    if (len < 0)
-        len = 0;
-    if (offset < 0)
-        offset = 0;
-
-    if (offset > slen)
-        offset = slen;
-
-    if (offset + len > slen)
-        len = slen - offset;
-
-    RESULTSTR = (char *) calloc (1, 1 + len);
-    memcpy (RESULTSTR, src + offset, len);
-
-    return 0;
-}
-
-static int fun_sqrt (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = (int) sqrt (ARGINT (0));
-    return 0;
-}
-
-static int
-fun_map_level (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    RESULTINT = map[ARGLOCATION (0).m].name[4] - '0';
-    return 0;
-}
-
-static int fun_map_nr (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    const char *mapname = map[ARGLOCATION (0).m].name;
-
-    RESULTINT = ((mapname[0] - '0') * 100)
-        + ((mapname[1] - '0') * 10) + ((mapname[2] - '0'));
-    return 0;
-}
-
-static int
-fun_dir_towards (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    int  dx;
-    int  dy;
-
-    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
-        return 1;
-
-    dx = ARGLOCATION (1).x - ARGLOCATION (0).x;
-    dy = ARGLOCATION (1).y - ARGLOCATION (0).y;
-
-    if (ARGINT (1))
-    {
-        /* 8-direction mode */
-        if (abs (dx) > abs (dy) * 2)
-        {                       /* east or west */
-            if (dx < 0)
-                RESULTINT = 2 /* west */ ;
-            else
-                RESULTINT = 6 /* east */ ;
-        }
-        else if (abs (dy) > abs (dx) * 2)
-        {                       /* north or south */
-            if (dy > 0)
-                RESULTINT = 0 /* south */ ;
-            else
-                RESULTINT = 4 /* north */ ;
-        }
-        else if (dx < 0)
-        {                       /* north-west or south-west */
-            if (dy < 0)
-                RESULTINT = 3 /* north-west */ ;
-            else
-                RESULTINT = 1 /* south-west */ ;
-        }
-        else
-        {                       /* north-east or south-east */
-            if (dy < 0)
-                RESULTINT = 5 /* north-east */ ;
-            else
-                RESULTINT = 7 /* south-east */ ;
-        }
-    }
-    else
-    {
-        /* 4-direction mode */
-        if (abs (dx) > abs (dy))
-        {                       /* east or west */
-            if (dx < 0)
-                RESULTINT = 2 /* west */ ;
-            else
-                RESULTINT = 6 /* east */ ;
-        }
-        else
-        {                       /* north or south */
-            if (dy > 0)
-                RESULTINT = 0 /* south */ ;
-            else
-                RESULTINT = 4 /* north */ ;
-        }
-    }
-
-    return 0;
-}
-
-static int
-fun_extract_healer_xp (env_t * env, int args_nr, val_t * result, val_t * args)
-{
-    character_t *sd = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-
-    if (!sd)
-        RESULTINT = 0;
-    else
-        RESULTINT = pc_extract_healer_exp (sd, ARGINT (1));
-    return 0;
-}
-
-#define BATTLE_RECORD2(sname, name) { sname, "e", 'i', fun_get_##name }
-#define BATTLE_RECORD(name) BATTLE_RECORD2(#name, name)
-static fun_t functions[] = {
-    {"+", "..", '.', fun_add},
-    {"-", "ii", 'i', fun_sub},
-    {"*", "ii", 'i', fun_mul},
-    {"/", "ii", 'i', fun_div},
-    {"%", "ii", 'i', fun_mod},
-    {"||", "ii", 'i', fun_or},
-    {"&&", "ii", 'i', fun_and},
-    {">", "..", 'i', fun_gt},
-    {">=", "..", 'i', fun_gte},
-    {"=", "..", 'i', fun_eq},
-    {"|", "..", 'i', fun_bitor},
-    {"&", "ii", 'i', fun_bitand},
-    {"^", "ii", 'i', fun_bitxor},
-    {"<<", "ii", 'i', fun_bitshl},
-    {">>", "ii", 'i', fun_bitshr},
-    {"not", "i", 'i', fun_not},
-    {"neg", "i", 'i', fun_neg},
-    {"max", "ii", 'i', fun_max},
-    {"min", "ii", 'i', fun_min},
-    {"is_in", "la", 'i', fun_is_in},
-    {"if_then_else", "i__", '_', fun_if_then_else},
-    {"skill", "ei", 'i', fun_skill},
-    BATTLE_RECORD (str),
-    BATTLE_RECORD (agi),
-    BATTLE_RECORD (vit),
-    BATTLE_RECORD (dex),
-    BATTLE_RECORD (luk),
-    BATTLE_RECORD (int),
-    BATTLE_RECORD2 ("level", lv),
-    BATTLE_RECORD (mdef),
-    BATTLE_RECORD (def),
-    BATTLE_RECORD (hp),
-    BATTLE_RECORD (max_hp),
-    BATTLE_RECORD (sp),
-    BATTLE_RECORD (max_sp),
-    {"dir", "e", 'd', fun_get_dir},
-    {"name_of", ".", 's', fun_name_of},
-    {"mob_id", "e", 'i', fun_mob_id},
-    {"location", "e", 'l', fun_location},
-    {"random", "i", 'i', fun_random},
-    {"random_dir", "i", 'd', fun_random_dir},
-    {"hash_entity", "e", 'i', fun_hash_entity},
-    {"is_married", "e", 'i', fun_is_married},
-    {"partner", "e", 'e', fun_partner},
-    {"awayfrom", "ldi", 'l', fun_awayfrom},
-    {"failed", "_", 'i', fun_failed},
-    {"pc", "s", 'e', fun_pc},
-    {"npc", "s", 'e', fun_npc},
-    {"distance", "ll", 'i', fun_distance},
-    {"rdistance", "ll", 'i', fun_rdistance},
-    {"anchor", "s", 'a', fun_anchor},
-    {"random_location", "a", 'l', fun_pick_location},
-    {"script_int", "es", 'i', fun_read_script_int},
-    {"rbox", "li", 'a', fun_rbox},
-    {"count_item", "e.", 'i', fun_count_item},
-    {"line_of_sight", "ll", 'i', fun_line_of_sight},
-    {"running_status_update", "ei", 'i', fun_running_status_update},
-    {"status_option", "ei", 'i', fun_status_option},
-    {"element", "e", 'i', fun_element},
-    {"element_level", "e", 'i', fun_element_level},
-    {"has_shroud", "e", 'i', fun_has_shroud},
-    {"is_equipped", "e.", 'i', fun_is_equipped},
-    {"spell_index", "S", 'i', fun_index},
-    {"is_exterior", "l", 'i', fun_is_exterior},
-    {"contains_string", "ss", 'i', fun_contains_string},
-    {"strstr", "ss", 'i', fun_strstr},
-    {"strlen", "s", 'i', fun_strlen},
-    {"substr", "sii", 's', fun_substr},
-    {"sqrt", "i", 'i', fun_sqrt},
-    {"map_level", "l", 'i', fun_map_level},
-    {"map_nr", "l", 'i', fun_map_nr},
-    {"dir_towards", "lli", 'd', fun_dir_towards},
-    {"is_dead", "e", 'i', fun_is_dead},
-    {"is_pc", "e", 'i', fun_is_pc},
-    {"extract_healer_experience", "ei", 'i', fun_extract_healer_xp},
-    {NULL, NULL, '.', NULL}
-};
-
-static int functions_are_sorted = 0;
-
-int compare_fun (const void *lhs, const void *rhs)
-{
-    return strcmp (((fun_t *) lhs)->name, ((fun_t *) rhs)->name);
-}
-
-fun_t *magic_get_fun (const char *name, int *index)
-{
-    static int functions_nr;
-    fun_t *result;
-    fun_t key;
-
-    if (!functions_are_sorted)
-    {
-        fun_t *it = functions;
-
-        while (it->name)
-            ++it;
-        functions_nr = it - functions;
-
-        qsort (functions, functions_nr, sizeof (fun_t), compare_fun);
-        functions_are_sorted = 1;
-    }
-
-    key.name = name;
-    result = (fun_t *) bsearch (&key, functions, functions_nr, sizeof (fun_t),
-                                compare_fun);
-
-    if (result && index)
-        *index = result - functions;
-
-    return result;
-}
-
-static int                      // 1 on failure
-eval_location (env_t * env, location_t * dest, e_location_t * expr)
-{
-    val_t m, x, y;
-    magic_eval (env, &m, expr->m);
-    magic_eval (env, &x, expr->x);
-    magic_eval (env, &y, expr->y);
-
-    if (CHECK_TYPE (&m, TY_STRING)
-        && CHECK_TYPE (&x, TY_INT) && CHECK_TYPE (&y, TY_INT))
-    {
-        int  map_id = map_mapname2mapid (m.v.v_string);
-        magic_clear_var (&m);
-        if (map_id < 0)
-            return 1;
-        dest->m = map_id;
-        dest->x = x.v.v_int;
-        dest->y = y.v.v_int;
-        return 0;
-    }
-    else
-    {
-        magic_clear_var (&m);
-        magic_clear_var (&x);
-        magic_clear_var (&y);
-        return 1;
-    }
-}
-
-static area_t *eval_area (env_t * env, e_area_t * expr)
-{
-    area_t *area = (area_t *)malloc (sizeof (area_t));
-    area->ty = expr->ty;
-
-    switch (expr->ty)
-    {
-        case AREA_LOCATION:
-            area->size = 1;
-            if (eval_location (env, &area->a.a_loc, &expr->a.a_loc))
-            {
-                free (area);
-                return NULL;
-            }
-            else
-                return area;
-
-        case AREA_UNION:
-        {
-            int  i, fail = 0;
-            for (i = 0; i < 2; i++)
-            {
-                area->a.a_union[i] = eval_area (env, expr->a.a_union[i]);
-                if (!area->a.a_union[i])
-                    fail = 1;
-            }
-
-            if (fail)
-            {
-                for (i = 0; i < 2; i++)
-                {
-                    if (area->a.a_union[i])
-                        free_area (area->a.a_union[i]);
-                }
-                free (area);
-                return NULL;
-            }
-            area->size = area->a.a_union[0]->size + area->a.a_union[1]->size;
-            return area;
-        }
-
-        case AREA_RECT:
-        {
-            val_t width, height;
-            magic_eval (env, &width, expr->a.a_rect.width);
-            magic_eval (env, &height, expr->a.a_rect.height);
-
-            area->a.a_rect.width = width.v.v_int;
-            area->a.a_rect.height = height.v.v_int;
-
-            if (CHECK_TYPE (&width, TY_INT)
-                && CHECK_TYPE (&height, TY_INT)
-                && !eval_location (env, &(area->a.a_rect.loc),
-                                   &expr->a.a_rect.loc))
-            {
-                area->size = area->a.a_rect.width * area->a.a_rect.height;
-                magic_clear_var (&width);
-                magic_clear_var (&height);
-                return area;
-            }
-            else
-            {
-                free (area);
-                magic_clear_var (&width);
-                magic_clear_var (&height);
-                return NULL;
-            }
-        }
-
-        case AREA_BAR:
-        {
-            val_t width, depth, dir;
-            magic_eval (env, &width, expr->a.a_bar.width);
-            magic_eval (env, &depth, expr->a.a_bar.depth);
-            magic_eval (env, &dir, expr->a.a_bar.dir);
-
-            area->a.a_bar.width = width.v.v_int;
-            area->a.a_bar.depth = depth.v.v_int;
-            area->a.a_bar.dir = dir.v.v_int;
-
-            if (CHECK_TYPE (&width, TY_INT)
-                && CHECK_TYPE (&depth, TY_INT)
-                && CHECK_TYPE (&dir, TY_DIR)
-                && !eval_location (env, &area->a.a_bar.loc,
-                                   &expr->a.a_bar.loc))
-            {
-                area->size =
-                    (area->a.a_bar.width * 2 + 1) * area->a.a_bar.depth;
-                magic_clear_var (&width);
-                magic_clear_var (&depth);
-                magic_clear_var (&dir);
-                return area;
-            }
-            else
-            {
-                free (area);
-                magic_clear_var (&width);
-                magic_clear_var (&depth);
-                magic_clear_var (&dir);
-                return NULL;
-            }
-        }
-
-        default:
-            fprintf (stderr, "INTERNAL ERROR: Unknown area type %d\n",
-                     area->ty);
-            free (area);
-            return NULL;
-    }
-}
-
-static int type_key (char ty_key)
-{
-    switch (ty_key)
-    {
-        case 'i':
-            return TY_INT;
-        case 'd':
-            return TY_DIR;
-        case 's':
-            return TY_STRING;
-        case 'e':
-            return TY_ENTITY;
-        case 'l':
-            return TY_LOCATION;
-        case 'a':
-            return TY_AREA;
-        case 'S':
-            return TY_SPELL;
-        case 'I':
-            return TY_INVOCATION;
-        default:
-            return -1;
-    }
-}
-
-int
-magic_signature_check (char *opname, char *funname, char *signature,
-                       int args_nr, val_t * args, int line, int column)
-{
-    int  i;
-    for (i = 0; i < args_nr; i++)
-    {
-        val_t *arg = &args[i];
-        char ty_key = signature[i];
-        int  ty = arg->ty;
-        int  desired_ty = type_key (ty_key);
-
-        if (ty == TY_ENTITY)
-        {
-            /* Dereference entities in preparation for calling function */
-            arg->v.v_entity = map_id2bl (arg->v.v_int);
-            if (!arg->v.v_entity)
-                ty = arg->ty = TY_FAIL;
-        }
-        else if (ty == TY_INVOCATION)
-        {
-            arg->v.v_invocation = (invocation_t *) map_id2bl (arg->v.v_int);
-            if (!arg->v.v_entity)
-                ty = arg->ty = TY_FAIL;
-        }
-
-        if (!ty_key)
-        {
-            fprintf (stderr,
-                     "[magic-eval]:  L%d:%d: Too many arguments (%d) to %s `%s'\n",
-                     line, column, args_nr, opname, funname);
-            return 1;
-        }
-
-        if (ty == TY_FAIL && ty_key != '_')
-            return 1;           /* Fail `in a sane way':  This is a perfectly permissible error */
-
-        if (ty == desired_ty || desired_ty < 0 /* `dontcare' */ )
-            continue;
-
-        if (ty == TY_UNDEF)
-        {
-            fprintf (stderr,
-                     "[magic-eval]:  L%d:%d: Argument #%d to %s `%s' undefined\n",
-                     line, column, i + 1, opname, funname);
-            return 1;
-        }
-
-        /* If we are here, we have a type mismatch but no failure _yet_.  Try to coerce. */
-        switch (desired_ty)
-        {
-            case TY_INT:
-                intify (arg);
-                break;          /* 100% success rate */
-            case TY_STRING:
-                stringify (arg, 1);
-                break;          /* 100% success rate */
-            case TY_AREA:
-                make_area (arg);
-                break;          /* Only works for locations */
-            case TY_LOCATION:
-                make_location (arg);
-                break;          /* Only works for some areas */
-            case TY_SPELL:
-                make_spell (arg);
-                break;          /* Only works for still-active invocatoins */
-            default:
-                break;          /* We'll fail right below */
-        }
-
-        ty = arg->ty;
-        if (ty != desired_ty)
-        {                       /* Coercion failed? */
-            if (ty != TY_FAIL)
-                fprintf (stderr,
-                         "[magic-eval]:  L%d:%d: Argument #%d to %s `%s' of incorrect type (%d)\n",
-                         line, column, i + 1, opname, funname, ty);
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-void magic_eval (env_t * env, val_t * dest, expr_t * expr)
-{
-    switch (expr->ty)
-    {
-        case EXPR_VAL:
-            magic_copy_var (dest, &expr->e.e_val);
-            break;
-
-        case EXPR_LOCATION:
-            if (eval_location (env, &dest->v.v_location, &expr->e.e_location))
-                dest->ty = TY_FAIL;
-            else
-                dest->ty = TY_LOCATION;
-            break;
-
-        case EXPR_AREA:
-            if ((dest->v.v_area = eval_area (env, &expr->e.e_area)))
-                dest->ty = TY_AREA;
-            else
-                dest->ty = TY_FAIL;
-            break;
-
-        case EXPR_FUNAPP:
-        {
-            val_t arguments[MAX_ARGS];
-            int  args_nr = expr->e.e_funapp.args_nr;
-            int  i;
-            fun_t *f = functions + expr->e.e_funapp.id;
-
-            for (i = 0; i < args_nr; ++i)
-                magic_eval (env, &arguments[i], expr->e.e_funapp.args[i]);
-            if (magic_signature_check
-                ("function", f->name, f->signature, args_nr, arguments,
-                 expr->e.e_funapp.line_nr, expr->e.e_funapp.column)
-                || f->fun (env, args_nr, dest, arguments))
-                dest->ty = TY_FAIL;
-            else
-            {
-                int  dest_ty = type_key (f->ret_ty);
-                if (dest_ty != -1)
-                    dest->ty = dest_ty;
-
-                /* translate entity back into persistent int */
-                if (dest->ty == TY_ENTITY)
-                {
-                    if (dest->v.v_entity)
-                        dest->v.v_int = dest->v.v_entity->id;
-                    else
-                        dest->ty = TY_FAIL;
-                }
-            }
-
-            for (i = 0; i < args_nr; ++i)
-                magic_clear_var (&arguments[i]);
-            break;
-        }
-
-        case EXPR_ID:
-        {
-            val_t v = VAR (expr->e.e_id);
-            magic_copy_var (dest, &v);
-            break;
-        }
-
-        case EXPR_SPELLFIELD:
-        {
-            val_t v;
-            int  id = expr->e.e_field.id;
-            magic_eval (env, &v, expr->e.e_field.expr);
-
-            if (v.ty == TY_INVOCATION)
-            {
-                invocation_t *t = (invocation_t *) map_id2bl (v.v.v_int);
-
-                if (!t)
-                    dest->ty = TY_UNDEF;
-                else
-                {
-                    env_t *env = t->env;
-                    val_t v = VAR (id);
-                    magic_copy_var (dest, &v);
-                }
-            }
-            else
-            {
-                fprintf (stderr,
-                         "[magic] Attempt to access field %s on non-spell\n",
-                         env->base_env->var_name[id]);
-                dest->ty = TY_FAIL;
-            }
-            break;
-        }
-
-        default:
-            fprintf (stderr,
-                     "[magic] INTERNAL ERROR: Unknown expression type %d\n",
-                     expr->ty);
-            break;
-    }
-}
-
-int magic_eval_int (env_t * env, expr_t * expr)
-{
-    val_t result;
-    magic_eval (env, &result, expr);
-
-    if (result.ty == TY_FAIL || result.ty == TY_UNDEF)
-        return 0;
-
-    intify (&result);
-
-    return result.v.v_int;
-}
-
-char *magic_eval_str (env_t * env, expr_t * expr)
-{
-    val_t result;
-    magic_eval (env, &result, expr);
-
-    if (result.ty == TY_FAIL || result.ty == TY_UNDEF)
-        return strdup ("?");
-
-    stringify (&result, 0);
-
-    return result.v.v_string;
-}
-
-expr_t *magic_new_expr (int ty)
-{
-    expr_t *expr = (expr_t *) malloc (sizeof (expr_t));
-    expr->ty = ty;
-    return expr;
-}
diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp
new file mode 100644
index 0000000..d75042d
--- /dev/null
+++ b/src/map/magic-expr.cpp
@@ -0,0 +1,1655 @@
+#include "magic-expr.hpp"
+#include "magic-expr-eval.hpp"
+#include "itemdb.hpp"
+#include <math.h>
+
+#include "../common/mt_rand.hpp"
+
+#define IS_SOLID(c) ((c) == 1 || (c) == 5)
+
+int map_is_solid (int m, int x, int y)
+{
+    return (IS_SOLID (map_getcell (m, x, y)));
+}
+
+#undef IS_SOLID
+
+static void free_area (area_t * area)
+{
+    if (!area)
+        return;
+
+    switch (area->ty)
+    {
+        case AREA_UNION:
+            free_area (area->a.a_union[0]);
+            free_area (area->a.a_union[1]);
+            break;
+        default:
+            break;
+    }
+
+    free (area);
+}
+
+static area_t *dup_area (area_t * area)
+{
+    area_t *retval = (area_t *)malloc (sizeof (area_t));
+    *retval = *area;
+
+    switch (area->ty)
+    {
+        case AREA_UNION:
+            retval->a.a_union[0] = dup_area (retval->a.a_union[0]);
+            retval->a.a_union[1] = dup_area (retval->a.a_union[1]);
+            break;
+        default:
+            break;
+    }
+
+    return retval;
+}
+
+void magic_copy_var (val_t * dest, val_t * src)
+{
+    *dest = *src;
+
+    switch (dest->ty)
+    {
+        case TY_STRING:
+            dest->v.v_string = strdup (dest->v.v_string);
+            break;
+        case TY_AREA:
+            dest->v.v_area = dup_area (dest->v.v_area);
+            break;
+        default:
+            break;
+    }
+
+}
+
+void magic_clear_var (val_t * v)
+{
+    switch (v->ty)
+    {
+        case TY_STRING:
+            free (v->v.v_string);
+            break;
+        case TY_AREA:
+            free_area (v->v.v_area);
+            break;
+        default:
+            break;
+    }
+}
+
+static char *show_entity (entity_t * entity)
+{
+    switch (entity->type)
+    {
+        case BL_PC:
+            return ((struct map_session_data *) entity)->status.name;
+        case BL_NPC:
+            return ((struct npc_data *) entity)->name;
+        case BL_MOB:
+            return ((struct mob_data *) entity)->name;
+        case BL_ITEM:
+            /* Sorry about this one... */
+            return ((struct item_data
+                     *) (&((struct flooritem_data *) entity)->
+                         item_data))->name;
+        case BL_SKILL:
+            return "%skill";
+        case BL_SPELL:
+            return "%invocation(ERROR:this-should-not-be-an-entity)";
+        default:
+            return "%unknown-entity";
+    }
+}
+
+static void stringify (val_t * v, int within_op)
+{
+    static char *dirs[8] =
+        { "south", "south-west", "west", "north-west", "north", "north-east",
+        "east", "south-east"
+    };
+    char *buf;
+
+    switch (v->ty)
+    {
+        case TY_UNDEF:
+            buf = strdup ("UNDEF");
+            break;
+
+        case TY_INT:
+            buf = (char *)malloc (32);
+            sprintf (buf, "%i", v->v.v_int);
+            break;
+
+        case TY_STRING:
+            return;
+
+        case TY_DIR:
+            buf = strdup (dirs[v->v.v_int]);
+            break;
+
+        case TY_ENTITY:
+            buf = strdup (show_entity (v->v.v_entity));
+            break;
+
+        case TY_LOCATION:
+            buf = (char *) malloc (128);
+            sprintf (buf, "<\"%s\", %d, %d>", map[v->v.v_location.m].name,
+                     v->v.v_location.x, v->v.v_location.y);
+            break;
+
+        case TY_AREA:
+            buf = strdup ("%area");
+            free_area (v->v.v_area);
+            break;
+
+        case TY_SPELL:
+            buf = strdup (v->v.v_spell->name);
+            break;
+
+        case TY_INVOCATION:
+        {
+            invocation_t *invocation = within_op
+                ? v->v.v_invocation : (invocation_t *) map_id2bl (v->v.v_int);
+            buf = strdup (invocation->spell->name);
+        }
+            break;
+
+        default:
+            fprintf (stderr, "[magic] INTERNAL ERROR: Cannot stringify %d\n",
+                     v->ty);
+            return;
+    }
+
+    v->v.v_string = buf;
+    v->ty = TY_STRING;
+}
+
+static void intify (val_t * v)
+{
+    if (v->ty == TY_INT)
+        return;
+
+    magic_clear_var (v);
+    v->ty = TY_INT;
+    v->v.v_int = 1;
+}
+
+area_t *area_new (int ty)
+{
+    area_t *retval;
+    CREATE (retval, area_t, 1);
+    retval->ty = ty;
+    return retval;
+}
+
+area_t *area_union (area_t * area, area_t * other_area)
+{
+    area_t *retval = area_new (AREA_UNION);
+    retval->a.a_union[0] = area;
+    retval->a.a_union[1] = other_area;
+    retval->size = area->size + other_area->size;   /* Assume no overlap */
+    return retval;
+}
+
+/**
+ * Turns location into area, leaves other types untouched
+ */
+static void make_area (val_t * v)
+{
+    if (v->ty == TY_LOCATION)
+    {
+        area_t *a = (char *)malloc (sizeof (area_t));
+        v->ty = TY_AREA;
+        a->ty = AREA_LOCATION;
+        a->a.a_loc = v->v.v_location;
+        v->v.v_area = a;
+    }
+}
+
+static void make_location (val_t * v)
+{
+    if (v->ty == TY_AREA && v->v.v_area->ty == AREA_LOCATION)
+    {
+        location_t location = v->v.v_area->a.a_loc;
+        free_area (v->v.v_area);
+        v->ty = TY_LOCATION;
+        v->v.v_location = location;
+    }
+}
+
+static void make_spell (val_t * v)
+{
+    if (v->ty == TY_INVOCATION)
+    {
+        invocation_t *invoc = v->v.v_invocation;    //(invocation_t *) map_id2bl(v->v.v_int);
+        if (!invoc)
+            v->ty = TY_FAIL;
+        else
+        {
+            v->ty = TY_SPELL;
+            v->v.v_spell = invoc->spell;
+        }
+    }
+}
+
+static int fun_add (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (TY (0) == TY_INT && TY (1) == TY_INT)
+    {
+        /* Integer addition */
+        RESULTINT = ARGINT (0) + ARGINT (1);
+        result->ty = TY_INT;
+    }
+    else if (ARG_MAY_BE_AREA (0) && ARG_MAY_BE_AREA (1))
+    {
+        /* Area union */
+        make_area (&args[0]);
+        make_area (&args[1]);
+        RESULTAREA = area_union (ARGAREA (0), ARGAREA (1));
+        ARGAREA (0) = NULL;
+        ARGAREA (1) = NULL;
+        result->ty = TY_AREA;
+    }
+    else
+    {
+        /* Anything else -> string concatenation */
+        stringify (&args[0], 1);
+        stringify (&args[1], 1);
+        /* Yes, we could speed this up. */
+        RESULTSTR =
+            (char *) malloc (1 + strlen (ARGSTR (0)) + strlen (ARGSTR (1)));
+        strcpy (RESULTSTR, ARGSTR (0));
+        strcat (RESULTSTR, ARGSTR (1));
+        result->ty = TY_STRING;
+    }
+    return 0;
+}
+
+static int fun_sub (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) - ARGINT (1);
+    return 0;
+}
+
+static int fun_mul (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) * ARGINT (1);
+    return 0;
+}
+
+static int fun_div (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (!ARGINT (1))
+        return 1;               /* division by zero */
+    RESULTINT = ARGINT (0) / ARGINT (1);
+    return 0;
+}
+
+static int fun_mod (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (!ARGINT (1))
+        return 1;               /* division by zero */
+    RESULTINT = ARGINT (0) % ARGINT (1);
+    return 0;
+}
+
+static int fun_or (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) || ARGINT (1);
+    return 0;
+}
+
+static int fun_and (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) && ARGINT (1);
+    return 0;
+}
+
+static int fun_not (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = !ARGINT (0);
+    return 0;
+}
+
+static int fun_neg (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ~ARGINT (0);
+    return 0;
+}
+
+static int fun_gte (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
+    {
+        stringify (&args[0], 1);
+        stringify (&args[1], 1);
+        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) >= 0;
+    }
+    else
+    {
+        intify (&args[0]);
+        intify (&args[1]);
+        RESULTINT = ARGINT (0) >= ARGINT (1);
+    }
+    return 0;
+}
+
+static int fun_gt (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
+    {
+        stringify (&args[0], 1);
+        stringify (&args[1], 1);
+        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) > 0;
+    }
+    else
+    {
+        intify (&args[0]);
+        intify (&args[1]);
+        RESULTINT = ARGINT (0) > ARGINT (1);
+    }
+    return 0;
+}
+
+static int fun_eq (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (TY (0) == TY_STRING || TY (1) == TY_STRING)
+    {
+        stringify (&args[0], 1);
+        stringify (&args[1], 1);
+        RESULTINT = strcmp (ARGSTR (0), ARGSTR (1)) == 0;
+    }
+    else if (TY (0) == TY_DIR && TY (1) == TY_DIR)
+        RESULTINT = ARGDIR (0) == ARGDIR (1);
+    else if (TY (0) == TY_ENTITY && TY (1) == TY_ENTITY)
+        RESULTINT = ARGENTITY (0) == ARGENTITY (1);
+    else if (TY (0) == TY_LOCATION && TY (1) == TY_LOCATION)
+        RESULTINT = (ARGLOCATION (0).x == ARGLOCATION (1).x
+                     && ARGLOCATION (0).y == ARGLOCATION (1).y
+                     && ARGLOCATION (0).m == ARGLOCATION (1).m);
+    else if (TY (0) == TY_AREA && TY (1) == TY_AREA)
+        RESULTINT = ARGAREA (0) == ARGAREA (1); /* Probably not that great an idea... */
+    else if (TY (0) == TY_SPELL && TY (1) == TY_SPELL)
+        RESULTINT = ARGSPELL (0) == ARGSPELL (1);
+    else if (TY (0) == TY_INVOCATION && TY (1) == TY_INVOCATION)
+        RESULTINT = ARGINVOCATION (0) == ARGINVOCATION (1);
+    else
+    {
+        intify (&args[0]);
+        intify (&args[1]);
+        RESULTINT = ARGINT (0) == ARGINT (1);
+    }
+    return 0;
+}
+
+static int fun_bitand (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) & ARGINT (1);
+    return 0;
+}
+
+static int fun_bitor (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) | ARGINT (1);
+    return 0;
+}
+
+static int fun_bitxor (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) ^ ARGINT (1);
+    return 0;
+}
+
+static int fun_bitshl (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) << ARGINT (1);
+    return 0;
+}
+
+static int fun_bitshr (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGINT (0) >> ARGINT (1);
+    return 0;
+}
+
+static int fun_max (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = MAX (ARGINT (0), ARGINT (1));
+    return 0;
+}
+
+static int fun_min (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = MIN (ARGINT (0), ARGINT (1));
+    return 0;
+}
+
+static int
+fun_if_then_else (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ARGINT (0))
+        magic_copy_var (result, &args[1]);
+    else
+        magic_copy_var (result, &args[2]);
+    return 0;
+}
+
+void
+magic_area_rect (int *m, int *x, int *y, int *width, int *height,
+                 area_t * area)
+{
+    switch (area->ty)
+    {
+        case AREA_UNION:
+            break;
+
+        case AREA_LOCATION:
+            *m = area->a.a_loc.m;
+            *x = area->a.a_loc.x;
+            *y = area->a.a_loc.y;
+            *width = 1;
+            *height = 1;
+            break;
+
+        case AREA_RECT:
+            *m = area->a.a_rect.loc.m;
+            *x = area->a.a_rect.loc.x;
+            *y = area->a.a_rect.loc.y;
+            *width = area->a.a_rect.width;
+            *height = area->a.a_rect.height;
+            break;
+
+        case AREA_BAR:
+        {
+            int  tx = area->a.a_bar.loc.x;
+            int  ty = area->a.a_bar.loc.y;
+            int  twidth = area->a.a_bar.width;
+            int  tdepth = area->a.a_bar.width;
+            *m = area->a.a_bar.loc.m;
+
+            switch (area->a.a_bar.dir)
+            {
+                case DIR_S:
+                    *x = tx - twidth;
+                    *y = ty;
+                    *width = twidth * 2 + 1;
+                    *height = tdepth;
+                    break;
+
+                case DIR_W:
+                    *x = tx - tdepth;
+                    *y = ty - twidth;
+                    *width = tdepth;
+                    *height = twidth * 2 + 1;
+                    break;
+
+                case DIR_N:
+                    *x = tx - twidth;
+                    *y = ty - tdepth;
+                    *width = twidth * 2 + 1;
+                    *height = tdepth;
+                    break;
+
+                case DIR_E:
+                    *x = tx;
+                    *y = ty - twidth;
+                    *width = tdepth;
+                    *height = twidth * 2 + 1;
+                    break;
+
+                default:
+                    fprintf (stderr,
+                             "Error: Trying to compute area of NE/SE/NW/SW-facing bar");
+                    *x = tx;
+                    *y = ty;
+                    *width = *height = 1;
+            }
+            break;
+        }
+    }
+}
+
+int magic_location_in_area (int m, int x, int y, area_t * area)
+{
+    switch (area->ty)
+    {
+        case AREA_UNION:
+            return magic_location_in_area (m, x, y, area->a.a_union[0])
+                || magic_location_in_area (m, x, y, area->a.a_union[1]);
+        case AREA_LOCATION:
+        case AREA_RECT:
+        case AREA_BAR:
+        {
+            int  am;
+            int  ax, ay, awidth, aheight;
+            magic_area_rect (&am, &ax, &ay, &awidth, &aheight, area);
+            return (am == m
+                    && (x >= ax) && (y >= ay)
+                    && (x < ax + awidth) && (y < ay + aheight));
+        }
+        default:
+            fprintf (stderr, "INTERNAL ERROR: Invalid area\n");
+            return 0;
+    }
+}
+
+static int fun_is_in (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = magic_location_in_area (ARGLOCATION (0).m,
+                                        ARGLOCATION (0).x,
+                                        ARGLOCATION (0).y, ARGAREA (1));
+    return 0;
+}
+
+static int fun_skill (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ETY (0) != BL_PC
+        || ARGINT (1) < 0
+        || ARGINT (1) >= MAX_SKILL
+        || ARGPC (0)->status.skill[ARGINT (1)].id != ARGINT (1))
+        RESULTINT = 0;
+    else
+        RESULTINT = ARGPC (0)->status.skill[ARGINT (1)].lv;
+    return 0;
+}
+
+static int
+fun_has_shroud (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = (ETY (0) == BL_PC && ARGPC (0)->state.shroud_active);
+    return 0;
+}
+
+#define BATTLE_GETTER(name) static int fun_get_##name(env_t *env, int args_nr, val_t *result, val_t *args) { RESULTINT = battle_get_##name(ARGENTITY(0)); return 0; }
+
+BATTLE_GETTER (str);
+BATTLE_GETTER (agi);
+BATTLE_GETTER (vit);
+BATTLE_GETTER (dex);
+BATTLE_GETTER (luk);
+BATTLE_GETTER (int);
+BATTLE_GETTER (lv);
+BATTLE_GETTER (hp);
+BATTLE_GETTER (mdef);
+BATTLE_GETTER (def);
+BATTLE_GETTER (max_hp);
+BATTLE_GETTER (dir);
+
+#define MMO_GETTER(name) static int fun_get_##name(env_t *env, int args_nr, val_t *result, val_t *args) {	\
+                if (ETY(0) == BL_PC)								\
+                	RESULTINT = ARGPC(0)->status.name;					\
+		else										\
+		        RESULTINT = 0;								\
+		return 0; }
+
+MMO_GETTER (sp);
+MMO_GETTER (max_sp);
+
+static int
+fun_name_of (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (TY (0) == TY_ENTITY)
+    {
+        RESULTSTR = strdup (show_entity (ARGENTITY (0)));
+        return 0;
+    }
+    else if (TY (0) == TY_SPELL)
+    {
+        RESULTSTR = strdup (ARGSPELL (0)->name);
+        return 0;
+    }
+    else if (TY (0) == TY_INVOCATION)
+    {
+        RESULTSTR = strdup (ARGINVOCATION (0)->spell->name);
+        return 0;
+    }
+    return 1;
+}
+
+/* [Freeyorp] I'm putting this one in as name_of seems to have issues with summoned or spawned mobs. */
+static int
+fun_mob_id (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ETY (0) != BL_MOB) return 1;
+    RESULTINT = ((struct mob_data *) (ARGENTITY(0)))->mob_class;
+    return 0;
+}
+
+#define COPY_LOCATION(dest, src) (dest).x = (src).x; (dest).y = (src).y; (dest).m = (src).m;
+
+static int
+fun_location (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    COPY_LOCATION (RESULTLOCATION, *(ARGENTITY (0)));
+    return 0;
+}
+
+static int fun_random (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    int  delta = ARGINT (0);
+    if (delta < 0)
+        delta = -delta;
+    if (delta == 0)
+    {
+        RESULTINT = 0;
+        return 0;
+    }
+    RESULTINT = MRAND (delta);
+
+    if (ARGINT (0) < 0)
+        RESULTINT = -RESULTINT;
+    return 0;
+}
+
+static int
+fun_random_dir (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ARGINT (0))
+        RESULTDIR = mt_random () & 0x7;
+    else
+        RESULTDIR = (mt_random () & 0x3) * 2;
+    return 0;
+}
+
+static int
+fun_hash_entity (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGENTITY (0)->id;
+    return 0;
+}
+
+int                             // ret -1: not a string, ret 1: no such item, ret 0: OK
+magic_find_item (val_t * args, int index, struct item *item, int *stackable)
+{
+    struct item_data *item_data;
+    int  must_add_sequentially;
+
+    if (TY (index) == TY_INT)
+        item_data = itemdb_exists (ARGINT (index));
+    else if (TY (index) == TY_STRING)
+        item_data = itemdb_searchname (ARGSTR (index));
+    else
+        return -1;
+
+    if (!item_data)
+        return 1;
+
+    must_add_sequentially = (item_data->type == 4 || item_data->type == 5 || item_data->type == 7 || item_data->type == 8); /* Very elegant. */
+
+    if (stackable)
+        *stackable = !must_add_sequentially;
+
+    memset (item, 0, sizeof (struct item));
+    item->nameid = item_data->nameid;
+    item->identify = 1;
+
+    return 0;
+}
+
+static int
+fun_count_item (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    character_t *chr = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+    int  stackable;
+    struct item item;
+
+    GET_ARG_ITEM (1, item, stackable);
+
+    if (!chr)
+        return 1;
+
+    RESULTINT = pc_count_all_items (chr, item.nameid);
+    return 0;
+}
+
+static int
+fun_is_equipped (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    character_t *chr = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+    int  stackable;
+    struct item item;
+    int  i;
+    int  retval = 0;
+
+    GET_ARG_ITEM (1, item, stackable);
+
+    if (!chr)
+        return 1;
+
+    for (i = 0; i < 11; i++)
+        if (chr->equip_index[i] >= 0
+            && chr->status.inventory[chr->equip_index[i]].nameid ==
+            item.nameid)
+        {
+            retval = i + 1;
+            break;
+        }
+
+    RESULTINT = retval;
+    return 0;
+}
+
+static int
+fun_is_married (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = (ETY (0) == BL_PC && ARGPC (0)->status.partner_id);
+    return 0;
+}
+
+static int
+fun_is_dead (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = (ETY (0) == BL_PC && pc_isdead (ARGPC (0)));
+    return 0;
+}
+
+static int fun_is_pc (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = (ETY (0) == BL_PC);
+    return 0;
+}
+
+static int
+fun_partner (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ETY (0) == BL_PC && ARGPC (0)->status.partner_id)
+    {
+        RESULTENTITY =
+            (entity_t *)
+            map_nick2sd (map_charid2nick (ARGPC (0)->status.partner_id));
+        return 0;
+    }
+    else
+        return 1;
+}
+
+static int
+fun_awayfrom (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    location_t *loc = &ARGLOCATION (0);
+    int  dx = heading_x[ARGDIR (1)];
+    int  dy = heading_y[ARGDIR (1)];
+    int  distance = ARGINT (2);
+    while (distance-- && !map_is_solid (loc->m, loc->x + dx, loc->y + dy))
+    {
+        loc->x += dx;
+        loc->y += dy;
+    }
+
+    RESULTLOCATION = *loc;
+    return 0;
+}
+
+static int fun_failed (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = TY (0) == TY_FAIL;
+    return 0;
+}
+
+static int fun_npc (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTENTITY = (entity_t *) npc_name2id (ARGSTR (0));
+    return RESULTENTITY == NULL;
+}
+
+static int fun_pc (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTENTITY = (entity_t *) map_nick2sd (ARGSTR (0));
+    return RESULTENTITY == NULL;
+}
+
+static int
+fun_distance (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
+        RESULTINT = INT_MAX;
+    else
+        RESULTINT = MAX (abs (ARGLOCATION (0).x - ARGLOCATION (1).x),
+                         abs (ARGLOCATION (0).y - ARGLOCATION (1).y));
+    return 0;
+}
+
+static int
+fun_rdistance (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
+        RESULTINT = INT_MAX;
+    else
+    {
+        int  dx = ARGLOCATION (0).x - ARGLOCATION (1).x;
+        int  dy = ARGLOCATION (0).y - ARGLOCATION (1).y;
+        RESULTINT = (int) (sqrt ((dx * dx) + (dy * dy)));
+    }
+    return 0;
+}
+
+static int fun_anchor (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    teleport_anchor_t *anchor = magic_find_anchor (ARGSTR (0));
+
+    if (!anchor)
+        return 1;
+
+    magic_eval (env, result, anchor->location);
+
+    make_area (result);
+    if (result->ty != TY_AREA)
+    {
+        magic_clear_var (result);
+        return 1;
+    }
+
+    return 0;
+}
+
+static int
+fun_line_of_sight (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    entity_t e1, e2;
+
+    COPY_LOCATION (e1, ARGLOCATION (0));
+    COPY_LOCATION (e2, ARGLOCATION (1));
+
+    RESULTINT = battle_check_range (&e1, &e2, 0);
+
+    return 0;
+}
+
+void magic_random_location (location_t * dest, area_t * area)
+{
+    switch (area->ty)
+    {
+        case AREA_UNION:
+        {
+            int  rv = MRAND (area->size);
+            if (rv < area->a.a_union[0]->size)
+                magic_random_location (dest, area->a.a_union[0]);
+            else
+                magic_random_location (dest, area->a.a_union[1]);
+            break;
+        }
+
+        case AREA_LOCATION:
+        case AREA_RECT:
+        case AREA_BAR:
+        {
+            int  m, x, y, w, h;
+            magic_area_rect (&m, &x, &y, &w, &h, area);
+
+            if (w <= 1)
+                w = 1;
+
+            if (h <= 1)
+                h = 1;
+
+            x += MRAND (w);
+            y += MRAND (h);
+
+            if (!map_is_solid (m, x, y))
+            {
+                int  start_x = x;
+                int  start_y = y;
+                int  i;
+                int  initial_dir = mt_random () & 0x7;
+                int  dir = initial_dir;
+
+                /* try all directions, up to a distance to 10, for a free slot */
+                do
+                {
+                    x = start_x;
+                    y = start_y;
+
+                    for (i = 0; i < 10 && map_is_solid (m, x, y); i++)
+                    {
+                        x += heading_x[dir];
+                        y += heading_y[dir];
+                    }
+
+                    dir = (dir + 1) & 0x7;
+                }
+                while (map_is_solid (m, x, y) && dir != initial_dir);
+
+            }
+            /* We've tried our best.  If the map is still solid, the engine will automatically randomise the target location if we try to warp. */
+
+            dest->m = m;
+            dest->x = x;
+            dest->y = y;
+            break;
+        }
+
+        default:
+            fprintf (stderr, "Unknown area type %d\n", area->ty);
+    }
+}
+
+static int
+fun_pick_location (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    magic_random_location (&result->v.v_location, ARGAREA (0));
+    return 0;
+}
+
+static int
+fun_read_script_int (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    entity_t *subject_p = ARGENTITY (0);
+    char *var_name = ARGSTR (1);
+
+    if (subject_p->type != BL_PC)
+        return 1;
+
+    RESULTINT = pc_readglobalreg ((character_t *) subject_p, var_name);
+    return 0;
+}
+
+static int fun_rbox (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    location_t loc = ARGLOCATION (0);
+    int  radius = ARGINT (1);
+
+    RESULTAREA = area_new (AREA_RECT);
+    RESULTAREA->a.a_rect.loc.m = loc.m;
+    RESULTAREA->a.a_rect.loc.x = loc.x - radius;
+    RESULTAREA->a.a_rect.loc.y = loc.y - radius;
+    RESULTAREA->a.a_rect.width = radius * 2 + 1;
+    RESULTAREA->a.a_rect.height = radius * 2 + 1;
+
+    return 0;
+}
+
+static int
+fun_running_status_update (env_t * env, int args_nr, val_t * result,
+                           val_t * args)
+{
+    if (ETY (0) != BL_PC && ETY (0) != BL_MOB)
+        return 1;
+
+    RESULTINT = battle_get_sc_data (ARGENTITY (0))[ARGINT (1)].timer != -1;
+    return 0;
+}
+
+static int
+fun_status_option (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT =
+        ((((struct map_session_data *) ARGENTITY (0))->
+          status.option & ARGINT (0)) != 0);
+    return 0;
+}
+
+static int
+fun_element (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = battle_get_element (ARGENTITY (0)) % 10;
+    return 0;
+}
+
+static int
+fun_element_level (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = battle_get_element (ARGENTITY (0)) / 10;
+    return 0;
+}
+
+static int fun_index (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = ARGSPELL (0)->index;
+    return 0;
+}
+
+static int
+fun_is_exterior (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = map[ARGLOCATION (0).m].name[4] == '1';
+    return 0;
+}
+
+static int
+fun_contains_string (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = NULL != strstr (ARGSTR (0), ARGSTR (1));
+    return 0;
+}
+
+static int fun_strstr (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    char *offset = strstr (ARGSTR (0), ARGSTR (1));
+    RESULTINT = offset - ARGSTR (0);
+    return offset == NULL;
+}
+
+static int fun_strlen (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = strlen (ARGSTR (0));
+    return 0;
+}
+
+static int fun_substr (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    const char *src = ARGSTR (0);
+    const int slen = strlen (src);
+    int  offset = ARGINT (1);
+    int  len = ARGINT (2);
+
+    if (len < 0)
+        len = 0;
+    if (offset < 0)
+        offset = 0;
+
+    if (offset > slen)
+        offset = slen;
+
+    if (offset + len > slen)
+        len = slen - offset;
+
+    RESULTSTR = (char *) calloc (1, 1 + len);
+    memcpy (RESULTSTR, src + offset, len);
+
+    return 0;
+}
+
+static int fun_sqrt (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = (int) sqrt (ARGINT (0));
+    return 0;
+}
+
+static int
+fun_map_level (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    RESULTINT = map[ARGLOCATION (0).m].name[4] - '0';
+    return 0;
+}
+
+static int fun_map_nr (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    const char *mapname = map[ARGLOCATION (0).m].name;
+
+    RESULTINT = ((mapname[0] - '0') * 100)
+        + ((mapname[1] - '0') * 10) + ((mapname[2] - '0'));
+    return 0;
+}
+
+static int
+fun_dir_towards (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    int  dx;
+    int  dy;
+
+    if (ARGLOCATION (0).m != ARGLOCATION (1).m)
+        return 1;
+
+    dx = ARGLOCATION (1).x - ARGLOCATION (0).x;
+    dy = ARGLOCATION (1).y - ARGLOCATION (0).y;
+
+    if (ARGINT (1))
+    {
+        /* 8-direction mode */
+        if (abs (dx) > abs (dy) * 2)
+        {                       /* east or west */
+            if (dx < 0)
+                RESULTINT = 2 /* west */ ;
+            else
+                RESULTINT = 6 /* east */ ;
+        }
+        else if (abs (dy) > abs (dx) * 2)
+        {                       /* north or south */
+            if (dy > 0)
+                RESULTINT = 0 /* south */ ;
+            else
+                RESULTINT = 4 /* north */ ;
+        }
+        else if (dx < 0)
+        {                       /* north-west or south-west */
+            if (dy < 0)
+                RESULTINT = 3 /* north-west */ ;
+            else
+                RESULTINT = 1 /* south-west */ ;
+        }
+        else
+        {                       /* north-east or south-east */
+            if (dy < 0)
+                RESULTINT = 5 /* north-east */ ;
+            else
+                RESULTINT = 7 /* south-east */ ;
+        }
+    }
+    else
+    {
+        /* 4-direction mode */
+        if (abs (dx) > abs (dy))
+        {                       /* east or west */
+            if (dx < 0)
+                RESULTINT = 2 /* west */ ;
+            else
+                RESULTINT = 6 /* east */ ;
+        }
+        else
+        {                       /* north or south */
+            if (dy > 0)
+                RESULTINT = 0 /* south */ ;
+            else
+                RESULTINT = 4 /* north */ ;
+        }
+    }
+
+    return 0;
+}
+
+static int
+fun_extract_healer_xp (env_t * env, int args_nr, val_t * result, val_t * args)
+{
+    character_t *sd = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+
+    if (!sd)
+        RESULTINT = 0;
+    else
+        RESULTINT = pc_extract_healer_exp (sd, ARGINT (1));
+    return 0;
+}
+
+#define BATTLE_RECORD2(sname, name) { sname, "e", 'i', fun_get_##name }
+#define BATTLE_RECORD(name) BATTLE_RECORD2(#name, name)
+static fun_t functions[] = {
+    {"+", "..", '.', fun_add},
+    {"-", "ii", 'i', fun_sub},
+    {"*", "ii", 'i', fun_mul},
+    {"/", "ii", 'i', fun_div},
+    {"%", "ii", 'i', fun_mod},
+    {"||", "ii", 'i', fun_or},
+    {"&&", "ii", 'i', fun_and},
+    {">", "..", 'i', fun_gt},
+    {">=", "..", 'i', fun_gte},
+    {"=", "..", 'i', fun_eq},
+    {"|", "..", 'i', fun_bitor},
+    {"&", "ii", 'i', fun_bitand},
+    {"^", "ii", 'i', fun_bitxor},
+    {"<<", "ii", 'i', fun_bitshl},
+    {">>", "ii", 'i', fun_bitshr},
+    {"not", "i", 'i', fun_not},
+    {"neg", "i", 'i', fun_neg},
+    {"max", "ii", 'i', fun_max},
+    {"min", "ii", 'i', fun_min},
+    {"is_in", "la", 'i', fun_is_in},
+    {"if_then_else", "i__", '_', fun_if_then_else},
+    {"skill", "ei", 'i', fun_skill},
+    BATTLE_RECORD (str),
+    BATTLE_RECORD (agi),
+    BATTLE_RECORD (vit),
+    BATTLE_RECORD (dex),
+    BATTLE_RECORD (luk),
+    BATTLE_RECORD (int),
+    BATTLE_RECORD2 ("level", lv),
+    BATTLE_RECORD (mdef),
+    BATTLE_RECORD (def),
+    BATTLE_RECORD (hp),
+    BATTLE_RECORD (max_hp),
+    BATTLE_RECORD (sp),
+    BATTLE_RECORD (max_sp),
+    {"dir", "e", 'd', fun_get_dir},
+    {"name_of", ".", 's', fun_name_of},
+    {"mob_id", "e", 'i', fun_mob_id},
+    {"location", "e", 'l', fun_location},
+    {"random", "i", 'i', fun_random},
+    {"random_dir", "i", 'd', fun_random_dir},
+    {"hash_entity", "e", 'i', fun_hash_entity},
+    {"is_married", "e", 'i', fun_is_married},
+    {"partner", "e", 'e', fun_partner},
+    {"awayfrom", "ldi", 'l', fun_awayfrom},
+    {"failed", "_", 'i', fun_failed},
+    {"pc", "s", 'e', fun_pc},
+    {"npc", "s", 'e', fun_npc},
+    {"distance", "ll", 'i', fun_distance},
+    {"rdistance", "ll", 'i', fun_rdistance},
+    {"anchor", "s", 'a', fun_anchor},
+    {"random_location", "a", 'l', fun_pick_location},
+    {"script_int", "es", 'i', fun_read_script_int},
+    {"rbox", "li", 'a', fun_rbox},
+    {"count_item", "e.", 'i', fun_count_item},
+    {"line_of_sight", "ll", 'i', fun_line_of_sight},
+    {"running_status_update", "ei", 'i', fun_running_status_update},
+    {"status_option", "ei", 'i', fun_status_option},
+    {"element", "e", 'i', fun_element},
+    {"element_level", "e", 'i', fun_element_level},
+    {"has_shroud", "e", 'i', fun_has_shroud},
+    {"is_equipped", "e.", 'i', fun_is_equipped},
+    {"spell_index", "S", 'i', fun_index},
+    {"is_exterior", "l", 'i', fun_is_exterior},
+    {"contains_string", "ss", 'i', fun_contains_string},
+    {"strstr", "ss", 'i', fun_strstr},
+    {"strlen", "s", 'i', fun_strlen},
+    {"substr", "sii", 's', fun_substr},
+    {"sqrt", "i", 'i', fun_sqrt},
+    {"map_level", "l", 'i', fun_map_level},
+    {"map_nr", "l", 'i', fun_map_nr},
+    {"dir_towards", "lli", 'd', fun_dir_towards},
+    {"is_dead", "e", 'i', fun_is_dead},
+    {"is_pc", "e", 'i', fun_is_pc},
+    {"extract_healer_experience", "ei", 'i', fun_extract_healer_xp},
+    {NULL, NULL, '.', NULL}
+};
+
+static int functions_are_sorted = 0;
+
+int compare_fun (const void *lhs, const void *rhs)
+{
+    return strcmp (((fun_t *) lhs)->name, ((fun_t *) rhs)->name);
+}
+
+fun_t *magic_get_fun (const char *name, int *index)
+{
+    static int functions_nr;
+    fun_t *result;
+    fun_t key;
+
+    if (!functions_are_sorted)
+    {
+        fun_t *it = functions;
+
+        while (it->name)
+            ++it;
+        functions_nr = it - functions;
+
+        qsort (functions, functions_nr, sizeof (fun_t), compare_fun);
+        functions_are_sorted = 1;
+    }
+
+    key.name = name;
+    result = (fun_t *) bsearch (&key, functions, functions_nr, sizeof (fun_t),
+                                compare_fun);
+
+    if (result && index)
+        *index = result - functions;
+
+    return result;
+}
+
+static int                      // 1 on failure
+eval_location (env_t * env, location_t * dest, e_location_t * expr)
+{
+    val_t m, x, y;
+    magic_eval (env, &m, expr->m);
+    magic_eval (env, &x, expr->x);
+    magic_eval (env, &y, expr->y);
+
+    if (CHECK_TYPE (&m, TY_STRING)
+        && CHECK_TYPE (&x, TY_INT) && CHECK_TYPE (&y, TY_INT))
+    {
+        int  map_id = map_mapname2mapid (m.v.v_string);
+        magic_clear_var (&m);
+        if (map_id < 0)
+            return 1;
+        dest->m = map_id;
+        dest->x = x.v.v_int;
+        dest->y = y.v.v_int;
+        return 0;
+    }
+    else
+    {
+        magic_clear_var (&m);
+        magic_clear_var (&x);
+        magic_clear_var (&y);
+        return 1;
+    }
+}
+
+static area_t *eval_area (env_t * env, e_area_t * expr)
+{
+    area_t *area = (area_t *)malloc (sizeof (area_t));
+    area->ty = expr->ty;
+
+    switch (expr->ty)
+    {
+        case AREA_LOCATION:
+            area->size = 1;
+            if (eval_location (env, &area->a.a_loc, &expr->a.a_loc))
+            {
+                free (area);
+                return NULL;
+            }
+            else
+                return area;
+
+        case AREA_UNION:
+        {
+            int  i, fail = 0;
+            for (i = 0; i < 2; i++)
+            {
+                area->a.a_union[i] = eval_area (env, expr->a.a_union[i]);
+                if (!area->a.a_union[i])
+                    fail = 1;
+            }
+
+            if (fail)
+            {
+                for (i = 0; i < 2; i++)
+                {
+                    if (area->a.a_union[i])
+                        free_area (area->a.a_union[i]);
+                }
+                free (area);
+                return NULL;
+            }
+            area->size = area->a.a_union[0]->size + area->a.a_union[1]->size;
+            return area;
+        }
+
+        case AREA_RECT:
+        {
+            val_t width, height;
+            magic_eval (env, &width, expr->a.a_rect.width);
+            magic_eval (env, &height, expr->a.a_rect.height);
+
+            area->a.a_rect.width = width.v.v_int;
+            area->a.a_rect.height = height.v.v_int;
+
+            if (CHECK_TYPE (&width, TY_INT)
+                && CHECK_TYPE (&height, TY_INT)
+                && !eval_location (env, &(area->a.a_rect.loc),
+                                   &expr->a.a_rect.loc))
+            {
+                area->size = area->a.a_rect.width * area->a.a_rect.height;
+                magic_clear_var (&width);
+                magic_clear_var (&height);
+                return area;
+            }
+            else
+            {
+                free (area);
+                magic_clear_var (&width);
+                magic_clear_var (&height);
+                return NULL;
+            }
+        }
+
+        case AREA_BAR:
+        {
+            val_t width, depth, dir;
+            magic_eval (env, &width, expr->a.a_bar.width);
+            magic_eval (env, &depth, expr->a.a_bar.depth);
+            magic_eval (env, &dir, expr->a.a_bar.dir);
+
+            area->a.a_bar.width = width.v.v_int;
+            area->a.a_bar.depth = depth.v.v_int;
+            area->a.a_bar.dir = dir.v.v_int;
+
+            if (CHECK_TYPE (&width, TY_INT)
+                && CHECK_TYPE (&depth, TY_INT)
+                && CHECK_TYPE (&dir, TY_DIR)
+                && !eval_location (env, &area->a.a_bar.loc,
+                                   &expr->a.a_bar.loc))
+            {
+                area->size =
+                    (area->a.a_bar.width * 2 + 1) * area->a.a_bar.depth;
+                magic_clear_var (&width);
+                magic_clear_var (&depth);
+                magic_clear_var (&dir);
+                return area;
+            }
+            else
+            {
+                free (area);
+                magic_clear_var (&width);
+                magic_clear_var (&depth);
+                magic_clear_var (&dir);
+                return NULL;
+            }
+        }
+
+        default:
+            fprintf (stderr, "INTERNAL ERROR: Unknown area type %d\n",
+                     area->ty);
+            free (area);
+            return NULL;
+    }
+}
+
+static int type_key (char ty_key)
+{
+    switch (ty_key)
+    {
+        case 'i':
+            return TY_INT;
+        case 'd':
+            return TY_DIR;
+        case 's':
+            return TY_STRING;
+        case 'e':
+            return TY_ENTITY;
+        case 'l':
+            return TY_LOCATION;
+        case 'a':
+            return TY_AREA;
+        case 'S':
+            return TY_SPELL;
+        case 'I':
+            return TY_INVOCATION;
+        default:
+            return -1;
+    }
+}
+
+int
+magic_signature_check (char *opname, char *funname, char *signature,
+                       int args_nr, val_t * args, int line, int column)
+{
+    int  i;
+    for (i = 0; i < args_nr; i++)
+    {
+        val_t *arg = &args[i];
+        char ty_key = signature[i];
+        int  ty = arg->ty;
+        int  desired_ty = type_key (ty_key);
+
+        if (ty == TY_ENTITY)
+        {
+            /* Dereference entities in preparation for calling function */
+            arg->v.v_entity = map_id2bl (arg->v.v_int);
+            if (!arg->v.v_entity)
+                ty = arg->ty = TY_FAIL;
+        }
+        else if (ty == TY_INVOCATION)
+        {
+            arg->v.v_invocation = (invocation_t *) map_id2bl (arg->v.v_int);
+            if (!arg->v.v_entity)
+                ty = arg->ty = TY_FAIL;
+        }
+
+        if (!ty_key)
+        {
+            fprintf (stderr,
+                     "[magic-eval]:  L%d:%d: Too many arguments (%d) to %s `%s'\n",
+                     line, column, args_nr, opname, funname);
+            return 1;
+        }
+
+        if (ty == TY_FAIL && ty_key != '_')
+            return 1;           /* Fail `in a sane way':  This is a perfectly permissible error */
+
+        if (ty == desired_ty || desired_ty < 0 /* `dontcare' */ )
+            continue;
+
+        if (ty == TY_UNDEF)
+        {
+            fprintf (stderr,
+                     "[magic-eval]:  L%d:%d: Argument #%d to %s `%s' undefined\n",
+                     line, column, i + 1, opname, funname);
+            return 1;
+        }
+
+        /* If we are here, we have a type mismatch but no failure _yet_.  Try to coerce. */
+        switch (desired_ty)
+        {
+            case TY_INT:
+                intify (arg);
+                break;          /* 100% success rate */
+            case TY_STRING:
+                stringify (arg, 1);
+                break;          /* 100% success rate */
+            case TY_AREA:
+                make_area (arg);
+                break;          /* Only works for locations */
+            case TY_LOCATION:
+                make_location (arg);
+                break;          /* Only works for some areas */
+            case TY_SPELL:
+                make_spell (arg);
+                break;          /* Only works for still-active invocatoins */
+            default:
+                break;          /* We'll fail right below */
+        }
+
+        ty = arg->ty;
+        if (ty != desired_ty)
+        {                       /* Coercion failed? */
+            if (ty != TY_FAIL)
+                fprintf (stderr,
+                         "[magic-eval]:  L%d:%d: Argument #%d to %s `%s' of incorrect type (%d)\n",
+                         line, column, i + 1, opname, funname, ty);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+void magic_eval (env_t * env, val_t * dest, expr_t * expr)
+{
+    switch (expr->ty)
+    {
+        case EXPR_VAL:
+            magic_copy_var (dest, &expr->e.e_val);
+            break;
+
+        case EXPR_LOCATION:
+            if (eval_location (env, &dest->v.v_location, &expr->e.e_location))
+                dest->ty = TY_FAIL;
+            else
+                dest->ty = TY_LOCATION;
+            break;
+
+        case EXPR_AREA:
+            if ((dest->v.v_area = eval_area (env, &expr->e.e_area)))
+                dest->ty = TY_AREA;
+            else
+                dest->ty = TY_FAIL;
+            break;
+
+        case EXPR_FUNAPP:
+        {
+            val_t arguments[MAX_ARGS];
+            int  args_nr = expr->e.e_funapp.args_nr;
+            int  i;
+            fun_t *f = functions + expr->e.e_funapp.id;
+
+            for (i = 0; i < args_nr; ++i)
+                magic_eval (env, &arguments[i], expr->e.e_funapp.args[i]);
+            if (magic_signature_check
+                ("function", f->name, f->signature, args_nr, arguments,
+                 expr->e.e_funapp.line_nr, expr->e.e_funapp.column)
+                || f->fun (env, args_nr, dest, arguments))
+                dest->ty = TY_FAIL;
+            else
+            {
+                int  dest_ty = type_key (f->ret_ty);
+                if (dest_ty != -1)
+                    dest->ty = dest_ty;
+
+                /* translate entity back into persistent int */
+                if (dest->ty == TY_ENTITY)
+                {
+                    if (dest->v.v_entity)
+                        dest->v.v_int = dest->v.v_entity->id;
+                    else
+                        dest->ty = TY_FAIL;
+                }
+            }
+
+            for (i = 0; i < args_nr; ++i)
+                magic_clear_var (&arguments[i]);
+            break;
+        }
+
+        case EXPR_ID:
+        {
+            val_t v = VAR (expr->e.e_id);
+            magic_copy_var (dest, &v);
+            break;
+        }
+
+        case EXPR_SPELLFIELD:
+        {
+            val_t v;
+            int  id = expr->e.e_field.id;
+            magic_eval (env, &v, expr->e.e_field.expr);
+
+            if (v.ty == TY_INVOCATION)
+            {
+                invocation_t *t = (invocation_t *) map_id2bl (v.v.v_int);
+
+                if (!t)
+                    dest->ty = TY_UNDEF;
+                else
+                {
+                    env_t *env = t->env;
+                    val_t v = VAR (id);
+                    magic_copy_var (dest, &v);
+                }
+            }
+            else
+            {
+                fprintf (stderr,
+                         "[magic] Attempt to access field %s on non-spell\n",
+                         env->base_env->var_name[id]);
+                dest->ty = TY_FAIL;
+            }
+            break;
+        }
+
+        default:
+            fprintf (stderr,
+                     "[magic] INTERNAL ERROR: Unknown expression type %d\n",
+                     expr->ty);
+            break;
+    }
+}
+
+int magic_eval_int (env_t * env, expr_t * expr)
+{
+    val_t result;
+    magic_eval (env, &result, expr);
+
+    if (result.ty == TY_FAIL || result.ty == TY_UNDEF)
+        return 0;
+
+    intify (&result);
+
+    return result.v.v_int;
+}
+
+char *magic_eval_str (env_t * env, expr_t * expr)
+{
+    val_t result;
+    magic_eval (env, &result, expr);
+
+    if (result.ty == TY_FAIL || result.ty == TY_UNDEF)
+        return strdup ("?");
+
+    stringify (&result, 0);
+
+    return result.v.v_string;
+}
+
+expr_t *magic_new_expr (int ty)
+{
+    expr_t *expr = (expr_t *) malloc (sizeof (expr_t));
+    expr->ty = ty;
+    return expr;
+}
diff --git a/src/map/magic-expr.h b/src/map/magic-expr.h
deleted file mode 100644
index e912d14..0000000
--- a/src/map/magic-expr.h
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef MAGIC_EXPR_H_
-#define MAGIC_EXPR_H_
-#include "magic-interpreter.h"
-#include "magic-interpreter-aux.h"
-
-#ifndef MAX
-#  define MAX(x,y) (((x)>(y)) ? (x) : (y))
-#endif
-#ifndef MIN
-#  define MIN(x,y) (((x)<(y)) ? (x) : (y))
-#endif
-
-#ifndef INT_MAX
-#  define INT_MAX (1<<30)       // It's more than that, but this is quite sufficient for our purposes.
-#endif
-
-/*
- * Argument types:
- *  i : int
- *  d : dir
- *  s : string
- *  e : entity
- *  l : location
- *  a : area
- *  S : spell
- *  I : invocation
- *  . : any, except for fail/undef
- *  _ : any, including fail, but not undef
- */
-typedef struct fun
-{
-    char *name;
-    char *signature;
-    char ret_ty;
-    int  (*fun) (env_t * env, int args_nr, val_t * result, val_t * args);
-} fun_t;
-
-typedef struct op
-{
-    char *name;
-    char *signature;
-    int  (*op) (env_t * env, int args_nr, val_t * args);
-} op_t;
-
-/**
- * Retrieves a function by name
- * @param name The name to look up
- * @return A function of that name, or NULL, and a function index
- */
-fun_t *magic_get_fun (const char *name, int *index);
-
-/**
- * Retrieves an operation by name
- * @param name The name to look up
- * @return An operation of that name, or NULL, and a function index
- */
-op_t *magic_get_op (char *name, int *index);
-
-/**
- * Evaluates an expression and stores the result in `dest'
- */
-void magic_eval (env_t * env, val_t * dest, expr_t * expr);
-
-/**
- * Evaluates an expression and coerces the result into an integer
- */
-int  magic_eval_int (env_t * env, expr_t * expr);
-
-/**
- * Evaluates an expression and coerces the result into a string
- */
-char *magic_eval_str (env_t * env, expr_t * expr);
-
-int  map_is_solid (int m, int x, int y);
-
-expr_t *magic_new_expr (int ty);
-
-void magic_clear_var (val_t * v);
-
-void magic_copy_var (val_t * dest, val_t * src);
-
-void magic_random_location (location_t * dest, area_t * area);
-
-int                             // ret -1: not a string, ret 1: no such item, ret 0: OK
-
-
-
-
- magic_find_item (val_t * args, int index, struct item *item, int *stackable);
-
-#define GET_ARG_ITEM(index, dest, stackable) switch(magic_find_item(args, index, &dest, &stackable)) { case -1 : return 1; case 1 : return 0; }
-
-int  magic_location_in_area (int m, int x, int y, area_t * area);
-
-#endif /* !defined(MAGIC_EXPR_H_) */
diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp
new file mode 100644
index 0000000..4551585
--- /dev/null
+++ b/src/map/magic-expr.hpp
@@ -0,0 +1,95 @@
+#ifndef MAGIC_EXPR_HPP
+#define MAGIC_EXPR_HPP
+#include "magic-interpreter.hpp"
+#include "magic-interpreter-aux.hpp"
+
+#ifndef MAX
+#  define MAX(x,y) (((x)>(y)) ? (x) : (y))
+#endif
+#ifndef MIN
+#  define MIN(x,y) (((x)<(y)) ? (x) : (y))
+#endif
+
+#ifndef INT_MAX
+#  define INT_MAX (1<<30)       // It's more than that, but this is quite sufficient for our purposes.
+#endif
+
+/*
+ * Argument types:
+ *  i : int
+ *  d : dir
+ *  s : string
+ *  e : entity
+ *  l : location
+ *  a : area
+ *  S : spell
+ *  I : invocation
+ *  . : any, except for fail/undef
+ *  _ : any, including fail, but not undef
+ */
+typedef struct fun
+{
+    char *name;
+    char *signature;
+    char ret_ty;
+    int  (*fun) (env_t * env, int args_nr, val_t * result, val_t * args);
+} fun_t;
+
+typedef struct op
+{
+    char *name;
+    char *signature;
+    int  (*op) (env_t * env, int args_nr, val_t * args);
+} op_t;
+
+/**
+ * Retrieves a function by name
+ * @param name The name to look up
+ * @return A function of that name, or NULL, and a function index
+ */
+fun_t *magic_get_fun (const char *name, int *index);
+
+/**
+ * Retrieves an operation by name
+ * @param name The name to look up
+ * @return An operation of that name, or NULL, and a function index
+ */
+op_t *magic_get_op (char *name, int *index);
+
+/**
+ * Evaluates an expression and stores the result in `dest'
+ */
+void magic_eval (env_t * env, val_t * dest, expr_t * expr);
+
+/**
+ * Evaluates an expression and coerces the result into an integer
+ */
+int  magic_eval_int (env_t * env, expr_t * expr);
+
+/**
+ * Evaluates an expression and coerces the result into a string
+ */
+char *magic_eval_str (env_t * env, expr_t * expr);
+
+int  map_is_solid (int m, int x, int y);
+
+expr_t *magic_new_expr (int ty);
+
+void magic_clear_var (val_t * v);
+
+void magic_copy_var (val_t * dest, val_t * src);
+
+void magic_random_location (location_t * dest, area_t * area);
+
+int                             // ret -1: not a string, ret 1: no such item, ret 0: OK
+
+
+
+
+ magic_find_item (val_t * args, int index, struct item *item, int *stackable);
+
+#define GET_ARG_ITEM(index, dest, stackable) switch(magic_find_item(args, index, &dest, &stackable)) { case -1 : return 1; case 1 : return 0; }
+
+int  magic_location_in_area (int m, int x, int y, area_t * area);
+
+#endif /* !defined(MAGIC_EXPR_H_) */
diff --git a/src/map/magic-interpreter-aux.h b/src/map/magic-interpreter-aux.h
deleted file mode 100644
index 975e502..0000000
--- a/src/map/magic-interpreter-aux.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef MAGIC_INTERPRETER_AUX_H_
-#define MAGIC_INTERPRETER_AUX_H_
-
-#define CHECK_TYPE(v, t) ((v)->ty == t)
-
-#define VAR(i) ((!env->vars || env->vars[i].ty == TY_UNDEF)? env->base_env->vars[i] : env->vars[i])
-
-#endif /* !defined(MAGIC_INTERPRETER_AUX_H_) */
diff --git a/src/map/magic-interpreter-aux.hpp b/src/map/magic-interpreter-aux.hpp
new file mode 100644
index 0000000..ea05b88
--- /dev/null
+++ b/src/map/magic-interpreter-aux.hpp
@@ -0,0 +1,8 @@
+#ifndef MAGIC_INTERPRETER_AUX_HPP
+#define MAGIC_INTERPRETER_AUX_HPP
+
+#define CHECK_TYPE(v, t) ((v)->ty == t)
+
+#define VAR(i) ((!env->vars || env->vars[i].ty == TY_UNDEF)? env->base_env->vars[i] : env->vars[i])
+
+#endif /* !defined(MAGIC_INTERPRETER_AUX_H_) */
diff --git a/src/map/magic-interpreter-base.c b/src/map/magic-interpreter-base.c
deleted file mode 100644
index 671f962..0000000
--- a/src/map/magic-interpreter-base.c
+++ /dev/null
@@ -1,562 +0,0 @@
-#include "magic.h"
-#include "magic-interpreter.h"
-#include "magic-expr.h"
-#include "magic-interpreter-aux.h"
-
-static void set_int_p (val_t * v, int i, int t)
-{
-    v->ty = t;
-    v->v.v_int = i;
-}
-
-#define set_int(v, i) set_int_p(v, i, TY_INT)
-#define set_dir(v, i) set_int_p(v, i, TY_DIR)
-
-#define SETTER(tty, dyn_ty, field) (val_t *v, tty x) { v->ty = dyn_ty; v->v.field = x; }
-
-static void set_string SETTER (char *, TY_STRING, v_string);
-
-static void set_entity (val_t * v, entity_t * e)
-{
-    v->ty = TY_ENTITY;
-    v->v.v_int = e->id;
-}
-
-static void set_invocation (val_t * v, invocation_t * i)
-{
-    v->ty = TY_INVOCATION;
-    v->v.v_int = i->bl.id;
-}
-
-static void set_spell SETTER (spell_t *, TY_SPELL, v_spell);
-
-#define setenv(f, v, x) f(&(env->vars[v]), x)
-
-#define set_env_int(v, x) setenv(set_int, v, x)
-#define set_env_dir(v, x) setenv(set_dir, v, x)
-#define set_env_string(v, x) setenv(set_string, v, x)
-#define set_env_entity(v, x) setenv(set_entity, v, x)
-#define set_env_location(v, x) setenv(set_location, v, x)
-#define set_env_area(v, x) setenv(set_area, v, x)
-#define set_env_invocation(v, x) setenv(set_invocation, v, x)
-#define set_env_spell(v, x) setenv(set_spell, v, x)
-
-magic_conf_t magic_conf;        /* Global magic conf */
-env_t magic_default_env = { &magic_conf, NULL };
-
-static int spells_sorted = 0;
-
-char *magic_find_invocation (char *spellname)
-{
-    int  i;
-
-    for (i = 0; i < abs (magic_conf.spells_nr); i++)
-        if (!strcmp (magic_conf.spells[i]->name, spellname))
-            return magic_conf.spells[i]->invocation;
-
-    return NULL;
-}
-
-static int spell_compare (const void *lhs, const void *rhs)
-{
-    return strcmp ((*((spell_t **) lhs))->invocation,
-                   (*((spell_t **) rhs))->invocation);
-}
-
-spell_t *magic_find_spell (char *invocation)
-{
-    spell_t key;
-    spell_t *keyp = &key;
-    spell_t **retval;
-
-    if (!spells_sorted)
-    {
-        qsort (magic_conf.spells, magic_conf.spells_nr, sizeof (spell_t *),
-               spell_compare);
-        spells_sorted = 1;
-    }
-
-    key.invocation = invocation;
-
-    retval =
-        ((spell_t **)
-         bsearch (&keyp, magic_conf.spells, magic_conf.spells_nr,
-                  sizeof (spell_t *), spell_compare));
-
-    if (!retval)
-        return NULL;
-    else
-        return *retval;
-}
-
-/* -------------------------------------------------------------------------------- */
-/* Spell anchors */
-/* -------------------------------------------------------------------------------- */
-
-static int compare_teleport_anchor (const void *lhs, const void *rhs)
-{
-    return strcmp ((*((teleport_anchor_t **) lhs))->invocation,
-                   (*((teleport_anchor_t **) rhs))->invocation);
-}
-
-char *magic_find_anchor_invocation (char *anchor_name)
-{
-    int  i;
-
-    for (i = 0; i < abs (magic_conf.anchors_nr); i++)
-        if (!strcmp (magic_conf.anchors[i]->name, anchor_name))
-            return magic_conf.anchors[i]->invocation;
-
-    return NULL;
-}
-
-teleport_anchor_t *magic_find_anchor (char *name)
-{
-    teleport_anchor_t key;
-    teleport_anchor_t *keyp = &key;
-    teleport_anchor_t **retval;
-
-    if (magic_conf.anchors_nr > 0)
-    {                           /* unsorted */
-        qsort (magic_conf.anchors, magic_conf.anchors_nr,
-               sizeof (teleport_anchor_t *), compare_teleport_anchor);
-        magic_conf.anchors_nr = -magic_conf.anchors_nr;
-    }
-
-    key.invocation = name;
-
-    retval = (teleport_anchor_t **) bsearch (&keyp,
-                                             magic_conf.anchors,
-                                             -magic_conf.anchors_nr,
-                                             sizeof (teleport_anchor_t *),
-                                             compare_teleport_anchor);
-
-    if (!retval)
-        return NULL;
-    else
-        return *retval;
-}
-
-/* -------------------------------------------------------------------------------- */
-/* Spell guard checks */
-/* -------------------------------------------------------------------------------- */
-
-static env_t *alloc_env (magic_conf_t * conf)
-{
-    env_t *env;
-    CREATE (env, env_t, 1);
-    CREATE (env->vars, val_t, conf->vars_nr);
-    env->base_env = conf;
-    return env;
-}
-
-static env_t *clone_env (env_t * src)
-{
-    env_t *retval = alloc_env (src->base_env);
-    int  i;
-
-    for (i = 0; i < src->base_env->vars_nr; i++)
-        magic_copy_var (&retval->vars[i], &src->vars[i]);
-
-    return retval;
-}
-
-void magic_free_env (env_t * env)
-{
-    int  i;
-    for (i = 0; i < env->base_env->vars_nr; i++)
-        magic_clear_var (&env->vars[i]);
-    free (env);
-}
-
-env_t *spell_create_env (magic_conf_t * conf, spell_t * spell,
-                         character_t * caster, int spellpower, char *param)
-{
-    env_t *env = alloc_env (conf);
-
-    switch (spell->spellarg_ty)
-    {
-
-        case SPELLARG_STRING:
-            set_env_string (spell->arg, param);
-            break;
-
-        case SPELLARG_PC:
-        {
-            character_t *subject = map_nick2sd (param);
-            if (!subject)
-                subject = caster;
-            set_env_entity (spell->arg, &subject->bl);
-            free (param);
-            break;
-        }
-
-        case SPELLARG_NONE:
-            free (param);
-            break;
-
-        default:
-            free (param);
-            fprintf (stderr, "Unexpected spellarg type %d\n",
-                     spell->spellarg_ty);
-    }
-
-    set_env_entity (VAR_CASTER, &caster->bl);
-    set_env_int (VAR_SPELLPOWER, spellpower);
-    set_env_spell (VAR_SPELL, spell);
-
-    return env;
-}
-
-static void free_components (component_t ** component_holder)
-{
-    if (*component_holder == NULL)
-        return;
-    free_components (&(*component_holder)->next);
-    free (*component_holder);
-    *component_holder = NULL;
-}
-
-void magic_add_component (component_t ** component_holder, int id, int count)
-{
-    if (count <= 0)
-        return;
-
-    if (*component_holder == NULL)
-    {
-        component_t *component =
-            (component_t *) malloc (sizeof (component_t));
-        component->next = NULL;
-        component->item_id = id;
-        component->count = count;
-        *component_holder = component;
-    }
-    else
-    {
-        component_t *component = *component_holder;
-        if (component->item_id == id)
-        {
-            component->count += count;
-            return;
-        }
-        else
-            magic_add_component (&component->next, id, count);
-        /* Tail-recurse; gcc can optimise this.  Not that it matters. */
-    }
-}
-
-static void
-copy_components (component_t ** component_holder, component_t * component)
-{
-    if (component == NULL)
-        return;
-
-    magic_add_component (component_holder, component->item_id,
-                         component->count);
-    copy_components (component_holder, component->next);
-}
-
-typedef struct spellguard_check
-{
-    component_t *catalysts, *components;
-    int  mana, casttime;
-} spellguard_check_t;
-
-static int check_prerequisites (character_t * caster, component_t * component)
-{
-    while (component)
-    {
-        if (pc_count_all_items (caster, component->item_id)
-            < component->count)
-            return 0;           /* insufficient */
-
-        component = component->next;
-    }
-
-    return 1;
-}
-
-static void consume_components (character_t * caster, component_t * component)
-{
-    while (component)
-    {
-        pc_remove_items (caster, component->item_id, component->count);
-        component = component->next;
-    }
-}
-
-static int
-spellguard_can_satisfy (spellguard_check_t * check, character_t * caster,
-                        env_t * env, int *near_miss)
-{
-    unsigned int tick = gettick ();
-
-    int  retval = check_prerequisites (caster, check->catalysts);
-
-/*
-        fprintf(stderr, "MC(%d/%s)? %d%d%d%d (%u <= %u)\n",
-                caster->bl.id, caster->status.name,
-                retval,
-                caster->cast_tick <= tick,
-                check->mana <= caster->status.sp,
-                check_prerequisites(caster, check->components),
-                caster->cast_tick, tick);
-*/
-
-    if (retval && near_miss)
-        *near_miss = 1;         // close enough!
-
-    retval = retval && caster->cast_tick <= tick    /* Hasn't cast a spell too recently */
-        && check->mana <= caster->status.sp
-        && check_prerequisites (caster, check->components);
-
-    if (retval)
-    {
-        unsigned int casttime = (unsigned int) check->casttime;
-
-        if (VAR (VAR_MIN_CASTTIME).ty == TY_INT)
-            casttime = MAX (casttime, VAR (VAR_MIN_CASTTIME).v.v_int);
-
-        caster->cast_tick = tick + casttime;    /* Make sure not to cast too frequently */
-
-        consume_components (caster, check->components);
-        pc_heal (caster, 0, -check->mana);
-    }
-
-    return retval;
-}
-
-static effect_set_t *spellguard_check_sub (spellguard_check_t * check,
-                                           spellguard_t * guard,
-                                           character_t * caster, env_t * env,
-                                           int *near_miss)
-{
-    if (guard == NULL)
-        return NULL;
-
-    switch (guard->ty)
-    {
-        case SPELLGUARD_CONDITION:
-            if (!magic_eval_int (env, guard->s.s_condition))
-                return NULL;
-            break;
-
-        case SPELLGUARD_COMPONENTS:
-            copy_components (&check->components, guard->s.s_components);
-            break;
-
-        case SPELLGUARD_CATALYSTS:
-            copy_components (&check->catalysts, guard->s.s_catalysts);
-            break;
-
-        case SPELLGUARD_CHOICE:
-        {
-            spellguard_check_t altcheck = *check;
-            effect_set_t *retval;
-
-            altcheck.components = NULL;
-            altcheck.catalysts = NULL;
-
-            copy_components (&altcheck.catalysts, check->catalysts);
-            copy_components (&altcheck.components, check->components);
-
-            retval =
-                spellguard_check_sub (&altcheck, guard->next, caster, env,
-                                      near_miss);
-            free_components (&altcheck.catalysts);
-            free_components (&altcheck.components);
-            if (retval)
-                return retval;
-            else
-                return spellguard_check_sub (check, guard->s.s_alt, caster,
-                                             env, near_miss);
-        }
-
-        case SPELLGUARD_MANA:
-            check->mana += magic_eval_int (env, guard->s.s_mana);
-            break;
-
-        case SPELLGUARD_CASTTIME:
-            check->casttime += magic_eval_int (env, guard->s.s_mana);
-            break;
-
-        case SPELLGUARD_EFFECT:
-            if (spellguard_can_satisfy (check, caster, env, near_miss))
-                return &guard->s.s_effect;
-            else
-                return NULL;
-
-        default:
-            fprintf (stderr, "Unexpected spellguard type %d\n", guard->ty);
-            return NULL;
-    }
-
-    return spellguard_check_sub (check, guard->next, caster, env, near_miss);
-}
-
-static effect_set_t *check_spellguard (spellguard_t * guard,
-                                       character_t * caster, env_t * env,
-                                       int *near_miss)
-{
-    spellguard_check_t check;
-    effect_set_t *retval;
-    check.catalysts = NULL;
-    check.components = NULL;
-    check.mana = check.casttime = 0;
-
-    retval = spellguard_check_sub (&check, guard, caster, env, near_miss);
-
-    free_components (&check.catalysts);
-    free_components (&check.components);
-
-    return retval;
-}
-
-/* -------------------------------------------------------------------------------- */
-/* Public API */
-/* -------------------------------------------------------------------------------- */
-
-effect_set_t *spell_trigger (spell_t * spell, character_t * caster,
-                             env_t * env, int *near_miss)
-{
-    int  i;
-    spellguard_t *guard = spell->spellguard;
-
-    if (near_miss)
-        *near_miss = 0;
-
-    for (i = 0; i < spell->letdefs_nr; i++)
-        magic_eval (env,
-                    &env->vars[spell->letdefs[i].id], spell->letdefs[i].expr);
-
-    return check_spellguard (guard, caster, env, near_miss);
-}
-
-static void spell_set_location (invocation_t * invocation, entity_t * entity)
-{
-    magic_clear_var (&invocation->env->vars[VAR_LOCATION]);
-    invocation->env->vars[VAR_LOCATION].ty = TY_LOCATION;
-    invocation->env->vars[VAR_LOCATION].v.v_location.m = entity->m;
-    invocation->env->vars[VAR_LOCATION].v.v_location.x = entity->x;
-    invocation->env->vars[VAR_LOCATION].v.v_location.y = entity->y;
-}
-
-void spell_update_location (invocation_t * invocation)
-{
-    if (invocation->spell->flags & SPELL_FLAG_LOCAL)
-        return;
-    else
-    {
-        character_t *owner = (character_t *) map_id2bl (invocation->subject);
-        if (!owner)
-            return;
-
-        spell_set_location (invocation, (entity_t *) owner);
-    }
-}
-
-invocation_t *spell_instantiate (effect_set_t * effect_set, env_t * env)
-{
-    invocation_t *retval;
-    CREATE (retval, invocation_t, 1);
-    entity_t *caster;
-
-    retval->env = env;
-
-    retval->caster = VAR (VAR_CASTER).v.v_int;
-    retval->spell = VAR (VAR_SPELL).v.v_spell;
-    retval->stack_size = 0;
-    retval->current_effect = effect_set->effect;
-    retval->trigger_effect = effect_set->at_trigger;
-    retval->end_effect = effect_set->at_end;
-
-    caster = map_id2bl (retval->caster);    // must still exist
-    retval->bl.id = map_addobject (&retval->bl);
-    retval->bl.type = BL_SPELL;
-    retval->bl.m = caster->m;
-    retval->bl.x = caster->x;
-    retval->bl.y = caster->y;
-
-    map_addblock (&retval->bl);
-    set_env_invocation (VAR_INVOCATION, retval);
-
-    return retval;
-}
-
-invocation_t *spell_clone_effect (invocation_t * base)
-{
-    invocation_t *retval = (invocation_t *) malloc (sizeof (invocation_t));
-    env_t *env;
-
-    memcpy (retval, base, sizeof (invocation_t));
-
-    retval->env = clone_env (retval->env);
-    env = retval->env;
-    retval->current_effect = retval->trigger_effect;
-    retval->next_invocation = NULL;
-    retval->end_effect = NULL;
-    retval->script_pos = 0;
-    retval->stack_size = 0;
-    retval->timer = 0;
-    retval->subject = 0;
-    retval->status_change_refs_nr = 0;
-    retval->status_change_refs = NULL;
-    retval->flags = 0;
-
-    retval->bl.id = 0;
-    retval->bl.prev = NULL;
-    retval->bl.next = NULL;
-
-    retval->bl.id = map_addobject (&retval->bl);
-    set_env_invocation (VAR_INVOCATION, retval);
-
-    return retval;
-}
-
-void spell_bind (character_t * subject, invocation_t * invocation)
-{
-    /* Only bind nonlocal spells */
-
-    if (!(invocation->spell->flags & SPELL_FLAG_LOCAL))
-    {
-        if (invocation->flags & INVOCATION_FLAG_BOUND
-            || invocation->subject || invocation->next_invocation)
-        {
-            int *i = NULL;
-            fprintf (stderr,
-                     "[magic] INTERNAL ERROR: Attempt to re-bind spell invocation `%s'\n",
-                     invocation->spell->name);
-            *i = 1;
-            return;
-        }
-
-        invocation->next_invocation = subject->active_spells;
-        subject->active_spells = invocation;
-        invocation->flags |= INVOCATION_FLAG_BOUND;
-        invocation->subject = subject->bl.id;
-    }
-
-    spell_set_location (invocation, (entity_t *) subject);
-}
-
-int spell_unbind (character_t * subject, invocation_t * invocation)
-{
-    invocation_t **seeker = &subject->active_spells;
-
-    while (*seeker)
-    {
-        if (*seeker == invocation)
-        {
-            *seeker = invocation->next_invocation;
-
-            invocation->flags &= ~INVOCATION_FLAG_BOUND;
-            invocation->next_invocation = NULL;
-            invocation->subject = 0;
-
-            return 0;
-        }
-        seeker = &((*seeker)->next_invocation);
-    }
-
-    return 1;
-}
diff --git a/src/map/magic-interpreter-base.cpp b/src/map/magic-interpreter-base.cpp
new file mode 100644
index 0000000..1dc90a5
--- /dev/null
+++ b/src/map/magic-interpreter-base.cpp
@@ -0,0 +1,562 @@
+#include "magic.hpp"
+#include "magic-interpreter.hpp"
+#include "magic-expr.hpp"
+#include "magic-interpreter-aux.hpp"
+
+static void set_int_p (val_t * v, int i, int t)
+{
+    v->ty = t;
+    v->v.v_int = i;
+}
+
+#define set_int(v, i) set_int_p(v, i, TY_INT)
+#define set_dir(v, i) set_int_p(v, i, TY_DIR)
+
+#define SETTER(tty, dyn_ty, field) (val_t *v, tty x) { v->ty = dyn_ty; v->v.field = x; }
+
+static void set_string SETTER (char *, TY_STRING, v_string);
+
+static void set_entity (val_t * v, entity_t * e)
+{
+    v->ty = TY_ENTITY;
+    v->v.v_int = e->id;
+}
+
+static void set_invocation (val_t * v, invocation_t * i)
+{
+    v->ty = TY_INVOCATION;
+    v->v.v_int = i->bl.id;
+}
+
+static void set_spell SETTER (spell_t *, TY_SPELL, v_spell);
+
+#define setenv(f, v, x) f(&(env->vars[v]), x)
+
+#define set_env_int(v, x) setenv(set_int, v, x)
+#define set_env_dir(v, x) setenv(set_dir, v, x)
+#define set_env_string(v, x) setenv(set_string, v, x)
+#define set_env_entity(v, x) setenv(set_entity, v, x)
+#define set_env_location(v, x) setenv(set_location, v, x)
+#define set_env_area(v, x) setenv(set_area, v, x)
+#define set_env_invocation(v, x) setenv(set_invocation, v, x)
+#define set_env_spell(v, x) setenv(set_spell, v, x)
+
+magic_conf_t magic_conf;        /* Global magic conf */
+env_t magic_default_env = { &magic_conf, NULL };
+
+static int spells_sorted = 0;
+
+char *magic_find_invocation (char *spellname)
+{
+    int  i;
+
+    for (i = 0; i < abs (magic_conf.spells_nr); i++)
+        if (!strcmp (magic_conf.spells[i]->name, spellname))
+            return magic_conf.spells[i]->invocation;
+
+    return NULL;
+}
+
+static int spell_compare (const void *lhs, const void *rhs)
+{
+    return strcmp ((*((spell_t **) lhs))->invocation,
+                   (*((spell_t **) rhs))->invocation);
+}
+
+spell_t *magic_find_spell (char *invocation)
+{
+    spell_t key;
+    spell_t *keyp = &key;
+    spell_t **retval;
+
+    if (!spells_sorted)
+    {
+        qsort (magic_conf.spells, magic_conf.spells_nr, sizeof (spell_t *),
+               spell_compare);
+        spells_sorted = 1;
+    }
+
+    key.invocation = invocation;
+
+    retval =
+        ((spell_t **)
+         bsearch (&keyp, magic_conf.spells, magic_conf.spells_nr,
+                  sizeof (spell_t *), spell_compare));
+
+    if (!retval)
+        return NULL;
+    else
+        return *retval;
+}
+
+/* -------------------------------------------------------------------------------- */
+/* Spell anchors */
+/* -------------------------------------------------------------------------------- */
+
+static int compare_teleport_anchor (const void *lhs, const void *rhs)
+{
+    return strcmp ((*((teleport_anchor_t **) lhs))->invocation,
+                   (*((teleport_anchor_t **) rhs))->invocation);
+}
+
+char *magic_find_anchor_invocation (char *anchor_name)
+{
+    int  i;
+
+    for (i = 0; i < abs (magic_conf.anchors_nr); i++)
+        if (!strcmp (magic_conf.anchors[i]->name, anchor_name))
+            return magic_conf.anchors[i]->invocation;
+
+    return NULL;
+}
+
+teleport_anchor_t *magic_find_anchor (char *name)
+{
+    teleport_anchor_t key;
+    teleport_anchor_t *keyp = &key;
+    teleport_anchor_t **retval;
+
+    if (magic_conf.anchors_nr > 0)
+    {                           /* unsorted */
+        qsort (magic_conf.anchors, magic_conf.anchors_nr,
+               sizeof (teleport_anchor_t *), compare_teleport_anchor);
+        magic_conf.anchors_nr = -magic_conf.anchors_nr;
+    }
+
+    key.invocation = name;
+
+    retval = (teleport_anchor_t **) bsearch (&keyp,
+                                             magic_conf.anchors,
+                                             -magic_conf.anchors_nr,
+                                             sizeof (teleport_anchor_t *),
+                                             compare_teleport_anchor);
+
+    if (!retval)
+        return NULL;
+    else
+        return *retval;
+}
+
+/* -------------------------------------------------------------------------------- */
+/* Spell guard checks */
+/* -------------------------------------------------------------------------------- */
+
+static env_t *alloc_env (magic_conf_t * conf)
+{
+    env_t *env;
+    CREATE (env, env_t, 1);
+    CREATE (env->vars, val_t, conf->vars_nr);
+    env->base_env = conf;
+    return env;
+}
+
+static env_t *clone_env (env_t * src)
+{
+    env_t *retval = alloc_env (src->base_env);
+    int  i;
+
+    for (i = 0; i < src->base_env->vars_nr; i++)
+        magic_copy_var (&retval->vars[i], &src->vars[i]);
+
+    return retval;
+}
+
+void magic_free_env (env_t * env)
+{
+    int  i;
+    for (i = 0; i < env->base_env->vars_nr; i++)
+        magic_clear_var (&env->vars[i]);
+    free (env);
+}
+
+env_t *spell_create_env (magic_conf_t * conf, spell_t * spell,
+                         character_t * caster, int spellpower, char *param)
+{
+    env_t *env = alloc_env (conf);
+
+    switch (spell->spellarg_ty)
+    {
+
+        case SPELLARG_STRING:
+            set_env_string (spell->arg, param);
+            break;
+
+        case SPELLARG_PC:
+        {
+            character_t *subject = map_nick2sd (param);
+            if (!subject)
+                subject = caster;
+            set_env_entity (spell->arg, &subject->bl);
+            free (param);
+            break;
+        }
+
+        case SPELLARG_NONE:
+            free (param);
+            break;
+
+        default:
+            free (param);
+            fprintf (stderr, "Unexpected spellarg type %d\n",
+                     spell->spellarg_ty);
+    }
+
+    set_env_entity (VAR_CASTER, &caster->bl);
+    set_env_int (VAR_SPELLPOWER, spellpower);
+    set_env_spell (VAR_SPELL, spell);
+
+    return env;
+}
+
+static void free_components (component_t ** component_holder)
+{
+    if (*component_holder == NULL)
+        return;
+    free_components (&(*component_holder)->next);
+    free (*component_holder);
+    *component_holder = NULL;
+}
+
+void magic_add_component (component_t ** component_holder, int id, int count)
+{
+    if (count <= 0)
+        return;
+
+    if (*component_holder == NULL)
+    {
+        component_t *component =
+            (component_t *) malloc (sizeof (component_t));
+        component->next = NULL;
+        component->item_id = id;
+        component->count = count;
+        *component_holder = component;
+    }
+    else
+    {
+        component_t *component = *component_holder;
+        if (component->item_id == id)
+        {
+            component->count += count;
+            return;
+        }
+        else
+            magic_add_component (&component->next, id, count);
+        /* Tail-recurse; gcc can optimise this.  Not that it matters. */
+    }
+}
+
+static void
+copy_components (component_t ** component_holder, component_t * component)
+{
+    if (component == NULL)
+        return;
+
+    magic_add_component (component_holder, component->item_id,
+                         component->count);
+    copy_components (component_holder, component->next);
+}
+
+typedef struct spellguard_check
+{
+    component_t *catalysts, *components;
+    int  mana, casttime;
+} spellguard_check_t;
+
+static int check_prerequisites (character_t * caster, component_t * component)
+{
+    while (component)
+    {
+        if (pc_count_all_items (caster, component->item_id)
+            < component->count)
+            return 0;           /* insufficient */
+
+        component = component->next;
+    }
+
+    return 1;
+}
+
+static void consume_components (character_t * caster, component_t * component)
+{
+    while (component)
+    {
+        pc_remove_items (caster, component->item_id, component->count);
+        component = component->next;
+    }
+}
+
+static int
+spellguard_can_satisfy (spellguard_check_t * check, character_t * caster,
+                        env_t * env, int *near_miss)
+{
+    unsigned int tick = gettick ();
+
+    int  retval = check_prerequisites (caster, check->catalysts);
+
+/*
+        fprintf(stderr, "MC(%d/%s)? %d%d%d%d (%u <= %u)\n",
+                caster->bl.id, caster->status.name,
+                retval,
+                caster->cast_tick <= tick,
+                check->mana <= caster->status.sp,
+                check_prerequisites(caster, check->components),
+                caster->cast_tick, tick);
+*/
+
+    if (retval && near_miss)
+        *near_miss = 1;         // close enough!
+
+    retval = retval && caster->cast_tick <= tick    /* Hasn't cast a spell too recently */
+        && check->mana <= caster->status.sp
+        && check_prerequisites (caster, check->components);
+
+    if (retval)
+    {
+        unsigned int casttime = (unsigned int) check->casttime;
+
+        if (VAR (VAR_MIN_CASTTIME).ty == TY_INT)
+            casttime = MAX (casttime, VAR (VAR_MIN_CASTTIME).v.v_int);
+
+        caster->cast_tick = tick + casttime;    /* Make sure not to cast too frequently */
+
+        consume_components (caster, check->components);
+        pc_heal (caster, 0, -check->mana);
+    }
+
+    return retval;
+}
+
+static effect_set_t *spellguard_check_sub (spellguard_check_t * check,
+                                           spellguard_t * guard,
+                                           character_t * caster, env_t * env,
+                                           int *near_miss)
+{
+    if (guard == NULL)
+        return NULL;
+
+    switch (guard->ty)
+    {
+        case SPELLGUARD_CONDITION:
+            if (!magic_eval_int (env, guard->s.s_condition))
+                return NULL;
+            break;
+
+        case SPELLGUARD_COMPONENTS:
+            copy_components (&check->components, guard->s.s_components);
+            break;
+
+        case SPELLGUARD_CATALYSTS:
+            copy_components (&check->catalysts, guard->s.s_catalysts);
+            break;
+
+        case SPELLGUARD_CHOICE:
+        {
+            spellguard_check_t altcheck = *check;
+            effect_set_t *retval;
+
+            altcheck.components = NULL;
+            altcheck.catalysts = NULL;
+
+            copy_components (&altcheck.catalysts, check->catalysts);
+            copy_components (&altcheck.components, check->components);
+
+            retval =
+                spellguard_check_sub (&altcheck, guard->next, caster, env,
+                                      near_miss);
+            free_components (&altcheck.catalysts);
+            free_components (&altcheck.components);
+            if (retval)
+                return retval;
+            else
+                return spellguard_check_sub (check, guard->s.s_alt, caster,
+                                             env, near_miss);
+        }
+
+        case SPELLGUARD_MANA:
+            check->mana += magic_eval_int (env, guard->s.s_mana);
+            break;
+
+        case SPELLGUARD_CASTTIME:
+            check->casttime += magic_eval_int (env, guard->s.s_mana);
+            break;
+
+        case SPELLGUARD_EFFECT:
+            if (spellguard_can_satisfy (check, caster, env, near_miss))
+                return &guard->s.s_effect;
+            else
+                return NULL;
+
+        default:
+            fprintf (stderr, "Unexpected spellguard type %d\n", guard->ty);
+            return NULL;
+    }
+
+    return spellguard_check_sub (check, guard->next, caster, env, near_miss);
+}
+
+static effect_set_t *check_spellguard (spellguard_t * guard,
+                                       character_t * caster, env_t * env,
+                                       int *near_miss)
+{
+    spellguard_check_t check;
+    effect_set_t *retval;
+    check.catalysts = NULL;
+    check.components = NULL;
+    check.mana = check.casttime = 0;
+
+    retval = spellguard_check_sub (&check, guard, caster, env, near_miss);
+
+    free_components (&check.catalysts);
+    free_components (&check.components);
+
+    return retval;
+}
+
+/* -------------------------------------------------------------------------------- */
+/* Public API */
+/* -------------------------------------------------------------------------------- */
+
+effect_set_t *spell_trigger (spell_t * spell, character_t * caster,
+                             env_t * env, int *near_miss)
+{
+    int  i;
+    spellguard_t *guard = spell->spellguard;
+
+    if (near_miss)
+        *near_miss = 0;
+
+    for (i = 0; i < spell->letdefs_nr; i++)
+        magic_eval (env,
+                    &env->vars[spell->letdefs[i].id], spell->letdefs[i].expr);
+
+    return check_spellguard (guard, caster, env, near_miss);
+}
+
+static void spell_set_location (invocation_t * invocation, entity_t * entity)
+{
+    magic_clear_var (&invocation->env->vars[VAR_LOCATION]);
+    invocation->env->vars[VAR_LOCATION].ty = TY_LOCATION;
+    invocation->env->vars[VAR_LOCATION].v.v_location.m = entity->m;
+    invocation->env->vars[VAR_LOCATION].v.v_location.x = entity->x;
+    invocation->env->vars[VAR_LOCATION].v.v_location.y = entity->y;
+}
+
+void spell_update_location (invocation_t * invocation)
+{
+    if (invocation->spell->flags & SPELL_FLAG_LOCAL)
+        return;
+    else
+    {
+        character_t *owner = (character_t *) map_id2bl (invocation->subject);
+        if (!owner)
+            return;
+
+        spell_set_location (invocation, (entity_t *) owner);
+    }
+}
+
+invocation_t *spell_instantiate (effect_set_t * effect_set, env_t * env)
+{
+    invocation_t *retval;
+    CREATE (retval, invocation_t, 1);
+    entity_t *caster;
+
+    retval->env = env;
+
+    retval->caster = VAR (VAR_CASTER).v.v_int;
+    retval->spell = VAR (VAR_SPELL).v.v_spell;
+    retval->stack_size = 0;
+    retval->current_effect = effect_set->effect;
+    retval->trigger_effect = effect_set->at_trigger;
+    retval->end_effect = effect_set->at_end;
+
+    caster = map_id2bl (retval->caster);    // must still exist
+    retval->bl.id = map_addobject (&retval->bl);
+    retval->bl.type = BL_SPELL;
+    retval->bl.m = caster->m;
+    retval->bl.x = caster->x;
+    retval->bl.y = caster->y;
+
+    map_addblock (&retval->bl);
+    set_env_invocation (VAR_INVOCATION, retval);
+
+    return retval;
+}
+
+invocation_t *spell_clone_effect (invocation_t * base)
+{
+    invocation_t *retval = (invocation_t *) malloc (sizeof (invocation_t));
+    env_t *env;
+
+    memcpy (retval, base, sizeof (invocation_t));
+
+    retval->env = clone_env (retval->env);
+    env = retval->env;
+    retval->current_effect = retval->trigger_effect;
+    retval->next_invocation = NULL;
+    retval->end_effect = NULL;
+    retval->script_pos = 0;
+    retval->stack_size = 0;
+    retval->timer = 0;
+    retval->subject = 0;
+    retval->status_change_refs_nr = 0;
+    retval->status_change_refs = NULL;
+    retval->flags = 0;
+
+    retval->bl.id = 0;
+    retval->bl.prev = NULL;
+    retval->bl.next = NULL;
+
+    retval->bl.id = map_addobject (&retval->bl);
+    set_env_invocation (VAR_INVOCATION, retval);
+
+    return retval;
+}
+
+void spell_bind (character_t * subject, invocation_t * invocation)
+{
+    /* Only bind nonlocal spells */
+
+    if (!(invocation->spell->flags & SPELL_FLAG_LOCAL))
+    {
+        if (invocation->flags & INVOCATION_FLAG_BOUND
+            || invocation->subject || invocation->next_invocation)
+        {
+            int *i = NULL;
+            fprintf (stderr,
+                     "[magic] INTERNAL ERROR: Attempt to re-bind spell invocation `%s'\n",
+                     invocation->spell->name);
+            *i = 1;
+            return;
+        }
+
+        invocation->next_invocation = subject->active_spells;
+        subject->active_spells = invocation;
+        invocation->flags |= INVOCATION_FLAG_BOUND;
+        invocation->subject = subject->bl.id;
+    }
+
+    spell_set_location (invocation, (entity_t *) subject);
+}
+
+int spell_unbind (character_t * subject, invocation_t * invocation)
+{
+    invocation_t **seeker = &subject->active_spells;
+
+    while (*seeker)
+    {
+        if (*seeker == invocation)
+        {
+            *seeker = invocation->next_invocation;
+
+            invocation->flags &= ~INVOCATION_FLAG_BOUND;
+            invocation->next_invocation = NULL;
+            invocation->subject = 0;
+
+            return 0;
+        }
+        seeker = &((*seeker)->next_invocation);
+    }
+
+    return 1;
+}
diff --git a/src/map/magic-interpreter-lexer.l b/src/map/magic-interpreter-lexer.l
deleted file mode 100644
index 2c9792f..0000000
--- a/src/map/magic-interpreter-lexer.l
+++ /dev/null
@@ -1,140 +0,0 @@
-%{
-#include "magic-interpreter.h"
-#include "magic-interpreter-parser.h"
-
-#ifdef HEADING
-#  undef HEADING
-#endif
-
-#define FIXLOC magic_frontend_lloc.first_line = magic_frontend_lineno
-
-#define HEADING(dir) { magic_frontend_lval.i = dir; FIXLOC; return DIR; }
-
-%}
-
-%option yylineno
-%option noyywrap
-%option prefix="magic_frontend_"
-%option nounput
-%option noinput
-%option bison-bridge bison-locations
-
-%%
-
-"S"			HEADING(0);
-"SW"			HEADING(1);
-"W"			HEADING(2);
-"NW"			HEADING(3);
-"N"			HEADING(4);
-"NE"			HEADING(5);
-"E"			HEADING(6);
-"SE"			HEADING(7);
-"="			{FIXLOC; return '=';}
-"=="			{FIXLOC; return EQ;}
-"<>"			{FIXLOC; return NEQ;}
-"!="			{FIXLOC; return NEQ;}
-">"			{FIXLOC; return '>';}
-"<"			{FIXLOC; return '<';}
-">="			{FIXLOC; return GTE;}
-"<="			{FIXLOC; return LTE;}
-"("			{FIXLOC; return '(';}
-")"			{FIXLOC; return ')';}
-"+"			{FIXLOC; return '+';}
-"-"			{FIXLOC; return '-';}
-"*"			{FIXLOC; return '*';}
-"/"			{FIXLOC; return '/';}
-"%"			{FIXLOC; return '%';}
-"&&"			{FIXLOC; return ANDAND;}
-"||"			{FIXLOC; return OROR;}
-";"			{FIXLOC; return ';';}
-":"			{FIXLOC; return ':';}
-","			{FIXLOC; return ',';}
-"@"			{FIXLOC; return '@';}
-"|"			{FIXLOC; return '|';}
-"["			{FIXLOC; return '[';}
-"]"			{FIXLOC; return ']';}
-"&"			{FIXLOC; return '&';}
-"^"			{FIXLOC; return '^';}
-"."			{FIXLOC; return '.';}
-"<<"			{FIXLOC; return SHL;}
-">>"			{FIXLOC; return SHR;}
-"PROCEDURE"		{FIXLOC; return PROCEDURE;}
-"CALL"			{FIXLOC; return CALL;}
-"OR"			{FIXLOC; return OR;}
-"TO"			{FIXLOC; return TO;}
-"TOWARDS"		{FIXLOC; return TOWARDS;}
-"TELEPORT-ANCHOR"	{FIXLOC; return TELEPORT_ANCHOR;}
-"SILENT"		{FIXLOC; return SILENT;}
-"LOCAL"			{FIXLOC; return LOCAL;}
-"NONMAGIC"		{FIXLOC; return NONMAGIC;}
-"SPELL"			{FIXLOC; return SPELL;}
-"LET"			{FIXLOC; return LET;}
-"IN"			{FIXLOC; return IN;}
-"END"			{FIXLOC; return END;}
-"=>"			{FIXLOC; return DARROW;}
-"STRING"		{FIXLOC; return STRING_TY;}
-"REQUIRE"		{FIXLOC; return REQUIRE;}
-"CATALYSTS"		{FIXLOC; return CATALYSTS;}
-"COMPONENTS"		{FIXLOC; return COMPONENTS;}
-"MANA"			{FIXLOC; return MANA;}
-"CASTTIME"		{FIXLOC; return CASTTIME;}
-"SKIP"			{FIXLOC; return SKIP;}
-"ABORT"			{FIXLOC; return ABORT;}
-"BREAK"			{FIXLOC; return BREAK;}
-"EFFECT"		{FIXLOC; return EFFECT;}
-"ATEND"			{FIXLOC; return ATEND;}
-"ATTRIGGER"		{FIXLOC; return ATTRIGGER;}
-"CONST"			{FIXLOC; return CONST;}
-"PC"			{FIXLOC; return PC_F;}
-"NPC"			{FIXLOC; return NPC_F;}
-"MOB"			{FIXLOC; return MOB_F;}
-"ENTITY"		{FIXLOC; return ENTITY_F;}
-"TARGET"		{FIXLOC; return TARGET_F;}
-"IF"			{FIXLOC; return IF;}
-"THEN"			{FIXLOC; return THEN;}
-"ELSE"			{FIXLOC; return ELSE;}
-"FOREACH"		{FIXLOC; return FOREACH;}
-"FOR"			{FIXLOC; return FOR;}
-"DO"			{FIXLOC; return DO;}
-"WAIT"			{FIXLOC; return SLEEP;}
-
-\{([^\}]|\\.)*\} { char *string = strdup(yytext);
-                   magic_frontend_lval.s = string;
-		   FIXLOC;
-                   return SCRIPT_DATA;
-                   }
-
-\"([^\"]|\\.)*\" { char *string = strdup(yytext + 1);
-                   char *src = string;
-                   char *dst = string;
-                   while (*src && *src != '"')
-                       if (*src == '\\') {
-                           *dst++ = src[1];
-                           src += 2;
-                       } else
-                           *dst++ = *src++;
-                   *dst = '\0'; /* terminate */
-                   magic_frontend_lval.s = string;
-		   FIXLOC;
-                   return STRING;
-                   }
-
-"-"?[0-9]+	    { magic_frontend_lval.i = atoi(yytext);
-		      FIXLOC;
-                      return INT; }
-
-"0x"[0-9a-fA-F]+    { magic_frontend_lval.i = strtol(yytext + 2, NULL, 16);
-		      FIXLOC;
-                      return INT; }
-
-[a-zA-Z][-_a-zA-Z0-9?!]*  { magic_frontend_lval.s = strdup(yytext);
-		            FIXLOC;
-                            return ID; }
-
-"#".*$		/* Ignore comments */
-"//".*$		/* Ignore comments */
-[ \n\t\r]	/* ignore whitespace */	
-.       	fprintf(stderr, "%s: Unexpected character in line %d\n", MAGIC_CONFIG_FILE, magic_frontend_lineno);
-
-
-%%
diff --git a/src/map/magic-interpreter-lexer.lpp b/src/map/magic-interpreter-lexer.lpp
new file mode 100644
index 0000000..c7f9c09
--- /dev/null
+++ b/src/map/magic-interpreter-lexer.lpp
@@ -0,0 +1,140 @@
+%{
+#include "magic-interpreter.hpp"
+#include "magic-interpreter-parser.hpp"
+
+#ifdef HEADING
+#  undef HEADING
+#endif
+
+#define FIXLOC magic_frontend_lloc.first_line = magic_frontend_lineno
+
+#define HEADING(dir) { magic_frontend_lval.i = dir; FIXLOC; return DIR; }
+
+%}
+
+%option yylineno
+%option noyywrap
+%option prefix="magic_frontend_"
+%option nounput
+%option noinput
+%option bison-bridge bison-locations
+
+%%
+
+"S"			HEADING(0);
+"SW"			HEADING(1);
+"W"			HEADING(2);
+"NW"			HEADING(3);
+"N"			HEADING(4);
+"NE"			HEADING(5);
+"E"			HEADING(6);
+"SE"			HEADING(7);
+"="			{FIXLOC; return '=';}
+"=="			{FIXLOC; return EQ;}
+"<>"			{FIXLOC; return NEQ;}
+"!="			{FIXLOC; return NEQ;}
+">"			{FIXLOC; return '>';}
+"<"			{FIXLOC; return '<';}
+">="			{FIXLOC; return GTE;}
+"<="			{FIXLOC; return LTE;}
+"("			{FIXLOC; return '(';}
+")"			{FIXLOC; return ')';}
+"+"			{FIXLOC; return '+';}
+"-"			{FIXLOC; return '-';}
+"*"			{FIXLOC; return '*';}
+"/"			{FIXLOC; return '/';}
+"%"			{FIXLOC; return '%';}
+"&&"			{FIXLOC; return ANDAND;}
+"||"			{FIXLOC; return OROR;}
+";"			{FIXLOC; return ';';}
+":"			{FIXLOC; return ':';}
+","			{FIXLOC; return ',';}
+"@"			{FIXLOC; return '@';}
+"|"			{FIXLOC; return '|';}
+"["			{FIXLOC; return '[';}
+"]"			{FIXLOC; return ']';}
+"&"			{FIXLOC; return '&';}
+"^"			{FIXLOC; return '^';}
+"."			{FIXLOC; return '.';}
+"<<"			{FIXLOC; return SHL;}
+">>"			{FIXLOC; return SHR;}
+"PROCEDURE"		{FIXLOC; return PROCEDURE;}
+"CALL"			{FIXLOC; return CALL;}
+"OR"			{FIXLOC; return OR;}
+"TO"			{FIXLOC; return TO;}
+"TOWARDS"		{FIXLOC; return TOWARDS;}
+"TELEPORT-ANCHOR"	{FIXLOC; return TELEPORT_ANCHOR;}
+"SILENT"		{FIXLOC; return SILENT;}
+"LOCAL"			{FIXLOC; return LOCAL;}
+"NONMAGIC"		{FIXLOC; return NONMAGIC;}
+"SPELL"			{FIXLOC; return SPELL;}
+"LET"			{FIXLOC; return LET;}
+"IN"			{FIXLOC; return IN;}
+"END"			{FIXLOC; return END;}
+"=>"			{FIXLOC; return DARROW;}
+"STRING"		{FIXLOC; return STRING_TY;}
+"REQUIRE"		{FIXLOC; return REQUIRE;}
+"CATALYSTS"		{FIXLOC; return CATALYSTS;}
+"COMPONENTS"		{FIXLOC; return COMPONENTS;}
+"MANA"			{FIXLOC; return MANA;}
+"CASTTIME"		{FIXLOC; return CASTTIME;}
+"SKIP"			{FIXLOC; return SKIP;}
+"ABORT"			{FIXLOC; return ABORT;}
+"BREAK"			{FIXLOC; return BREAK;}
+"EFFECT"		{FIXLOC; return EFFECT;}
+"ATEND"			{FIXLOC; return ATEND;}
+"ATTRIGGER"		{FIXLOC; return ATTRIGGER;}
+"CONST"			{FIXLOC; return CONST;}
+"PC"			{FIXLOC; return PC_F;}
+"NPC"			{FIXLOC; return NPC_F;}
+"MOB"			{FIXLOC; return MOB_F;}
+"ENTITY"		{FIXLOC; return ENTITY_F;}
+"TARGET"		{FIXLOC; return TARGET_F;}
+"IF"			{FIXLOC; return IF;}
+"THEN"			{FIXLOC; return THEN;}
+"ELSE"			{FIXLOC; return ELSE;}
+"FOREACH"		{FIXLOC; return FOREACH;}
+"FOR"			{FIXLOC; return FOR;}
+"DO"			{FIXLOC; return DO;}
+"WAIT"			{FIXLOC; return SLEEP;}
+
+\{([^\}]|\\.)*\} { char *string = strdup(yytext);
+                   magic_frontend_lval.s = string;
+		   FIXLOC;
+                   return SCRIPT_DATA;
+                   }
+
+\"([^\"]|\\.)*\" { char *string = strdup(yytext + 1);
+                   char *src = string;
+                   char *dst = string;
+                   while (*src && *src != '"')
+                       if (*src == '\\') {
+                           *dst++ = src[1];
+                           src += 2;
+                       } else
+                           *dst++ = *src++;
+                   *dst = '\0'; /* terminate */
+                   magic_frontend_lval.s = string;
+		   FIXLOC;
+                   return STRING;
+                   }
+
+"-"?[0-9]+	    { magic_frontend_lval.i = atoi(yytext);
+		      FIXLOC;
+                      return INT; }
+
+"0x"[0-9a-fA-F]+    { magic_frontend_lval.i = strtol(yytext + 2, NULL, 16);
+		      FIXLOC;
+                      return INT; }
+
+[a-zA-Z][-_a-zA-Z0-9?!]*  { magic_frontend_lval.s = strdup(yytext);
+		            FIXLOC;
+                            return ID; }
+
+"#".*$		/* Ignore comments */
+"//".*$		/* Ignore comments */
+[ \n\t\r]	/* ignore whitespace */	
+.       	fprintf(stderr, "%s: Unexpected character in line %d\n", MAGIC_CONFIG_FILE, magic_frontend_lineno);
+
+
+%%
diff --git a/src/map/magic-interpreter-parser.y b/src/map/magic-interpreter-parser.y
deleted file mode 100644
index 9df0f3e..0000000
--- a/src/map/magic-interpreter-parser.y
+++ /dev/null
@@ -1,1089 +0,0 @@
-%{
-#include "magic-interpreter.h"
-#include "magic-expr.h"
-#include <stdarg.h>
-
-magic_conf_t magic_conf;
-
-static int
-intern_id(const char *id_name);
-
-
-static expr_t *
-fun_expr(const char *name, int args_nr, expr_t **args, int line, int column);
-
-static expr_t *
-dot_expr(expr_t *lhs, int id);
-
-#define BIN_EXPR(x, name, arg1, arg2, line, column) { expr_t *e[2]; e[0] = arg1; e[1] = arg2; x = fun_expr(name, 2, e, line, column); }
-
-static int failed_flag = 0;
-
-static void
-magic_frontend_error(const char *msg);
-
-static void
-fail(int line, int column, const char *fmt, ...);
-
-static spell_t *
-new_spell(spellguard_t *guard);
-
-static spellguard_t *
-spellguard_implication(spellguard_t *a, spellguard_t *b);
-
-static spellguard_t *
-new_spellguard(int ty);
-
-static effect_t *
-new_effect(int ty);
-
-static effect_t *
-set_effect_continuation(effect_t *src, effect_t *continuation);
-
-static void
-add_spell(spell_t *spell, int line_nr);
-
-static void
-add_teleport_anchor(teleport_anchor_t *anchor, int line_nr);
-
-static effect_t *
-op_effect(char *name, int args_nr, expr_t **args, int line, int column);
-
-int
-magic_frontend_lex(void);
-
-static void
-install_proc(proc_t *proc);
-
-static effect_t *
-call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column);
-
-static void
-bind_constant(char *name, val_t *val, int line_nr);
-
-static val_t *
-find_constant(char *name);
-
-
-%}
-
-%name-prefix="magic_frontend_"
-
-%locations
-
-%union {
-    int i;
-    char *s;
-    int op;
-    magic_conf_t *magic_conf;
-    val_t value;
-    expr_t *expr;
-    e_location_t location;
-    e_area_t area;
-    args_rec_t arg_list;
-    struct { int letdefs_nr; letdef_t *letdefs; } letdefs;
-    spell_t *spell;
-    struct { int id, ty; } spellarg_def;
-    letdef_t vardef;
-    spellguard_t *spellguard;
-    component_t *components;
-    struct {int id, count; } component;
-    effect_t *effect;
-    proc_t *proc;
-};
-
-%expect 7
-
-%token <i> INT
-%token <s> STRING
-%token <s> ID
-%token <i> DIR
-
-%token '='
-%token '<'
-%token '>'
-%token '+'
-%token '-'
-%token '*'
-%token '/'
-%token '%'
-%token '@'
-%token ','
-%token '.'
-%token ':'
-%token ';'
-%token '|'
-%token '['
-%token ']'
-%token '&'
-%token '^'
-
-%token CONST
-%token PROCEDURE
-%token CALL
-%token SILENT
-%token LOCAL
-%token NONMAGIC
-%token SHL
-%token SHR
-%token EQ
-%token NEQ
-%token GTE
-%token LTE
-%token ANDAND
-%token OROR
-%token <s> SCRIPT_DATA
-%token TO
-%token TOWARDS
-%token TELEPORT_ANCHOR
-%token SPELL
-%token LET
-%token IN
-%token END
-%token DARROW
-%token STRING_TY
-%token REQUIRE
-%token CATALYSTS
-%token COMPONENTS
-%token MANA
-%token CASTTIME
-%token SKIP
-%token ABORT
-%token BREAK
-%token EFFECT
-%token ATEND
-%token ATTRIGGER
-%token PC_F
-%token NPC_F
-%token MOB_F
-%token ENTITY_F
-%token TARGET_F
-%token IF
-%token THEN
-%token ELSE
-%token FOREACH
-%token FOR
-%token DO
-%token SLEEP
-
-%type <value> value
-%type <location> location
-%type <area> area
-%type <arg_list> arg_list
-%type <arg_list> arg_list_ne
-%type <letdefs> defs
-%type <spell> spelldef
-%type <spellarg_def> argopt
-%type <vardef> def
-%type <spellguard> spellbody_list
-%type <spellguard> spellbody
-%type <spellguard> spellguard
-%type <spellguard> spellguard_list
-%type <spellguard> prereq
-%type <component> item
-%type <components> items
-%type <components> item_list
-%type <i> item_name
-%type <i> selection;
-%type <effect> effect
-%type <effect> effect_list
-%type <effect> maybe_trigger
-%type <effect> maybe_end
-%type <i> spell_flags;
-
-%type <expr> expr
-%type <i> arg_ty
-%type <proc> proc_formals_list
-%type <proc> proc_formals_list_ne
-
-%left OROR
-%left ANDAND
-%left '<' '>' GTE LTE NEQ EQ
-%left '+' '-'
-%left '*' '/' '%'
-%left SHL SHR '&' '^' '|'
-%right '='
-%left OR
-%left DARROW
-%left '.'
-
-%%
-
-spellconf		: /* empty */
-                          {}
-                        | spellconf_option semicolons spellconf
-                          {}
-			;
-
-
-semicolons		: /* empty */
-			  {}
-                        | semicolons ';'
-                          {}
-			;
-
-
-proc_formals_list	: /* empty  */
-                          { CREATE ($$, proc_t, 1); }
-			| proc_formals_list_ne
-                          { $$ = $1; }
-			;
-
-proc_formals_list_ne	: ID
-                          { CREATE ($$, proc_t, 1);
-                            $$->args_nr = 1;
-                            $$->args = (int*)malloc(sizeof(int));
-                            $$->args[0] = intern_id($1);
-                          }
-			| proc_formals_list_ne ',' ID
-                          { $$ = $1;
-                            $$->args = (int*)realloc($$->args, sizeof(int) * (1 + $$->args_nr));
-                            $$->args[$$->args_nr++] = intern_id($3);
-                          }
-			;
-
-spellconf_option	: ID '=' expr
-			  {
-                            int var_id;
-                            if (find_constant($1)) {
-                                    fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1);
-                                    free($1);
-                            } else {
-                                    var_id = intern_id($1);
-                                    magic_eval(&magic_default_env, &magic_conf.vars[var_id], $3);
-                            }
-                          }
-			| CONST ID '=' expr
-			  {
-                            val_t var;
-                            magic_eval(&magic_default_env, &var, $4);
-                            bind_constant($2, &var, @1.first_line);
-                          }
-                        | TELEPORT_ANCHOR ID ':' expr '=' expr
-                          {
-                              teleport_anchor_t *anchor;
-                              CREATE (anchor, teleport_anchor_t, 1);
-                              anchor->name = $2;
-                              anchor->invocation = magic_eval_str(&magic_default_env, $4);
-                              anchor->location = $6;
-
-                              if (!failed_flag)
-                                  add_teleport_anchor(anchor, @1.first_line);
-                              else
-                                  free(anchor);
-                              failed_flag = 0;
-                          }
-			| PROCEDURE ID '(' proc_formals_list ')' '=' effect_list
-                          {
-                              proc_t *proc = $4;
-                              proc->name = $2;
-                              proc->body = $7;
-                              if (!failed_flag)
-                                  install_proc(proc);
-                              failed_flag = 0;
-                          }
-                        | spell_flags SPELL ID argopt ':' expr '=' spelldef
-                          { spell_t *spell = $8;
-                            spell->name = $3;
-                            spell->invocation = magic_eval_str(&magic_default_env, $6);
-                            spell->arg = $4.id;
-                            spell->spellarg_ty = $4.ty;
-                            spell->flags = $1;
-                            if (!failed_flag)
-                                add_spell(spell, @1.first_line);
-                            failed_flag = 0;
-                          }
-
-spell_flags		: /* empty */
-				{ $$ = 0; }
-			| LOCAL spell_flags
-                        	{ if ($2 & SPELL_FLAG_LOCAL)
-                                        fail(@1.first_line, @1.first_column, "`LOCAL' specified more than once");
-                                   $$ = $2 | SPELL_FLAG_LOCAL;
-                                }
-			| NONMAGIC spell_flags
-                        	{ if ($2 & SPELL_FLAG_NONMAGIC)
-                                        fail(@1.first_line, @1.first_column, "`NONMAGIC' specified more than once");
-                                   $$ = $2 | SPELL_FLAG_NONMAGIC;
-                                }
-			| SILENT spell_flags
-                        	{ if ($2 & SPELL_FLAG_SILENT)
-                                        fail(@1.first_line, @1.first_column, "`SILENT' specified more than once");
-                                   $$ = $2 | SPELL_FLAG_SILENT;
-                                }
-
-
-argopt			: /* empty */
-                          { $$.ty = SPELLARG_NONE; }
-                        | '(' ID ':' arg_ty ')'
-                          { $$.id = intern_id($2);
-                            $$.ty = $4; }
-                        ;
-
-
-arg_ty                  : PC_F
-                          { $$ = SPELLARG_PC; }
-                        | STRING_TY
-                          { $$ = SPELLARG_STRING; }
-                        ;
-
-
-value			: DIR
-				{ $$.ty = TY_DIR;
-                                  $$.v.v_int = $1; }
-			| INT
-				{ $$.ty = TY_INT;
-                                  $$.v.v_int = $1; }
-			| STRING
-				{ $$.ty = TY_STRING;
-                                  $$.v.v_string = $1; }
-			;
-
-
-expr			: value
-				{ $$ = magic_new_expr(EXPR_VAL);
-                                  $$->e.e_val = $1; }
-			| ID
-				{
-                                        val_t *val;
-                                        if ((val = find_constant($1))) {
-                                                $$ = magic_new_expr(EXPR_VAL);
-                                                $$->e.e_val = *val;
-                                        } else {
-                                                $$ = magic_new_expr(EXPR_ID);
-                                                $$->e.e_id = intern_id($1);
-                                        }
-                                }
-			| area
-				{ $$ = magic_new_expr(EXPR_AREA);
-                                  $$->e.e_area = $1; }
-			| expr '+' expr
-	                        { BIN_EXPR($$, "+", $1, $3, @1.first_line, @1.first_column); }
-			| expr '-' expr
-	                        { BIN_EXPR($$, "-", $1, $3, @1.first_line, @1.first_column); }
-			| expr '*' expr
-	                        { BIN_EXPR($$, "*", $1, $3, @1.first_line, @1.first_column); }
-			| expr '%' expr
-	                        { BIN_EXPR($$, "%", $1, $3, @1.first_line, @1.first_column); }
-			| expr '/' expr
-	                        { BIN_EXPR($$, "/", $1, $3, @1.first_line, @1.first_column); }
-			| expr '<' expr
-	                        { BIN_EXPR($$, ">", $3, $1, @1.first_line, @1.first_column); }
-			| expr '>' expr
-	                        { BIN_EXPR($$, ">", $1, $3, @1.first_line, @1.first_column); }
-			| expr '&' expr
-	                        { BIN_EXPR($$, "&", $1, $3, @1.first_line, @1.first_column); }
-			| expr '^' expr
-	                        { BIN_EXPR($$, "^", $1, $3, @1.first_line, @1.first_column); }
-			| expr '|' expr
-	                        { BIN_EXPR($$, "|", $1, $3, @1.first_line, @1.first_column); }
-			| expr SHL expr
-	                        { BIN_EXPR($$, "<<", $1, $3, @1.first_line, @1.first_column); }
-			| expr SHR expr
-	                        { BIN_EXPR($$, ">>", $1, $3, @1.first_line, @1.first_column); }
-			| expr LTE expr
-	                        { BIN_EXPR($$, ">=", $3, $1, @1.first_line, @1.first_column); }
-			| expr GTE expr
-	                        { BIN_EXPR($$, ">=", $1, $3, @1.first_line, @1.first_column); }
-			| expr ANDAND expr
-	                        { BIN_EXPR($$, "&&", $1, $3, @1.first_line, @1.first_column); }
-			| expr OROR expr
-	                        { BIN_EXPR($$, "||", $1, $3, @1.first_line, @1.first_column); }
-			| expr EQ expr
-	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
-			| expr '=' expr
-	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
-			| expr NEQ expr
-	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column);
-                                  $$ = fun_expr("not", 1, &$$, @1.first_line, @1.first_column); }
-			| ID '(' arg_list ')'
-                        	{ $$ = fun_expr($1, $3.args_nr, $3.args, @1.first_line, @1.first_column);
-                                  if ($3.args)
-                                          free($3.args);
-                                  free($1); }
-			| '(' expr ')'
-                        	{ $$ = $2; }
-			| expr '.' ID
-                        	{ $$ = dot_expr($1, intern_id($3)); }
-			;
-
-arg_list		: /* empty */
-				{ $$.args_nr = 0; }
-			| arg_list_ne
-				{ $$ = $1; }
-			;
-
-
-arg_list_ne		: expr
-				{ CREATE($$.args, expr_t *, 1);
-                                  $$.args_nr = 1;
-                                  $$.args[0] = $1;
-                                }
-			| arg_list_ne ',' expr
-                        	{ RECREATE($$.args, expr_t *, 1 + $$.args_nr);
-                                  $$.args[$$.args_nr++] = $3;
-                                }
-			;
-
-
-location		: '@' '(' expr ',' expr ',' expr ')'
-				{ $$.m = $3; $$.x = $5; $$.y = $7; }
-			;
-
-area			: location
-				{ $$.ty = AREA_LOCATION;
-                                  $$.a.a_loc = $1;
-				}
-			| location '@' '+' '(' expr ',' expr ')'
-				{ $$.ty = AREA_RECT;
-                                  $$.a.a_rect.loc = $1;
-                                  $$.a.a_rect.width = $5;
-                                  $$.a.a_rect.height = $7;
-                                }
-			| location TOWARDS expr ':' '(' expr ',' expr ')'
-				{ $$.ty = AREA_BAR;
-                                  $$.a.a_bar.loc = $1;
-                                  $$.a.a_bar.width = $6;
-                                  $$.a.a_bar.depth = $8;
-                                  $$.a.a_bar.dir = $3;
-                                }
-			;
-
-
-spelldef		: spellbody_list
-                                {  $$ = new_spell($1); }
-			| LET defs IN spellbody_list
-                                {  $$ = new_spell($4);
-                                   $$->letdefs_nr = $2.letdefs_nr;
-                                   $$->letdefs = $2.letdefs;
-                                   $$->spellguard = $4;
-                                }
-			;
-
-
-defs			: semicolons
-				{ $$.letdefs_nr = 0;
-                                  CREATE($$.letdefs, letdef_t, 1);
-                                }
-			| defs def semicolons
-	                        { $$ = $1;
-                                  $$.letdefs_nr++;
-                                  RECREATE ($$.letdefs, letdef_t, $$.letdefs_nr);
-                                  $$.letdefs[$1.letdefs_nr] = $2;
-                                }
-                        ;
-
-
-def			: ID '=' expr
-				{
-                                        if (find_constant($1)) {
-                                                fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1);
-                                                free($1);
-                                        } else {
-                                                $$.id = intern_id($1);
-                                                $$.expr = $3;
-                                        }
-                                }
-			;
-
-
-spellbody_list		: spellbody
-				{ $$ = $1; }
-			| spellbody '|' spellbody_list
-                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
-                                  sg->next = $1;
-                                  sg->s.s_alt = $3;
-                                  $$ = sg;
-                                }
-			;
-
-
-spellbody		: spellguard DARROW spellbody
-				{ $$ = spellguard_implication($1, $3); }
-			| '(' spellbody_list ')'
-                        	{ $$ = $2; }
-			| EFFECT effect_list maybe_trigger maybe_end
-                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_EFFECT);
-                                  sg->s.s_effect.effect = $2;
-                                  sg->s.s_effect.at_trigger = $3;
-                                  sg->s.s_effect.at_end = $4;
-                                  $$ = sg;
-                                }
-			;
-
-
-maybe_trigger		: /* empty */
-				{ $$ = NULL; }
-			| ATTRIGGER effect_list
-				{ $$ = $2; }
-			;
-
-
-maybe_end		: /* empty */
-				{ $$ = NULL; }
-			| ATEND effect_list
-				{ $$ = $2; }
-			;
-
-
-spellguard		: prereq
-				{ $$ = $1; }
-			| spellguard OR spellguard
-                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
-                                  sg->next = $1;
-                                  sg->s.s_alt = $3;
-                                  $$ = sg;
-                                }
-			| '(' spellguard_list ')'
-                        	{ $$ = $2; }
-			;
-
-
-spellguard_list		: spellguard
-				{ $$ = $1; }
-			| spellguard ',' spellguard_list
-                        	{ $$ = spellguard_implication ($1, $3); }
-			;
-
-
-prereq			: REQUIRE expr
-				{ $$ = new_spellguard(SPELLGUARD_CONDITION);
-                                  $$->s.s_condition = $2;
-                                }
-			| CATALYSTS items
-				{ $$ = new_spellguard(SPELLGUARD_CATALYSTS);
-                                  $$->s.s_catalysts = $2;
-                                }
-			| COMPONENTS items
-				{ $$ = new_spellguard(SPELLGUARD_COMPONENTS);
-                                  $$->s.s_components = $2;
-                                }
-			| MANA expr
-				{ $$ = new_spellguard(SPELLGUARD_MANA);
-                                  $$->s.s_mana = $2;
-                                }
-			| CASTTIME expr
-				{ $$ = new_spellguard(SPELLGUARD_CASTTIME);
-                                  $$->s.s_casttime = $2;
-                                }
-			;
-
-
-items			: '[' item_list ']'
-				{ $$ = $2; }
-			;
-
-
-item_list		: item
-				{ $$ = NULL;
-                                  magic_add_component(&$$, $1.id, $1.count);
-                                }
-			| item_list ',' item
-				{ $$ = $1;
-                                  magic_add_component(&$$, $3.id, $3.count);
-                                }
-			;
-
-
-item			: INT '*' item_name
-				{ $$.id = $3; $$.count = $1; }
-			| item_name
-				{ $$.id = $1; $$.count = 1; }
-			;
-
-
-item_name		: STRING
-				{ struct item_data *item = itemdb_searchname($1);
-                                  if (!item) {
-                                          fail (@1.first_line, @1.first_column, "Unknown item `%s'\n", $1);
-                                          $$ = 0;
-                                  } else
-                                          $$ = item->nameid;
-                                  free ($1);
-                                }
-			| INT
-				{ $$ = $1; }
-			;
-
-
-selection		: PC_F
-				{ $$ = FOREACH_FILTER_PC; }
-			| MOB_F
-				{ $$ = FOREACH_FILTER_MOB; }
-			| ENTITY_F
-				{ $$ = FOREACH_FILTER_ENTITY; }
-			| SPELL
-				{ $$ = FOREACH_FILTER_SPELL; }
-			| TARGET_F
-				{ $$ = FOREACH_FILTER_TARGET; }
-			| NPC_F
-				{ $$ = FOREACH_FILTER_NPC; }
-			;
-
-
-effect			: '(' effect_list ')'
-				{ $$ = $2; }
-			| SKIP ';'
-                        	{ $$ = new_effect(EFFECT_SKIP); }
-			| ABORT ';'
-                        	{ $$ = new_effect(EFFECT_ABORT); }
-			| END ';'
-                        	{ $$ = new_effect(EFFECT_END); }
-			| BREAK ';'
-                        	{ $$ = new_effect(EFFECT_BREAK); }
-			| ID '=' expr ';'
-                        	{
-                                        if (find_constant($1)) {
-                                                fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1);
-                                                free($1);
-                                        } else {
-                                                $$ = new_effect(EFFECT_ASSIGN);
-                                                $$->e.e_assign.id = intern_id($1);
-                                                $$->e.e_assign.expr = $3;
-                                        }
-                                }
-			| FOREACH selection ID IN expr DO effect
-                        	{ $$ = new_effect(EFFECT_FOREACH);
-                                  $$->e.e_foreach.id = intern_id($3);
-                                  $$->e.e_foreach.area = $5;
-                                  $$->e.e_foreach.body = $7;
-                                  $$->e.e_foreach.filter = $2;
-                                }
-			| FOR ID '=' expr TO expr DO effect
-                        	{ $$ = new_effect(EFFECT_FOR);
-                                  $$->e.e_for.id = intern_id($2);
-                                  $$->e.e_for.start = $4;
-                                  $$->e.e_for.stop = $6;
-                                  $$->e.e_for.body = $8;
-                                }
-			| IF expr THEN effect ELSE effect
-                        	{ $$ = new_effect(EFFECT_IF);
-                                  $$->e.e_if.cond = $2;
-                                  $$->e.e_if.true_branch = $4;
-                                  $$->e.e_if.false_branch = $6;
-                                }
-			| IF expr THEN effect
-                        	{ $$ = new_effect(EFFECT_IF);
-                                  $$->e.e_if.cond = $2;
-                                  $$->e.e_if.true_branch = $4;
-                                  $$->e.e_if.false_branch = new_effect(EFFECT_SKIP);
-                                }
-			| SLEEP expr ';'
-                        	{ $$ = new_effect(EFFECT_SLEEP);
-                                  $$->e.e_sleep = $2;
-                                }
-			| ID '(' arg_list ')' ';'
-                                { $$ = op_effect($1, $3.args_nr, $3.args, @1.first_line, @1.first_column);
-                                  free($1);
-                                }
-			| SCRIPT_DATA
-                        	{ $$ = new_effect(EFFECT_SCRIPT);
-                                  $$->e.e_script = parse_script((unsigned char *) $1, @1.first_line);
-                                  free($1);
-                                  if ($$->e.e_script == NULL)
-                                      fail(@1.first_line, @1.first_column, "Failed to compile script\n");
-                                }
-			| CALL ID '(' arg_list ')' ';'
-                        	{ $$ = call_proc($2, $4.args_nr, $4.args, @1.first_line, @1.first_column);
-                                  free($2);
-                                }
-			;
-
-effect_list		: /* empty */
-                        	{ $$ = new_effect(EFFECT_SKIP); }
-			| effect semicolons effect_list
-                        	{ $$ = set_effect_continuation($1, $3); }
-			;
-
-
-%%
-
-/* We do incremental realloc here to store our results.  Since this happens only once
- * during startup for a relatively manageable set of configs, it should be fine. */
-
-static int
-intern_id(const char *id_name)
-{
-        int i;
-
-        for (i = 0; i < magic_conf.vars_nr; i++)
-                if (!strcmp(id_name, magic_conf.var_name[i])) {
-                        free((char*)id_name);
-                        return i;
-                }
-
-        /* Must add new */
-        i = magic_conf.vars_nr++;
-        RECREATE(magic_conf.var_name, const char *, magic_conf.vars_nr);
-        magic_conf.var_name[i] = id_name;
-        RECREATE(magic_conf.vars, val_t, magic_conf.vars_nr);
-        magic_conf.vars[i].ty = TY_UNDEF;
-
-        return i;
-}
-
-static void
-add_spell(spell_t *spell, int line_nr)
-{
-        int index = magic_conf.spells_nr;
-        int i;
-
-        for (i = 0; i < index; i++) {
-                if (!strcmp(magic_conf.spells[i]->name, spell->name)) {
-                        fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name);
-                        return;
-                }
-                if (!strcmp(magic_conf.spells[i]->invocation, spell->invocation)) {
-                        fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n",
-                             spell->invocation, magic_conf.spells[i]->name, spell->name);
-                        return;
-                }
-        }
-        magic_conf.spells_nr++;
-
-        RECREATE(magic_conf.spells, spell_t *, magic_conf.spells_nr);
-        magic_conf.spells[index] = spell;
-
-
-}
-
-static void
-add_teleport_anchor(teleport_anchor_t *anchor, int line_nr)
-{
-        int index = magic_conf.anchors_nr;
-        int i;
-
-        for (i = 0; i < index; i++) {
-                if (!strcmp(magic_conf.anchors[i]->name, anchor->name)) {
-                        fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name);
-                        return;
-                }
-                if (!strcmp(magic_conf.anchors[i]->invocation, anchor->invocation)) {
-                        fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n",
-                             anchor->invocation, magic_conf.anchors[i]->name, anchor->name);
-                        return;
-                }
-        }
-        magic_conf.anchors_nr++;
-
-        RECREATE(magic_conf.anchors, teleport_anchor_t *, magic_conf.anchors_nr);
-        magic_conf.anchors[index] = anchor;
-}
-
-
-static void
-fail(int line, int column, const char *fmt, ...)
-{
-        va_list ap;
-        fprintf(stderr, "[magic-init]  L%d:%d: ", line, column);
-        va_start(ap, fmt);
-        vfprintf(stderr, fmt, ap);
-        failed_flag = 1;
-}
-
-static expr_t *
-dot_expr(expr_t *expr, int id)
-{
-        expr_t *retval = magic_new_expr(EXPR_SPELLFIELD);
-        retval->e.e_field.id = id;
-        retval->e.e_field.expr = expr;
-
-        return retval;
-}
-
-static expr_t *
-fun_expr(const char *name, int args_nr, expr_t **args, int line, int column)
-{
-        int id;
-        expr_t *expr;
-        fun_t *fun = magic_get_fun(name, &id);
-
-        if (!fun) {
-                fail(line, column, "Unknown function `%s'\n", name);
-        } else if (strlen(fun->signature) != args_nr) {
-                fail(line, column, "Incorrect number of arguments to function `%s': Expected %d, found %d\n", name, strlen(fun->signature), args_nr);
-                fun = NULL;
-        }
-
-        if (fun) {
-                int i;
-
-                expr = magic_new_expr(EXPR_FUNAPP);
-                expr->e.e_funapp.line_nr = line;
-                expr->e.e_funapp.column = column;
-                expr->e.e_funapp.id = id;
-                expr->e.e_funapp.args_nr = args_nr;
-
-                for (i = 0; i < args_nr; i++)
-                        expr->e.e_funapp.args[i] = args[i];
-        } else { /* failure */
-                expr = magic_new_expr(EXPR_VAL);
-                expr->e.e_val.ty = TY_FAIL;
-        }
-
-        return expr;
-}
-
-static spell_t *
-new_spell(spellguard_t *guard)
-{
-        static int spell_counter = 0;
-
-        spell_t *retval = (spell_t*)calloc(1, sizeof(spell_t));
-        retval->index = ++spell_counter;
-        retval->spellguard = guard;
-        return retval;
-}
-
-static spellguard_t *
-new_spellguard(int ty)
-{
-        spellguard_t *retval = (spellguard_t *)calloc(1, sizeof(spellguard_t));
-        retval->ty = ty;
-        return retval;
-}
-
-static spellguard_t *
-spellguard_implication(spellguard_t *a, spellguard_t *b)
-{
-        spellguard_t *retval = a;
-
-        if (a == b) /* This can happen due to reference sharing:
-                     * e.g.,
-                     *  (R0 -> (R1 | R2)) => (R3)
-                     * yields
-                     *  (R0 -> (R1 -> R3 | R2 -> R3))
-                     *
-                     * So if we now add => R4 to that, we want
-                     *  (R0 -> (R1 -> R3 -> R4 | R2 -> R3 -> R4))
-                     *
-                     * but we only need to add it once, because the R3 reference is shared.
-                    */
-                return retval;
-
-                /* If the premise is a disjunction, b is the continuation of _all_ branches */
-        if (a->ty == SPELLGUARD_CHOICE)
-                spellguard_implication(a->s.s_alt, b);
-        if (a->next)
-                spellguard_implication(a->next, b);
-        else
-                a->next = b;
-
-
-        return retval;
-}
-
-static effect_t *
-new_effect(int ty)
-{
-        effect_t *effect = (effect_t *) calloc(1, sizeof(effect_t));
-        effect->ty = ty;
-        return effect;
-}
-
-static effect_t *
-set_effect_continuation(effect_t *src, effect_t *continuation)
-{
-        effect_t *retval = src;
-        /* This function is completely analogous to `spellguard_implication' above; read the control flow implications above first before pondering it. */
-
-        if (src == continuation)
-                return retval;
-
-        /* For FOR and FOREACH, we use special stack handlers and thus don't have to set
-         * the continuation.  It's only IF that we need to handle in this fashion. */
-        if (src->ty == EFFECT_IF) {
-                set_effect_continuation(src->e.e_if.true_branch, continuation);
-                set_effect_continuation(src->e.e_if.false_branch, continuation);
-        }
-        if (src->next)
-                set_effect_continuation(src->next, continuation);
-        else
-                src->next = continuation;
-
-        return retval;
-}
-
-static effect_t *
-op_effect(char *name, int args_nr, expr_t **args, int line, int column)
-{
-        int id;
-        effect_t *effect;
-        op_t *op = magic_get_op(name, &id);
-
-        if (!op)
-                fail(line, column, "Unknown operation `%s'\n", name);
-        else if (strlen(op->signature) != args_nr) {
-                fail(line, column, "Incorrect number of arguments to operation `%s': Expected %d, found %d\n", name, strlen(op->signature), args_nr);
-                op = NULL;
-        }
-
-        if (op) {
-                int i;
-
-                effect = new_effect(EFFECT_OP);
-                effect->e.e_op.line_nr = line;
-                effect->e.e_op.column = column;
-                effect->e.e_op.id = id;
-                effect->e.e_op.args_nr = args_nr;
-
-                for (i = 0; i < args_nr; i++)
-                        effect->e.e_op.args[i] = args[i];
-        } else /* failure */
-                effect = new_effect(EFFECT_SKIP);
-
-        return effect;
-}
-
-
-proc_t *procs = NULL;
-int procs_nr = 0;
-
-// I think this is a memory leak, or undefined behavior
-static void
-install_proc(proc_t *proc)
-{
-        if (!procs) {
-                procs = proc;
-                procs_nr = 1;
-        } else {
-                RECREATE (procs, proc_t, 1 + procs_nr);
-                procs[procs_nr++] = *proc;
-        }
-}
-
-static effect_t *
-call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column)
-{
-        proc_t *p = NULL;
-        int i;
-        effect_t *retval;
-
-        for (i = 0; i < procs_nr; i++)
-                if (!strcmp(procs[i].name, name)) {
-                        p = &procs[i];
-                        break;
-                }
-
-        if (!p) {
-                fail(line_nr, column, "Unknown procedure `%s'\n", name);
-                return new_effect(EFFECT_SKIP);
-        }
-
-        if (p->args_nr != args_nr) {
-                fail(line_nr, column, "Procedure %s/%d invoked with %d parameters\n", name, p->args_nr, args_nr);
-                return new_effect(EFFECT_SKIP);
-        }
-
-        retval = new_effect(EFFECT_CALL);
-        retval->e.e_call.body = p->body;
-        retval->e.e_call.args_nr = args_nr;
-        retval->e.e_call.formals = p->args;
-        retval->e.e_call.actuals = args;
-        return retval;
-}
-
-struct const_def_rec {
-        char *name;
-        val_t val;
-} *const_defs = NULL;
-
-int const_defs_nr = 0;
-
-static void
-bind_constant(char *name, val_t *val, int line_nr)
-{
-        if (find_constant(name)) {
-                fail(line_nr, 0, "Redefinition of constant `%s'\n", name);
-                return;
-        }
-
-        if (!const_defs)
-                const_defs = (struct const_def_rec *)malloc(sizeof(struct const_def_rec));
-        else
-                const_defs = (struct const_def_rec *)realloc(const_defs,
-                                                             (const_defs_nr + 1) * sizeof(struct const_def_rec));
-
-        const_defs[const_defs_nr].name = name;
-        const_defs[const_defs_nr].val = *val;
-        ++const_defs_nr;
-}
-
-static val_t *
-find_constant(char *name)
-{
-        int i;
-        for (i = 0; i < const_defs_nr; i++) {
-                if (!strcmp(const_defs[i].name, name)) {
-                        free(name);
-                        return &const_defs[i].val;
-                }
-        }
-
-        return NULL;
-}
-
-
-
-
-#define INTERN_ASSERT(name, id) { int zid = intern_id(name); if (zid != id) fprintf(stderr, "[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n", name, zid, id); error_flag = 1; }
-
-extern FILE *magic_frontend_in;
-
-int
-magic_init(char *conffile) // must be called after itemdb initialisation
-{
-        int error_flag = 0;
-
-        magic_conf.vars_nr = 0;
-        magic_conf.var_name = (char **)malloc(1);
-        magic_conf.vars = (val_t *)malloc(1);
-
-        magic_conf.obscure_chance = 95;
-        magic_conf.min_casttime = 100;
-
-        magic_conf.spells_nr = 0;
-        CREATE(magic_conf.spells, spell_t *, 1);
-
-        magic_conf.anchors_nr = 0;
-        CREATE(magic_conf.anchors, teleport_anchor_t *, 1);
-
-        INTERN_ASSERT("min_casttime", VAR_MIN_CASTTIME);
-        INTERN_ASSERT("obscure_chance", VAR_OBSCURE_CHANCE);
-        INTERN_ASSERT("caster", VAR_CASTER);
-        INTERN_ASSERT("spellpower", VAR_SPELLPOWER);
-        INTERN_ASSERT("self_spell", VAR_SPELL);
-        INTERN_ASSERT("self_invocation", VAR_INVOCATION);
-        INTERN_ASSERT("target", VAR_TARGET);
-        INTERN_ASSERT("script_target", VAR_SCRIPTTARGET);
-        INTERN_ASSERT("location", VAR_LOCATION);
-
-        magic_frontend_in = fopen(conffile, "r");
-        if (!magic_frontend_in) {
-                fprintf(stderr, "[magic-conf] Magic configuration file `%s' not found -> no magic.\n", conffile);
-                return 0;
-        }
-        magic_frontend_parse();
-
-        if (magic_conf.vars[VAR_MIN_CASTTIME].ty == TY_INT)
-                magic_conf.min_casttime = magic_conf.vars[VAR_MIN_CASTTIME].v.v_int;
-
-        if (magic_conf.vars[VAR_OBSCURE_CHANCE].ty == TY_INT)
-                magic_conf.obscure_chance = magic_conf.vars[VAR_OBSCURE_CHANCE].v.v_int;
-
-        printf("[magic-conf] Magic initialised; obscure at %d%%.  %d spells, %d teleport anchors.\n",
-               magic_conf.obscure_chance, magic_conf.spells_nr, magic_conf.anchors_nr);
-
-        if (procs)
-                free(procs);
-        return error_flag;
-}
-
-extern int magic_frontend_lineno;
-
-static void
-magic_frontend_error(const char *msg)
-{
-    fprintf(stderr, "[magic-conf] Parse error: %s at line %d\n", msg, magic_frontend_lineno);
-    failed_flag = 1;
-}
diff --git a/src/map/magic-interpreter-parser.ypp b/src/map/magic-interpreter-parser.ypp
new file mode 100644
index 0000000..2648be9
--- /dev/null
+++ b/src/map/magic-interpreter-parser.ypp
@@ -0,0 +1,1089 @@
+%{
+#include "magic-interpreter.hpp"
+#include "magic-expr.hpp"
+#include <stdarg.h>
+
+magic_conf_t magic_conf;
+
+static int
+intern_id(const char *id_name);
+
+
+static expr_t *
+fun_expr(const char *name, int args_nr, expr_t **args, int line, int column);
+
+static expr_t *
+dot_expr(expr_t *lhs, int id);
+
+#define BIN_EXPR(x, name, arg1, arg2, line, column) { expr_t *e[2]; e[0] = arg1; e[1] = arg2; x = fun_expr(name, 2, e, line, column); }
+
+static int failed_flag = 0;
+
+static void
+magic_frontend_error(const char *msg);
+
+static void
+fail(int line, int column, const char *fmt, ...);
+
+static spell_t *
+new_spell(spellguard_t *guard);
+
+static spellguard_t *
+spellguard_implication(spellguard_t *a, spellguard_t *b);
+
+static spellguard_t *
+new_spellguard(int ty);
+
+static effect_t *
+new_effect(int ty);
+
+static effect_t *
+set_effect_continuation(effect_t *src, effect_t *continuation);
+
+static void
+add_spell(spell_t *spell, int line_nr);
+
+static void
+add_teleport_anchor(teleport_anchor_t *anchor, int line_nr);
+
+static effect_t *
+op_effect(char *name, int args_nr, expr_t **args, int line, int column);
+
+int
+magic_frontend_lex(void);
+
+static void
+install_proc(proc_t *proc);
+
+static effect_t *
+call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column);
+
+static void
+bind_constant(char *name, val_t *val, int line_nr);
+
+static val_t *
+find_constant(char *name);
+
+
+%}
+
+%name-prefix="magic_frontend_"
+
+%locations
+
+%union {
+    int i;
+    char *s;
+    int op;
+    magic_conf_t *magic_conf;
+    val_t value;
+    expr_t *expr;
+    e_location_t location;
+    e_area_t area;
+    args_rec_t arg_list;
+    struct { int letdefs_nr; letdef_t *letdefs; } letdefs;
+    spell_t *spell;
+    struct { int id, ty; } spellarg_def;
+    letdef_t vardef;
+    spellguard_t *spellguard;
+    component_t *components;
+    struct {int id, count; } component;
+    effect_t *effect;
+    proc_t *proc;
+};
+
+%expect 7
+
+%token <i> INT
+%token <s> STRING
+%token <s> ID
+%token <i> DIR
+
+%token '='
+%token '<'
+%token '>'
+%token '+'
+%token '-'
+%token '*'
+%token '/'
+%token '%'
+%token '@'
+%token ','
+%token '.'
+%token ':'
+%token ';'
+%token '|'
+%token '['
+%token ']'
+%token '&'
+%token '^'
+
+%token CONST
+%token PROCEDURE
+%token CALL
+%token SILENT
+%token LOCAL
+%token NONMAGIC
+%token SHL
+%token SHR
+%token EQ
+%token NEQ
+%token GTE
+%token LTE
+%token ANDAND
+%token OROR
+%token <s> SCRIPT_DATA
+%token TO
+%token TOWARDS
+%token TELEPORT_ANCHOR
+%token SPELL
+%token LET
+%token IN
+%token END
+%token DARROW
+%token STRING_TY
+%token REQUIRE
+%token CATALYSTS
+%token COMPONENTS
+%token MANA
+%token CASTTIME
+%token SKIP
+%token ABORT
+%token BREAK
+%token EFFECT
+%token ATEND
+%token ATTRIGGER
+%token PC_F
+%token NPC_F
+%token MOB_F
+%token ENTITY_F
+%token TARGET_F
+%token IF
+%token THEN
+%token ELSE
+%token FOREACH
+%token FOR
+%token DO
+%token SLEEP
+
+%type <value> value
+%type <location> location
+%type <area> area
+%type <arg_list> arg_list
+%type <arg_list> arg_list_ne
+%type <letdefs> defs
+%type <spell> spelldef
+%type <spellarg_def> argopt
+%type <vardef> def
+%type <spellguard> spellbody_list
+%type <spellguard> spellbody
+%type <spellguard> spellguard
+%type <spellguard> spellguard_list
+%type <spellguard> prereq
+%type <component> item
+%type <components> items
+%type <components> item_list
+%type <i> item_name
+%type <i> selection;
+%type <effect> effect
+%type <effect> effect_list
+%type <effect> maybe_trigger
+%type <effect> maybe_end
+%type <i> spell_flags;
+
+%type <expr> expr
+%type <i> arg_ty
+%type <proc> proc_formals_list
+%type <proc> proc_formals_list_ne
+
+%left OROR
+%left ANDAND
+%left '<' '>' GTE LTE NEQ EQ
+%left '+' '-'
+%left '*' '/' '%'
+%left SHL SHR '&' '^' '|'
+%right '='
+%left OR
+%left DARROW
+%left '.'
+
+%%
+
+spellconf		: /* empty */
+                          {}
+                        | spellconf_option semicolons spellconf
+                          {}
+			;
+
+
+semicolons		: /* empty */
+			  {}
+                        | semicolons ';'
+                          {}
+			;
+
+
+proc_formals_list	: /* empty  */
+                          { CREATE ($$, proc_t, 1); }
+			| proc_formals_list_ne
+                          { $$ = $1; }
+			;
+
+proc_formals_list_ne	: ID
+                          { CREATE ($$, proc_t, 1);
+                            $$->args_nr = 1;
+                            $$->args = (int*)malloc(sizeof(int));
+                            $$->args[0] = intern_id($1);
+                          }
+			| proc_formals_list_ne ',' ID
+                          { $$ = $1;
+                            $$->args = (int*)realloc($$->args, sizeof(int) * (1 + $$->args_nr));
+                            $$->args[$$->args_nr++] = intern_id($3);
+                          }
+			;
+
+spellconf_option	: ID '=' expr
+			  {
+                            int var_id;
+                            if (find_constant($1)) {
+                                    fail(@1.first_line, 0, "Attempt to redefine constant `%s' as global\n", $1);
+                                    free($1);
+                            } else {
+                                    var_id = intern_id($1);
+                                    magic_eval(&magic_default_env, &magic_conf.vars[var_id], $3);
+                            }
+                          }
+			| CONST ID '=' expr
+			  {
+                            val_t var;
+                            magic_eval(&magic_default_env, &var, $4);
+                            bind_constant($2, &var, @1.first_line);
+                          }
+                        | TELEPORT_ANCHOR ID ':' expr '=' expr
+                          {
+                              teleport_anchor_t *anchor;
+                              CREATE (anchor, teleport_anchor_t, 1);
+                              anchor->name = $2;
+                              anchor->invocation = magic_eval_str(&magic_default_env, $4);
+                              anchor->location = $6;
+
+                              if (!failed_flag)
+                                  add_teleport_anchor(anchor, @1.first_line);
+                              else
+                                  free(anchor);
+                              failed_flag = 0;
+                          }
+			| PROCEDURE ID '(' proc_formals_list ')' '=' effect_list
+                          {
+                              proc_t *proc = $4;
+                              proc->name = $2;
+                              proc->body = $7;
+                              if (!failed_flag)
+                                  install_proc(proc);
+                              failed_flag = 0;
+                          }
+                        | spell_flags SPELL ID argopt ':' expr '=' spelldef
+                          { spell_t *spell = $8;
+                            spell->name = $3;
+                            spell->invocation = magic_eval_str(&magic_default_env, $6);
+                            spell->arg = $4.id;
+                            spell->spellarg_ty = $4.ty;
+                            spell->flags = $1;
+                            if (!failed_flag)
+                                add_spell(spell, @1.first_line);
+                            failed_flag = 0;
+                          }
+
+spell_flags		: /* empty */
+				{ $$ = 0; }
+			| LOCAL spell_flags
+                        	{ if ($2 & SPELL_FLAG_LOCAL)
+                                        fail(@1.first_line, @1.first_column, "`LOCAL' specified more than once");
+                                   $$ = $2 | SPELL_FLAG_LOCAL;
+                                }
+			| NONMAGIC spell_flags
+                        	{ if ($2 & SPELL_FLAG_NONMAGIC)
+                                        fail(@1.first_line, @1.first_column, "`NONMAGIC' specified more than once");
+                                   $$ = $2 | SPELL_FLAG_NONMAGIC;
+                                }
+			| SILENT spell_flags
+                        	{ if ($2 & SPELL_FLAG_SILENT)
+                                        fail(@1.first_line, @1.first_column, "`SILENT' specified more than once");
+                                   $$ = $2 | SPELL_FLAG_SILENT;
+                                }
+
+
+argopt			: /* empty */
+                          { $$.ty = SPELLARG_NONE; }
+                        | '(' ID ':' arg_ty ')'
+                          { $$.id = intern_id($2);
+                            $$.ty = $4; }
+                        ;
+
+
+arg_ty                  : PC_F
+                          { $$ = SPELLARG_PC; }
+                        | STRING_TY
+                          { $$ = SPELLARG_STRING; }
+                        ;
+
+
+value			: DIR
+				{ $$.ty = TY_DIR;
+                                  $$.v.v_int = $1; }
+			| INT
+				{ $$.ty = TY_INT;
+                                  $$.v.v_int = $1; }
+			| STRING
+				{ $$.ty = TY_STRING;
+                                  $$.v.v_string = $1; }
+			;
+
+
+expr			: value
+				{ $$ = magic_new_expr(EXPR_VAL);
+                                  $$->e.e_val = $1; }
+			| ID
+				{
+                                        val_t *val;
+                                        if ((val = find_constant($1))) {
+                                                $$ = magic_new_expr(EXPR_VAL);
+                                                $$->e.e_val = *val;
+                                        } else {
+                                                $$ = magic_new_expr(EXPR_ID);
+                                                $$->e.e_id = intern_id($1);
+                                        }
+                                }
+			| area
+				{ $$ = magic_new_expr(EXPR_AREA);
+                                  $$->e.e_area = $1; }
+			| expr '+' expr
+	                        { BIN_EXPR($$, "+", $1, $3, @1.first_line, @1.first_column); }
+			| expr '-' expr
+	                        { BIN_EXPR($$, "-", $1, $3, @1.first_line, @1.first_column); }
+			| expr '*' expr
+	                        { BIN_EXPR($$, "*", $1, $3, @1.first_line, @1.first_column); }
+			| expr '%' expr
+	                        { BIN_EXPR($$, "%", $1, $3, @1.first_line, @1.first_column); }
+			| expr '/' expr
+	                        { BIN_EXPR($$, "/", $1, $3, @1.first_line, @1.first_column); }
+			| expr '<' expr
+	                        { BIN_EXPR($$, ">", $3, $1, @1.first_line, @1.first_column); }
+			| expr '>' expr
+	                        { BIN_EXPR($$, ">", $1, $3, @1.first_line, @1.first_column); }
+			| expr '&' expr
+	                        { BIN_EXPR($$, "&", $1, $3, @1.first_line, @1.first_column); }
+			| expr '^' expr
+	                        { BIN_EXPR($$, "^", $1, $3, @1.first_line, @1.first_column); }
+			| expr '|' expr
+	                        { BIN_EXPR($$, "|", $1, $3, @1.first_line, @1.first_column); }
+			| expr SHL expr
+	                        { BIN_EXPR($$, "<<", $1, $3, @1.first_line, @1.first_column); }
+			| expr SHR expr
+	                        { BIN_EXPR($$, ">>", $1, $3, @1.first_line, @1.first_column); }
+			| expr LTE expr
+	                        { BIN_EXPR($$, ">=", $3, $1, @1.first_line, @1.first_column); }
+			| expr GTE expr
+	                        { BIN_EXPR($$, ">=", $1, $3, @1.first_line, @1.first_column); }
+			| expr ANDAND expr
+	                        { BIN_EXPR($$, "&&", $1, $3, @1.first_line, @1.first_column); }
+			| expr OROR expr
+	                        { BIN_EXPR($$, "||", $1, $3, @1.first_line, @1.first_column); }
+			| expr EQ expr
+	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
+			| expr '=' expr
+	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column); }
+			| expr NEQ expr
+	                        { BIN_EXPR($$, "=", $1, $3, @1.first_line, @1.first_column);
+                                  $$ = fun_expr("not", 1, &$$, @1.first_line, @1.first_column); }
+			| ID '(' arg_list ')'
+                        	{ $$ = fun_expr($1, $3.args_nr, $3.args, @1.first_line, @1.first_column);
+                                  if ($3.args)
+                                          free($3.args);
+                                  free($1); }
+			| '(' expr ')'
+                        	{ $$ = $2; }
+			| expr '.' ID
+                        	{ $$ = dot_expr($1, intern_id($3)); }
+			;
+
+arg_list		: /* empty */
+				{ $$.args_nr = 0; }
+			| arg_list_ne
+				{ $$ = $1; }
+			;
+
+
+arg_list_ne		: expr
+				{ CREATE($$.args, expr_t *, 1);
+                                  $$.args_nr = 1;
+                                  $$.args[0] = $1;
+                                }
+			| arg_list_ne ',' expr
+                        	{ RECREATE($$.args, expr_t *, 1 + $$.args_nr);
+                                  $$.args[$$.args_nr++] = $3;
+                                }
+			;
+
+
+location		: '@' '(' expr ',' expr ',' expr ')'
+				{ $$.m = $3; $$.x = $5; $$.y = $7; }
+			;
+
+area			: location
+				{ $$.ty = AREA_LOCATION;
+                                  $$.a.a_loc = $1;
+				}
+			| location '@' '+' '(' expr ',' expr ')'
+				{ $$.ty = AREA_RECT;
+                                  $$.a.a_rect.loc = $1;
+                                  $$.a.a_rect.width = $5;
+                                  $$.a.a_rect.height = $7;
+                                }
+			| location TOWARDS expr ':' '(' expr ',' expr ')'
+				{ $$.ty = AREA_BAR;
+                                  $$.a.a_bar.loc = $1;
+                                  $$.a.a_bar.width = $6;
+                                  $$.a.a_bar.depth = $8;
+                                  $$.a.a_bar.dir = $3;
+                                }
+			;
+
+
+spelldef		: spellbody_list
+                                {  $$ = new_spell($1); }
+			| LET defs IN spellbody_list
+                                {  $$ = new_spell($4);
+                                   $$->letdefs_nr = $2.letdefs_nr;
+                                   $$->letdefs = $2.letdefs;
+                                   $$->spellguard = $4;
+                                }
+			;
+
+
+defs			: semicolons
+				{ $$.letdefs_nr = 0;
+                                  CREATE($$.letdefs, letdef_t, 1);
+                                }
+			| defs def semicolons
+	                        { $$ = $1;
+                                  $$.letdefs_nr++;
+                                  RECREATE ($$.letdefs, letdef_t, $$.letdefs_nr);
+                                  $$.letdefs[$1.letdefs_nr] = $2;
+                                }
+                        ;
+
+
+def			: ID '=' expr
+				{
+                                        if (find_constant($1)) {
+                                                fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' as LET-bound variable.\n", $1);
+                                                free($1);
+                                        } else {
+                                                $$.id = intern_id($1);
+                                                $$.expr = $3;
+                                        }
+                                }
+			;
+
+
+spellbody_list		: spellbody
+				{ $$ = $1; }
+			| spellbody '|' spellbody_list
+                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
+                                  sg->next = $1;
+                                  sg->s.s_alt = $3;
+                                  $$ = sg;
+                                }
+			;
+
+
+spellbody		: spellguard DARROW spellbody
+				{ $$ = spellguard_implication($1, $3); }
+			| '(' spellbody_list ')'
+                        	{ $$ = $2; }
+			| EFFECT effect_list maybe_trigger maybe_end
+                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_EFFECT);
+                                  sg->s.s_effect.effect = $2;
+                                  sg->s.s_effect.at_trigger = $3;
+                                  sg->s.s_effect.at_end = $4;
+                                  $$ = sg;
+                                }
+			;
+
+
+maybe_trigger		: /* empty */
+				{ $$ = NULL; }
+			| ATTRIGGER effect_list
+				{ $$ = $2; }
+			;
+
+
+maybe_end		: /* empty */
+				{ $$ = NULL; }
+			| ATEND effect_list
+				{ $$ = $2; }
+			;
+
+
+spellguard		: prereq
+				{ $$ = $1; }
+			| spellguard OR spellguard
+                        	{ spellguard_t *sg = new_spellguard(SPELLGUARD_CHOICE);
+                                  sg->next = $1;
+                                  sg->s.s_alt = $3;
+                                  $$ = sg;
+                                }
+			| '(' spellguard_list ')'
+                        	{ $$ = $2; }
+			;
+
+
+spellguard_list		: spellguard
+				{ $$ = $1; }
+			| spellguard ',' spellguard_list
+                        	{ $$ = spellguard_implication ($1, $3); }
+			;
+
+
+prereq			: REQUIRE expr
+				{ $$ = new_spellguard(SPELLGUARD_CONDITION);
+                                  $$->s.s_condition = $2;
+                                }
+			| CATALYSTS items
+				{ $$ = new_spellguard(SPELLGUARD_CATALYSTS);
+                                  $$->s.s_catalysts = $2;
+                                }
+			| COMPONENTS items
+				{ $$ = new_spellguard(SPELLGUARD_COMPONENTS);
+                                  $$->s.s_components = $2;
+                                }
+			| MANA expr
+				{ $$ = new_spellguard(SPELLGUARD_MANA);
+                                  $$->s.s_mana = $2;
+                                }
+			| CASTTIME expr
+				{ $$ = new_spellguard(SPELLGUARD_CASTTIME);
+                                  $$->s.s_casttime = $2;
+                                }
+			;
+
+
+items			: '[' item_list ']'
+				{ $$ = $2; }
+			;
+
+
+item_list		: item
+				{ $$ = NULL;
+                                  magic_add_component(&$$, $1.id, $1.count);
+                                }
+			| item_list ',' item
+				{ $$ = $1;
+                                  magic_add_component(&$$, $3.id, $3.count);
+                                }
+			;
+
+
+item			: INT '*' item_name
+				{ $$.id = $3; $$.count = $1; }
+			| item_name
+				{ $$.id = $1; $$.count = 1; }
+			;
+
+
+item_name		: STRING
+				{ struct item_data *item = itemdb_searchname($1);
+                                  if (!item) {
+                                          fail (@1.first_line, @1.first_column, "Unknown item `%s'\n", $1);
+                                          $$ = 0;
+                                  } else
+                                          $$ = item->nameid;
+                                  free ($1);
+                                }
+			| INT
+				{ $$ = $1; }
+			;
+
+
+selection		: PC_F
+				{ $$ = FOREACH_FILTER_PC; }
+			| MOB_F
+				{ $$ = FOREACH_FILTER_MOB; }
+			| ENTITY_F
+				{ $$ = FOREACH_FILTER_ENTITY; }
+			| SPELL
+				{ $$ = FOREACH_FILTER_SPELL; }
+			| TARGET_F
+				{ $$ = FOREACH_FILTER_TARGET; }
+			| NPC_F
+				{ $$ = FOREACH_FILTER_NPC; }
+			;
+
+
+effect			: '(' effect_list ')'
+				{ $$ = $2; }
+			| SKIP ';'
+                        	{ $$ = new_effect(EFFECT_SKIP); }
+			| ABORT ';'
+                        	{ $$ = new_effect(EFFECT_ABORT); }
+			| END ';'
+                        	{ $$ = new_effect(EFFECT_END); }
+			| BREAK ';'
+                        	{ $$ = new_effect(EFFECT_BREAK); }
+			| ID '=' expr ';'
+                        	{
+                                        if (find_constant($1)) {
+                                                fail(@1.first_line, @1.first_column, "Attempt to re-define constant `%s' in assignment.", $1);
+                                                free($1);
+                                        } else {
+                                                $$ = new_effect(EFFECT_ASSIGN);
+                                                $$->e.e_assign.id = intern_id($1);
+                                                $$->e.e_assign.expr = $3;
+                                        }
+                                }
+			| FOREACH selection ID IN expr DO effect
+                        	{ $$ = new_effect(EFFECT_FOREACH);
+                                  $$->e.e_foreach.id = intern_id($3);
+                                  $$->e.e_foreach.area = $5;
+                                  $$->e.e_foreach.body = $7;
+                                  $$->e.e_foreach.filter = $2;
+                                }
+			| FOR ID '=' expr TO expr DO effect
+                        	{ $$ = new_effect(EFFECT_FOR);
+                                  $$->e.e_for.id = intern_id($2);
+                                  $$->e.e_for.start = $4;
+                                  $$->e.e_for.stop = $6;
+                                  $$->e.e_for.body = $8;
+                                }
+			| IF expr THEN effect ELSE effect
+                        	{ $$ = new_effect(EFFECT_IF);
+                                  $$->e.e_if.cond = $2;
+                                  $$->e.e_if.true_branch = $4;
+                                  $$->e.e_if.false_branch = $6;
+                                }
+			| IF expr THEN effect
+                        	{ $$ = new_effect(EFFECT_IF);
+                                  $$->e.e_if.cond = $2;
+                                  $$->e.e_if.true_branch = $4;
+                                  $$->e.e_if.false_branch = new_effect(EFFECT_SKIP);
+                                }
+			| SLEEP expr ';'
+                        	{ $$ = new_effect(EFFECT_SLEEP);
+                                  $$->e.e_sleep = $2;
+                                }
+			| ID '(' arg_list ')' ';'
+                                { $$ = op_effect($1, $3.args_nr, $3.args, @1.first_line, @1.first_column);
+                                  free($1);
+                                }
+			| SCRIPT_DATA
+                        	{ $$ = new_effect(EFFECT_SCRIPT);
+                                  $$->e.e_script = parse_script((unsigned char *) $1, @1.first_line);
+                                  free($1);
+                                  if ($$->e.e_script == NULL)
+                                      fail(@1.first_line, @1.first_column, "Failed to compile script\n");
+                                }
+			| CALL ID '(' arg_list ')' ';'
+                        	{ $$ = call_proc($2, $4.args_nr, $4.args, @1.first_line, @1.first_column);
+                                  free($2);
+                                }
+			;
+
+effect_list		: /* empty */
+                        	{ $$ = new_effect(EFFECT_SKIP); }
+			| effect semicolons effect_list
+                        	{ $$ = set_effect_continuation($1, $3); }
+			;
+
+
+%%
+
+/* We do incremental realloc here to store our results.  Since this happens only once
+ * during startup for a relatively manageable set of configs, it should be fine. */
+
+static int
+intern_id(const char *id_name)
+{
+        int i;
+
+        for (i = 0; i < magic_conf.vars_nr; i++)
+                if (!strcmp(id_name, magic_conf.var_name[i])) {
+                        free((char*)id_name);
+                        return i;
+                }
+
+        /* Must add new */
+        i = magic_conf.vars_nr++;
+        RECREATE(magic_conf.var_name, const char *, magic_conf.vars_nr);
+        magic_conf.var_name[i] = id_name;
+        RECREATE(magic_conf.vars, val_t, magic_conf.vars_nr);
+        magic_conf.vars[i].ty = TY_UNDEF;
+
+        return i;
+}
+
+static void
+add_spell(spell_t *spell, int line_nr)
+{
+        int index = magic_conf.spells_nr;
+        int i;
+
+        for (i = 0; i < index; i++) {
+                if (!strcmp(magic_conf.spells[i]->name, spell->name)) {
+                        fail(line_nr, 0, "Attempt to redefine spell `%s'\n", spell->name);
+                        return;
+                }
+                if (!strcmp(magic_conf.spells[i]->invocation, spell->invocation)) {
+                        fail(line_nr, 0, "Attempt to redefine spell invocation `%s' between spells `%s' and `%s'\n",
+                             spell->invocation, magic_conf.spells[i]->name, spell->name);
+                        return;
+                }
+        }
+        magic_conf.spells_nr++;
+
+        RECREATE(magic_conf.spells, spell_t *, magic_conf.spells_nr);
+        magic_conf.spells[index] = spell;
+
+
+}
+
+static void
+add_teleport_anchor(teleport_anchor_t *anchor, int line_nr)
+{
+        int index = magic_conf.anchors_nr;
+        int i;
+
+        for (i = 0; i < index; i++) {
+                if (!strcmp(magic_conf.anchors[i]->name, anchor->name)) {
+                        fail(line_nr, 0, "Attempt to redefine teleport anchor `%s'\n", anchor->name);
+                        return;
+                }
+                if (!strcmp(magic_conf.anchors[i]->invocation, anchor->invocation)) {
+                        fail(line_nr, 0, "Attempt to redefine anchor invocation `%s' between anchors `%s' and `%s'\n",
+                             anchor->invocation, magic_conf.anchors[i]->name, anchor->name);
+                        return;
+                }
+        }
+        magic_conf.anchors_nr++;
+
+        RECREATE(magic_conf.anchors, teleport_anchor_t *, magic_conf.anchors_nr);
+        magic_conf.anchors[index] = anchor;
+}
+
+
+static void
+fail(int line, int column, const char *fmt, ...)
+{
+        va_list ap;
+        fprintf(stderr, "[magic-init]  L%d:%d: ", line, column);
+        va_start(ap, fmt);
+        vfprintf(stderr, fmt, ap);
+        failed_flag = 1;
+}
+
+static expr_t *
+dot_expr(expr_t *expr, int id)
+{
+        expr_t *retval = magic_new_expr(EXPR_SPELLFIELD);
+        retval->e.e_field.id = id;
+        retval->e.e_field.expr = expr;
+
+        return retval;
+}
+
+static expr_t *
+fun_expr(const char *name, int args_nr, expr_t **args, int line, int column)
+{
+        int id;
+        expr_t *expr;
+        fun_t *fun = magic_get_fun(name, &id);
+
+        if (!fun) {
+                fail(line, column, "Unknown function `%s'\n", name);
+        } else if (strlen(fun->signature) != args_nr) {
+                fail(line, column, "Incorrect number of arguments to function `%s': Expected %d, found %d\n", name, strlen(fun->signature), args_nr);
+                fun = NULL;
+        }
+
+        if (fun) {
+                int i;
+
+                expr = magic_new_expr(EXPR_FUNAPP);
+                expr->e.e_funapp.line_nr = line;
+                expr->e.e_funapp.column = column;
+                expr->e.e_funapp.id = id;
+                expr->e.e_funapp.args_nr = args_nr;
+
+                for (i = 0; i < args_nr; i++)
+                        expr->e.e_funapp.args[i] = args[i];
+        } else { /* failure */
+                expr = magic_new_expr(EXPR_VAL);
+                expr->e.e_val.ty = TY_FAIL;
+        }
+
+        return expr;
+}
+
+static spell_t *
+new_spell(spellguard_t *guard)
+{
+        static int spell_counter = 0;
+
+        spell_t *retval = (spell_t*)calloc(1, sizeof(spell_t));
+        retval->index = ++spell_counter;
+        retval->spellguard = guard;
+        return retval;
+}
+
+static spellguard_t *
+new_spellguard(int ty)
+{
+        spellguard_t *retval = (spellguard_t *)calloc(1, sizeof(spellguard_t));
+        retval->ty = ty;
+        return retval;
+}
+
+static spellguard_t *
+spellguard_implication(spellguard_t *a, spellguard_t *b)
+{
+        spellguard_t *retval = a;
+
+        if (a == b) /* This can happen due to reference sharing:
+                     * e.g.,
+                     *  (R0 -> (R1 | R2)) => (R3)
+                     * yields
+                     *  (R0 -> (R1 -> R3 | R2 -> R3))
+                     *
+                     * So if we now add => R4 to that, we want
+                     *  (R0 -> (R1 -> R3 -> R4 | R2 -> R3 -> R4))
+                     *
+                     * but we only need to add it once, because the R3 reference is shared.
+                    */
+                return retval;
+
+                /* If the premise is a disjunction, b is the continuation of _all_ branches */
+        if (a->ty == SPELLGUARD_CHOICE)
+                spellguard_implication(a->s.s_alt, b);
+        if (a->next)
+                spellguard_implication(a->next, b);
+        else
+                a->next = b;
+
+
+        return retval;
+}
+
+static effect_t *
+new_effect(int ty)
+{
+        effect_t *effect = (effect_t *) calloc(1, sizeof(effect_t));
+        effect->ty = ty;
+        return effect;
+}
+
+static effect_t *
+set_effect_continuation(effect_t *src, effect_t *continuation)
+{
+        effect_t *retval = src;
+        /* This function is completely analogous to `spellguard_implication' above; read the control flow implications above first before pondering it. */
+
+        if (src == continuation)
+                return retval;
+
+        /* For FOR and FOREACH, we use special stack handlers and thus don't have to set
+         * the continuation.  It's only IF that we need to handle in this fashion. */
+        if (src->ty == EFFECT_IF) {
+                set_effect_continuation(src->e.e_if.true_branch, continuation);
+                set_effect_continuation(src->e.e_if.false_branch, continuation);
+        }
+        if (src->next)
+                set_effect_continuation(src->next, continuation);
+        else
+                src->next = continuation;
+
+        return retval;
+}
+
+static effect_t *
+op_effect(char *name, int args_nr, expr_t **args, int line, int column)
+{
+        int id;
+        effect_t *effect;
+        op_t *op = magic_get_op(name, &id);
+
+        if (!op)
+                fail(line, column, "Unknown operation `%s'\n", name);
+        else if (strlen(op->signature) != args_nr) {
+                fail(line, column, "Incorrect number of arguments to operation `%s': Expected %d, found %d\n", name, strlen(op->signature), args_nr);
+                op = NULL;
+        }
+
+        if (op) {
+                int i;
+
+                effect = new_effect(EFFECT_OP);
+                effect->e.e_op.line_nr = line;
+                effect->e.e_op.column = column;
+                effect->e.e_op.id = id;
+                effect->e.e_op.args_nr = args_nr;
+
+                for (i = 0; i < args_nr; i++)
+                        effect->e.e_op.args[i] = args[i];
+        } else /* failure */
+                effect = new_effect(EFFECT_SKIP);
+
+        return effect;
+}
+
+
+proc_t *procs = NULL;
+int procs_nr = 0;
+
+// I think this is a memory leak, or undefined behavior
+static void
+install_proc(proc_t *proc)
+{
+        if (!procs) {
+                procs = proc;
+                procs_nr = 1;
+        } else {
+                RECREATE (procs, proc_t, 1 + procs_nr);
+                procs[procs_nr++] = *proc;
+        }
+}
+
+static effect_t *
+call_proc(char *name, int args_nr, expr_t **args, int line_nr, int column)
+{
+        proc_t *p = NULL;
+        int i;
+        effect_t *retval;
+
+        for (i = 0; i < procs_nr; i++)
+                if (!strcmp(procs[i].name, name)) {
+                        p = &procs[i];
+                        break;
+                }
+
+        if (!p) {
+                fail(line_nr, column, "Unknown procedure `%s'\n", name);
+                return new_effect(EFFECT_SKIP);
+        }
+
+        if (p->args_nr != args_nr) {
+                fail(line_nr, column, "Procedure %s/%d invoked with %d parameters\n", name, p->args_nr, args_nr);
+                return new_effect(EFFECT_SKIP);
+        }
+
+        retval = new_effect(EFFECT_CALL);
+        retval->e.e_call.body = p->body;
+        retval->e.e_call.args_nr = args_nr;
+        retval->e.e_call.formals = p->args;
+        retval->e.e_call.actuals = args;
+        return retval;
+}
+
+struct const_def_rec {
+        char *name;
+        val_t val;
+} *const_defs = NULL;
+
+int const_defs_nr = 0;
+
+static void
+bind_constant(char *name, val_t *val, int line_nr)
+{
+        if (find_constant(name)) {
+                fail(line_nr, 0, "Redefinition of constant `%s'\n", name);
+                return;
+        }
+
+        if (!const_defs)
+                const_defs = (struct const_def_rec *)malloc(sizeof(struct const_def_rec));
+        else
+                const_defs = (struct const_def_rec *)realloc(const_defs,
+                                                             (const_defs_nr + 1) * sizeof(struct const_def_rec));
+
+        const_defs[const_defs_nr].name = name;
+        const_defs[const_defs_nr].val = *val;
+        ++const_defs_nr;
+}
+
+static val_t *
+find_constant(char *name)
+{
+        int i;
+        for (i = 0; i < const_defs_nr; i++) {
+                if (!strcmp(const_defs[i].name, name)) {
+                        free(name);
+                        return &const_defs[i].val;
+                }
+        }
+
+        return NULL;
+}
+
+
+
+
+#define INTERN_ASSERT(name, id) { int zid = intern_id(name); if (zid != id) fprintf(stderr, "[magic-conf] INTERNAL ERROR: Builtin special var %s interned to %d, not %d as it should be!\n", name, zid, id); error_flag = 1; }
+
+extern FILE *magic_frontend_in;
+
+int
+magic_init(char *conffile) // must be called after itemdb initialisation
+{
+        int error_flag = 0;
+
+        magic_conf.vars_nr = 0;
+        magic_conf.var_name = (char **)malloc(1);
+        magic_conf.vars = (val_t *)malloc(1);
+
+        magic_conf.obscure_chance = 95;
+        magic_conf.min_casttime = 100;
+
+        magic_conf.spells_nr = 0;
+        CREATE(magic_conf.spells, spell_t *, 1);
+
+        magic_conf.anchors_nr = 0;
+        CREATE(magic_conf.anchors, teleport_anchor_t *, 1);
+
+        INTERN_ASSERT("min_casttime", VAR_MIN_CASTTIME);
+        INTERN_ASSERT("obscure_chance", VAR_OBSCURE_CHANCE);
+        INTERN_ASSERT("caster", VAR_CASTER);
+        INTERN_ASSERT("spellpower", VAR_SPELLPOWER);
+        INTERN_ASSERT("self_spell", VAR_SPELL);
+        INTERN_ASSERT("self_invocation", VAR_INVOCATION);
+        INTERN_ASSERT("target", VAR_TARGET);
+        INTERN_ASSERT("script_target", VAR_SCRIPTTARGET);
+        INTERN_ASSERT("location", VAR_LOCATION);
+
+        magic_frontend_in = fopen(conffile, "r");
+        if (!magic_frontend_in) {
+                fprintf(stderr, "[magic-conf] Magic configuration file `%s' not found -> no magic.\n", conffile);
+                return 0;
+        }
+        magic_frontend_parse();
+
+        if (magic_conf.vars[VAR_MIN_CASTTIME].ty == TY_INT)
+                magic_conf.min_casttime = magic_conf.vars[VAR_MIN_CASTTIME].v.v_int;
+
+        if (magic_conf.vars[VAR_OBSCURE_CHANCE].ty == TY_INT)
+                magic_conf.obscure_chance = magic_conf.vars[VAR_OBSCURE_CHANCE].v.v_int;
+
+        printf("[magic-conf] Magic initialised; obscure at %d%%.  %d spells, %d teleport anchors.\n",
+               magic_conf.obscure_chance, magic_conf.spells_nr, magic_conf.anchors_nr);
+
+        if (procs)
+                free(procs);
+        return error_flag;
+}
+
+extern int magic_frontend_lineno;
+
+static void
+magic_frontend_error(const char *msg)
+{
+    fprintf(stderr, "[magic-conf] Parse error: %s at line %d\n", msg, magic_frontend_lineno);
+    failed_flag = 1;
+}
diff --git a/src/map/magic-interpreter.h b/src/map/magic-interpreter.h
deleted file mode 100644
index 0b4b73c..0000000
--- a/src/map/magic-interpreter.h
+++ /dev/null
@@ -1,500 +0,0 @@
-/* Magic interpreter */
-
-#ifndef MAGIC_INTERPRETER_H
-#define MAGIC_INTERPRETER_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "../common/nullpo.h"
-
-#include "battle.h"
-#include "chat.h"
-#include "chrif.h"
-#include "clif.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "magic.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "pc.h"
-#include "party.h"
-#include "script.h"
-#include "skill.h"
-#include "storage.h"
-#include "trade.h"
-
-#include "../common/timer.h"
-#include "../common/socket.h"
-
-#define SPELLARG_NONE	0       /* No spell parameter */
-#define SPELLARG_PC	1           /* Spell parameter describes pc (defaults to self) */
-#define SPELLARG_STRING	2       /* Spell parameter describes pc (defaults to self) */
-
-/* ------ */
-/* Values */
-/* ------ */
-
-#define TY_UNDEF	0
-#define TY_INT		1
-#define TY_DIR		2
-#define TY_STRING	3
-#define TY_ENTITY	5
-#define TY_LOCATION	6
-#define TY_AREA		7
-#define TY_SPELL	8
-#define TY_INVOCATION	9
-#define TY_FAIL		127
-
-#define DIR_S	0
-#define DIR_SW	1
-#define DIR_W	2
-#define DIR_NW	3
-#define DIR_N	4
-#define DIR_NE	5
-#define DIR_E	6
-#define DIR_SE	7
-
-struct expr;
-struct val;
-struct location;
-struct area;
-struct spell;
-struct invocation;
-
-typedef struct location
-{
-    int  m;
-    int  x, y;
-} location_t;
-
-#define AREA_LOCATION	0
-#define AREA_UNION	1
-#define AREA_RECT	2
-#define AREA_BAR	3
-
-typedef struct area
-{
-    union a
-    {
-        location_t a_loc;
-        struct
-        {
-            location_t loc;
-            int  width, depth, dir;
-        } a_bar;
-        struct
-        {
-            location_t loc;
-            int  width, height;
-        } a_rect;
-        struct area *a_union[2];
-    } a;
-    int  size;
-    unsigned char ty;
-} area_t;
-
-typedef struct val
-{
-    union v
-    {
-        int  v_int;
-        char *v_string;
-        entity_t *v_entity;     /* Used ONLY during operation/function invocation; otherwise we use v_int */
-        area_t *v_area;
-        location_t v_location;
-        struct invocation *v_invocation;    /* Used ONLY during operation/function invocation; otherwise we use v_int */
-        struct spell *v_spell;
-    } v;
-    unsigned char ty;
-} val_t;
-
-/* ----------- */
-/* Expressions */
-/* ----------- */
-
-#define MAX_ARGS 7              /* Max. # of args used in builtin primitive functions */
-
-#define EXPR_VAL	0
-#define EXPR_LOCATION	1
-#define EXPR_AREA	2
-#define EXPR_FUNAPP	3
-#define EXPR_ID		4
-#define EXPR_SPELLFIELD	5
-
-typedef struct e_location
-{
-    struct expr *m, *x, *y;
-} e_location_t;
-
-typedef struct e_area
-{
-    union a0
-    {
-        e_location_t a_loc;
-        struct
-        {
-            e_location_t loc;
-            struct expr *width, *depth, *dir;
-        } a_bar;
-        struct
-        {
-            e_location_t loc;
-            struct expr *width, *height;
-        } a_rect;
-        struct e_area *a_union[2];
-    } a;
-    unsigned char ty;
-} e_area_t;
-
-typedef struct expr
-{
-    union e
-    {
-        val_t e_val;
-        e_location_t e_location;
-        e_area_t e_area;
-        struct
-        {
-            int  id, line_nr, column;
-            int  args_nr;
-            struct expr *args[MAX_ARGS];
-        } e_funapp;
-        int  e_id;
-        struct
-        {
-            struct expr *expr;
-            int  id;
-        } e_field;
-    } e;
-    unsigned char ty;
-} expr_t;
-
-/* ------- */
-/* Effects */
-/* ------- */
-
-#define EFFECT_SKIP	0
-#define EFFECT_ABORT	1
-#define EFFECT_ASSIGN	2
-#define EFFECT_FOREACH	3
-#define EFFECT_FOR	4
-#define EFFECT_IF	5
-#define EFFECT_SLEEP	6
-#define EFFECT_SCRIPT	7
-#define EFFECT_BREAK	8
-#define EFFECT_OP	9
-#define EFFECT_END	10
-#define EFFECT_CALL	11
-
-#define FOREACH_FILTER_MOB	1
-#define FOREACH_FILTER_PC	2
-#define FOREACH_FILTER_ENTITY	3
-#define FOREACH_FILTER_TARGET	4
-#define FOREACH_FILTER_SPELL	5
-#define FOREACH_FILTER_NPC	6
-
-typedef struct effect
-{
-    struct effect *next;
-    union e0
-    {
-        struct
-        {
-            int  id;
-            expr_t *expr;
-        } e_assign;
-        struct
-        {
-            int  id;
-            expr_t *area;
-            struct effect *body;
-            unsigned char filter;
-        } e_foreach;
-        struct
-        {
-            int  id;
-            expr_t *start, *stop;
-            struct effect *body;
-        } e_for;
-        struct
-        {
-            expr_t *cond;
-            struct effect *true_branch, *false_branch;
-        } e_if;
-        expr_t *e_sleep;        /* sleep time */
-        unsigned char *e_script;
-        struct
-        {
-            int  id;
-            int  args_nr;
-            int  line_nr, column;
-            expr_t *args[MAX_ARGS];
-        } e_op;
-        struct
-        {
-            int  args_nr, *formals;
-            expr_t **actuals;
-            struct effect *body;
-        } e_call;
-    } e;
-    unsigned char ty;
-} effect_t;
-
-/* ---------- */
-/* Components */
-/* ---------- */
-
-typedef struct component
-{
-    struct component *next;
-    int  item_id;
-    int  count;
-} component_t;
-
-/* ----------- */
-/* Spellguards */
-/* ----------- */
-
-#define SPELLGUARD_CONDITION	0
-#define SPELLGUARD_COMPONENTS	1
-#define SPELLGUARD_CATALYSTS	2
-#define SPELLGUARD_CHOICE	3
-#define SPELLGUARD_MANA		4
-#define SPELLGUARD_CASTTIME	5
-#define SPELLGUARD_EFFECT	6
-
-typedef struct effect_set
-{
-    effect_t *effect, *at_trigger, *at_end;
-} effect_set_t;
-
-typedef struct spellguard
-{
-    struct spellguard *next;
-    union s
-    {
-        expr_t *s_condition;
-        expr_t *s_mana;
-        expr_t *s_casttime;
-        component_t *s_components;
-        component_t *s_catalysts;
-        struct spellguard *s_alt;   /* either `next' or `s.s_alt' */
-        effect_set_t s_effect;
-    } s;
-    unsigned char ty;
-} spellguard_t;
-
-/* ------ */
-/* Spells */
-/* ------ */
-
-typedef struct letdef
-{
-    int  id;
-    expr_t *expr;
-} letdef_t;
-
-#define SPELL_FLAG_LOCAL	(1 << 0)    // spell associated not with caster but with place
-#define SPELL_FLAG_SILENT	(1 << 1)    // spell invocation never uttered
-#define SPELL_FLAG_NONMAGIC	(1 << 2)    // `magic word' only:  don't require spellcasting ability
-
-typedef struct spell
-{
-    char *name;
-    char *invocation;
-    int  index;                 // Relative location in the definitions file
-    int  flags;
-    int  arg;
-    int  spellarg_ty;
-
-    int  letdefs_nr;
-    letdef_t *letdefs;
-
-    spellguard_t *spellguard;
-} spell_t;
-
-/* ------- */
-/* Anchors */
-/* ------- */
-
-typedef struct teleport_anchor
-{
-    char *name;
-    char *invocation;
-    expr_t *location;
-} teleport_anchor_t;
-
-/* ------------------- */
-/* The big config blob */
-/* ------------------- */
-
-typedef struct
-{
-    int  vars_nr;
-    const char **var_name;
-    val_t *vars;                /* Initial assignments, if any, or NULL */
-
-    int  obscure_chance;
-    int  min_casttime;
-
-    int  spells_nr;
-    spell_t **spells;
-
-    int  anchors_nr;            /* NEGATIVE iff we have sorted the anchors */
-    teleport_anchor_t **anchors;
-} magic_conf_t;
-
-/* Execution environment */
-
-#define VAR_MIN_CASTTIME	0
-#define VAR_OBSCURE_CHANCE	1
-#define VAR_CASTER		2
-#define VAR_SPELLPOWER		3
-#define VAR_SPELL		4
-#define VAR_INVOCATION		5
-#define VAR_TARGET		6
-#define VAR_SCRIPTTARGET	7
-#define VAR_LOCATION		8
-
-struct magic_config;
-
-typedef struct env
-{
-    magic_conf_t *base_env;
-    val_t *vars;
-} env_t;
-
-#define MAX_STACK_SIZE 32
-
-#define CONT_STACK_FOREACH	0
-#define CONT_STACK_FOR		1
-#define CONT_STACK_PROC		2
-
-typedef struct cont_activation_record
-{
-    effect_t *return_location;
-    union c
-    {
-        struct
-        {
-            int  id, ty;
-            effect_t *body;
-            int  entities_nr;
-            int *entities;
-            int  index;
-        } c_foreach;
-        struct
-        {
-            int  id;
-            effect_t *body;
-            int  current;
-            int  stop;
-        } c_for;
-        struct
-        {
-            int  args_nr, *formals;
-            val_t *old_actuals;
-        } c_proc;
-    } c;
-    unsigned char ty;
-} cont_activation_record_t;
-
-typedef struct status_change_ref
-{
-    int  sc_type;
-    int  bl_id;
-} status_change_ref_t;
-
-#define INVOCATION_FLAG_BOUND		(1 << 0)    /* Bound directly to the caster (i.e., ignore its location) */
-#define INVOCATION_FLAG_ABORTED		(1 << 1)    /* Used `abort' to terminate */
-#define INVOCATION_FLAG_STOPATTACK	(1 << 2)    /* On magical attacks:  if we run out of steam, stop attacking altogether */
-
-typedef struct invocation
-{
-    struct block_list bl;
-
-    struct invocation *next_invocation; /* used for spells directly associated with a caster: they form a singly-linked list */
-    int  flags;
-
-    env_t *env;
-    spell_t *spell;
-    int  caster;                /* this is the person who originally invoked the spell */
-    int  subject;               /* when this person dies, the spell dies with it */
-
-    int  timer;                 /* spell timer, if any */
-
-    int  stack_size;
-    cont_activation_record_t stack[MAX_STACK_SIZE];
-
-    int  script_pos;            /* Script position; if nonzero, resume the script we were running. */
-    effect_t *current_effect;
-    effect_t *trigger_effect;   /* If non-NULL, this is used to spawn a cloned effect based on the same environment */
-    effect_t *end_effect;       /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */
-
-    /* Status change references:  for status change updates, keep track of whom we updated where */
-    int  status_change_refs_nr;
-    status_change_ref_t *status_change_refs;
-
-} invocation_t;
-
-extern magic_conf_t magic_conf; /* Global magic conf */
-extern env_t magic_default_env; /* Fake default environment */
-
-/**
- * Adds a component selection to a component holder (which may initially be NULL)
- */
-void magic_add_component (component_t ** component_holder, int id, int count);
-
-teleport_anchor_t *magic_find_anchor (char *name);
-
-/**
- * The parameter `param' must have been dynamically allocated; ownership is transferred to the resultant env_t.
- */
-env_t *spell_create_env (magic_conf_t * conf, spell_t * spell,
-                         character_t * caster, int spellpower, char *param);
-
-void magic_free_env (env_t * env);
-
-/**
- * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components)
- */
-effect_set_t *spell_trigger (spell_t * spell, character_t * caster,
-                             env_t * env, int *near_miss);
-
-invocation_t *spell_instantiate (effect_set_t * effect, env_t * env);
-
-/**
- * Bind a spell to a subject (this is a no-op for `local' spells).
- */
-void spell_bind (character_t * subject, invocation_t * invocation);
-
-int                             // 1 on failure
-     spell_unbind (character_t * subject, invocation_t * invocation);
-
-/**
- * Clones a spell to run the at_effect field
- */
-invocation_t *spell_clone_effect (invocation_t * source);
-
-spell_t *magic_find_spell (char *invocation);
-
-/* The following is used only by the parser: */
-typedef struct args_rec
-{
-    int  args_nr;
-    expr_t **args;
-} args_rec_t;
-
-typedef struct
-{
-    char *name;
-    int  args_nr;
-    int *args;
-    effect_t *body;
-} proc_t;
-
-#endif /* !defined (MAGIC_INTERPRETER_H) */
diff --git a/src/map/magic-interpreter.hpp b/src/map/magic-interpreter.hpp
new file mode 100644
index 0000000..e040975
--- /dev/null
+++ b/src/map/magic-interpreter.hpp
@@ -0,0 +1,500 @@
+/* Magic interpreter */
+
+#ifndef MAGIC_INTERPRETER_HPP
+#define MAGIC_INTERPRETER_HPP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "../common/nullpo.hpp"
+
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "magic.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "party.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+#include "trade.hpp"
+
+#include "../common/timer.hpp"
+#include "../common/socket.hpp"
+
+#define SPELLARG_NONE	0       /* No spell parameter */
+#define SPELLARG_PC	1           /* Spell parameter describes pc (defaults to self) */
+#define SPELLARG_STRING	2       /* Spell parameter describes pc (defaults to self) */
+
+/* ------ */
+/* Values */
+/* ------ */
+
+#define TY_UNDEF	0
+#define TY_INT		1
+#define TY_DIR		2
+#define TY_STRING	3
+#define TY_ENTITY	5
+#define TY_LOCATION	6
+#define TY_AREA		7
+#define TY_SPELL	8
+#define TY_INVOCATION	9
+#define TY_FAIL		127
+
+#define DIR_S	0
+#define DIR_SW	1
+#define DIR_W	2
+#define DIR_NW	3
+#define DIR_N	4
+#define DIR_NE	5
+#define DIR_E	6
+#define DIR_SE	7
+
+struct expr;
+struct val;
+struct location;
+struct area;
+struct spell;
+struct invocation;
+
+typedef struct location
+{
+    int  m;
+    int  x, y;
+} location_t;
+
+#define AREA_LOCATION	0
+#define AREA_UNION	1
+#define AREA_RECT	2
+#define AREA_BAR	3
+
+typedef struct area
+{
+    union a
+    {
+        location_t a_loc;
+        struct
+        {
+            location_t loc;
+            int  width, depth, dir;
+        } a_bar;
+        struct
+        {
+            location_t loc;
+            int  width, height;
+        } a_rect;
+        struct area *a_union[2];
+    } a;
+    int  size;
+    unsigned char ty;
+} area_t;
+
+typedef struct val
+{
+    union v
+    {
+        int  v_int;
+        char *v_string;
+        entity_t *v_entity;     /* Used ONLY during operation/function invocation; otherwise we use v_int */
+        area_t *v_area;
+        location_t v_location;
+        struct invocation *v_invocation;    /* Used ONLY during operation/function invocation; otherwise we use v_int */
+        struct spell *v_spell;
+    } v;
+    unsigned char ty;
+} val_t;
+
+/* ----------- */
+/* Expressions */
+/* ----------- */
+
+#define MAX_ARGS 7              /* Max. # of args used in builtin primitive functions */
+
+#define EXPR_VAL	0
+#define EXPR_LOCATION	1
+#define EXPR_AREA	2
+#define EXPR_FUNAPP	3
+#define EXPR_ID		4
+#define EXPR_SPELLFIELD	5
+
+typedef struct e_location
+{
+    struct expr *m, *x, *y;
+} e_location_t;
+
+typedef struct e_area
+{
+    union a0
+    {
+        e_location_t a_loc;
+        struct
+        {
+            e_location_t loc;
+            struct expr *width, *depth, *dir;
+        } a_bar;
+        struct
+        {
+            e_location_t loc;
+            struct expr *width, *height;
+        } a_rect;
+        struct e_area *a_union[2];
+    } a;
+    unsigned char ty;
+} e_area_t;
+
+typedef struct expr
+{
+    union e
+    {
+        val_t e_val;
+        e_location_t e_location;
+        e_area_t e_area;
+        struct
+        {
+            int  id, line_nr, column;
+            int  args_nr;
+            struct expr *args[MAX_ARGS];
+        } e_funapp;
+        int  e_id;
+        struct
+        {
+            struct expr *expr;
+            int  id;
+        } e_field;
+    } e;
+    unsigned char ty;
+} expr_t;
+
+/* ------- */
+/* Effects */
+/* ------- */
+
+#define EFFECT_SKIP	0
+#define EFFECT_ABORT	1
+#define EFFECT_ASSIGN	2
+#define EFFECT_FOREACH	3
+#define EFFECT_FOR	4
+#define EFFECT_IF	5
+#define EFFECT_SLEEP	6
+#define EFFECT_SCRIPT	7
+#define EFFECT_BREAK	8
+#define EFFECT_OP	9
+#define EFFECT_END	10
+#define EFFECT_CALL	11
+
+#define FOREACH_FILTER_MOB	1
+#define FOREACH_FILTER_PC	2
+#define FOREACH_FILTER_ENTITY	3
+#define FOREACH_FILTER_TARGET	4
+#define FOREACH_FILTER_SPELL	5
+#define FOREACH_FILTER_NPC	6
+
+typedef struct effect
+{
+    struct effect *next;
+    union e0
+    {
+        struct
+        {
+            int  id;
+            expr_t *expr;
+        } e_assign;
+        struct
+        {
+            int  id;
+            expr_t *area;
+            struct effect *body;
+            unsigned char filter;
+        } e_foreach;
+        struct
+        {
+            int  id;
+            expr_t *start, *stop;
+            struct effect *body;
+        } e_for;
+        struct
+        {
+            expr_t *cond;
+            struct effect *true_branch, *false_branch;
+        } e_if;
+        expr_t *e_sleep;        /* sleep time */
+        unsigned char *e_script;
+        struct
+        {
+            int  id;
+            int  args_nr;
+            int  line_nr, column;
+            expr_t *args[MAX_ARGS];
+        } e_op;
+        struct
+        {
+            int  args_nr, *formals;
+            expr_t **actuals;
+            struct effect *body;
+        } e_call;
+    } e;
+    unsigned char ty;
+} effect_t;
+
+/* ---------- */
+/* Components */
+/* ---------- */
+
+typedef struct component
+{
+    struct component *next;
+    int  item_id;
+    int  count;
+} component_t;
+
+/* ----------- */
+/* Spellguards */
+/* ----------- */
+
+#define SPELLGUARD_CONDITION	0
+#define SPELLGUARD_COMPONENTS	1
+#define SPELLGUARD_CATALYSTS	2
+#define SPELLGUARD_CHOICE	3
+#define SPELLGUARD_MANA		4
+#define SPELLGUARD_CASTTIME	5
+#define SPELLGUARD_EFFECT	6
+
+typedef struct effect_set
+{
+    effect_t *effect, *at_trigger, *at_end;
+} effect_set_t;
+
+typedef struct spellguard
+{
+    struct spellguard *next;
+    union s
+    {
+        expr_t *s_condition;
+        expr_t *s_mana;
+        expr_t *s_casttime;
+        component_t *s_components;
+        component_t *s_catalysts;
+        struct spellguard *s_alt;   /* either `next' or `s.s_alt' */
+        effect_set_t s_effect;
+    } s;
+    unsigned char ty;
+} spellguard_t;
+
+/* ------ */
+/* Spells */
+/* ------ */
+
+typedef struct letdef
+{
+    int  id;
+    expr_t *expr;
+} letdef_t;
+
+#define SPELL_FLAG_LOCAL	(1 << 0)    // spell associated not with caster but with place
+#define SPELL_FLAG_SILENT	(1 << 1)    // spell invocation never uttered
+#define SPELL_FLAG_NONMAGIC	(1 << 2)    // `magic word' only:  don't require spellcasting ability
+
+typedef struct spell
+{
+    char *name;
+    char *invocation;
+    int  index;                 // Relative location in the definitions file
+    int  flags;
+    int  arg;
+    int  spellarg_ty;
+
+    int  letdefs_nr;
+    letdef_t *letdefs;
+
+    spellguard_t *spellguard;
+} spell_t;
+
+/* ------- */
+/* Anchors */
+/* ------- */
+
+typedef struct teleport_anchor
+{
+    char *name;
+    char *invocation;
+    expr_t *location;
+} teleport_anchor_t;
+
+/* ------------------- */
+/* The big config blob */
+/* ------------------- */
+
+typedef struct
+{
+    int  vars_nr;
+    const char **var_name;
+    val_t *vars;                /* Initial assignments, if any, or NULL */
+
+    int  obscure_chance;
+    int  min_casttime;
+
+    int  spells_nr;
+    spell_t **spells;
+
+    int  anchors_nr;            /* NEGATIVE iff we have sorted the anchors */
+    teleport_anchor_t **anchors;
+} magic_conf_t;
+
+/* Execution environment */
+
+#define VAR_MIN_CASTTIME	0
+#define VAR_OBSCURE_CHANCE	1
+#define VAR_CASTER		2
+#define VAR_SPELLPOWER		3
+#define VAR_SPELL		4
+#define VAR_INVOCATION		5
+#define VAR_TARGET		6
+#define VAR_SCRIPTTARGET	7
+#define VAR_LOCATION		8
+
+struct magic_config;
+
+typedef struct env
+{
+    magic_conf_t *base_env;
+    val_t *vars;
+} env_t;
+
+#define MAX_STACK_SIZE 32
+
+#define CONT_STACK_FOREACH	0
+#define CONT_STACK_FOR		1
+#define CONT_STACK_PROC		2
+
+typedef struct cont_activation_record
+{
+    effect_t *return_location;
+    union c
+    {
+        struct
+        {
+            int  id, ty;
+            effect_t *body;
+            int  entities_nr;
+            int *entities;
+            int  index;
+        } c_foreach;
+        struct
+        {
+            int  id;
+            effect_t *body;
+            int  current;
+            int  stop;
+        } c_for;
+        struct
+        {
+            int  args_nr, *formals;
+            val_t *old_actuals;
+        } c_proc;
+    } c;
+    unsigned char ty;
+} cont_activation_record_t;
+
+typedef struct status_change_ref
+{
+    int  sc_type;
+    int  bl_id;
+} status_change_ref_t;
+
+#define INVOCATION_FLAG_BOUND		(1 << 0)    /* Bound directly to the caster (i.e., ignore its location) */
+#define INVOCATION_FLAG_ABORTED		(1 << 1)    /* Used `abort' to terminate */
+#define INVOCATION_FLAG_STOPATTACK	(1 << 2)    /* On magical attacks:  if we run out of steam, stop attacking altogether */
+
+typedef struct invocation
+{
+    struct block_list bl;
+
+    struct invocation *next_invocation; /* used for spells directly associated with a caster: they form a singly-linked list */
+    int  flags;
+
+    env_t *env;
+    spell_t *spell;
+    int  caster;                /* this is the person who originally invoked the spell */
+    int  subject;               /* when this person dies, the spell dies with it */
+
+    int  timer;                 /* spell timer, if any */
+
+    int  stack_size;
+    cont_activation_record_t stack[MAX_STACK_SIZE];
+
+    int  script_pos;            /* Script position; if nonzero, resume the script we were running. */
+    effect_t *current_effect;
+    effect_t *trigger_effect;   /* If non-NULL, this is used to spawn a cloned effect based on the same environment */
+    effect_t *end_effect;       /* If non-NULL, this is executed when the spell terminates naturally, e.g. when all status changes have run out or all delays are over. */
+
+    /* Status change references:  for status change updates, keep track of whom we updated where */
+    int  status_change_refs_nr;
+    status_change_ref_t *status_change_refs;
+
+} invocation_t;
+
+extern magic_conf_t magic_conf; /* Global magic conf */
+extern env_t magic_default_env; /* Fake default environment */
+
+/**
+ * Adds a component selection to a component holder (which may initially be NULL)
+ */
+void magic_add_component (component_t ** component_holder, int id, int count);
+
+teleport_anchor_t *magic_find_anchor (char *name);
+
+/**
+ * The parameter `param' must have been dynamically allocated; ownership is transferred to the resultant env_t.
+ */
+env_t *spell_create_env (magic_conf_t * conf, spell_t * spell,
+                         character_t * caster, int spellpower, char *param);
+
+void magic_free_env (env_t * env);
+
+/**
+ * near_miss is set to nonzero iff the spell only failed due to ephemereal issues (spell delay in effect, out of mana, out of components)
+ */
+effect_set_t *spell_trigger (spell_t * spell, character_t * caster,
+                             env_t * env, int *near_miss);
+
+invocation_t *spell_instantiate (effect_set_t * effect, env_t * env);
+
+/**
+ * Bind a spell to a subject (this is a no-op for `local' spells).
+ */
+void spell_bind (character_t * subject, invocation_t * invocation);
+
+int                             // 1 on failure
+     spell_unbind (character_t * subject, invocation_t * invocation);
+
+/**
+ * Clones a spell to run the at_effect field
+ */
+invocation_t *spell_clone_effect (invocation_t * source);
+
+spell_t *magic_find_spell (char *invocation);
+
+/* The following is used only by the parser: */
+typedef struct args_rec
+{
+    int  args_nr;
+    expr_t **args;
+} args_rec_t;
+
+typedef struct
+{
+    char *name;
+    int  args_nr;
+    int *args;
+    effect_t *body;
+} proc_t;
+
+#endif /* !defined (MAGIC_INTERPRETER_H) */
diff --git a/src/map/magic-stmt.c b/src/map/magic-stmt.c
deleted file mode 100644
index 5569217..0000000
--- a/src/map/magic-stmt.c
+++ /dev/null
@@ -1,1597 +0,0 @@
-#include "magic-interpreter.h"
-#include "magic-expr.h"
-#include "magic-expr-eval.h"
-#include "magic-interpreter-aux.h"
-
-int
- clif_spawn_fake_npc_for_player (struct map_session_data *sd,
-                                 int fake_npc_id);
-
-#define INVISIBLE_NPC 127       /* used for local spell effects */
-
-//#define DEBUG
-
-#ifdef DEBUG
-static void print_val (val_t * v)
-{
-    switch (v->ty)
-    {
-        case TY_UNDEF:
-            fprintf (stderr, "UNDEF");
-            break;
-        case TY_INT:
-            fprintf (stderr, "%d", v->v.v_int);
-            break;
-        case TY_DIR:
-            fprintf (stderr, "dir%d", v->v.v_int);
-            break;
-        case TY_STRING:
-            fprintf (stderr, "`%s'", v->v.v_string);
-            break;
-        default:
-            fprintf (stderr, "ty%d", v->ty);
-            break;
-    }
-}
-
-static void dump_env (env_t * env)
-{
-    int  i;
-    for (i = 0; i < env->base_env->vars_nr; i++)
-    {
-        val_t *v = &env->vars[i];
-        val_t *bv = &env->base_env->vars[i];
-
-        fprintf (stderr, "%02x %30s ", i, env->base_env->var_name[i]);
-        print_val (v);
-        fprintf (stderr, "\t(");
-        print_val (bv);
-        fprintf (stderr, ")\n");
-    }
-}
-#endif
-
-static void clear_activation_record (cont_activation_record_t * ar)
-{
-    switch (ar->ty)
-    {
-        case CONT_STACK_FOREACH:
-            free (ar->c.c_foreach.entities);
-            break;
-        case CONT_STACK_PROC:
-            free (ar->c.c_proc.old_actuals);
-            break;
-    }
-}
-
-static void
-invocation_timer_callback (timer_id UNUSED, tick_t UNUSED, custom_id_t id, custom_data_t data)
-{
-    invocation_t *invocation = (invocation_t *) map_id2bl (id);
-
-    if (invocation)
-    {
-        invocation->timer = 0;
-        spell_execute (invocation);
-    }
-}
-
-static void clear_stack (invocation_t * invocation)
-{
-    int  i;
-
-    for (i = 0; i < invocation->stack_size; i++)
-        clear_activation_record (&invocation->stack[i]);
-
-    invocation->stack_size = 0;
-}
-
-void spell_free_invocation (invocation_t * invocation)
-{
-    if (invocation->status_change_refs)
-    {
-        free (invocation->status_change_refs);
-        /* The following cleanup shouldn't be necessary, but I've added it to help tracking a certain bug */
-        invocation->status_change_refs = NULL;
-        invocation->status_change_refs_nr = 0;
-    }
-
-    if (invocation->flags & INVOCATION_FLAG_BOUND)
-    {
-        entity_t *e = map_id2bl (invocation->subject);
-        if (e && e->type == BL_PC)
-            spell_unbind ((character_t *) e, invocation);
-    }
-
-    clear_stack (invocation);
-
-    if (invocation->timer)
-        delete_timer (invocation->timer, invocation_timer_callback);
-
-    magic_free_env (invocation->env);
-
-    map_delblock (&invocation->bl);
-    map_delobject (invocation->bl.id, BL_SPELL);    // also frees the object
-//        free(invocation);
-}
-
-static void
-char_set_weapon_icon (character_t * subject, int count, int icon, int look)
-{
-    const int old_icon = subject->attack_spell_icon_override;
-
-    subject->attack_spell_icon_override = icon;
-    subject->attack_spell_look_override = look;
-
-    if (old_icon && old_icon != icon)
-        clif_status_change (&subject->bl, old_icon, 0);
-
-    clif_fixpcpos (subject);
-    if (count)
-    {
-        clif_changelook (&subject->bl, LOOK_WEAPON, look);
-        if (icon)
-            clif_status_change (&subject->bl, icon, 1);
-    }
-    else
-    {
-        /* Set it to `normal' */
-        clif_changelook (&subject->bl, LOOK_WEAPON, subject->status.weapon);
-    }
-}
-
-static void char_set_attack_info (character_t * subject, int speed, int range)
-{
-    subject->attack_spell_delay = speed;
-    subject->attack_spell_range = range;
-
-    if (speed == 0)
-    {
-        pc_calcstatus (subject, 1);
-        clif_updatestatus (subject, SP_ASPD);
-        clif_updatestatus (subject, SP_ATTACKRANGE);
-    }
-    else
-    {
-        subject->aspd = speed;
-        clif_updatestatus (subject, SP_ASPD);
-        clif_updatestatus (subject, SP_ATTACKRANGE);
-    }
-}
-
-void magic_stop_completely (character_t * c)
-{
-    int  i;
-    // Zap all status change references to spells
-    for (i = 0; i < MAX_STATUSCHANGE; i++)
-        c->sc_data[i].spell_invocation = 0;
-
-    while (c->active_spells)
-        spell_free_invocation (c->active_spells);
-
-    if (c->attack_spell_override)
-    {
-        invocation_t *attack_spell =
-            (invocation_t *) map_id2bl (c->attack_spell_override);
-        if (attack_spell)
-            spell_free_invocation (attack_spell);
-        c->attack_spell_override = 0;
-        char_set_weapon_icon (c, 0, 0, 0);
-        char_set_attack_info (c, 0, 0);
-    }
-}
-
-/* Spell execution has finished normally or we have been notified by a finished skill timer */
-static void try_to_finish_invocation (invocation_t * invocation)
-{
-    if (invocation->status_change_refs_nr == 0 && !invocation->current_effect)
-    {
-        if (invocation->end_effect)
-        {
-            clear_stack (invocation);
-            invocation->current_effect = invocation->end_effect;
-            invocation->end_effect = NULL;
-            spell_execute (invocation);
-        }
-        else
-            spell_free_invocation (invocation);
-    }
-}
-
-static int trigger_spell (int subject, int spell)
-{
-    invocation_t *invocation = (invocation_t *) map_id2bl (spell);
-
-    if (!invocation)
-        return 0;
-
-    invocation = spell_clone_effect (invocation);
-
-    spell_bind ((character_t *) map_id2bl (subject), invocation);
-    magic_clear_var (&invocation->env->vars[VAR_CASTER]);
-    invocation->env->vars[VAR_CASTER].ty = TY_ENTITY;
-    invocation->env->vars[VAR_CASTER].v.v_int = subject;
-
-    return invocation->bl.id;
-}
-
-static void entity_warp (entity_t * target, int destm, int destx, int desty);
-
-static void char_update (character_t * character)
-{
-    entity_warp ((entity_t *) character, character->bl.m, character->bl.x,
-                 character->bl.y);
-}
-
-static void timer_callback_effect (timer_id UNUSED, tick_t UNUSED, custom_id_t id, custom_data_t data)
-{
-    entity_t *target = map_id2bl (id);
-    if (target)
-        clif_misceffect (target, data);
-}
-
-static void entity_effect (entity_t * entity, int effect_nr, int delay)
-{
-    add_timer (gettick () + delay,
-               &timer_callback_effect, entity->id, effect_nr);
-}
-
-void magic_unshroud (character_t * other_char)
-{
-    other_char->state.shroud_active = 0;
-    // Now warp the caster out of and back into here to refresh everyone's display
-    char_update (other_char);
-    clif_displaymessage (other_char->fd, "Your shroud has been dispelled!");
-//        entity_effect(&other_char->bl, MAGIC_EFFECT_REVEAL);
-}
-
-static void
-timer_callback_effect_npc_delete (timer_id UNUSED, tick_t odelay,
-                                  custom_id_t npc_id, custom_data_t UNUSED)
-{
-    struct npc_data *effect_npc = (struct npc_data *) map_id2bl (npc_id);
-    npc_free (effect_npc);
-}
-
-static struct npc_data *local_spell_effect (int m, int x, int y, int effect,
-                                            int tdelay)
-{
-    int  delay = 30000;         /* 1 minute should be enough for all interesting spell effects, I hope */
-    struct npc_data *effect_npc = npc_spawn_text (m, x, y,
-                                                  INVISIBLE_NPC, "", "?");
-    int  effect_npc_id = effect_npc->bl.id;
-
-    entity_effect (&effect_npc->bl, effect, tdelay);
-    add_timer (gettick () + delay,
-               timer_callback_effect_npc_delete, effect_npc_id, 0);
-
-    return effect_npc;
-}
-
-static int op_sfx (env_t * env, int args_nr, val_t * args)
-{
-    int  delay = ARGINT (2);
-
-    if (TY (0) == TY_ENTITY)
-    {
-        entity_effect (ARGENTITY (0), ARGINT (1), delay);
-    }
-    else if (TY (0) == TY_LOCATION)
-    {
-        local_spell_effect (ARGLOCATION (0).m,
-                            ARGLOCATION (0).x,
-                            ARGLOCATION (0).y, ARGINT (1), delay);
-    }
-    else
-        return 1;
-
-    return 0;
-}
-
-static int op_instaheal (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *caster = (VAR (VAR_CASTER).ty == TY_ENTITY)
-        ? map_id2bl (VAR (VAR_CASTER).v.v_int) : NULL;
-    entity_t *subject = ARGENTITY (0);
-    if (!caster)
-        caster = subject;
-
-    if (caster->type == BL_PC && subject->type == BL_PC)
-    {
-        character_t *caster_pc = (character_t *) caster;
-        character_t *subject_pc = (character_t *) subject;
-        MAP_LOG_PC (caster_pc, "SPELLHEAL-INSTA PC%d FOR %d",
-                    subject_pc->status.char_id, ARGINT (1));
-    }
-
-    battle_heal (caster, subject, ARGINT (1), ARGINT (2), 0);
-    return 0;
-}
-
-static int op_itemheal (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-    if (subject->type == BL_PC)
-    {
-        pc_itemheal ((struct map_session_data *) subject,
-                     ARGINT (1), ARGINT (2));
-    }
-    else
-        return op_instaheal (env, args_nr, args);
-
-    return 0;
-}
-
-#define SHROUD_HIDE_NAME_TALKING_FLAG	(1 << 0)
-#define SHROUD_DISAPPEAR_ON_PICKUP_FLAG	(1 << 1)
-#define SHROUD_DISAPPEAR_ON_TALK_FLAG	(1 << 2)
-
-#define ARGCHAR(n) (ARGENTITY(n)->type == BL_PC) ? (character_t *)(ARGENTITY(n)) : NULL
-
-static int op_shroud (env_t * env, int args_nr, val_t * args)
-{
-    character_t *subject = ARGCHAR (0);
-    int  arg = ARGINT (1);
-
-    if (!subject)
-        return 0;
-
-    subject->state.shroud_active = 1;
-    subject->state.shroud_hides_name_talking =
-        (arg & SHROUD_HIDE_NAME_TALKING_FLAG) != 0;
-    subject->state.shroud_disappears_on_pickup =
-        (arg & SHROUD_DISAPPEAR_ON_PICKUP_FLAG) != 0;
-    subject->state.shroud_disappears_on_talk =
-        (arg & SHROUD_DISAPPEAR_ON_TALK_FLAG) != 0;
-    return 0;
-}
-
-static int op_reveal (env_t * env, int args_nr, val_t * args)
-{
-    character_t *subject = ARGCHAR (0);
-
-    if (subject && subject->state.shroud_active)
-        magic_unshroud (subject);
-
-    return 0;
-}
-
-static int op_message (env_t * env, int args_nr, val_t * args)
-{
-    character_t *subject = ARGCHAR (0);
-
-    if (subject)
-        clif_displaymessage (subject->fd, ARGSTR (1));
-
-    return 0;
-}
-
-static void
-timer_callback_kill_npc (timer_id UNUSED, tick_t odelay, custom_id_t npc_id,
-                         custom_data_t data)
-{
-    struct npc_data *npc = (struct npc_data *) map_id2bl (npc_id);
-    if (npc)
-        npc_free (npc);
-}
-
-static int op_messenger_npc (env_t * env, int args_nr, val_t * args)
-{
-    struct npc_data *npc;
-    location_t *loc = &ARGLOCATION (0);
-
-    npc = npc_spawn_text (loc->m, loc->x, loc->y,
-                          ARGINT (1), ARGSTR (2), ARGSTR (3));
-
-    add_timer (gettick () + ARGINT (4),
-               &timer_callback_kill_npc, npc->bl.id, 0);
-
-    return 0;
-}
-
-static void entity_warp (entity_t * target, int destm, int destx, int desty)
-{
-    if (target->type == BL_PC || target->type == BL_MOB)
-    {
-
-        switch (target->type)
-        {
-            case BL_PC:
-            {
-                character_t *character = (character_t *) target;
-                char *map_name;
-                clif_clearchar_area (&character->bl, 3);
-                map_delblock (&character->bl);
-                character->bl.x = destx;
-                character->bl.y = desty;
-                character->bl.m = destm;
-
-                pc_touch_all_relevant_npcs (character);
-
-                // Note that touching NPCs may have triggered warping and thereby updated x and y:
-                map_name = map[character->bl.m].name;
-
-                // Warp part #1: update relevant data, interrupt trading etc.:
-                pc_setpos (character, map_name, character->bl.x, character->bl.y, 0);
-                // Warp part #2: now notify the client
-                clif_changemap (character, map_name,
-                                character->bl.x, character->bl.y);
-                break;
-            }
-            case BL_MOB:
-                target->x = destx;
-                target->y = desty;
-                target->m = destm;
-                clif_fixmobpos ((struct mob_data *) target);
-                break;
-        }
-    }
-}
-
-static int op_move (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-    int  dir = ARGDIR (1);
-
-    int  newx = subject->x + heading_x[dir];
-    int  newy = subject->y + heading_y[dir];
-
-    if (!map_is_solid (subject->m, newx, newy))
-        entity_warp (subject, subject->m, newx, newy);
-
-    return 0;
-}
-
-static int op_warp (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-    location_t *loc = &ARGLOCATION (1);
-
-    entity_warp (subject, loc->m, loc->x, loc->y);
-
-    return 0;
-}
-
-static int op_banish (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-
-    if (subject->type == BL_MOB)
-    {
-        struct mob_data *mob = (struct mob_data *) subject;
-
-        if (mob->mode & MOB_MODE_SUMMONED)
-            mob_catch_delete (mob, 3);
-    }
-
-    return 0;
-}
-
-static void
-record_status_change (invocation_t * invocation, int bl_id, int sc_id)
-{
-    int  index = invocation->status_change_refs_nr++;
-    status_change_ref_t *cr;
-
-    RECREATE (invocation->status_change_refs, status_change_ref_t, invocation->status_change_refs_nr);
-
-    cr = &invocation->status_change_refs[index];
-
-    cr->sc_type = sc_id;
-    cr->bl_id = bl_id;
-}
-
-static int op_status_change (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-    int  invocation_id = VAR (VAR_INVOCATION).ty == TY_INVOCATION
-        ? VAR (VAR_INVOCATION).v.v_int : 0;
-    invocation_t *invocation = (invocation_t *) map_id2bl (invocation_id);
-
-    skill_status_effect (subject, ARGINT (1), ARGINT (2), ARGINT (3),
-                         ARGINT (4), ARGINT (5), ARGINT (6), 0,
-                         invocation_id);
-
-    if (invocation && subject->type == BL_PC)
-        record_status_change (invocation, subject->id, ARGINT (1));
-
-    return 0;
-}
-
-static int op_stop_status_change (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *subject = ARGENTITY (0);
-
-    skill_status_change_end (subject, ARGINT (1), -1);
-
-    return 0;
-}
-
-static int op_override_attack (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *psubject = ARGENTITY (0);
-    int  charges = ARGINT (1);
-    int  attack_delay = ARGINT (2);
-    int  attack_range = ARGINT (3);
-    int  icon = ARGINT (4);
-    int  look = ARGINT (5);
-    int  stopattack = ARGINT (6);
-    character_t *subject;
-
-    if (psubject->type != BL_PC)
-        return 0;
-
-    subject = (character_t *) psubject;
-
-    if (subject->attack_spell_override)
-    {
-        invocation_t *old_invocation =
-            (invocation_t *) map_id2bl (subject->attack_spell_override);
-        if (old_invocation)
-            spell_free_invocation (old_invocation);
-    }
-
-    subject->attack_spell_override =
-        trigger_spell (subject->bl.id, VAR (VAR_INVOCATION).v.v_int);
-    subject->attack_spell_charges = charges;
-
-    if (subject->attack_spell_override)
-    {
-        invocation_t *attack_spell =
-            (invocation_t *) map_id2bl (subject->attack_spell_override);
-        if (attack_spell && stopattack)
-            attack_spell->flags |= INVOCATION_FLAG_STOPATTACK;
-
-        char_set_weapon_icon (subject, charges, icon, look);
-        char_set_attack_info (subject, attack_delay, attack_range);
-    }
-
-    return 0;
-}
-
-static int op_create_item (env_t * env, int args_nr, val_t * args)
-{
-    struct item item;
-    entity_t *entity = ARGENTITY (0);
-    character_t *subject;
-    int  stackable;
-    int  count = ARGINT (2);
-    if (count <= 0)
-        return 0;
-
-    if (entity->type == BL_PC)
-        subject = (character_t *) entity;
-    else
-        return 0;
-
-    GET_ARG_ITEM (1, item, stackable);
-
-    if (!stackable)
-        while (count--)
-            pc_additem (subject, &item, 1);
-    else
-        pc_additem (subject, &item, count);
-
-    return 0;
-}
-
-#define AGGRAVATION_MODE_ATTACKS_CASTER(n) 	((n) == 0 || (n) == 2)
-#define AGGRAVATION_MODE_MAKES_AGGRESSIVE(n)	((n) > 0)
-
-static int op_aggravate (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *victim = ARGENTITY (2);
-    int  mode = ARGINT (1);
-    entity_t *target = ARGENTITY (0);
-    struct mob_data *other;
-
-    if (target->type == BL_MOB)
-        other = (struct mob_data *) target;
-    else
-        return 0;
-
-    mob_target (other, victim, battle_get_range (victim));
-
-    if (AGGRAVATION_MODE_MAKES_AGGRESSIVE (mode))
-        other->mode = 0x85 | (other->mode & MOB_SENSIBLE_MASK); /* war */
-
-    if (AGGRAVATION_MODE_ATTACKS_CASTER (mode))
-    {
-        other->target_id = victim->id;
-        other->attacked_id = victim->id;
-    }
-
-    return 0;
-}
-
-#define MONSTER_ATTITUDE_HOSTILE	0
-#define MONSTER_ATTITUDE_FRIENDLY	1
-#define MONSTER_ATTITUDE_SERVANT	2
-#define MONSTER_ATTITUDE_FROZEN		3
-
-static int op_spawn (env_t * env, int args_nr, val_t * args)
-{
-    area_t *area = ARGAREA (0);
-    entity_t *owner_e = ARGENTITY (1);
-    int  monster_id = ARGINT (2);
-    int  monster_attitude = ARGINT (3);
-    int  monster_count = ARGINT (4);
-    int  monster_lifetime = ARGINT (5);
-    int  i;
-
-    character_t *owner = (monster_attitude == MONSTER_ATTITUDE_SERVANT
-                          && owner_e->type ==
-                          BL_PC) ? (character_t *) owner_e : NULL;
-
-    for (i = 0; i < monster_count; i++)
-    {
-        location_t loc;
-        magic_random_location (&loc, area);
-
-        int  mob_id;
-        struct mob_data *mob;
-
-        mob_id = mob_once_spawn (owner, map[loc.m].name, loc.x, loc.y, "--ja--",    // Is that needed?
-                                 monster_id, 1, "");
-
-        mob = (struct mob_data *) map_id2bl (mob_id);
-
-        if (mob)
-        {
-            mob->mode = mob_db[monster_id].mode;
-
-            switch (monster_attitude)
-            {
-
-                case MONSTER_ATTITUDE_SERVANT:
-                    mob->state.special_mob_ai = 1;
-                    mob->mode |= 0x04;
-                    break;
-
-                case MONSTER_ATTITUDE_FRIENDLY:
-                    mob->mode = 0x80 | (mob->mode & 1);
-                    break;
-
-                case MONSTER_ATTITUDE_HOSTILE:
-                    mob->mode = 0x84 | (mob->mode & 1);
-                    if (owner)
-                    {
-                        mob->target_id = owner->bl.id;
-                        mob->attacked_id = owner->bl.id;
-                    }
-                    break;
-
-                case MONSTER_ATTITUDE_FROZEN:
-                    mob->mode = 0;
-                    break;
-            }
-
-            mob->mode |=
-                MOB_MODE_SUMMONED | MOB_MODE_TURNS_AGAINST_BAD_MASTER;
-
-            mob->deletetimer = add_timer (gettick () + monster_lifetime,
-                                          mob_timer_delete, mob_id, 0);
-
-            if (owner)
-            {
-                mob->master_id = owner->bl.id;
-                mob->master_dist = 6;
-            }
-        }
-    }
-
-    return 0;
-}
-
-static char *get_invocation_name (env_t * env)
-{
-    invocation_t *invocation;
-
-    if (VAR (VAR_INVOCATION).ty != TY_INVOCATION)
-        return "?";
-    invocation = (invocation_t *) map_id2bl (VAR (VAR_INVOCATION).v.v_int);
-
-    if (invocation)
-        return invocation->spell->name;
-    else
-        return "??";
-}
-
-static int op_injure (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *caster = ARGENTITY (0);
-    entity_t *target = ARGENTITY (1);
-    int  damage_caused = ARGINT (2);
-    int  mp_damage = ARGINT (3);
-    int  target_hp = battle_get_hp (target);
-    int  mdef = battle_get_mdef (target);
-
-    if (target->type == BL_PC && !map[target->m].flag.pvp && !((character_t *) target)->special_state.killable && (caster->type != BL_PC || !((character_t *) caster)->special_state.killer))
-        return 0;               /* Cannot damage other players outside of pvp */
-
-    if (target != caster)
-    {
-        /* Not protected against own spells */
-        damage_caused = (damage_caused * (100 - mdef)) / 100;
-        mp_damage = (mp_damage * (100 - mdef)) / 100;
-    }
-
-    damage_caused = (damage_caused > target_hp) ? target_hp : damage_caused;
-
-    if (damage_caused < 0)
-        damage_caused = 0;
-
-    // display damage first, because dealing damage may deallocate the target.
-    clif_damage (caster, target, gettick (), 0, 0, damage_caused, 0, 0, 0);
-
-    if (caster->type == BL_PC)
-    {
-        character_t *caster_pc = (character_t *) caster;
-        if (target->type == BL_MOB)
-        {
-            struct mob_data *mob = (struct mob_data *) target;
-
-            MAP_LOG_PC (caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s",
-                        mob->bl.id, mob->mob_class, damage_caused,
-                        get_invocation_name (env));
-        }
-    }
-    battle_damage (caster, target, damage_caused, mp_damage);
-
-    return 0;
-}
-
-static int op_emote (env_t * env, int args_nr, val_t * args)
-{
-    entity_t *victim = ARGENTITY (0);
-    int  emotion = ARGINT (1);
-    clif_emotion (victim, emotion);
-
-    return 0;
-}
-
-static int op_set_script_variable (env_t * env, int args_nr, val_t * args)
-{
-    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-
-    if (!c)
-        return 1;
-
-    pc_setglobalreg (c, ARGSTR (1), ARGINT (2));
-
-    return 0;
-}
-
-static int op_set_hair_colour (env_t * env, int args_nr, val_t * args)
-{
-    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-
-    if (!c)
-        return 1;
-
-    pc_changelook (c, LOOK_HAIR_COLOR, ARGINT (1));
-
-    return 0;
-}
-
-static int op_set_hair_style (env_t * env, int args_nr, val_t * args)
-{
-    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-
-    if (!c)
-        return 1;
-
-    pc_changelook (c, LOOK_HAIR, ARGINT (1));
-
-    return 0;
-}
-
-static int op_drop_item_for (env_t * env, int args_nr, val_t * args)
-{
-    struct item item;
-    int  stackable;
-    location_t *loc = &ARGLOCATION (0);
-    int  count = ARGINT (2);
-    int  time = ARGINT (3);
-    character_t *c = ((args_nr > 4) && (ETY (4) == BL_PC)) ? ARGPC (4) : NULL;
-    int  delay = (args_nr > 5) ? ARGINT (5) : 0;
-    int  delaytime[3] = { delay, delay, delay };
-    character_t *owners[3] = { c, NULL, NULL };
-
-    GET_ARG_ITEM (1, item, stackable);
-
-    if (stackable)
-        map_addflooritem_any (&item, count, loc->m, loc->x, loc->y,
-                              owners, delaytime, time, 0);
-    else
-        while (count-- > 0)
-            map_addflooritem_any (&item, 1, loc->m, loc->x, loc->y,
-                                  owners, delaytime, time, 0);
-
-    return 0;
-}
-
-static int op_gain_exp (env_t * env, int args_nr, val_t * args)
-{
-    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
-
-    if (!c)
-        return 1;
-
-    pc_gainexp_reason (c, ARGINT (1), ARGINT (2), ARGINT (3));
-    return 0;
-}
-
-static op_t operations[] = {
-    {"sfx", ".ii", op_sfx},
-    {"instaheal", "eii", op_instaheal},
-    {"itemheal", "eii", op_itemheal},
-    {"shroud", "ei", op_shroud},
-    {"unshroud", "e", op_reveal},
-    {"message", "es", op_message},
-    {"messenger_npc", "lissi", op_messenger_npc},
-    {"move", "ed", op_move},
-    {"warp", "el", op_warp},
-    {"banish", "e", op_banish},
-    {"status_change", "eiiiiii", op_status_change},
-    {"stop_status_change", "ei", op_stop_status_change},
-    {"override_attack", "eiiiiii", op_override_attack},
-    {"create_item", "e.i", op_create_item},
-    {"aggravate", "eie", op_aggravate},
-    {"spawn", "aeiiii", op_spawn},
-    {"injure", "eeii", op_injure},
-    {"emote", "ei", op_emote},
-    {"set_script_variable", "esi", op_set_script_variable},
-    {"set_hair_colour", "ei", op_set_hair_colour},
-    {"set_hair_style", "ei", op_set_hair_style},
-    {"drop_item", "l.ii", op_drop_item_for},
-    {"drop_item_for", "l.iiei", op_drop_item_for},
-    {"gain_experience", "eiii", op_gain_exp},
-    {NULL, NULL, NULL}
-};
-
-static int operations_sorted = 0;
-static int operation_count;
-
-int compare_operations (const void *lhs, const void *rhs)
-{
-    return strcmp (((op_t *) lhs)->name, ((op_t *) rhs)->name);
-}
-
-op_t *magic_get_op (char *name, int *index)
-{
-    op_t key;
-
-    if (!operations_sorted)
-    {
-        op_t *opc = operations;
-
-        while (opc->name)
-            ++opc;
-
-        operation_count = opc - operations;
-
-        qsort (operations, operation_count, sizeof (op_t),
-               compare_operations);
-        operations_sorted = 1;
-    }
-
-    key.name = name;
-    op_t *op = (op_t *)bsearch (&key, operations, operation_count, sizeof (op_t),
-                        compare_operations);
-
-    if (op && index)
-        *index = op - operations;
-
-    return op;
-}
-
-void
-spell_effect_report_termination (int invocation_id, int bl_id, int sc_id,
-                                 int supplanted)
-{
-    int  i;
-    int  index = -1;
-    invocation_t *invocation = (invocation_t *) map_id2bl (invocation_id);
-
-    if (!invocation || invocation->bl.type != BL_SPELL)
-        return;
-
-    for (i = 0; i < invocation->status_change_refs_nr; i++)
-    {
-        status_change_ref_t *cr = &invocation->status_change_refs[i];
-        if (cr->sc_type == sc_id && cr->bl_id == bl_id)
-        {
-            index = i;
-            break;
-        }
-    }
-
-    if (index == -1)
-    {
-        entity_t *entity = map_id2bl (bl_id);
-        if (entity->type == BL_PC)
-            fprintf (stderr,
-                     "[magic] INTERNAL ERROR: spell-effect-report-termination:  tried to terminate on unexpected bl %d, sc %d\n",
-                     bl_id, sc_id);
-        return;
-    }
-
-    if (index == invocation->status_change_refs_nr - 1)
-        invocation->status_change_refs_nr--;
-    else                        /* Copy last change ref to the one we are deleting */
-        invocation->status_change_refs[index] =
-            invocation->
-            status_change_refs[--invocation->status_change_refs_nr];
-
-    try_to_finish_invocation (invocation);
-}
-
-static effect_t *return_to_stack (invocation_t * invocation)
-{
-    if (!invocation->stack_size)
-        return NULL;
-    else
-    {
-        cont_activation_record_t *ar =
-            invocation->stack + (invocation->stack_size - 1);
-        switch (ar->ty)
-        {
-
-            case CONT_STACK_PROC:
-            {
-                effect_t *ret = ar->return_location;
-                int  i;
-
-                for (i = 0; i < ar->c.c_proc.args_nr; i++)
-                {
-                    val_t *var =
-                        &invocation->env->vars[ar->c.c_proc.formals[i]];
-                    magic_clear_var (var);
-                    *var = ar->c.c_proc.old_actuals[i];
-                }
-
-                clear_activation_record (ar);
-                --invocation->stack_size;
-
-                return ret;
-            }
-
-            case CONT_STACK_FOREACH:
-            {
-                int  entity_id;
-                val_t *var = &invocation->env->vars[ar->c.c_foreach.id];
-
-                do
-                {
-                    if (ar->c.c_foreach.index >= ar->c.c_foreach.entities_nr)
-                    {
-                        effect_t *ret = ar->return_location;
-                        clear_activation_record (ar);
-                        --invocation->stack_size;
-                        return ret;
-                    }
-
-                    entity_id =
-                        ar->c.c_foreach.entities[ar->c.c_foreach.index++];
-                }
-                while (!entity_id || !map_id2bl (entity_id));
-
-                magic_clear_var (var);
-                var->ty = ar->c.c_foreach.ty;
-                var->v.v_int = entity_id;
-
-                return ar->c.c_foreach.body;
-            }
-
-            case CONT_STACK_FOR:
-                if (ar->c.c_for.current > ar->c.c_for.stop)
-                {
-                    effect_t *ret = ar->return_location;
-                    clear_activation_record (ar);
-                    --invocation->stack_size;
-                    return ret;
-                }
-
-                magic_clear_var (&invocation->env->vars[ar->c.c_for.id]);
-                invocation->env->vars[ar->c.c_for.id].ty = TY_INT;
-                invocation->env->vars[ar->c.c_for.id].v.v_int =
-                    ar->c.c_for.current++;
-
-                return ar->c.c_for.body;
-
-            default:
-                fprintf (stderr,
-                         "[magic] INTERNAL ERROR: While executing spell `%s':  stack corruption\n",
-                         invocation->spell->name);
-                return NULL;
-        }
-    }
-}
-
-static cont_activation_record_t *add_stack_entry (invocation_t * invocation,
-                                                  int ty,
-                                                  effect_t * return_location)
-{
-    cont_activation_record_t *ar =
-        invocation->stack + invocation->stack_size++;
-    if (invocation->stack_size >= MAX_STACK_SIZE)
-    {
-        fprintf (stderr,
-                 "[magic] Execution stack size exceeded in spell `%s'; truncating effect\n",
-                 invocation->spell->name);
-        invocation->stack_size--;
-        return NULL;
-    }
-
-    ar->ty = ty;
-    ar->return_location = return_location;
-    return ar;
-}
-
-static int find_entities_in_area_c (entity_t * target, va_list va)
-{
-    int *entities_allocd_p = va_arg (va, int *);
-    int *entities_nr_p = va_arg (va, int *);
-    int **entities_p = va_arg (va, int **);
-    int  filter = va_arg (va, int);
-
-/* The following macro adds an entity to the result list: */
-#define ADD_ENTITY(e)                                                   \
-        if (*entities_nr_p == *entities_allocd_p) {                     \
-                /* Need more space */                                   \
-                (*entities_allocd_p) += 32;                             \
-                RECREATE (*entities_p, int, *entities_allocd_p); \
-        }                                                               \
-        (*entities_p)[(*entities_nr_p)++] = e;
-
-    switch (target->type)
-    {
-
-        case BL_PC:
-            if (filter == FOREACH_FILTER_PC
-                || filter == FOREACH_FILTER_ENTITY
-                || (filter == FOREACH_FILTER_TARGET
-                    && map[target->m].flag.pvp))
-                break;
-            else if (filter == FOREACH_FILTER_SPELL)
-            {                   /* Check all spells bound to the caster */
-                invocation_t *invoc = ((character_t *) target)->active_spells;
-                /* Add all spells locked onto thie PC */
-
-                while (invoc)
-                {
-                    ADD_ENTITY (invoc->bl.id);
-                    invoc = invoc->next_invocation;
-                }
-            }
-            return 0;
-
-        case BL_MOB:
-            if (filter == FOREACH_FILTER_MOB
-                || filter == FOREACH_FILTER_ENTITY
-                || filter == FOREACH_FILTER_TARGET)
-                break;
-            else
-                return 0;
-
-        case BL_SPELL:
-            if (filter == FOREACH_FILTER_SPELL)
-            {
-                invocation_t *invocation = (invocation_t *) target;
-
-                /* Check whether the spell is `bound'-- if so, we'll consider it iff we see the caster (case BL_PC). */
-                if (invocation->flags & INVOCATION_FLAG_BOUND)
-                    return 0;
-                else
-                    break;      /* Add the spell */
-            }
-            else
-                return 0;
-
-        case BL_NPC:
-            if (filter == FOREACH_FILTER_NPC)
-                break;
-            else
-                return 0;
-
-        default:
-            return 0;
-    }
-
-    ADD_ENTITY (target->id);
-#undef ADD_ENTITY
-    return 0;
-}
-
-static void
-find_entities_in_area (area_t * area, int *entities_allocd_p,
-                       int *entities_nr_p, int **entities_p, int filter)
-{
-    switch (area->ty)
-    {
-        case AREA_UNION:
-            find_entities_in_area (area->a.a_union[0], entities_allocd_p,
-                                   entities_nr_p, entities_p, filter);
-            find_entities_in_area (area->a.a_union[1], entities_allocd_p,
-                                   entities_nr_p, entities_p, filter);
-            break;
-
-        default:
-        {
-            int  m, x, y, width, height;
-            magic_area_rect (&m, &x, &y, &width, &height, area);
-            map_foreachinarea (find_entities_in_area_c,
-                               m, x, y, x + width, y + height,
-                               0 /* filter elsewhere */ ,
-                               entities_allocd_p, entities_nr_p, entities_p,
-                               filter);
-        }
-    }
-}
-
-static effect_t *run_foreach (invocation_t * invocation, effect_t * foreach,
-                              effect_t * return_location)
-{
-    val_t area;
-    int  filter = foreach->e.e_foreach.filter;
-    int  id = foreach->e.e_foreach.id;
-    effect_t *body = foreach->e.e_foreach.body;
-
-    magic_eval (invocation->env, &area, foreach->e.e_foreach.area);
-
-    if (area.ty != TY_AREA)
-    {
-        magic_clear_var (&area);
-        fprintf (stderr,
-                 "[magic] Error in spell `%s':  FOREACH loop over non-area\n",
-                 invocation->spell->name);
-        return return_location;
-    }
-    else
-    {
-        cont_activation_record_t *ar =
-            add_stack_entry (invocation, CONT_STACK_FOREACH, return_location);
-        int  entities_allocd = 64;
-        int *entities_collect;
-        int *entities;
-        int *shuffle_board;
-        int  entities_nr = 0;
-        int  i;
-
-        if (!ar)
-            return return_location;
-
-        CREATE (entities_collect, int, entities_allocd);
-
-        find_entities_in_area (area.v.v_area, &entities_allocd, &entities_nr,
-                               &entities_collect, filter);
-
-        /* Now shuffle */
-        CREATE (shuffle_board, int, entities_nr);
-        CREATE (entities, int, entities_nr);
-        for (i = 0; i < entities_nr; i++)
-            shuffle_board[i] = i;
-
-        for (i = entities_nr - 1; i >= 0; i--)
-        {
-            int  random_index = rand () % (i + 1);
-            entities[i] = entities_collect[shuffle_board[random_index]];
-            shuffle_board[random_index] = shuffle_board[i]; // thus, we are guaranteed only to use unused indices
-        }
-
-        free (entities_collect);
-        free (shuffle_board);
-        /* Done shuffling */
-
-        ar->c.c_foreach.id = id;
-        ar->c.c_foreach.body = body;
-        ar->c.c_foreach.index = 0;
-        ar->c.c_foreach.entities_nr = entities_nr;
-        ar->c.c_foreach.entities = entities;
-        ar->c.c_foreach.ty =
-            (filter == FOREACH_FILTER_SPELL) ? TY_INVOCATION : TY_ENTITY;
-
-        magic_clear_var (&area);
-
-        return return_to_stack (invocation);
-    }
-}
-
-static effect_t *run_for (invocation_t * invocation, effect_t * for_,
-                          effect_t * return_location)
-{
-    cont_activation_record_t *ar;
-    int  id = for_->e.e_for.id;
-    val_t start;
-    val_t stop;
-
-    magic_eval (invocation->env, &start, for_->e.e_for.start);
-    magic_eval (invocation->env, &stop, for_->e.e_for.stop);
-
-    if (start.ty != TY_INT || stop.ty != TY_INT)
-    {
-        magic_clear_var (&start);
-        magic_clear_var (&stop);
-        fprintf (stderr,
-                 "[magic] Error in spell `%s':  FOR loop start or stop point is not an integer\n",
-                 invocation->spell->name);
-        return return_location;
-    }
-
-    ar = add_stack_entry (invocation, CONT_STACK_FOR, return_location);
-
-    if (!ar)
-        return return_location;
-
-    ar->c.c_for.id = id;
-    ar->c.c_for.current = start.v.v_int;
-    ar->c.c_for.stop = stop.v.v_int;
-    ar->c.c_for.body = for_->e.e_for.body;
-
-    return return_to_stack (invocation);
-}
-
-static effect_t *run_call (invocation_t * invocation,
-                           effect_t * return_location)
-{
-    effect_t *current = invocation->current_effect;
-    cont_activation_record_t *ar;
-    int  args_nr = current->e.e_call.args_nr;
-    int *formals = current->e.e_call.formals;
-    val_t *old_actuals;
-    CREATE (old_actuals, val_t, args_nr);
-    int  i;
-
-    ar = add_stack_entry (invocation, CONT_STACK_PROC, return_location);
-    ar->c.c_proc.args_nr = args_nr;
-    ar->c.c_proc.formals = formals;
-    ar->c.c_proc.old_actuals = old_actuals;
-    for (i = 0; i < args_nr; i++)
-    {
-        val_t *env_val = &invocation->env->vars[formals[i]];
-        val_t result;
-        magic_copy_var (&old_actuals[i], env_val);
-        magic_eval (invocation->env, &result, current->e.e_call.actuals[i]);
-        *env_val = result;
-    }
-
-    return current->e.e_call.body;
-}
-
-#ifdef DEBUG
-static void print_cfg (int i, effect_t * e)
-{
-    int  j;
-    for (j = 0; j < i; j++)
-        printf ("    ");
-
-    printf ("%p: ", e);
-
-    if (!e)
-    {
-        puts (" -- end --");
-        return;
-    }
-
-    switch (e->ty)
-    {
-        case EFFECT_SKIP:
-            puts ("SKIP");
-            break;
-        case EFFECT_END:
-            puts ("END");
-            break;
-        case EFFECT_ABORT:
-            puts ("ABORT");
-            break;
-        case EFFECT_ASSIGN:
-            puts ("ASSIGN");
-            break;
-        case EFFECT_FOREACH:
-            puts ("FOREACH");
-            print_cfg (i + 1, e->e.e_foreach.body);
-            break;
-        case EFFECT_FOR:
-            puts ("FOR");
-            print_cfg (i + 1, e->e.e_for.body);
-            break;
-        case EFFECT_IF:
-            puts ("IF");
-            for (j = 0; j < i; j++)
-                printf ("    ");
-            puts ("THEN");
-            print_cfg (i + 1, e->e.e_if.true_branch);
-            for (j = 0; j < i; j++)
-                printf ("    ");
-            puts ("ELSE");
-            print_cfg (i + 1, e->e.e_if.false_branch);
-            break;
-        case EFFECT_SLEEP:
-            puts ("SLEEP");
-            break;
-        case EFFECT_SCRIPT:
-            puts ("SCRIPT");
-            break;
-        case EFFECT_BREAK:
-            puts ("BREAK");
-            break;
-        case EFFECT_OP:
-            puts ("OP");
-            break;
-    }
-    print_cfg (i, e->next);
-}
-#endif
-
-/**
- * Execute a spell invocation until we abort, finish, or hit the next `sleep'.
- *
- * Use spell_execute() to automate handling of timers
- *
- * Returns: 0 if finished (all memory is freed implicitly)
- *          >1 if we hit `sleep'; the result is the number of ticks we should sleep for.
- *          -1 if we paused to wait for a user action (via script interaction)
- */
-static int spell_run (invocation_t * invocation, int allow_delete)
-{
-    const int invocation_id = invocation->bl.id;
-#define REFRESH_INVOCATION invocation = (invocation_t *) map_id2bl(invocation_id); if (!invocation) return 0;
-
-#ifdef DEBUG
-    fprintf (stderr, "Resuming execution:  invocation of `%s'\n",
-             invocation->spell->name);
-    print_cfg (1, invocation->current_effect);
-#endif
-    while (invocation->current_effect)
-    {
-        effect_t *e = invocation->current_effect;
-        effect_t *next = e->next;
-        int  i;
-
-#ifdef DEBUG
-        fprintf (stderr, "Next step of type %d\n", e->ty);
-        dump_env (invocation->env);
-#endif
-
-        switch (e->ty)
-        {
-            case EFFECT_SKIP:
-                break;
-
-            case EFFECT_ABORT:
-                invocation->flags |= INVOCATION_FLAG_ABORTED;
-                invocation->end_effect = NULL;
-            case EFFECT_END:
-                clear_stack (invocation);
-                next = NULL;
-                break;
-
-            case EFFECT_ASSIGN:
-                magic_eval (invocation->env,
-                            &invocation->env->vars[e->e.e_assign.id],
-                            e->e.e_assign.expr);
-                break;
-
-            case EFFECT_FOREACH:
-                next = run_foreach (invocation, e, next);
-                break;
-
-            case EFFECT_FOR:
-                next = run_for (invocation, e, next);
-                break;
-
-            case EFFECT_IF:
-                if (magic_eval_int (invocation->env, e->e.e_if.cond))
-                    next = e->e.e_if.true_branch;
-                else
-                    next = e->e.e_if.false_branch;
-                break;
-
-            case EFFECT_SLEEP:
-            {
-                int  sleeptime =
-                    magic_eval_int (invocation->env, e->e.e_sleep);
-                invocation->current_effect = next;
-                if (sleeptime > 0)
-                    return sleeptime;
-                break;
-            }
-
-            case EFFECT_SCRIPT:
-            {
-                character_t *caster =
-                    (character_t *) map_id2bl (invocation->caster);
-                if (caster)
-                {
-                    env_t *env = invocation->env;
-                    character_t *caster =
-                        (character_t *) map_id2bl (invocation->caster);
-                    argrec_t arg[] = { {"@target",.v.i =
-                                        VAR (VAR_TARGET).ty ==
-                                        TY_ENTITY ? 0 : VAR (VAR_TARGET).
-                                        v.v_int}
-                    ,
-                    {"@caster",.v.i = invocation->caster}
-                    ,
-                    {"@caster_name$",.v.s = caster ? caster->status.name : ""}
-                    };
-                    int  message_recipient =
-                        VAR (VAR_SCRIPTTARGET).ty ==
-                        TY_ENTITY ? VAR (VAR_SCRIPTTARGET).
-                        v.v_int : invocation->caster;
-                    character_t *recipient =
-                        (character_t *) map_id2bl (message_recipient);
-
-                    if (recipient->npc_id
-                        && recipient->npc_id != invocation->bl.id)
-                        break;  /* Don't send multiple message boxes at once */
-
-                    if (!invocation->script_pos)    // first time running this script?
-                        clif_spawn_fake_npc_for_player (recipient,
-                                                        invocation->bl.id);
-                    // We have to do this or otherwise the client won't think that it's
-                    // dealing with an NPC
-
-                    int  newpos = run_script_l (e->e.e_script,
-                                                invocation->script_pos,
-                                                message_recipient,
-                                                invocation->bl.id,
-                                                3, arg);
-                    /* Returns the new script position, or -1 once the script is finished */
-                    if (newpos != -1)
-                    {
-                        /* Must set up for continuation */
-                        recipient->npc_id = invocation->bl.id;
-                        recipient->npc_pos = invocation->script_pos = newpos;
-                        return -1;  /* Signal `wait for script' */
-                    }
-                    else
-                        invocation->script_pos = 0;
-                    clif_clearchar_id (invocation->bl.id, 1, caster->fd);
-                }
-                REFRESH_INVOCATION; // Script may have killed the caster
-                break;
-            }
-
-            case EFFECT_BREAK:
-                next = return_to_stack (invocation);
-                break;
-
-            case EFFECT_OP:
-            {
-                op_t *op = &operations[e->e.e_op.id];
-                val_t args[MAX_ARGS];
-
-                for (i = 0; i < e->e.e_op.args_nr; i++)
-                    magic_eval (invocation->env, &args[i], e->e.e_op.args[i]);
-
-                if (!magic_signature_check ("effect", op->name, op->signature,
-                                            e->e.e_op.args_nr, args,
-                                            e->e.e_op.line_nr,
-                                            e->e.e_op.column))
-                    op->op (invocation->env, e->e.e_op.args_nr, args);
-
-                for (i = 0; i < e->e.e_op.args_nr; i++)
-                    magic_clear_var (&args[i]);
-
-                REFRESH_INVOCATION; // Effect may have killed the caster
-                break;
-            }
-
-            case EFFECT_CALL:
-                next = run_call (invocation, next);
-                break;
-
-            default:
-                fprintf (stderr,
-                         "[magic] INTERNAL ERROR: Unknown effect %d\n",
-                         e->ty);
-        }
-
-        if (!next)
-            next = return_to_stack (invocation);
-
-        invocation->current_effect = next;
-    }
-
-    if (allow_delete)
-        try_to_finish_invocation (invocation);
-    return 0;
-#undef REFRESH_INVOCATION
-}
-
-extern void spell_update_location (invocation_t * invocation);
-
-void spell_execute_d (invocation_t * invocation, int allow_deletion)
-{
-    int  delta;
-
-    spell_update_location (invocation);
-    delta = spell_run (invocation, allow_deletion);
-
-    if (delta > 0)
-    {
-        if (invocation->timer)
-        {
-            fprintf (stderr,
-                     "[magic] FATAL ERROR: Trying to add multiple timers to the same spell! Already had timer: %d\n",
-                     invocation->timer);
-            /* *((int *)0x0) = 0; */
-        }
-        invocation->timer = add_timer (gettick () + delta,
-                                       &invocation_timer_callback,
-                                       invocation->bl.id, 0);
-    }
-
-    /* If 0, the script cleaned itself.  If -1 (wait-for-script), we must wait for the user. */
-}
-
-void spell_execute (invocation_t * invocation)
-{
-    spell_execute_d (invocation, 1);
-}
-
-void spell_execute_script (invocation_t * invocation)
-{
-    if (invocation->script_pos)
-        spell_execute_d (invocation, 1);
-    /* Otherwise the script-within-the-spell has been terminated by some other means.
-     * In practice this happens when the script doesn't wait for user input: the client
-     * may still notify the server that it's done.  Without the above check, we'd be
-     * running the same spell twice! */
-}
-
-int spell_attack (int caster_id, int target_id)
-{
-    character_t *caster = (character_t *) map_id2bl (caster_id);
-    invocation_t *invocation;
-    int  stop_attack = 0;
-
-    if (!caster)
-        return 0;
-
-    invocation = (invocation_t *) map_id2bl (caster->attack_spell_override);
-
-    if (invocation && invocation->flags & INVOCATION_FLAG_STOPATTACK)
-        stop_attack = 1;
-
-    if (invocation && caster->attack_spell_charges > 0)
-    {
-        magic_clear_var (&invocation->env->vars[VAR_TARGET]);
-        invocation->env->vars[VAR_TARGET].ty = TY_ENTITY;
-        invocation->env->vars[VAR_TARGET].v.v_int = target_id;
-
-        invocation->current_effect = invocation->trigger_effect;
-        invocation->flags &= ~INVOCATION_FLAG_ABORTED;
-        spell_execute_d (invocation,
-                         0 /* don't delete the invocation if done */ );
-
-        // If the caster died, we need to refresh here:
-        invocation =
-            (invocation_t *) map_id2bl (caster->attack_spell_override);
-
-        if (invocation && !(invocation->flags & INVOCATION_FLAG_ABORTED))   // If we didn't abort:
-            caster->attack_spell_charges--;
-    }
-
-    if (invocation && caster->attack_spell_override != invocation->bl.id)
-    {
-        /* Attack spell changed / was refreshed */
-        // spell_free_invocation(invocation); // [Fate] This would be a double free.
-    }
-    else if (!invocation || caster->attack_spell_charges <= 0)
-    {
-        caster->attack_spell_override = 0;
-        char_set_weapon_icon (caster, 0, 0, 0);
-        char_set_attack_info (caster, 0, 0);
-
-        if (stop_attack)
-            pc_stopattack (caster);
-
-        if (invocation)
-            spell_free_invocation (invocation);
-    }
-
-    return 1;
-}
diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp
new file mode 100644
index 0000000..20130dd
--- /dev/null
+++ b/src/map/magic-stmt.cpp
@@ -0,0 +1,1597 @@
+#include "magic-interpreter.hpp"
+#include "magic-expr.hpp"
+#include "magic-expr-eval.hpp"
+#include "magic-interpreter-aux.hpp"
+
+int
+ clif_spawn_fake_npc_for_player (struct map_session_data *sd,
+                                 int fake_npc_id);
+
+#define INVISIBLE_NPC 127       /* used for local spell effects */
+
+//#define DEBUG
+
+#ifdef DEBUG
+static void print_val (val_t * v)
+{
+    switch (v->ty)
+    {
+        case TY_UNDEF:
+            fprintf (stderr, "UNDEF");
+            break;
+        case TY_INT:
+            fprintf (stderr, "%d", v->v.v_int);
+            break;
+        case TY_DIR:
+            fprintf (stderr, "dir%d", v->v.v_int);
+            break;
+        case TY_STRING:
+            fprintf (stderr, "`%s'", v->v.v_string);
+            break;
+        default:
+            fprintf (stderr, "ty%d", v->ty);
+            break;
+    }
+}
+
+static void dump_env (env_t * env)
+{
+    int  i;
+    for (i = 0; i < env->base_env->vars_nr; i++)
+    {
+        val_t *v = &env->vars[i];
+        val_t *bv = &env->base_env->vars[i];
+
+        fprintf (stderr, "%02x %30s ", i, env->base_env->var_name[i]);
+        print_val (v);
+        fprintf (stderr, "\t(");
+        print_val (bv);
+        fprintf (stderr, ")\n");
+    }
+}
+#endif
+
+static void clear_activation_record (cont_activation_record_t * ar)
+{
+    switch (ar->ty)
+    {
+        case CONT_STACK_FOREACH:
+            free (ar->c.c_foreach.entities);
+            break;
+        case CONT_STACK_PROC:
+            free (ar->c.c_proc.old_actuals);
+            break;
+    }
+}
+
+static void
+invocation_timer_callback (timer_id UNUSED, tick_t UNUSED, custom_id_t id, custom_data_t data)
+{
+    invocation_t *invocation = (invocation_t *) map_id2bl (id);
+
+    if (invocation)
+    {
+        invocation->timer = 0;
+        spell_execute (invocation);
+    }
+}
+
+static void clear_stack (invocation_t * invocation)
+{
+    int  i;
+
+    for (i = 0; i < invocation->stack_size; i++)
+        clear_activation_record (&invocation->stack[i]);
+
+    invocation->stack_size = 0;
+}
+
+void spell_free_invocation (invocation_t * invocation)
+{
+    if (invocation->status_change_refs)
+    {
+        free (invocation->status_change_refs);
+        /* The following cleanup shouldn't be necessary, but I've added it to help tracking a certain bug */
+        invocation->status_change_refs = NULL;
+        invocation->status_change_refs_nr = 0;
+    }
+
+    if (invocation->flags & INVOCATION_FLAG_BOUND)
+    {
+        entity_t *e = map_id2bl (invocation->subject);
+        if (e && e->type == BL_PC)
+            spell_unbind ((character_t *) e, invocation);
+    }
+
+    clear_stack (invocation);
+
+    if (invocation->timer)
+        delete_timer (invocation->timer, invocation_timer_callback);
+
+    magic_free_env (invocation->env);
+
+    map_delblock (&invocation->bl);
+    map_delobject (invocation->bl.id, BL_SPELL);    // also frees the object
+//        free(invocation);
+}
+
+static void
+char_set_weapon_icon (character_t * subject, int count, int icon, int look)
+{
+    const int old_icon = subject->attack_spell_icon_override;
+
+    subject->attack_spell_icon_override = icon;
+    subject->attack_spell_look_override = look;
+
+    if (old_icon && old_icon != icon)
+        clif_status_change (&subject->bl, old_icon, 0);
+
+    clif_fixpcpos (subject);
+    if (count)
+    {
+        clif_changelook (&subject->bl, LOOK_WEAPON, look);
+        if (icon)
+            clif_status_change (&subject->bl, icon, 1);
+    }
+    else
+    {
+        /* Set it to `normal' */
+        clif_changelook (&subject->bl, LOOK_WEAPON, subject->status.weapon);
+    }
+}
+
+static void char_set_attack_info (character_t * subject, int speed, int range)
+{
+    subject->attack_spell_delay = speed;
+    subject->attack_spell_range = range;
+
+    if (speed == 0)
+    {
+        pc_calcstatus (subject, 1);
+        clif_updatestatus (subject, SP_ASPD);
+        clif_updatestatus (subject, SP_ATTACKRANGE);
+    }
+    else
+    {
+        subject->aspd = speed;
+        clif_updatestatus (subject, SP_ASPD);
+        clif_updatestatus (subject, SP_ATTACKRANGE);
+    }
+}
+
+void magic_stop_completely (character_t * c)
+{
+    int  i;
+    // Zap all status change references to spells
+    for (i = 0; i < MAX_STATUSCHANGE; i++)
+        c->sc_data[i].spell_invocation = 0;
+
+    while (c->active_spells)
+        spell_free_invocation (c->active_spells);
+
+    if (c->attack_spell_override)
+    {
+        invocation_t *attack_spell =
+            (invocation_t *) map_id2bl (c->attack_spell_override);
+        if (attack_spell)
+            spell_free_invocation (attack_spell);
+        c->attack_spell_override = 0;
+        char_set_weapon_icon (c, 0, 0, 0);
+        char_set_attack_info (c, 0, 0);
+    }
+}
+
+/* Spell execution has finished normally or we have been notified by a finished skill timer */
+static void try_to_finish_invocation (invocation_t * invocation)
+{
+    if (invocation->status_change_refs_nr == 0 && !invocation->current_effect)
+    {
+        if (invocation->end_effect)
+        {
+            clear_stack (invocation);
+            invocation->current_effect = invocation->end_effect;
+            invocation->end_effect = NULL;
+            spell_execute (invocation);
+        }
+        else
+            spell_free_invocation (invocation);
+    }
+}
+
+static int trigger_spell (int subject, int spell)
+{
+    invocation_t *invocation = (invocation_t *) map_id2bl (spell);
+
+    if (!invocation)
+        return 0;
+
+    invocation = spell_clone_effect (invocation);
+
+    spell_bind ((character_t *) map_id2bl (subject), invocation);
+    magic_clear_var (&invocation->env->vars[VAR_CASTER]);
+    invocation->env->vars[VAR_CASTER].ty = TY_ENTITY;
+    invocation->env->vars[VAR_CASTER].v.v_int = subject;
+
+    return invocation->bl.id;
+}
+
+static void entity_warp (entity_t * target, int destm, int destx, int desty);
+
+static void char_update (character_t * character)
+{
+    entity_warp ((entity_t *) character, character->bl.m, character->bl.x,
+                 character->bl.y);
+}
+
+static void timer_callback_effect (timer_id UNUSED, tick_t UNUSED, custom_id_t id, custom_data_t data)
+{
+    entity_t *target = map_id2bl (id);
+    if (target)
+        clif_misceffect (target, data);
+}
+
+static void entity_effect (entity_t * entity, int effect_nr, int delay)
+{
+    add_timer (gettick () + delay,
+               &timer_callback_effect, entity->id, effect_nr);
+}
+
+void magic_unshroud (character_t * other_char)
+{
+    other_char->state.shroud_active = 0;
+    // Now warp the caster out of and back into here to refresh everyone's display
+    char_update (other_char);
+    clif_displaymessage (other_char->fd, "Your shroud has been dispelled!");
+//        entity_effect(&other_char->bl, MAGIC_EFFECT_REVEAL);
+}
+
+static void
+timer_callback_effect_npc_delete (timer_id UNUSED, tick_t odelay,
+                                  custom_id_t npc_id, custom_data_t UNUSED)
+{
+    struct npc_data *effect_npc = (struct npc_data *) map_id2bl (npc_id);
+    npc_free (effect_npc);
+}
+
+static struct npc_data *local_spell_effect (int m, int x, int y, int effect,
+                                            int tdelay)
+{
+    int  delay = 30000;         /* 1 minute should be enough for all interesting spell effects, I hope */
+    struct npc_data *effect_npc = npc_spawn_text (m, x, y,
+                                                  INVISIBLE_NPC, "", "?");
+    int  effect_npc_id = effect_npc->bl.id;
+
+    entity_effect (&effect_npc->bl, effect, tdelay);
+    add_timer (gettick () + delay,
+               timer_callback_effect_npc_delete, effect_npc_id, 0);
+
+    return effect_npc;
+}
+
+static int op_sfx (env_t * env, int args_nr, val_t * args)
+{
+    int  delay = ARGINT (2);
+
+    if (TY (0) == TY_ENTITY)
+    {
+        entity_effect (ARGENTITY (0), ARGINT (1), delay);
+    }
+    else if (TY (0) == TY_LOCATION)
+    {
+        local_spell_effect (ARGLOCATION (0).m,
+                            ARGLOCATION (0).x,
+                            ARGLOCATION (0).y, ARGINT (1), delay);
+    }
+    else
+        return 1;
+
+    return 0;
+}
+
+static int op_instaheal (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *caster = (VAR (VAR_CASTER).ty == TY_ENTITY)
+        ? map_id2bl (VAR (VAR_CASTER).v.v_int) : NULL;
+    entity_t *subject = ARGENTITY (0);
+    if (!caster)
+        caster = subject;
+
+    if (caster->type == BL_PC && subject->type == BL_PC)
+    {
+        character_t *caster_pc = (character_t *) caster;
+        character_t *subject_pc = (character_t *) subject;
+        MAP_LOG_PC (caster_pc, "SPELLHEAL-INSTA PC%d FOR %d",
+                    subject_pc->status.char_id, ARGINT (1));
+    }
+
+    battle_heal (caster, subject, ARGINT (1), ARGINT (2), 0);
+    return 0;
+}
+
+static int op_itemheal (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+    if (subject->type == BL_PC)
+    {
+        pc_itemheal ((struct map_session_data *) subject,
+                     ARGINT (1), ARGINT (2));
+    }
+    else
+        return op_instaheal (env, args_nr, args);
+
+    return 0;
+}
+
+#define SHROUD_HIDE_NAME_TALKING_FLAG	(1 << 0)
+#define SHROUD_DISAPPEAR_ON_PICKUP_FLAG	(1 << 1)
+#define SHROUD_DISAPPEAR_ON_TALK_FLAG	(1 << 2)
+
+#define ARGCHAR(n) (ARGENTITY(n)->type == BL_PC) ? (character_t *)(ARGENTITY(n)) : NULL
+
+static int op_shroud (env_t * env, int args_nr, val_t * args)
+{
+    character_t *subject = ARGCHAR (0);
+    int  arg = ARGINT (1);
+
+    if (!subject)
+        return 0;
+
+    subject->state.shroud_active = 1;
+    subject->state.shroud_hides_name_talking =
+        (arg & SHROUD_HIDE_NAME_TALKING_FLAG) != 0;
+    subject->state.shroud_disappears_on_pickup =
+        (arg & SHROUD_DISAPPEAR_ON_PICKUP_FLAG) != 0;
+    subject->state.shroud_disappears_on_talk =
+        (arg & SHROUD_DISAPPEAR_ON_TALK_FLAG) != 0;
+    return 0;
+}
+
+static int op_reveal (env_t * env, int args_nr, val_t * args)
+{
+    character_t *subject = ARGCHAR (0);
+
+    if (subject && subject->state.shroud_active)
+        magic_unshroud (subject);
+
+    return 0;
+}
+
+static int op_message (env_t * env, int args_nr, val_t * args)
+{
+    character_t *subject = ARGCHAR (0);
+
+    if (subject)
+        clif_displaymessage (subject->fd, ARGSTR (1));
+
+    return 0;
+}
+
+static void
+timer_callback_kill_npc (timer_id UNUSED, tick_t odelay, custom_id_t npc_id,
+                         custom_data_t data)
+{
+    struct npc_data *npc = (struct npc_data *) map_id2bl (npc_id);
+    if (npc)
+        npc_free (npc);
+}
+
+static int op_messenger_npc (env_t * env, int args_nr, val_t * args)
+{
+    struct npc_data *npc;
+    location_t *loc = &ARGLOCATION (0);
+
+    npc = npc_spawn_text (loc->m, loc->x, loc->y,
+                          ARGINT (1), ARGSTR (2), ARGSTR (3));
+
+    add_timer (gettick () + ARGINT (4),
+               &timer_callback_kill_npc, npc->bl.id, 0);
+
+    return 0;
+}
+
+static void entity_warp (entity_t * target, int destm, int destx, int desty)
+{
+    if (target->type == BL_PC || target->type == BL_MOB)
+    {
+
+        switch (target->type)
+        {
+            case BL_PC:
+            {
+                character_t *character = (character_t *) target;
+                char *map_name;
+                clif_clearchar_area (&character->bl, 3);
+                map_delblock (&character->bl);
+                character->bl.x = destx;
+                character->bl.y = desty;
+                character->bl.m = destm;
+
+                pc_touch_all_relevant_npcs (character);
+
+                // Note that touching NPCs may have triggered warping and thereby updated x and y:
+                map_name = map[character->bl.m].name;
+
+                // Warp part #1: update relevant data, interrupt trading etc.:
+                pc_setpos (character, map_name, character->bl.x, character->bl.y, 0);
+                // Warp part #2: now notify the client
+                clif_changemap (character, map_name,
+                                character->bl.x, character->bl.y);
+                break;
+            }
+            case BL_MOB:
+                target->x = destx;
+                target->y = desty;
+                target->m = destm;
+                clif_fixmobpos ((struct mob_data *) target);
+                break;
+        }
+    }
+}
+
+static int op_move (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+    int  dir = ARGDIR (1);
+
+    int  newx = subject->x + heading_x[dir];
+    int  newy = subject->y + heading_y[dir];
+
+    if (!map_is_solid (subject->m, newx, newy))
+        entity_warp (subject, subject->m, newx, newy);
+
+    return 0;
+}
+
+static int op_warp (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+    location_t *loc = &ARGLOCATION (1);
+
+    entity_warp (subject, loc->m, loc->x, loc->y);
+
+    return 0;
+}
+
+static int op_banish (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+
+    if (subject->type == BL_MOB)
+    {
+        struct mob_data *mob = (struct mob_data *) subject;
+
+        if (mob->mode & MOB_MODE_SUMMONED)
+            mob_catch_delete (mob, 3);
+    }
+
+    return 0;
+}
+
+static void
+record_status_change (invocation_t * invocation, int bl_id, int sc_id)
+{
+    int  index = invocation->status_change_refs_nr++;
+    status_change_ref_t *cr;
+
+    RECREATE (invocation->status_change_refs, status_change_ref_t, invocation->status_change_refs_nr);
+
+    cr = &invocation->status_change_refs[index];
+
+    cr->sc_type = sc_id;
+    cr->bl_id = bl_id;
+}
+
+static int op_status_change (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+    int  invocation_id = VAR (VAR_INVOCATION).ty == TY_INVOCATION
+        ? VAR (VAR_INVOCATION).v.v_int : 0;
+    invocation_t *invocation = (invocation_t *) map_id2bl (invocation_id);
+
+    skill_status_effect (subject, ARGINT (1), ARGINT (2), ARGINT (3),
+                         ARGINT (4), ARGINT (5), ARGINT (6), 0,
+                         invocation_id);
+
+    if (invocation && subject->type == BL_PC)
+        record_status_change (invocation, subject->id, ARGINT (1));
+
+    return 0;
+}
+
+static int op_stop_status_change (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *subject = ARGENTITY (0);
+
+    skill_status_change_end (subject, ARGINT (1), -1);
+
+    return 0;
+}
+
+static int op_override_attack (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *psubject = ARGENTITY (0);
+    int  charges = ARGINT (1);
+    int  attack_delay = ARGINT (2);
+    int  attack_range = ARGINT (3);
+    int  icon = ARGINT (4);
+    int  look = ARGINT (5);
+    int  stopattack = ARGINT (6);
+    character_t *subject;
+
+    if (psubject->type != BL_PC)
+        return 0;
+
+    subject = (character_t *) psubject;
+
+    if (subject->attack_spell_override)
+    {
+        invocation_t *old_invocation =
+            (invocation_t *) map_id2bl (subject->attack_spell_override);
+        if (old_invocation)
+            spell_free_invocation (old_invocation);
+    }
+
+    subject->attack_spell_override =
+        trigger_spell (subject->bl.id, VAR (VAR_INVOCATION).v.v_int);
+    subject->attack_spell_charges = charges;
+
+    if (subject->attack_spell_override)
+    {
+        invocation_t *attack_spell =
+            (invocation_t *) map_id2bl (subject->attack_spell_override);
+        if (attack_spell && stopattack)
+            attack_spell->flags |= INVOCATION_FLAG_STOPATTACK;
+
+        char_set_weapon_icon (subject, charges, icon, look);
+        char_set_attack_info (subject, attack_delay, attack_range);
+    }
+
+    return 0;
+}
+
+static int op_create_item (env_t * env, int args_nr, val_t * args)
+{
+    struct item item;
+    entity_t *entity = ARGENTITY (0);
+    character_t *subject;
+    int  stackable;
+    int  count = ARGINT (2);
+    if (count <= 0)
+        return 0;
+
+    if (entity->type == BL_PC)
+        subject = (character_t *) entity;
+    else
+        return 0;
+
+    GET_ARG_ITEM (1, item, stackable);
+
+    if (!stackable)
+        while (count--)
+            pc_additem (subject, &item, 1);
+    else
+        pc_additem (subject, &item, count);
+
+    return 0;
+}
+
+#define AGGRAVATION_MODE_ATTACKS_CASTER(n) 	((n) == 0 || (n) == 2)
+#define AGGRAVATION_MODE_MAKES_AGGRESSIVE(n)	((n) > 0)
+
+static int op_aggravate (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *victim = ARGENTITY (2);
+    int  mode = ARGINT (1);
+    entity_t *target = ARGENTITY (0);
+    struct mob_data *other;
+
+    if (target->type == BL_MOB)
+        other = (struct mob_data *) target;
+    else
+        return 0;
+
+    mob_target (other, victim, battle_get_range (victim));
+
+    if (AGGRAVATION_MODE_MAKES_AGGRESSIVE (mode))
+        other->mode = 0x85 | (other->mode & MOB_SENSIBLE_MASK); /* war */
+
+    if (AGGRAVATION_MODE_ATTACKS_CASTER (mode))
+    {
+        other->target_id = victim->id;
+        other->attacked_id = victim->id;
+    }
+
+    return 0;
+}
+
+#define MONSTER_ATTITUDE_HOSTILE	0
+#define MONSTER_ATTITUDE_FRIENDLY	1
+#define MONSTER_ATTITUDE_SERVANT	2
+#define MONSTER_ATTITUDE_FROZEN		3
+
+static int op_spawn (env_t * env, int args_nr, val_t * args)
+{
+    area_t *area = ARGAREA (0);
+    entity_t *owner_e = ARGENTITY (1);
+    int  monster_id = ARGINT (2);
+    int  monster_attitude = ARGINT (3);
+    int  monster_count = ARGINT (4);
+    int  monster_lifetime = ARGINT (5);
+    int  i;
+
+    character_t *owner = (monster_attitude == MONSTER_ATTITUDE_SERVANT
+                          && owner_e->type ==
+                          BL_PC) ? (character_t *) owner_e : NULL;
+
+    for (i = 0; i < monster_count; i++)
+    {
+        location_t loc;
+        magic_random_location (&loc, area);
+
+        int  mob_id;
+        struct mob_data *mob;
+
+        mob_id = mob_once_spawn (owner, map[loc.m].name, loc.x, loc.y, "--ja--",    // Is that needed?
+                                 monster_id, 1, "");
+
+        mob = (struct mob_data *) map_id2bl (mob_id);
+
+        if (mob)
+        {
+            mob->mode = mob_db[monster_id].mode;
+
+            switch (monster_attitude)
+            {
+
+                case MONSTER_ATTITUDE_SERVANT:
+                    mob->state.special_mob_ai = 1;
+                    mob->mode |= 0x04;
+                    break;
+
+                case MONSTER_ATTITUDE_FRIENDLY:
+                    mob->mode = 0x80 | (mob->mode & 1);
+                    break;
+
+                case MONSTER_ATTITUDE_HOSTILE:
+                    mob->mode = 0x84 | (mob->mode & 1);
+                    if (owner)
+                    {
+                        mob->target_id = owner->bl.id;
+                        mob->attacked_id = owner->bl.id;
+                    }
+                    break;
+
+                case MONSTER_ATTITUDE_FROZEN:
+                    mob->mode = 0;
+                    break;
+            }
+
+            mob->mode |=
+                MOB_MODE_SUMMONED | MOB_MODE_TURNS_AGAINST_BAD_MASTER;
+
+            mob->deletetimer = add_timer (gettick () + monster_lifetime,
+                                          mob_timer_delete, mob_id, 0);
+
+            if (owner)
+            {
+                mob->master_id = owner->bl.id;
+                mob->master_dist = 6;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static char *get_invocation_name (env_t * env)
+{
+    invocation_t *invocation;
+
+    if (VAR (VAR_INVOCATION).ty != TY_INVOCATION)
+        return "?";
+    invocation = (invocation_t *) map_id2bl (VAR (VAR_INVOCATION).v.v_int);
+
+    if (invocation)
+        return invocation->spell->name;
+    else
+        return "??";
+}
+
+static int op_injure (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *caster = ARGENTITY (0);
+    entity_t *target = ARGENTITY (1);
+    int  damage_caused = ARGINT (2);
+    int  mp_damage = ARGINT (3);
+    int  target_hp = battle_get_hp (target);
+    int  mdef = battle_get_mdef (target);
+
+    if (target->type == BL_PC && !map[target->m].flag.pvp && !((character_t *) target)->special_state.killable && (caster->type != BL_PC || !((character_t *) caster)->special_state.killer))
+        return 0;               /* Cannot damage other players outside of pvp */
+
+    if (target != caster)
+    {
+        /* Not protected against own spells */
+        damage_caused = (damage_caused * (100 - mdef)) / 100;
+        mp_damage = (mp_damage * (100 - mdef)) / 100;
+    }
+
+    damage_caused = (damage_caused > target_hp) ? target_hp : damage_caused;
+
+    if (damage_caused < 0)
+        damage_caused = 0;
+
+    // display damage first, because dealing damage may deallocate the target.
+    clif_damage (caster, target, gettick (), 0, 0, damage_caused, 0, 0, 0);
+
+    if (caster->type == BL_PC)
+    {
+        character_t *caster_pc = (character_t *) caster;
+        if (target->type == BL_MOB)
+        {
+            struct mob_data *mob = (struct mob_data *) target;
+
+            MAP_LOG_PC (caster_pc, "SPELLDMG MOB%d %d FOR %d BY %s",
+                        mob->bl.id, mob->mob_class, damage_caused,
+                        get_invocation_name (env));
+        }
+    }
+    battle_damage (caster, target, damage_caused, mp_damage);
+
+    return 0;
+}
+
+static int op_emote (env_t * env, int args_nr, val_t * args)
+{
+    entity_t *victim = ARGENTITY (0);
+    int  emotion = ARGINT (1);
+    clif_emotion (victim, emotion);
+
+    return 0;
+}
+
+static int op_set_script_variable (env_t * env, int args_nr, val_t * args)
+{
+    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+
+    if (!c)
+        return 1;
+
+    pc_setglobalreg (c, ARGSTR (1), ARGINT (2));
+
+    return 0;
+}
+
+static int op_set_hair_colour (env_t * env, int args_nr, val_t * args)
+{
+    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+
+    if (!c)
+        return 1;
+
+    pc_changelook (c, LOOK_HAIR_COLOR, ARGINT (1));
+
+    return 0;
+}
+
+static int op_set_hair_style (env_t * env, int args_nr, val_t * args)
+{
+    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+
+    if (!c)
+        return 1;
+
+    pc_changelook (c, LOOK_HAIR, ARGINT (1));
+
+    return 0;
+}
+
+static int op_drop_item_for (env_t * env, int args_nr, val_t * args)
+{
+    struct item item;
+    int  stackable;
+    location_t *loc = &ARGLOCATION (0);
+    int  count = ARGINT (2);
+    int  time = ARGINT (3);
+    character_t *c = ((args_nr > 4) && (ETY (4) == BL_PC)) ? ARGPC (4) : NULL;
+    int  delay = (args_nr > 5) ? ARGINT (5) : 0;
+    int  delaytime[3] = { delay, delay, delay };
+    character_t *owners[3] = { c, NULL, NULL };
+
+    GET_ARG_ITEM (1, item, stackable);
+
+    if (stackable)
+        map_addflooritem_any (&item, count, loc->m, loc->x, loc->y,
+                              owners, delaytime, time, 0);
+    else
+        while (count-- > 0)
+            map_addflooritem_any (&item, 1, loc->m, loc->x, loc->y,
+                                  owners, delaytime, time, 0);
+
+    return 0;
+}
+
+static int op_gain_exp (env_t * env, int args_nr, val_t * args)
+{
+    character_t *c = (ETY (0) == BL_PC) ? ARGPC (0) : NULL;
+
+    if (!c)
+        return 1;
+
+    pc_gainexp_reason (c, ARGINT (1), ARGINT (2), ARGINT (3));
+    return 0;
+}
+
+static op_t operations[] = {
+    {"sfx", ".ii", op_sfx},
+    {"instaheal", "eii", op_instaheal},
+    {"itemheal", "eii", op_itemheal},
+    {"shroud", "ei", op_shroud},
+    {"unshroud", "e", op_reveal},
+    {"message", "es", op_message},
+    {"messenger_npc", "lissi", op_messenger_npc},
+    {"move", "ed", op_move},
+    {"warp", "el", op_warp},
+    {"banish", "e", op_banish},
+    {"status_change", "eiiiiii", op_status_change},
+    {"stop_status_change", "ei", op_stop_status_change},
+    {"override_attack", "eiiiiii", op_override_attack},
+    {"create_item", "e.i", op_create_item},
+    {"aggravate", "eie", op_aggravate},
+    {"spawn", "aeiiii", op_spawn},
+    {"injure", "eeii", op_injure},
+    {"emote", "ei", op_emote},
+    {"set_script_variable", "esi", op_set_script_variable},
+    {"set_hair_colour", "ei", op_set_hair_colour},
+    {"set_hair_style", "ei", op_set_hair_style},
+    {"drop_item", "l.ii", op_drop_item_for},
+    {"drop_item_for", "l.iiei", op_drop_item_for},
+    {"gain_experience", "eiii", op_gain_exp},
+    {NULL, NULL, NULL}
+};
+
+static int operations_sorted = 0;
+static int operation_count;
+
+int compare_operations (const void *lhs, const void *rhs)
+{
+    return strcmp (((op_t *) lhs)->name, ((op_t *) rhs)->name);
+}
+
+op_t *magic_get_op (char *name, int *index)
+{
+    op_t key;
+
+    if (!operations_sorted)
+    {
+        op_t *opc = operations;
+
+        while (opc->name)
+            ++opc;
+
+        operation_count = opc - operations;
+
+        qsort (operations, operation_count, sizeof (op_t),
+               compare_operations);
+        operations_sorted = 1;
+    }
+
+    key.name = name;
+    op_t *op = (op_t *)bsearch (&key, operations, operation_count, sizeof (op_t),
+                        compare_operations);
+
+    if (op && index)
+        *index = op - operations;
+
+    return op;
+}
+
+void
+spell_effect_report_termination (int invocation_id, int bl_id, int sc_id,
+                                 int supplanted)
+{
+    int  i;
+    int  index = -1;
+    invocation_t *invocation = (invocation_t *) map_id2bl (invocation_id);
+
+    if (!invocation || invocation->bl.type != BL_SPELL)
+        return;
+
+    for (i = 0; i < invocation->status_change_refs_nr; i++)
+    {
+        status_change_ref_t *cr = &invocation->status_change_refs[i];
+        if (cr->sc_type == sc_id && cr->bl_id == bl_id)
+        {
+            index = i;
+            break;
+        }
+    }
+
+    if (index == -1)
+    {
+        entity_t *entity = map_id2bl (bl_id);
+        if (entity->type == BL_PC)
+            fprintf (stderr,
+                     "[magic] INTERNAL ERROR: spell-effect-report-termination:  tried to terminate on unexpected bl %d, sc %d\n",
+                     bl_id, sc_id);
+        return;
+    }
+
+    if (index == invocation->status_change_refs_nr - 1)
+        invocation->status_change_refs_nr--;
+    else                        /* Copy last change ref to the one we are deleting */
+        invocation->status_change_refs[index] =
+            invocation->
+            status_change_refs[--invocation->status_change_refs_nr];
+
+    try_to_finish_invocation (invocation);
+}
+
+static effect_t *return_to_stack (invocation_t * invocation)
+{
+    if (!invocation->stack_size)
+        return NULL;
+    else
+    {
+        cont_activation_record_t *ar =
+            invocation->stack + (invocation->stack_size - 1);
+        switch (ar->ty)
+        {
+
+            case CONT_STACK_PROC:
+            {
+                effect_t *ret = ar->return_location;
+                int  i;
+
+                for (i = 0; i < ar->c.c_proc.args_nr; i++)
+                {
+                    val_t *var =
+                        &invocation->env->vars[ar->c.c_proc.formals[i]];
+                    magic_clear_var (var);
+                    *var = ar->c.c_proc.old_actuals[i];
+                }
+
+                clear_activation_record (ar);
+                --invocation->stack_size;
+
+                return ret;
+            }
+
+            case CONT_STACK_FOREACH:
+            {
+                int  entity_id;
+                val_t *var = &invocation->env->vars[ar->c.c_foreach.id];
+
+                do
+                {
+                    if (ar->c.c_foreach.index >= ar->c.c_foreach.entities_nr)
+                    {
+                        effect_t *ret = ar->return_location;
+                        clear_activation_record (ar);
+                        --invocation->stack_size;
+                        return ret;
+                    }
+
+                    entity_id =
+                        ar->c.c_foreach.entities[ar->c.c_foreach.index++];
+                }
+                while (!entity_id || !map_id2bl (entity_id));
+
+                magic_clear_var (var);
+                var->ty = ar->c.c_foreach.ty;
+                var->v.v_int = entity_id;
+
+                return ar->c.c_foreach.body;
+            }
+
+            case CONT_STACK_FOR:
+                if (ar->c.c_for.current > ar->c.c_for.stop)
+                {
+                    effect_t *ret = ar->return_location;
+                    clear_activation_record (ar);
+                    --invocation->stack_size;
+                    return ret;
+                }
+
+                magic_clear_var (&invocation->env->vars[ar->c.c_for.id]);
+                invocation->env->vars[ar->c.c_for.id].ty = TY_INT;
+                invocation->env->vars[ar->c.c_for.id].v.v_int =
+                    ar->c.c_for.current++;
+
+                return ar->c.c_for.body;
+
+            default:
+                fprintf (stderr,
+                         "[magic] INTERNAL ERROR: While executing spell `%s':  stack corruption\n",
+                         invocation->spell->name);
+                return NULL;
+        }
+    }
+}
+
+static cont_activation_record_t *add_stack_entry (invocation_t * invocation,
+                                                  int ty,
+                                                  effect_t * return_location)
+{
+    cont_activation_record_t *ar =
+        invocation->stack + invocation->stack_size++;
+    if (invocation->stack_size >= MAX_STACK_SIZE)
+    {
+        fprintf (stderr,
+                 "[magic] Execution stack size exceeded in spell `%s'; truncating effect\n",
+                 invocation->spell->name);
+        invocation->stack_size--;
+        return NULL;
+    }
+
+    ar->ty = ty;
+    ar->return_location = return_location;
+    return ar;
+}
+
+static int find_entities_in_area_c (entity_t * target, va_list va)
+{
+    int *entities_allocd_p = va_arg (va, int *);
+    int *entities_nr_p = va_arg (va, int *);
+    int **entities_p = va_arg (va, int **);
+    int  filter = va_arg (va, int);
+
+/* The following macro adds an entity to the result list: */
+#define ADD_ENTITY(e)                                                   \
+        if (*entities_nr_p == *entities_allocd_p) {                     \
+                /* Need more space */                                   \
+                (*entities_allocd_p) += 32;                             \
+                RECREATE (*entities_p, int, *entities_allocd_p); \
+        }                                                               \
+        (*entities_p)[(*entities_nr_p)++] = e;
+
+    switch (target->type)
+    {
+
+        case BL_PC:
+            if (filter == FOREACH_FILTER_PC
+                || filter == FOREACH_FILTER_ENTITY
+                || (filter == FOREACH_FILTER_TARGET
+                    && map[target->m].flag.pvp))
+                break;
+            else if (filter == FOREACH_FILTER_SPELL)
+            {                   /* Check all spells bound to the caster */
+                invocation_t *invoc = ((character_t *) target)->active_spells;
+                /* Add all spells locked onto thie PC */
+
+                while (invoc)
+                {
+                    ADD_ENTITY (invoc->bl.id);
+                    invoc = invoc->next_invocation;
+                }
+            }
+            return 0;
+
+        case BL_MOB:
+            if (filter == FOREACH_FILTER_MOB
+                || filter == FOREACH_FILTER_ENTITY
+                || filter == FOREACH_FILTER_TARGET)
+                break;
+            else
+                return 0;
+
+        case BL_SPELL:
+            if (filter == FOREACH_FILTER_SPELL)
+            {
+                invocation_t *invocation = (invocation_t *) target;
+
+                /* Check whether the spell is `bound'-- if so, we'll consider it iff we see the caster (case BL_PC). */
+                if (invocation->flags & INVOCATION_FLAG_BOUND)
+                    return 0;
+                else
+                    break;      /* Add the spell */
+            }
+            else
+                return 0;
+
+        case BL_NPC:
+            if (filter == FOREACH_FILTER_NPC)
+                break;
+            else
+                return 0;
+
+        default:
+            return 0;
+    }
+
+    ADD_ENTITY (target->id);
+#undef ADD_ENTITY
+    return 0;
+}
+
+static void
+find_entities_in_area (area_t * area, int *entities_allocd_p,
+                       int *entities_nr_p, int **entities_p, int filter)
+{
+    switch (area->ty)
+    {
+        case AREA_UNION:
+            find_entities_in_area (area->a.a_union[0], entities_allocd_p,
+                                   entities_nr_p, entities_p, filter);
+            find_entities_in_area (area->a.a_union[1], entities_allocd_p,
+                                   entities_nr_p, entities_p, filter);
+            break;
+
+        default:
+        {
+            int  m, x, y, width, height;
+            magic_area_rect (&m, &x, &y, &width, &height, area);
+            map_foreachinarea (find_entities_in_area_c,
+                               m, x, y, x + width, y + height,
+                               0 /* filter elsewhere */ ,
+                               entities_allocd_p, entities_nr_p, entities_p,
+                               filter);
+        }
+    }
+}
+
+static effect_t *run_foreach (invocation_t * invocation, effect_t * foreach,
+                              effect_t * return_location)
+{
+    val_t area;
+    int  filter = foreach->e.e_foreach.filter;
+    int  id = foreach->e.e_foreach.id;
+    effect_t *body = foreach->e.e_foreach.body;
+
+    magic_eval (invocation->env, &area, foreach->e.e_foreach.area);
+
+    if (area.ty != TY_AREA)
+    {
+        magic_clear_var (&area);
+        fprintf (stderr,
+                 "[magic] Error in spell `%s':  FOREACH loop over non-area\n",
+                 invocation->spell->name);
+        return return_location;
+    }
+    else
+    {
+        cont_activation_record_t *ar =
+            add_stack_entry (invocation, CONT_STACK_FOREACH, return_location);
+        int  entities_allocd = 64;
+        int *entities_collect;
+        int *entities;
+        int *shuffle_board;
+        int  entities_nr = 0;
+        int  i;
+
+        if (!ar)
+            return return_location;
+
+        CREATE (entities_collect, int, entities_allocd);
+
+        find_entities_in_area (area.v.v_area, &entities_allocd, &entities_nr,
+                               &entities_collect, filter);
+
+        /* Now shuffle */
+        CREATE (shuffle_board, int, entities_nr);
+        CREATE (entities, int, entities_nr);
+        for (i = 0; i < entities_nr; i++)
+            shuffle_board[i] = i;
+
+        for (i = entities_nr - 1; i >= 0; i--)
+        {
+            int  random_index = rand () % (i + 1);
+            entities[i] = entities_collect[shuffle_board[random_index]];
+            shuffle_board[random_index] = shuffle_board[i]; // thus, we are guaranteed only to use unused indices
+        }
+
+        free (entities_collect);
+        free (shuffle_board);
+        /* Done shuffling */
+
+        ar->c.c_foreach.id = id;
+        ar->c.c_foreach.body = body;
+        ar->c.c_foreach.index = 0;
+        ar->c.c_foreach.entities_nr = entities_nr;
+        ar->c.c_foreach.entities = entities;
+        ar->c.c_foreach.ty =
+            (filter == FOREACH_FILTER_SPELL) ? TY_INVOCATION : TY_ENTITY;
+
+        magic_clear_var (&area);
+
+        return return_to_stack (invocation);
+    }
+}
+
+static effect_t *run_for (invocation_t * invocation, effect_t * for_,
+                          effect_t * return_location)
+{
+    cont_activation_record_t *ar;
+    int  id = for_->e.e_for.id;
+    val_t start;
+    val_t stop;
+
+    magic_eval (invocation->env, &start, for_->e.e_for.start);
+    magic_eval (invocation->env, &stop, for_->e.e_for.stop);
+
+    if (start.ty != TY_INT || stop.ty != TY_INT)
+    {
+        magic_clear_var (&start);
+        magic_clear_var (&stop);
+        fprintf (stderr,
+                 "[magic] Error in spell `%s':  FOR loop start or stop point is not an integer\n",
+                 invocation->spell->name);
+        return return_location;
+    }
+
+    ar = add_stack_entry (invocation, CONT_STACK_FOR, return_location);
+
+    if (!ar)
+        return return_location;
+
+    ar->c.c_for.id = id;
+    ar->c.c_for.current = start.v.v_int;
+    ar->c.c_for.stop = stop.v.v_int;
+    ar->c.c_for.body = for_->e.e_for.body;
+
+    return return_to_stack (invocation);
+}
+
+static effect_t *run_call (invocation_t * invocation,
+                           effect_t * return_location)
+{
+    effect_t *current = invocation->current_effect;
+    cont_activation_record_t *ar;
+    int  args_nr = current->e.e_call.args_nr;
+    int *formals = current->e.e_call.formals;
+    val_t *old_actuals;
+    CREATE (old_actuals, val_t, args_nr);
+    int  i;
+
+    ar = add_stack_entry (invocation, CONT_STACK_PROC, return_location);
+    ar->c.c_proc.args_nr = args_nr;
+    ar->c.c_proc.formals = formals;
+    ar->c.c_proc.old_actuals = old_actuals;
+    for (i = 0; i < args_nr; i++)
+    {
+        val_t *env_val = &invocation->env->vars[formals[i]];
+        val_t result;
+        magic_copy_var (&old_actuals[i], env_val);
+        magic_eval (invocation->env, &result, current->e.e_call.actuals[i]);
+        *env_val = result;
+    }
+
+    return current->e.e_call.body;
+}
+
+#ifdef DEBUG
+static void print_cfg (int i, effect_t * e)
+{
+    int  j;
+    for (j = 0; j < i; j++)
+        printf ("    ");
+
+    printf ("%p: ", e);
+
+    if (!e)
+    {
+        puts (" -- end --");
+        return;
+    }
+
+    switch (e->ty)
+    {
+        case EFFECT_SKIP:
+            puts ("SKIP");
+            break;
+        case EFFECT_END:
+            puts ("END");
+            break;
+        case EFFECT_ABORT:
+            puts ("ABORT");
+            break;
+        case EFFECT_ASSIGN:
+            puts ("ASSIGN");
+            break;
+        case EFFECT_FOREACH:
+            puts ("FOREACH");
+            print_cfg (i + 1, e->e.e_foreach.body);
+            break;
+        case EFFECT_FOR:
+            puts ("FOR");
+            print_cfg (i + 1, e->e.e_for.body);
+            break;
+        case EFFECT_IF:
+            puts ("IF");
+            for (j = 0; j < i; j++)
+                printf ("    ");
+            puts ("THEN");
+            print_cfg (i + 1, e->e.e_if.true_branch);
+            for (j = 0; j < i; j++)
+                printf ("    ");
+            puts ("ELSE");
+            print_cfg (i + 1, e->e.e_if.false_branch);
+            break;
+        case EFFECT_SLEEP:
+            puts ("SLEEP");
+            break;
+        case EFFECT_SCRIPT:
+            puts ("SCRIPT");
+            break;
+        case EFFECT_BREAK:
+            puts ("BREAK");
+            break;
+        case EFFECT_OP:
+            puts ("OP");
+            break;
+    }
+    print_cfg (i, e->next);
+}
+#endif
+
+/**
+ * Execute a spell invocation until we abort, finish, or hit the next `sleep'.
+ *
+ * Use spell_execute() to automate handling of timers
+ *
+ * Returns: 0 if finished (all memory is freed implicitly)
+ *          >1 if we hit `sleep'; the result is the number of ticks we should sleep for.
+ *          -1 if we paused to wait for a user action (via script interaction)
+ */
+static int spell_run (invocation_t * invocation, int allow_delete)
+{
+    const int invocation_id = invocation->bl.id;
+#define REFRESH_INVOCATION invocation = (invocation_t *) map_id2bl(invocation_id); if (!invocation) return 0;
+
+#ifdef DEBUG
+    fprintf (stderr, "Resuming execution:  invocation of `%s'\n",
+             invocation->spell->name);
+    print_cfg (1, invocation->current_effect);
+#endif
+    while (invocation->current_effect)
+    {
+        effect_t *e = invocation->current_effect;
+        effect_t *next = e->next;
+        int  i;
+
+#ifdef DEBUG
+        fprintf (stderr, "Next step of type %d\n", e->ty);
+        dump_env (invocation->env);
+#endif
+
+        switch (e->ty)
+        {
+            case EFFECT_SKIP:
+                break;
+
+            case EFFECT_ABORT:
+                invocation->flags |= INVOCATION_FLAG_ABORTED;
+                invocation->end_effect = NULL;
+            case EFFECT_END:
+                clear_stack (invocation);
+                next = NULL;
+                break;
+
+            case EFFECT_ASSIGN:
+                magic_eval (invocation->env,
+                            &invocation->env->vars[e->e.e_assign.id],
+                            e->e.e_assign.expr);
+                break;
+
+            case EFFECT_FOREACH:
+                next = run_foreach (invocation, e, next);
+                break;
+
+            case EFFECT_FOR:
+                next = run_for (invocation, e, next);
+                break;
+
+            case EFFECT_IF:
+                if (magic_eval_int (invocation->env, e->e.e_if.cond))
+                    next = e->e.e_if.true_branch;
+                else
+                    next = e->e.e_if.false_branch;
+                break;
+
+            case EFFECT_SLEEP:
+            {
+                int  sleeptime =
+                    magic_eval_int (invocation->env, e->e.e_sleep);
+                invocation->current_effect = next;
+                if (sleeptime > 0)
+                    return sleeptime;
+                break;
+            }
+
+            case EFFECT_SCRIPT:
+            {
+                character_t *caster =
+                    (character_t *) map_id2bl (invocation->caster);
+                if (caster)
+                {
+                    env_t *env = invocation->env;
+                    character_t *caster =
+                        (character_t *) map_id2bl (invocation->caster);
+                    argrec_t arg[] = { {"@target",.v.i =
+                                        VAR (VAR_TARGET).ty ==
+                                        TY_ENTITY ? 0 : VAR (VAR_TARGET).
+                                        v.v_int}
+                    ,
+                    {"@caster",.v.i = invocation->caster}
+                    ,
+                    {"@caster_name$",.v.s = caster ? caster->status.name : ""}
+                    };
+                    int  message_recipient =
+                        VAR (VAR_SCRIPTTARGET).ty ==
+                        TY_ENTITY ? VAR (VAR_SCRIPTTARGET).
+                        v.v_int : invocation->caster;
+                    character_t *recipient =
+                        (character_t *) map_id2bl (message_recipient);
+
+                    if (recipient->npc_id
+                        && recipient->npc_id != invocation->bl.id)
+                        break;  /* Don't send multiple message boxes at once */
+
+                    if (!invocation->script_pos)    // first time running this script?
+                        clif_spawn_fake_npc_for_player (recipient,
+                                                        invocation->bl.id);
+                    // We have to do this or otherwise the client won't think that it's
+                    // dealing with an NPC
+
+                    int  newpos = run_script_l (e->e.e_script,
+                                                invocation->script_pos,
+                                                message_recipient,
+                                                invocation->bl.id,
+                                                3, arg);
+                    /* Returns the new script position, or -1 once the script is finished */
+                    if (newpos != -1)
+                    {
+                        /* Must set up for continuation */
+                        recipient->npc_id = invocation->bl.id;
+                        recipient->npc_pos = invocation->script_pos = newpos;
+                        return -1;  /* Signal `wait for script' */
+                    }
+                    else
+                        invocation->script_pos = 0;
+                    clif_clearchar_id (invocation->bl.id, 1, caster->fd);
+                }
+                REFRESH_INVOCATION; // Script may have killed the caster
+                break;
+            }
+
+            case EFFECT_BREAK:
+                next = return_to_stack (invocation);
+                break;
+
+            case EFFECT_OP:
+            {
+                op_t *op = &operations[e->e.e_op.id];
+                val_t args[MAX_ARGS];
+
+                for (i = 0; i < e->e.e_op.args_nr; i++)
+                    magic_eval (invocation->env, &args[i], e->e.e_op.args[i]);
+
+                if (!magic_signature_check ("effect", op->name, op->signature,
+                                            e->e.e_op.args_nr, args,
+                                            e->e.e_op.line_nr,
+                                            e->e.e_op.column))
+                    op->op (invocation->env, e->e.e_op.args_nr, args);
+
+                for (i = 0; i < e->e.e_op.args_nr; i++)
+                    magic_clear_var (&args[i]);
+
+                REFRESH_INVOCATION; // Effect may have killed the caster
+                break;
+            }
+
+            case EFFECT_CALL:
+                next = run_call (invocation, next);
+                break;
+
+            default:
+                fprintf (stderr,
+                         "[magic] INTERNAL ERROR: Unknown effect %d\n",
+                         e->ty);
+        }
+
+        if (!next)
+            next = return_to_stack (invocation);
+
+        invocation->current_effect = next;
+    }
+
+    if (allow_delete)
+        try_to_finish_invocation (invocation);
+    return 0;
+#undef REFRESH_INVOCATION
+}
+
+extern void spell_update_location (invocation_t * invocation);
+
+void spell_execute_d (invocation_t * invocation, int allow_deletion)
+{
+    int  delta;
+
+    spell_update_location (invocation);
+    delta = spell_run (invocation, allow_deletion);
+
+    if (delta > 0)
+    {
+        if (invocation->timer)
+        {
+            fprintf (stderr,
+                     "[magic] FATAL ERROR: Trying to add multiple timers to the same spell! Already had timer: %d\n",
+                     invocation->timer);
+            /* *((int *)0x0) = 0; */
+        }
+        invocation->timer = add_timer (gettick () + delta,
+                                       &invocation_timer_callback,
+                                       invocation->bl.id, 0);
+    }
+
+    /* If 0, the script cleaned itself.  If -1 (wait-for-script), we must wait for the user. */
+}
+
+void spell_execute (invocation_t * invocation)
+{
+    spell_execute_d (invocation, 1);
+}
+
+void spell_execute_script (invocation_t * invocation)
+{
+    if (invocation->script_pos)
+        spell_execute_d (invocation, 1);
+    /* Otherwise the script-within-the-spell has been terminated by some other means.
+     * In practice this happens when the script doesn't wait for user input: the client
+     * may still notify the server that it's done.  Without the above check, we'd be
+     * running the same spell twice! */
+}
+
+int spell_attack (int caster_id, int target_id)
+{
+    character_t *caster = (character_t *) map_id2bl (caster_id);
+    invocation_t *invocation;
+    int  stop_attack = 0;
+
+    if (!caster)
+        return 0;
+
+    invocation = (invocation_t *) map_id2bl (caster->attack_spell_override);
+
+    if (invocation && invocation->flags & INVOCATION_FLAG_STOPATTACK)
+        stop_attack = 1;
+
+    if (invocation && caster->attack_spell_charges > 0)
+    {
+        magic_clear_var (&invocation->env->vars[VAR_TARGET]);
+        invocation->env->vars[VAR_TARGET].ty = TY_ENTITY;
+        invocation->env->vars[VAR_TARGET].v.v_int = target_id;
+
+        invocation->current_effect = invocation->trigger_effect;
+        invocation->flags &= ~INVOCATION_FLAG_ABORTED;
+        spell_execute_d (invocation,
+                         0 /* don't delete the invocation if done */ );
+
+        // If the caster died, we need to refresh here:
+        invocation =
+            (invocation_t *) map_id2bl (caster->attack_spell_override);
+
+        if (invocation && !(invocation->flags & INVOCATION_FLAG_ABORTED))   // If we didn't abort:
+            caster->attack_spell_charges--;
+    }
+
+    if (invocation && caster->attack_spell_override != invocation->bl.id)
+    {
+        /* Attack spell changed / was refreshed */
+        // spell_free_invocation(invocation); // [Fate] This would be a double free.
+    }
+    else if (!invocation || caster->attack_spell_charges <= 0)
+    {
+        caster->attack_spell_override = 0;
+        char_set_weapon_icon (caster, 0, 0, 0);
+        char_set_attack_info (caster, 0, 0);
+
+        if (stop_attack)
+            pc_stopattack (caster);
+
+        if (invocation)
+            spell_free_invocation (invocation);
+    }
+
+    return 1;
+}
diff --git a/src/map/magic.c b/src/map/magic.c
deleted file mode 100644
index 797dc16..0000000
--- a/src/map/magic.c
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "magic-interpreter.h"
-
-#undef DEBUG
-
-static char *magic_preprocess_message (character_t * character, char *start,
-                                       char *end)
-{
-    if (character->state.shroud_active
-        && character->state.shroud_disappears_on_talk)
-        magic_unshroud (character);
-
-    if (character->state.shroud_active
-        && character->state.shroud_hides_name_talking)
-    {
-        int  len = strlen (end);
-        strcpy (start, "? ");
-        memmove (start + 2, end, len + 1);
-        return start + 4;
-    }
-    else
-        return end + 2;         /* step past blank */
-}
-
-#define ISBLANK(c) ((c) == ' ')
-
-/* Returns a dynamically allocated copy of `src'.
- * `*parameter' may point within that copy or be NULL. */
-static char *magic_tokenise (char *src, char **parameter)
-{
-    char *retval = strdup (src);
-    char *seeker = retval;
-
-    while (*seeker && !ISBLANK (*seeker))
-        ++seeker;
-
-    if (!*seeker)
-        *parameter = NULL;
-    else
-    {
-        *seeker = 0;            /* Terminate invocation */
-        ++seeker;
-
-        while (ISBLANK (*seeker))
-            ++seeker;
-
-        *parameter = seeker;
-    }
-
-    return retval;
-}
-
-int magic_message (character_t * caster, char *spell_, size_t spell_len)
-{
-    if (pc_isdead (caster))
-        return 0;
-
-    int  power = caster->matk1;
-    char *invocation_base = spell_ + 8;
-    char *source_invocation =
-        1 + invocation_base + strlen (caster->status.name);
-    spell_t *spell;
-    char *parameter;
-    char *spell_invocation;
-
-    if (!source_invocation)
-        return 0;
-
-    /* Pre-message filter in case some spell alters output */
-    source_invocation =
-        magic_preprocess_message (caster, invocation_base, source_invocation);
-
-    spell_invocation = magic_tokenise (source_invocation, &parameter);
-    parameter = parameter ? strdup (parameter) : strdup ("");
-
-    spell = magic_find_spell (spell_invocation);
-    free (spell_invocation);
-
-    if (spell)
-    {
-        int  near_miss;
-        env_t *env =
-            spell_create_env (&magic_conf, spell, caster, power, parameter);
-        effect_set_t *effects;
-
-        if ((spell->flags & SPELL_FLAG_NONMAGIC) || (power >= 1))
-            effects = spell_trigger (spell, caster, env, &near_miss);
-        else
-            effects = NULL;
-
-#ifdef DEBUG
-        fprintf (stderr, "Found spell `%s', triggered = %d\n", spell_,
-                 effects != NULL);
-#endif
-        if (caster->status.option & OPTION_HIDE)
-            return 0;           // No spellcasting while hidden
-
-        MAP_LOG_PC (caster, "CAST %s %s",
-                    spell->name, effects ? "SUCCESS" : "FAILURE");
-
-        if (effects)
-        {
-            invocation_t *invocation = spell_instantiate (effects, env);
-
-            spell_bind (caster, invocation);
-            spell_execute (invocation);
-
-            return (spell->flags & SPELL_FLAG_SILENT) ? -1 : 1;
-        }
-        else
-            magic_free_env (env);
-
-        return 1;
-    }
-    else
-        free (parameter);
-
-    return 0;                   /* Not a spell */
-}
-
-int  magic_init (char *conffile);   // must be called after itemdb initialisation
-
-void do_init_magic (void)
-{
-    magic_init (MAGIC_CONFIG_FILE);
-}
diff --git a/src/map/magic.cpp b/src/map/magic.cpp
new file mode 100644
index 0000000..03b18a4
--- /dev/null
+++ b/src/map/magic.cpp
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "magic-interpreter.hpp"
+
+#undef DEBUG
+
+static char *magic_preprocess_message (character_t * character, char *start,
+                                       char *end)
+{
+    if (character->state.shroud_active
+        && character->state.shroud_disappears_on_talk)
+        magic_unshroud (character);
+
+    if (character->state.shroud_active
+        && character->state.shroud_hides_name_talking)
+    {
+        int  len = strlen (end);
+        strcpy (start, "? ");
+        memmove (start + 2, end, len + 1);
+        return start + 4;
+    }
+    else
+        return end + 2;         /* step past blank */
+}
+
+#define ISBLANK(c) ((c) == ' ')
+
+/* Returns a dynamically allocated copy of `src'.
+ * `*parameter' may point within that copy or be NULL. */
+static char *magic_tokenise (char *src, char **parameter)
+{
+    char *retval = strdup (src);
+    char *seeker = retval;
+
+    while (*seeker && !ISBLANK (*seeker))
+        ++seeker;
+
+    if (!*seeker)
+        *parameter = NULL;
+    else
+    {
+        *seeker = 0;            /* Terminate invocation */
+        ++seeker;
+
+        while (ISBLANK (*seeker))
+            ++seeker;
+
+        *parameter = seeker;
+    }
+
+    return retval;
+}
+
+int magic_message (character_t * caster, char *spell_, size_t spell_len)
+{
+    if (pc_isdead (caster))
+        return 0;
+
+    int  power = caster->matk1;
+    char *invocation_base = spell_ + 8;
+    char *source_invocation =
+        1 + invocation_base + strlen (caster->status.name);
+    spell_t *spell;
+    char *parameter;
+    char *spell_invocation;
+
+    if (!source_invocation)
+        return 0;
+
+    /* Pre-message filter in case some spell alters output */
+    source_invocation =
+        magic_preprocess_message (caster, invocation_base, source_invocation);
+
+    spell_invocation = magic_tokenise (source_invocation, &parameter);
+    parameter = parameter ? strdup (parameter) : strdup ("");
+
+    spell = magic_find_spell (spell_invocation);
+    free (spell_invocation);
+
+    if (spell)
+    {
+        int  near_miss;
+        env_t *env =
+            spell_create_env (&magic_conf, spell, caster, power, parameter);
+        effect_set_t *effects;
+
+        if ((spell->flags & SPELL_FLAG_NONMAGIC) || (power >= 1))
+            effects = spell_trigger (spell, caster, env, &near_miss);
+        else
+            effects = NULL;
+
+#ifdef DEBUG
+        fprintf (stderr, "Found spell `%s', triggered = %d\n", spell_,
+                 effects != NULL);
+#endif
+        if (caster->status.option & OPTION_HIDE)
+            return 0;           // No spellcasting while hidden
+
+        MAP_LOG_PC (caster, "CAST %s %s",
+                    spell->name, effects ? "SUCCESS" : "FAILURE");
+
+        if (effects)
+        {
+            invocation_t *invocation = spell_instantiate (effects, env);
+
+            spell_bind (caster, invocation);
+            spell_execute (invocation);
+
+            return (spell->flags & SPELL_FLAG_SILENT) ? -1 : 1;
+        }
+        else
+            magic_free_env (env);
+
+        return 1;
+    }
+    else
+        free (parameter);
+
+    return 0;                   /* Not a spell */
+}
+
+int  magic_init (char *conffile);   // must be called after itemdb initialisation
+
+void do_init_magic (void)
+{
+    magic_init (MAGIC_CONFIG_FILE);
+}
diff --git a/src/map/magic.h b/src/map/magic.h
deleted file mode 100644
index 1979914..0000000
--- a/src/map/magic.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef MAGIC_H_
-#define MAGIC_H_
-
-#include "clif.h"
-#include "intif.h"
-
-#define MAGIC_CONFIG_FILE "conf/magic.conf"
-
-typedef struct map_session_data character_t;
-typedef struct block_list entity_t;
-
-struct invocation;              /* Spell invocation */
-
-/**
- * Try to cast magic.
- *
- * As an intended side effect, the magic message may be distorted (text only).
- *
- * \param caster Player attempting to cast magic
- * \param spell The prospective incantation
- * \param spell_len Number of characters in the incantation
- * \return 1 or -1 if the input message was magic and was handled by this function, 0 otherwise.  -1 is returned when the
- *         message should not be repeated.
- */
-int  magic_message (character_t * caster, char *spell, size_t spell_len);
-
-/**
- * Removes the shroud from a character
- *
- * \param character The character to remove the shroud from
- */
-void magic_unshroud (character_t * character);
-
-/**
- * Notifies a running spell that a status_change timer triggered by the spell has expired
- *
- * \param invocation The invocation to notify
- * \param bl_id ID of the PC for whom this happened
- * \param type sc_id ID of the status change entry that finished
- * \param supplanted Whether the status_change finished normally (0) or was supplanted by a new status_change (1)
- */
-void
-spell_effect_report_termination (int invocation, int bl_id, int sc_id,
-                                 int supplanted);
-
-/**
- * Initialise all spells, read config data
- */
-void do_init_magic (void);
-
-/**
- * Identifies the invocation used to trigger a spell
- *
- * Returns NULL if not found
- */
-char *magic_find_invocation (char *spellame);
-
-/**
- * Identifies the invocation used to denote a teleport location
- *
- * Returns NULL if not found
- */
-char *magic_find_anchor_invocation (char *teleport_location);
-
-/**
- * Execute a spell invocation and sets up timers to finish
- */
-void spell_execute (struct invocation *invocation);
-
-/**
- * Continue an NPC script embedded in a spell
- */
-void spell_execute_script (struct invocation *invocation);
-
-/**
- * Stops all magic bound to the specified character
- *
- */
-void magic_stop_completely (character_t * c);
-
-/**
- * Attacks with a magical spell charged to the character
- *
- * Returns 0 if there is no charged spell or the spell is depleted.
- */
-int  spell_attack (int caster, int target);
-
-void spell_free_invocation (struct invocation *invocation);
-
-#endif /* !defined(MAGIC_H_) */
diff --git a/src/map/magic.hpp b/src/map/magic.hpp
new file mode 100644
index 0000000..0c776ea
--- /dev/null
+++ b/src/map/magic.hpp
@@ -0,0 +1,90 @@
+#ifndef MAGIC_HPP
+#define MAGIC_HPP
+
+#include "clif.hpp"
+#include "intif.hpp"
+
+#define MAGIC_CONFIG_FILE "conf/magic.conf"
+
+typedef struct map_session_data character_t;
+typedef struct block_list entity_t;
+
+struct invocation;              /* Spell invocation */
+
+/**
+ * Try to cast magic.
+ *
+ * As an intended side effect, the magic message may be distorted (text only).
+ *
+ * \param caster Player attempting to cast magic
+ * \param spell The prospective incantation
+ * \param spell_len Number of characters in the incantation
+ * \return 1 or -1 if the input message was magic and was handled by this function, 0 otherwise.  -1 is returned when the
+ *         message should not be repeated.
+ */
+int  magic_message (character_t * caster, char *spell, size_t spell_len);
+
+/**
+ * Removes the shroud from a character
+ *
+ * \param character The character to remove the shroud from
+ */
+void magic_unshroud (character_t * character);
+
+/**
+ * Notifies a running spell that a status_change timer triggered by the spell has expired
+ *
+ * \param invocation The invocation to notify
+ * \param bl_id ID of the PC for whom this happened
+ * \param type sc_id ID of the status change entry that finished
+ * \param supplanted Whether the status_change finished normally (0) or was supplanted by a new status_change (1)
+ */
+void
+spell_effect_report_termination (int invocation, int bl_id, int sc_id,
+                                 int supplanted);
+
+/**
+ * Initialise all spells, read config data
+ */
+void do_init_magic (void);
+
+/**
+ * Identifies the invocation used to trigger a spell
+ *
+ * Returns NULL if not found
+ */
+char *magic_find_invocation (char *spellame);
+
+/**
+ * Identifies the invocation used to denote a teleport location
+ *
+ * Returns NULL if not found
+ */
+char *magic_find_anchor_invocation (char *teleport_location);
+
+/**
+ * Execute a spell invocation and sets up timers to finish
+ */
+void spell_execute (struct invocation *invocation);
+
+/**
+ * Continue an NPC script embedded in a spell
+ */
+void spell_execute_script (struct invocation *invocation);
+
+/**
+ * Stops all magic bound to the specified character
+ *
+ */
+void magic_stop_completely (character_t * c);
+
+/**
+ * Attacks with a magical spell charged to the character
+ *
+ * Returns 0 if there is no charged spell or the spell is depleted.
+ */
+int  spell_attack (int caster, int target);
+
+void spell_free_invocation (struct invocation *invocation);
+
+#endif /* !defined(MAGIC_H_) */
diff --git a/src/map/map.c b/src/map/map.c
deleted file mode 100644
index d840486..0000000
--- a/src/map/map.c
+++ /dev/null
@@ -1,2215 +0,0 @@
-// $Id: map.c,v 1.6 2004/09/25 17:37:01 MouseJstr Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#ifdef LCCWIN32
-#include <winsock.h>
-#else
-#include <netdb.h>
-#endif
-
-#include "../common/core.h"
-#include "../common/timer.h"
-#include "../common/db.h"
-#include "../common/grfio.h"
-#include "../common/mt_rand.h"
-#include "map.h"
-#include "chrif.h"
-#include "clif.h"
-#include "intif.h"
-#include "npc.h"
-#include "pc.h"
-#include "mob.h"
-#include "chat.h"
-#include "itemdb.h"
-#include "storage.h"
-#include "skill.h"
-#include "trade.h"
-#include "party.h"
-#include "battle.h"
-#include "script.h"
-#include "guild.h"
-#include "atcommand.h"
-#include "../common/nullpo.h"
-#include "../common/socket.h"
-#include "magic.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-// 極力 staticでローカルに収める
-static struct dbt *id_db = NULL;
-static struct dbt *map_db = NULL;
-static struct dbt *nick_db = NULL;
-static struct dbt *charid_db = NULL;
-
-static int users = 0;
-static struct block_list *object[MAX_FLOORITEM];
-static int first_free_object_id = 0, last_object_id = 0;
-
-#define block_free_max 1048576
-static void *block_free[block_free_max];
-static int block_free_count = 0, block_free_lock = 0;
-
-#define BL_LIST_MAX 1048576
-static struct block_list *bl_list[BL_LIST_MAX];
-static int bl_list_count = 0;
-
-struct map_data map[MAX_MAP_PER_SERVER];
-int  map_num = 0;
-
-int  map_port = 0;
-
-int  autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-int  save_settings = 0xFFFF;
-int  agit_flag = 0;
-int  night_flag = 0;            // 0=day, 1=night [Yor]
-
-struct charid2nick
-{
-    char nick[24];
-    int  req_id;
-};
-
-char motd_txt[256] = "conf/motd.txt";
-char help_txt[256] = "conf/help.txt";
-
-char wisp_server_name[24] = "Server";   // can be modified in char-server configuration file
-
-/*==========================================
- * 全map鯖総計での接続数設定
- * (char鯖から送られてくる)
- *------------------------------------------
- */
-void map_setusers (int n)
-{
-    users = n;
-}
-
-/*==========================================
- * 全map鯖総計での接続数取得 (/wへの応答用)
- *------------------------------------------
- */
-int map_getusers (void)
-{
-    return users;
-}
-
-//
-// block削除の安全性確保処理
-//
-
-/*==========================================
- * blockをfreeするときfreeの変わりに呼ぶ
- * ロックされているときはバッファにためる
- *------------------------------------------
- */
-int map_freeblock (void *bl)
-{
-    if (block_free_lock == 0)
-    {
-        free (bl);
-        bl = NULL;
-    }
-    else
-    {
-        if (block_free_count >= block_free_max)
-        {
-            if (battle_config.error_log)
-                printf
-                    ("map_freeblock: *WARNING* too many free block! %d %d\n",
-                     block_free_count, block_free_lock);
-        }
-        else
-            block_free[block_free_count++] = bl;
-    }
-    return block_free_lock;
-}
-
-/*==========================================
- * blockのfreeを一時的に禁止する
- *------------------------------------------
- */
-int map_freeblock_lock (void)
-{
-    return ++block_free_lock;
-}
-
-/*==========================================
- * blockのfreeのロックを解除する
- * このとき、ロックが完全になくなると
- * バッファにたまっていたblockを全部削除
- *------------------------------------------
- */
-int map_freeblock_unlock (void)
-{
-    if ((--block_free_lock) == 0)
-    {
-        int  i;
-//      if(block_free_count>0) {
-//          if(battle_config.error_log)
-//              printf("map_freeblock_unlock: free %d object\n",block_free_count);
-//      }
-        for (i = 0; i < block_free_count; i++)
-        {
-            free (block_free[i]);
-            block_free[i] = NULL;
-        }
-        block_free_count = 0;
-    }
-    else if (block_free_lock < 0)
-    {
-        if (battle_config.error_log)
-            printf ("map_freeblock_unlock: lock count < 0 !\n");
-    }
-    return block_free_lock;
-}
-
-//
-// block化処理
-//
-/*==========================================
- * map[]のblock_listから繋がっている場合に
- * bl->prevにbl_headのアドレスを入れておく
- *------------------------------------------
- */
-static struct block_list bl_head;
-
-/*==========================================
- * map[]のblock_listに追加
- * mobは数が多いので別リスト
- *
- * 既にlink済みかの確認が無い。危険かも
- *------------------------------------------
- */
-int map_addblock (struct block_list *bl)
-{
-    int  m, x, y;
-
-    nullpo_retr (0, bl);
-
-    if (bl->prev != NULL)
-    {
-        if (battle_config.error_log)
-            printf ("map_addblock error : bl->prev!=NULL\n");
-        return 0;
-    }
-
-    m = bl->m;
-    x = bl->x;
-    y = bl->y;
-    if (m < 0 || m >= map_num ||
-        x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
-        return 1;
-
-    if (bl->type == BL_MOB)
-    {
-        bl->next =
-            map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs];
-        bl->prev = &bl_head;
-        if (bl->next)
-            bl->next->prev = bl;
-        map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl;
-        map[m].block_mob_count[x / BLOCK_SIZE +
-                               (y / BLOCK_SIZE) * map[m].bxs]++;
-    }
-    else
-    {
-        bl->next =
-            map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs];
-        bl->prev = &bl_head;
-        if (bl->next)
-            bl->next->prev = bl;
-        map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl;
-        map[m].block_count[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs]++;
-        if (bl->type == BL_PC)
-            map[m].users++;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * map[]のblock_listから外す
- * prevがNULLの場合listに繋がってない
- *------------------------------------------
- */
-int map_delblock (struct block_list *bl)
-{
-    int  b;
-    nullpo_retr (0, bl);
-
-    // 既にblocklistから抜けている
-    if (bl->prev == NULL)
-    {
-        if (bl->next != NULL)
-        {
-            // prevがNULLでnextがNULLでないのは有ってはならない
-            if (battle_config.error_log)
-                printf ("map_delblock error : bl->next!=NULL\n");
-        }
-        return 0;
-    }
-
-    b = bl->x / BLOCK_SIZE + (bl->y / BLOCK_SIZE) * map[bl->m].bxs;
-
-    if (bl->type == BL_PC)
-        map[bl->m].users--;
-
-    if (bl->next)
-        bl->next->prev = bl->prev;
-    if (bl->prev == &bl_head)
-    {
-        // リストの頭なので、map[]のblock_listを更新する
-        if (bl->type == BL_MOB)
-        {
-            map[bl->m].block_mob[b] = bl->next;
-            if ((map[bl->m].block_mob_count[b]--) < 0)
-                map[bl->m].block_mob_count[b] = 0;
-        }
-        else
-        {
-            map[bl->m].block[b] = bl->next;
-            if ((map[bl->m].block_count[b]--) < 0)
-                map[bl->m].block_count[b] = 0;
-        }
-    }
-    else
-    {
-        bl->prev->next = bl->next;
-    }
-    bl->next = NULL;
-    bl->prev = NULL;
-
-    return 0;
-}
-
-/*==========================================
- * 周囲のPC人数を数える (現在未使用)
- *------------------------------------------
- */
-int map_countnearpc (int m, int x, int y)
-{
-    int  bx, by, c = 0;
-    struct block_list *bl = NULL;
-
-    if (map[m].users == 0)
-        return 0;
-    for (by = y / BLOCK_SIZE - AREA_SIZE / BLOCK_SIZE - 1;
-         by <= y / BLOCK_SIZE + AREA_SIZE / BLOCK_SIZE + 1; by++)
-    {
-        if (by < 0 || by >= map[m].bys)
-            continue;
-        for (bx = x / BLOCK_SIZE - AREA_SIZE / BLOCK_SIZE - 1;
-             bx <= x / BLOCK_SIZE + AREA_SIZE / BLOCK_SIZE + 1; bx++)
-        {
-            if (bx < 0 || bx >= map[m].bxs)
-                continue;
-            bl = map[m].block[bx + by * map[m].bxs];
-            for (; bl; bl = bl->next)
-            {
-                if (bl->type == BL_PC)
-                    c++;
-            }
-        }
-    }
-    return c;
-}
-
-/*==========================================
- * セル上のPCとMOBの数を数える (グランドクロス用)
- *------------------------------------------
- */
-int map_count_oncell (int m, int x, int y)
-{
-    int  bx, by;
-    struct block_list *bl = NULL;
-    int  i, c;
-    int  count = 0;
-
-    if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
-        return 1;
-    bx = x / BLOCK_SIZE;
-    by = y / BLOCK_SIZE;
-
-    bl = map[m].block[bx + by * map[m].bxs];
-    c = map[m].block_count[bx + by * map[m].bxs];
-    for (i = 0; i < c && bl; i++, bl = bl->next)
-    {
-        if (bl->x == x && bl->y == y && bl->type == BL_PC)
-            count++;
-    }
-    bl = map[m].block_mob[bx + by * map[m].bxs];
-    c = map[m].block_mob_count[bx + by * map[m].bxs];
-    for (i = 0; i < c && bl; i++, bl = bl->next)
-    {
-        if (bl->x == x && bl->y == y)
-            count++;
-    }
-    if (!count)
-        count = 1;
-    return count;
-}
-
-/*==========================================
- * map m (x0,y0)-(x1,y1)内の全objに対して
- * funcを呼ぶ
- * type!=0 ならその種類のみ
- *------------------------------------------
- */
-void map_foreachinarea (int (*func) (struct block_list *, va_list), int m,
-                        int x0, int y0, int x1, int y1, int type, ...)
-{
-    int  bx, by;
-    struct block_list *bl = NULL;
-    va_list ap = NULL;
-    int  blockcount = bl_list_count, i, c;
-
-    if (m < 0)
-        return;
-    va_start (ap, type);
-    if (x0 < 0)
-        x0 = 0;
-    if (y0 < 0)
-        y0 = 0;
-    if (x1 >= map[m].xs)
-        x1 = map[m].xs - 1;
-    if (y1 >= map[m].ys)
-        y1 = map[m].ys - 1;
-    if (type == 0 || type != BL_MOB)
-        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
-        {
-            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
-            {
-                bl = map[m].block[bx + by * map[m].bxs];
-                c = map[m].block_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && type && bl->type != type)
-                        continue;
-                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-            }
-        }
-    if (type == 0 || type == BL_MOB)
-        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
-        {
-            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
-            {
-                bl = map[m].block_mob[bx + by * map[m].bxs];
-                c = map[m].block_mob_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-            }
-        }
-
-    if (bl_list_count >= BL_LIST_MAX)
-    {
-        if (battle_config.error_log)
-            printf ("map_foreachinarea: *WARNING* block count too many!\n");
-    }
-
-    map_freeblock_lock ();      // メモリからの解放を禁止する
-
-    for (i = blockcount; i < bl_list_count; i++)
-        if (bl_list[i]->prev)   // 有効かどうかチェック
-            func (bl_list[i], ap);
-
-    map_freeblock_unlock ();    // 解放を許可する
-
-    va_end (ap);
-    bl_list_count = blockcount;
-}
-
-/*==========================================
- * 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した時の
- * 領域外になる領域(矩形かL字形)内のobjに
- * 対してfuncを呼ぶ
- *
- * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
- *------------------------------------------
- */
-void map_foreachinmovearea (int (*func) (struct block_list *, va_list), int m,
-                            int x0, int y0, int x1, int y1, int dx, int dy,
-                            int type, ...)
-{
-    int  bx, by;
-    struct block_list *bl = NULL;
-    va_list ap = NULL;
-    int  blockcount = bl_list_count, i, c;
-
-    va_start (ap, type);
-    if (dx == 0 || dy == 0)
-    {
-        // 矩形領域の場合
-        if (dx == 0)
-        {
-            if (dy < 0)
-            {
-                y0 = y1 + dy + 1;
-            }
-            else
-            {
-                y1 = y0 + dy - 1;
-            }
-        }
-        else if (dy == 0)
-        {
-            if (dx < 0)
-            {
-                x0 = x1 + dx + 1;
-            }
-            else
-            {
-                x1 = x0 + dx - 1;
-            }
-        }
-        if (x0 < 0)
-            x0 = 0;
-        if (y0 < 0)
-            y0 = 0;
-        if (x1 >= map[m].xs)
-            x1 = map[m].xs - 1;
-        if (y1 >= map[m].ys)
-            y1 = map[m].ys - 1;
-        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
-        {
-            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
-            {
-                bl = map[m].block[bx + by * map[m].bxs];
-                c = map[m].block_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && type && bl->type != type)
-                        continue;
-                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-                bl = map[m].block_mob[bx + by * map[m].bxs];
-                c = map[m].block_mob_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && type && bl->type != type)
-                        continue;
-                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-            }
-        }
-    }
-    else
-    {
-        // L字領域の場合
-
-        if (x0 < 0)
-            x0 = 0;
-        if (y0 < 0)
-            y0 = 0;
-        if (x1 >= map[m].xs)
-            x1 = map[m].xs - 1;
-        if (y1 >= map[m].ys)
-            y1 = map[m].ys - 1;
-        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
-        {
-            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
-            {
-                bl = map[m].block[bx + by * map[m].bxs];
-                c = map[m].block_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && type && bl->type != type)
-                        continue;
-                    if ((bl)
-                        && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                             && bl->y <= y1))
-                        continue;
-                    if ((bl)
-                        && ((dx > 0 && bl->x < x0 + dx)
-                            || (dx < 0 && bl->x > x1 + dx) || (dy > 0
-                                                               && bl->y <
-                                                               y0 + dy)
-                            || (dy < 0 && bl->y > y1 + dy))
-                        && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-                bl = map[m].block_mob[bx + by * map[m].bxs];
-                c = map[m].block_mob_count[bx + by * map[m].bxs];
-                for (i = 0; i < c && bl; i++, bl = bl->next)
-                {
-                    if (bl && type && bl->type != type)
-                        continue;
-                    if ((bl)
-                        && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0
-                             && bl->y <= y1))
-                        continue;
-                    if ((bl)
-                        && ((dx > 0 && bl->x < x0 + dx)
-                            || (dx < 0 && bl->x > x1 + dx) || (dy > 0
-                                                               && bl->y <
-                                                               y0 + dy)
-                            || (dy < 0 && bl->y > y1 + dy))
-                        && bl_list_count < BL_LIST_MAX)
-                        bl_list[bl_list_count++] = bl;
-                }
-            }
-        }
-
-    }
-
-    if (bl_list_count >= BL_LIST_MAX)
-    {
-        if (battle_config.error_log)
-            printf ("map_foreachinarea: *WARNING* block count too many!\n");
-    }
-
-    map_freeblock_lock ();      // メモリからの解放を禁止する
-
-    for (i = blockcount; i < bl_list_count; i++)
-        if (bl_list[i]->prev)   // 有効かどうかチェック
-            func (bl_list[i], ap);
-
-    map_freeblock_unlock ();    // 解放を許可する
-
-    va_end (ap);
-    bl_list_count = blockcount;
-}
-
-// -- moonsoul  (added map_foreachincell which is a rework of map_foreachinarea but
-//           which only checks the exact single x/y passed to it rather than an
-//           area radius - may be more useful in some instances)
-//
-void map_foreachincell (int (*func) (struct block_list *, va_list), int m,
-                        int x, int y, int type, ...)
-{
-    int  bx, by;
-    struct block_list *bl = NULL;
-    va_list ap = NULL;
-    int  blockcount = bl_list_count, i, c;
-
-    va_start (ap, type);
-
-    by = y / BLOCK_SIZE;
-    bx = x / BLOCK_SIZE;
-
-    if (type == 0 || type != BL_MOB)
-    {
-        bl = map[m].block[bx + by * map[m].bxs];
-        c = map[m].block_count[bx + by * map[m].bxs];
-        for (i = 0; i < c && bl; i++, bl = bl->next)
-        {
-            if (type && bl && bl->type != type)
-                continue;
-            if (bl && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX)
-                bl_list[bl_list_count++] = bl;
-        }
-    }
-
-    if (type == 0 || type == BL_MOB)
-    {
-        bl = map[m].block_mob[bx + by * map[m].bxs];
-        c = map[m].block_mob_count[bx + by * map[m].bxs];
-        for (i = 0; i < c && bl; i++, bl = bl->next)
-        {
-            if (bl && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX)
-                bl_list[bl_list_count++] = bl;
-        }
-    }
-
-    if (bl_list_count >= BL_LIST_MAX)
-    {
-        if (battle_config.error_log)
-            printf ("map_foreachincell: *WARNING* block count too many!\n");
-    }
-
-    map_freeblock_lock ();      // メモリからの解放を禁止する
-
-    for (i = blockcount; i < bl_list_count; i++)
-        if (bl_list[i]->prev)   // 有効かどうかチェック
-            func (bl_list[i], ap);
-
-    map_freeblock_unlock ();    // 解放を許可する
-
-    va_end (ap);
-    bl_list_count = blockcount;
-}
-
-/*==========================================
- * 床アイテムやエフェクト用の一時obj割り当て
- * object[]への保存とid_db登録まで
- *
- * bl->idもこの中で設定して問題無い?
- *------------------------------------------
- */
-int map_addobject (struct block_list *bl)
-{
-    int  i;
-    if (bl == NULL)
-    {
-        printf ("map_addobject nullpo?\n");
-        return 0;
-    }
-    if (first_free_object_id < 2 || first_free_object_id >= MAX_FLOORITEM)
-        first_free_object_id = 2;
-    for (i = first_free_object_id; i < MAX_FLOORITEM; i++)
-        if (object[i] == NULL)
-            break;
-    if (i >= MAX_FLOORITEM)
-    {
-        if (battle_config.error_log)
-            printf ("no free object id\n");
-        return 0;
-    }
-    first_free_object_id = i;
-    if (last_object_id < i)
-        last_object_id = i;
-    object[i] = bl;
-    numdb_insert (id_db, i, bl);
-    return i;
-}
-
-/*==========================================
- * 一時objectの解放
- *	map_delobjectのfreeしないバージョン
- *------------------------------------------
- */
-int map_delobjectnofree (int id, int type)
-{
-    if (object[id] == NULL)
-        return 0;
-
-    if (object[id]->type != type)
-    {
-        fprintf (stderr, "Incorrect type: expected %d, got %d\n", type,
-                 object[id]->type);
-        *((char *) 0) = 0;      // break for backtrace
-    }
-
-    map_delblock (object[id]);
-    numdb_erase (id_db, id);
-//  map_freeblock(object[id]);
-    object[id] = NULL;
-
-    if (first_free_object_id > id)
-        first_free_object_id = id;
-
-    while (last_object_id > 2 && object[last_object_id] == NULL)
-        last_object_id--;
-
-    return 0;
-}
-
-/*==========================================
- * 一時objectの解放
- * block_listからの削除、id_dbからの削除
- * object dataのfree、object[]へのNULL代入
- *
- * addとの対称性が無いのが気になる
- *------------------------------------------
- */
-int map_delobject (int id, int type)
-{
-    struct block_list *obj = object[id];
-
-    if (obj == NULL)
-        return 0;
-
-    map_delobjectnofree (id, type);
-    if (obj->type == BL_PC)     // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from
-        pc_cleanup ((struct map_session_data *) obj);
-
-    map_freeblock (obj);
-
-    return 0;
-}
-
-/*==========================================
- * 全一時obj相手にfuncを呼ぶ
- *
- *------------------------------------------
- */
-void map_foreachobject (int (*func) (struct block_list *, va_list), int type,
-                        ...)
-{
-    int  i;
-    int  blockcount = bl_list_count;
-    va_list ap = NULL;
-
-    va_start (ap, type);
-
-    for (i = 2; i <= last_object_id; i++)
-    {
-        if (object[i])
-        {
-            if (type && object[i]->type != type)
-                continue;
-            if (bl_list_count >= BL_LIST_MAX)
-            {
-                if (battle_config.error_log)
-                    printf ("map_foreachobject: too many block !\n");
-            }
-            else
-                bl_list[bl_list_count++] = object[i];
-        }
-    }
-
-    map_freeblock_lock ();
-
-    for (i = blockcount; i < bl_list_count; i++)
-        if (bl_list[i]->prev || bl_list[i]->next)
-            func (bl_list[i], ap);
-
-    map_freeblock_unlock ();
-
-    va_end (ap);
-    bl_list_count = blockcount;
-}
-
-/*==========================================
- * 床アイテムを消す
- *
- * data==0の時はtimerで消えた時
- * data!=0の時は拾う等で消えた時として動作
- *
- * 後者は、map_clearflooritem(id)へ
- * map.h内で#defineしてある
- *------------------------------------------
- */
-void map_clearflooritem_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct flooritem_data *fitem = NULL;
-
-    fitem = (struct flooritem_data *) object[id];
-    if (fitem == NULL || fitem->bl.type != BL_ITEM
-        || (!data && fitem->cleartimer != tid))
-    {
-        if (battle_config.error_log)
-            printf ("map_clearflooritem_timer : error\n");
-        return;
-    }
-    if (data)
-        delete_timer (fitem->cleartimer, map_clearflooritem_timer);
-    clif_clearflooritem (fitem, 0);
-    map_delobject (fitem->bl.id, BL_ITEM);
-}
-
-/*==========================================
- * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの
- * 内から適当なマス目の座標をx+(y<<16)で返す
- *
- * 現状range=1でアイテムドロップ用途のみ
- *------------------------------------------
- */
-int map_searchrandfreecell (int m, int x, int y, int range)
-{
-    int  free_cell, i, j, c;
-
-    for (free_cell = 0, i = -range; i <= range; i++)
-    {
-        if (i + y < 0 || i + y >= map[m].ys)
-            continue;
-        for (j = -range; j <= range; j++)
-        {
-            if (j + x < 0 || j + x >= map[m].xs)
-                continue;
-            if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5)
-                continue;
-            free_cell++;
-        }
-    }
-    if (free_cell == 0)
-        return -1;
-    free_cell = MRAND (free_cell);
-    for (i = -range; i <= range; i++)
-    {
-        if (i + y < 0 || i + y >= map[m].ys)
-            continue;
-        for (j = -range; j <= range; j++)
-        {
-            if (j + x < 0 || j + x >= map[m].xs)
-                continue;
-            if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5)
-                continue;
-            if (free_cell == 0)
-            {
-                x += j;
-                y += i;
-                i = range + 1;
-                break;
-            }
-            free_cell--;
-        }
-    }
-
-    return x + (y << 16);
-}
-
-/*==========================================
- * (m,x,y)を中心に3x3以内に床アイテム設置
- *
- * item_dataはamount以外をcopyする
- *------------------------------------------
- */
-int map_addflooritem_any (struct item *item_data, int amount, int m, int x,
-                          int y, struct map_session_data **owners,
-                          int *owner_protection, int lifetime, int dispersal)
-{
-    int  xy, r;
-    unsigned int tick;
-    struct flooritem_data *fitem = NULL;
-
-    nullpo_retr (0, item_data);
-
-    if ((xy = map_searchrandfreecell (m, x, y, dispersal)) < 0)
-        return 0;
-    r = mt_random ();
-
-    CREATE (fitem, struct flooritem_data, 1);
-    fitem->bl.type = BL_ITEM;
-    fitem->bl.prev = fitem->bl.next = NULL;
-    fitem->bl.m = m;
-    fitem->bl.x = xy & 0xffff;
-    fitem->bl.y = (xy >> 16) & 0xffff;
-    fitem->first_get_id = 0;
-    fitem->first_get_tick = 0;
-    fitem->second_get_id = 0;
-    fitem->second_get_tick = 0;
-    fitem->third_get_id = 0;
-    fitem->third_get_tick = 0;
-
-    fitem->bl.id = map_addobject (&fitem->bl);
-    if (fitem->bl.id == 0)
-    {
-        free (fitem);
-        return 0;
-    }
-
-    tick = gettick ();
-
-    if (owners[0])
-        fitem->first_get_id = owners[0]->bl.id;
-    fitem->first_get_tick = tick + owner_protection[0];
-
-    if (owners[1])
-        fitem->second_get_id = owners[1]->bl.id;
-    fitem->second_get_tick = tick + owner_protection[1];
-
-    if (owners[2])
-        fitem->third_get_id = owners[2]->bl.id;
-    fitem->third_get_tick = tick + owner_protection[2];
-
-    memcpy (&fitem->item_data, item_data, sizeof (*item_data));
-    fitem->item_data.amount = amount;
-    fitem->subx = (r & 3) * 3 + 3;
-    fitem->suby = ((r >> 2) & 3) * 3 + 3;
-    fitem->cleartimer =
-        add_timer (gettick () + lifetime, map_clearflooritem_timer,
-                   fitem->bl.id, 0);
-
-    map_addblock (&fitem->bl);
-    clif_dropflooritem (fitem);
-
-    return fitem->bl.id;
-}
-
-int map_addflooritem (struct item *item_data, int amount, int m, int x, int y,
-                      struct map_session_data *first_sd,
-                      struct map_session_data *second_sd,
-                      struct map_session_data *third_sd, int type)
-{
-    struct map_session_data *owners[3] = { first_sd, second_sd, third_sd };
-    int  owner_protection[3];
-
-    if (type)
-    {
-        owner_protection[0] = battle_config.mvp_item_first_get_time;
-        owner_protection[1] =
-            owner_protection[0] + battle_config.mvp_item_second_get_time;
-        owner_protection[2] =
-            owner_protection[1] + battle_config.mvp_item_third_get_time;
-    }
-    else
-    {
-        owner_protection[0] = battle_config.item_first_get_time;
-        owner_protection[1] =
-            owner_protection[0] + battle_config.item_second_get_time;
-        owner_protection[2] =
-            owner_protection[1] + battle_config.item_third_get_time;
-    }
-
-    return map_addflooritem_any (item_data, amount, m, x, y,
-                                 owners, owner_protection,
-                                 battle_config.flooritem_lifetime, 1);
-}
-
-/* 	int xy,r; */
-/* 	unsigned int tick; */
-/* 	struct flooritem_data *fitem=NULL; */
-
-/* 	nullpo_retr(0, item_data); */
-
-/* 	if((xy=map_searchrandfreecell(m,x,y,1))<0) */
-/* 		return 0; */
-/* 	r=rand(); */
-
-/* 	fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem)); */
-/* 	fitem->bl.type=BL_ITEM; */
-/* 	fitem->bl.prev = fitem->bl.next = NULL; */
-/* 	fitem->bl.m=m; */
-/* 	fitem->bl.x=xy&0xffff; */
-/* 	fitem->bl.y=(xy>>16)&0xffff; */
-/* 	fitem->first_get_id = 0; */
-/* 	fitem->first_get_tick = 0; */
-/* 	fitem->second_get_id = 0; */
-/* 	fitem->second_get_tick = 0; */
-/* 	fitem->third_get_id = 0; */
-/* 	fitem->third_get_tick = 0; */
-
-/* 	fitem->bl.id = map_addobject(&fitem->bl); */
-/* 	if(fitem->bl.id==0){ */
-/* 		free(fitem); */
-/* 		return 0; */
-/* 	} */
-
-/* 	tick = gettick(); */
-/* 	if(first_sd) { */
-/* 		fitem->first_get_id = first_sd->bl.id; */
-/* 		if(type) */
-/* 			fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time; */
-/* 		else */
-/* 			fitem->first_get_tick = tick + battle_config.item_first_get_time; */
-/* 	} */
-/* 	if(second_sd) { */
-/* 		fitem->second_get_id = second_sd->bl.id; */
-/* 		if(type) */
-/* 			fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time; */
-/* 		else */
-/* 			fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time; */
-/* 	} */
-/* 	if(third_sd) { */
-/* 		fitem->third_get_id = third_sd->bl.id; */
-/* 		if(type) */
-/* 			fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time; */
-/* 		else */
-/* 			fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time; */
-/* 	} */
-
-/* 	memcpy(&fitem->item_data,item_data,sizeof(*item_data)); */
-/* 	fitem->item_data.amount=amount; */
-/* 	fitem->subx=(r&3)*3+3; */
-/* 	fitem->suby=((r>>2)&3)*3+3; */
-/* 	fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); */
-
-/* 	map_addblock(&fitem->bl); */
-/* 	clif_dropflooritem(fitem); */
-
-/* 	return fitem->bl.id; */
-/* } */
-
-/*==========================================
- * charid_dbへ追加(返信待ちがあれば返信)
- *------------------------------------------
- */
-void map_addchariddb (int charid, char *name)
-{
-    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid);
-    if (p == NULL)
-    {                           // データベースにない
-        CREATE (p, struct charid2nick, 1);
-        p->req_id = 0;
-    }
-    else
-        numdb_erase (charid_db, charid);
-
-    int req = p->req_id;
-    memcpy (p->nick, name, 24);
-    p->req_id = 0;
-    numdb_insert (charid_db, charid, p);
-    if (req)
-    {                           // 返信待ちがあれば返信
-        struct map_session_data *sd = map_id2sd (req);
-        if (sd != NULL)
-            clif_solved_charname (sd, charid);
-    }
-}
-
-/*==========================================
- * charid_dbへ追加(返信要求のみ)
- *------------------------------------------
- */
-int map_reqchariddb (struct map_session_data *sd, int charid)
-{
-    nullpo_retr (0, sd);
-
-    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid);
-    if (p != NULL)              // データベースにすでにある
-        return 0;
-    CREATE (p, struct charid2nick, 1);
-    p->req_id = sd->bl.id;
-    numdb_insert (charid_db, charid, p);
-    return 0;
-}
-
-/*==========================================
- * id_dbへblを追加
- *------------------------------------------
- */
-void map_addiddb (struct block_list *bl)
-{
-    nullpo_retv (bl);
-
-    numdb_insert (id_db, bl->id, bl);
-}
-
-/*==========================================
- * id_dbからblを削除
- *------------------------------------------
- */
-void map_deliddb (struct block_list *bl)
-{
-    nullpo_retv (bl);
-
-    numdb_erase (id_db, bl->id);
-}
-
-/*==========================================
- * nick_dbへsdを追加
- *------------------------------------------
- */
-void map_addnickdb (struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    strdb_insert (nick_db, sd->status.name, sd);
-}
-
-/*==========================================
- * PCのquit処理 map.c内分
- *
- * quit処理の主体が違うような気もしてきた
- *------------------------------------------
- */
-int map_quit (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->chatID)             // チャットから出る
-        chat_leavechat (sd);
-
-    if (sd->trade_partner)      // 取引を中断する
-        trade_tradecancel (sd);
-
-    if (sd->party_invite > 0)   // パーティ勧誘を拒否する
-        party_reply_invite (sd, sd->party_invite_account, 0);
-
-    if (sd->guild_invite > 0)   // ギルド勧誘を拒否する
-        guild_reply_invite (sd, sd->guild_invite, 0);
-    if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する
-        guild_reply_reqalliance (sd, sd->guild_alliance_account, 0);
-
-    party_send_logout (sd);     // パーティのログアウトメッセージ送信
-
-    guild_send_memberinfoshort (sd, 0); // ギルドのログアウトメッセージ送信
-
-    pc_cleareventtimer (sd);    // イベントタイマを破棄する
-
-    skill_castcancel (&sd->bl, 0);  // 詠唱を中断する
-    skill_stop_dancing (&sd->bl, 1);    // ダンス/演奏中断
-
-    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中の終了はHPを100に
-        sd->status.hp = 100;
-
-    skill_status_change_clear (&sd->bl, 1); // ステータス異常を解除する
-    skill_clear_unitgroup (&sd->bl);    // スキルユニットグループの削除
-    skill_cleartimerskill (&sd->bl);
-    pc_stop_walking (sd, 0);
-    pc_stopattack (sd);
-    pc_delinvincibletimer (sd);
-    pc_delspiritball (sd, sd->spiritball, 1);
-    skill_gangsterparadise (sd, 0);
-
-    pc_calcstatus (sd, 4);
-
-    clif_clearchar_area (&sd->bl, 2);
-
-    if (pc_isdead (sd))
-        pc_setrestartvalue (sd, 2);
-    pc_makesavestatus (sd);
-    //クローンスキルで覚えたスキルは消す
-
-    //The storage closing routines will save the char if needed. [Skotlex]
-    if (!sd->state.storage_flag)
-        chrif_save (sd);
-    else if (sd->state.storage_flag == 1)
-        storage_storage_quit (sd);
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storage_quit (sd, 1);
-
-    if (sd->npc_stackbuf && sd->npc_stackbuf != NULL)
-        free (sd->npc_stackbuf);
-
-    map_delblock (&sd->bl);
-
-    numdb_erase (id_db, sd->bl.id);
-    strdb_erase (nick_db, sd->status.name);
-    numdb_erase (charid_db, sd->status.char_id);
-
-    return 0;
-}
-
-/*==========================================
- * id番号のPCを探す。居なければNULL
- *------------------------------------------
- */
-struct map_session_data *map_id2sd (int id)
-{
-// remove search from db, because:
-// 1 - all players, npc, items and mob are in this db (to search, it's not speed, and search in session is more sure)
-// 2 - DB seems not always correct. Sometimes, when a player disconnects, its id (account value) is not removed and structure
-//     point to a memory area that is not more a session_data and value are incorrect (or out of available memory) -> crash
-// replaced by searching in all session.
-// by searching in session, we are sure that fd, session, and account exist.
-/*
-	struct block_list *bl;
-
-	bl=numdb_search(id_db,id);
-	if(bl && bl->type==BL_PC)
-		return (struct map_session_data*)bl;
-	return NULL;
-*/
-    int  i;
-    struct map_session_data *sd = NULL;
-
-    for (i = 0; i < fd_max; i++)
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->bl.id == id)
-            return sd;
-
-    return NULL;
-}
-
-/*==========================================
- * char_id番号の名前を探す
- *------------------------------------------
- */
-char *map_charid2nick (int id)
-{
-    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, id);
-
-    if (p == NULL)
-        return NULL;
-    if (p->req_id != 0)
-        return NULL;
-    return p->nick;
-}
-
-/*========================================*/
-/* [Fate] Operations to iterate over active map sessions */
-
-static struct map_session_data *map_get_session (int i)
-{
-    struct map_session_data *d;
-
-    if (i >= 0 && i < fd_max
-        && session[i] && (d = (struct map_session_data *)session[i]->session_data) && d->state.auth)
-        return d;
-
-    return NULL;
-}
-
-static struct map_session_data *map_get_session_forward (int start)
-{
-    int  i;
-    for (i = start; i < fd_max; i++)
-    {
-        struct map_session_data *d = map_get_session (i);
-        if (d)
-            return d;
-    }
-
-    return NULL;
-}
-
-static struct map_session_data *map_get_session_backward (int start)
-{
-    int  i;
-    for (i = start; i >= 0; i--)
-    {
-        struct map_session_data *d = map_get_session (i);
-        if (d)
-            return d;
-    }
-
-    return NULL;
-}
-
-struct map_session_data *map_get_first_session (void)
-{
-    return map_get_session_forward (0);
-}
-
-struct map_session_data *map_get_next_session (struct map_session_data *d)
-{
-    return map_get_session_forward (d->fd + 1);
-}
-
-struct map_session_data *map_get_last_session (void)
-{
-    return map_get_session_backward (fd_max);
-}
-
-struct map_session_data *map_get_prev_session (struct map_session_data *d)
-{
-    return map_get_session_backward (d->fd - 1);
-}
-
-/*==========================================
- * Search session data from a nick name
- * (without sensitive case if necessary)
- * return map_session_data pointer or NULL
- *------------------------------------------
- */
-struct map_session_data *map_nick2sd (char *nick)
-{
-    int  i, quantity = 0, nicklen;
-    struct map_session_data *sd = NULL;
-    struct map_session_data *pl_sd = NULL;
-
-    if (nick == NULL)
-        return NULL;
-
-    nicklen = strlen (nick);
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-            && pl_sd->state.auth)
-        {
-            // Without case sensitive check (increase the number of similar character names found)
-            if (strncasecmp (pl_sd->status.name, nick, nicklen) == 0)
-            {
-                // Strict comparison (if found, we finish the function immediatly with correct value)
-                if (strcmp (pl_sd->status.name, nick) == 0)
-                    return pl_sd;
-                quantity++;
-                sd = pl_sd;
-            }
-        }
-    }
-    // Here, the exact character name is not found
-    // We return the found index of a similar account ONLY if there is 1 similar character
-    if (quantity == 1)
-        return sd;
-
-    // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
-    return NULL;
-}
-
-/*==========================================
- * id番号の物を探す
- * 一時objectの場合は配列を引くのみ
- *------------------------------------------
- */
-struct block_list *map_id2bl (int id)
-{
-    struct block_list *bl = NULL;
-    if (id < sizeof (object) / sizeof (object[0]))
-        bl = object[id];
-    else
-        bl = (struct block_list *)numdb_search (id_db, id);
-
-    return bl;
-}
-
-/*==========================================
- * id_db内の全てにfuncを実行
- *------------------------------------------
- */
-int map_foreachiddb (db_func_t func, ...)
-{
-    va_list ap = NULL;
-
-    va_start (ap, func);
-    numdb_foreach (id_db, func, ap);
-    va_end (ap);
-    return 0;
-}
-
-/*==========================================
- * map.npcへ追加 (warp等の領域持ちのみ)
- *------------------------------------------
- */
-int map_addnpc (int m, struct npc_data *nd)
-{
-    int  i;
-    if (m < 0 || m >= map_num)
-        return -1;
-    for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++)
-        if (map[m].npc[i] == NULL)
-            break;
-    if (i == MAX_NPC_PER_MAP)
-    {
-        if (battle_config.error_log)
-            printf ("too many NPCs in one map %s\n", map[m].name);
-        return -1;
-    }
-    if (i == map[m].npc_num)
-    {
-        map[m].npc_num++;
-    }
-
-    nullpo_retr (0, nd);
-
-    map[m].npc[i] = nd;
-    nd->n = i;
-    numdb_insert (id_db, nd->bl.id, nd);
-
-    return i;
-}
-
-void map_removenpc (void)
-{
-    int  i, m, n = 0;
-
-    for (m = 0; m < map_num; m++)
-    {
-        for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++)
-        {
-            if (map[m].npc[i] != NULL)
-            {
-                clif_clearchar_area (&map[m].npc[i]->bl, 2);
-                map_delblock (&map[m].npc[i]->bl);
-                numdb_erase (id_db, map[m].npc[i]->bl.id);
-                if (map[m].npc[i]->bl.subtype == SCRIPT)
-                {
-//                    free(map[m].npc[i]->u.scr.script);
-//                    free(map[m].npc[i]->u.scr.label_list);
-                }
-                free (map[m].npc[i]);
-                map[m].npc[i] = NULL;
-                n++;
-            }
-        }
-    }
-    printf ("%d NPCs removed.\n", n);
-}
-
-/*==========================================
- * map名からmap番号へ変換
- *------------------------------------------
- */
-int map_mapname2mapid (char *name)
-{
-    struct map_data *md = (struct map_data *)strdb_search (map_db, name);
-    if (md == NULL || md->gat == NULL)
-        return -1;
-    return md->m;
-}
-
-/*==========================================
- * 他鯖map名からip,port変換
- *------------------------------------------
- */
-int map_mapname2ipport (char *name, int *ip, int *port)
-{
-    struct map_data_other_server *mdos = (struct map_data_other_server *)strdb_search (map_db, name);
-    if (mdos == NULL || mdos->gat)
-        return -1;
-    *ip = mdos->ip;
-    *port = mdos->port;
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int map_check_dir (int s_dir, int t_dir)
-{
-    if (s_dir == t_dir)
-        return 0;
-    switch (s_dir)
-    {
-        case 0:
-            if (t_dir == 7 || t_dir == 1 || t_dir == 0)
-                return 0;
-            break;
-        case 1:
-            if (t_dir == 0 || t_dir == 2 || t_dir == 1)
-                return 0;
-            break;
-        case 2:
-            if (t_dir == 1 || t_dir == 3 || t_dir == 2)
-                return 0;
-            break;
-        case 3:
-            if (t_dir == 2 || t_dir == 4 || t_dir == 3)
-                return 0;
-            break;
-        case 4:
-            if (t_dir == 3 || t_dir == 5 || t_dir == 4)
-                return 0;
-            break;
-        case 5:
-            if (t_dir == 4 || t_dir == 6 || t_dir == 5)
-                return 0;
-            break;
-        case 6:
-            if (t_dir == 5 || t_dir == 7 || t_dir == 6)
-                return 0;
-            break;
-        case 7:
-            if (t_dir == 6 || t_dir == 0 || t_dir == 7)
-                return 0;
-            break;
-    }
-    return 1;
-}
-
-/*==========================================
- * 彼我の方向を計算
- *------------------------------------------
- */
-int map_calc_dir (struct block_list *src, int x, int y)
-{
-    int  dir = 0;
-    int  dx, dy;
-
-    nullpo_retr (0, src);
-
-    dx = x - src->x;
-    dy = y - src->y;
-    if (dx == 0 && dy == 0)
-    {                           // 彼我の場所一致
-        dir = 0;                // 上
-    }
-    else if (dx >= 0 && dy >= 0)
-    {                           // 方向的に右上
-        dir = 7;                // 右上
-        if (dx * 3 - 1 < dy)
-            dir = 0;            // 上
-        if (dx > dy * 3)
-            dir = 6;            // 右
-    }
-    else if (dx >= 0 && dy <= 0)
-    {                           // 方向的に右下
-        dir = 5;                // 右下
-        if (dx * 3 - 1 < -dy)
-            dir = 4;            // 下
-        if (dx > -dy * 3)
-            dir = 6;            // 右
-    }
-    else if (dx <= 0 && dy <= 0)
-    {                           // 方向的に左下
-        dir = 3;                // 左下
-        if (dx * 3 + 1 > dy)
-            dir = 4;            // 下
-        if (dx < dy * 3)
-            dir = 2;            // 左
-    }
-    else
-    {                           // 方向的に左上
-        dir = 1;                // 左上
-        if (-dx * 3 - 1 < dy)
-            dir = 0;            // 上
-        if (-dx > dy * 3)
-            dir = 2;            // 左
-    }
-    return dir;
-}
-
-// gat系
-/*==========================================
- * (m,x,y)の状態を調べる
- *------------------------------------------
- */
-int map_getcell (int m, int x, int y)
-{
-    if (x < 0 || x >= map[m].xs - 1 || y < 0 || y >= map[m].ys - 1)
-        return 1;
-    return map[m].gat[x + y * map[m].xs];
-}
-
-/*==========================================
- * (m,x,y)の状態をtにする
- *------------------------------------------
- */
-int map_setcell (int m, int x, int y, int t)
-{
-    if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
-        return t;
-    return map[m].gat[x + y * map[m].xs] = t;
-}
-
-/*==========================================
- * 他鯖管理のマップをdbに追加
- *------------------------------------------
- */
-int map_setipport (char *name, unsigned long ip, int port)
-{
-    struct map_data_other_server *mdos = NULL;
-
-    struct map_data *md = (struct map_data *)strdb_search (map_db, name);
-    if (md == NULL)
-    {                           // not exist -> add new data
-        CREATE (mdos, struct map_data_other_server, 1);
-        memcpy (mdos->name, name, 24);
-        mdos->gat = NULL;
-        mdos->ip = ip;
-        mdos->port = port;
-        strdb_insert (map_db, mdos->name, mdos);
-    }
-    else
-    {
-        if (md->gat)
-        {                       // local -> check data
-            if (ip != clif_getip () || port != clif_getport ())
-            {
-                printf ("from char server : %s -> %08lx:%d\n", name, ip,
-                        port);
-                return 1;
-            }
-        }
-        else
-        {                       // update
-            mdos = (struct map_data_other_server *) md;
-            mdos->ip = ip;
-            mdos->port = port;
-        }
-    }
-    return 0;
-}
-
-// 初期化周り
-/*==========================================
- * 水場高さ設定
- *------------------------------------------
- */
-static struct Waterlist
-{
-    char mapname[24];
-    int  waterheight;
-}   *waterlist = NULL;
-
-#define NO_WATER 1000000
-
-static int map_waterheight (char *mapname)
-{
-    if (waterlist)
-    {
-        int  i;
-        for (i = 0; waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER; i++)
-            if (strcmp (waterlist[i].mapname, mapname) == 0)
-                return waterlist[i].waterheight;
-    }
-    return NO_WATER;
-}
-
-static void map_readwater (char *watertxt)
-{
-    char line[1024], w1[1024];
-    FILE *fp = NULL;
-    int  n = 0;
-
-    fp = fopen_ (watertxt, "r");
-    if (fp == NULL)
-    {
-        printf ("file not found: %s\n", watertxt);
-        return;
-    }
-    if (waterlist == NULL)
-    {
-        CREATE (waterlist, struct Waterlist, MAX_MAP_PER_SERVER);
-    }
-    while (fgets (line, 1020, fp) && n < MAX_MAP_PER_SERVER)
-    {
-        int  wh, count;
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if ((count = sscanf (line, "%s%d", w1, &wh)) < 1)
-        {
-            continue;
-        }
-        strcpy (waterlist[n].mapname, w1);
-        if (count >= 2)
-            waterlist[n].waterheight = wh;
-        else
-            waterlist[n].waterheight = 3;
-        n++;
-    }
-    fclose_ (fp);
-}
-
-/*==========================================
- * マップ1枚読み込み
- *------------------------------------------
- */
-static int map_readmap (int m, char *fn, char *alias)
-{
-    int  s;
-    int  x, y, xs, ys;
-    struct gat_1cell
-    {
-        char type;
-    }   *p;
-    int  wh;
-    size_t size;
-
-    // read & convert fn
-    uint8_t *gat = (uint8_t *)grfio_read (fn);
-    if (gat == NULL)
-        return -1;
-
-    printf ("\rLoading Maps [%d/%d]: %-50s  ", m, map_num, fn);
-    fflush (stdout);
-
-    map[m].m = m;
-    xs = map[m].xs = *(short *) (gat);
-    ys = map[m].ys = *(short *) (gat + 2);
-    printf ("\n%i %i\n", xs, ys);
-    map[m].gat = (uint8_t *)calloc (s = map[m].xs * map[m].ys, 1);
-    if (map[m].gat == NULL)
-    {
-        printf ("out of memory : map_readmap gat\n");
-        exit (1);
-    }
-
-    map[m].npc_num = 0;
-    map[m].users = 0;
-    memset (&map[m].flag, 0, sizeof (map[m].flag));
-    if (battle_config.pk_mode)
-        map[m].flag.pvp = 1;    // make all maps pvp for pk_mode [Valaris]
-    wh = map_waterheight (map[m].name);
-    for (y = 0; y < ys; y++)
-    {
-        p = (struct gat_1cell *) (gat + y * xs + 4);
-        for (x = 0; x < xs; x++)
-        {
-            /*if(wh!=NO_WATER && p->type==0){
-             * // 水場判定
-             * map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
-             * } else { */
-            map[m].gat[x + y * xs] = p->type;
-            //}
-            p++;
-        }
-    }
-    free (gat);
-
-    map[m].bxs = (xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
-    map[m].bys = (ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
-    size = map[m].bxs * map[m].bys;
-
-    CREATE (map[m].block, struct block_list *, size);
-
-    CREATE (map[m].block_mob, struct block_list *, size);
-
-    CREATE (map[m].block_count, int, size);
-
-    CREATE (map[m].block_mob_count, int, size);
-
-    strdb_insert (map_db, map[m].name, &map[m]);
-
-//  printf("%s read done\n",fn);
-
-    return 0;
-}
-
-/*==========================================
- * 全てのmapデータを読み込む
- *------------------------------------------
- */
-int map_readallmap (void)
-{
-    int  i, maps_removed = 0;
-    char fn[256] = "";
-
-    // 先に全部のャbプの存在を確認
-    for (i = 0; i < map_num; i++)
-    {
-        if (strstr (map[i].name, ".gat") == NULL)
-            continue;
-        sprintf (fn, "data\\%s", map[i].name);
-        // TODO - remove this, it is the last call to grfio_size, which is deprecated
-        if (!grfio_size (fn))
-        {
-            map_delmap (map[i].name);
-            maps_removed++;
-        }
-    }
-    for (i = 0; i < map_num; i++)
-    {
-        if (strstr (map[i].name, ".gat") != NULL)
-        {
-            char *p = strstr (map[i].name, ">");    // [MouseJstr]
-            if (p != NULL)
-            {
-                char alias[64];
-                *p = '\0';
-                strcpy (alias, map[i].name);
-                strcpy (map[i].name, p + 1);
-                sprintf (fn, "data\\%s", map[i].name);
-                if (map_readmap (i, fn, alias) == -1)
-                {
-                    map_delmap (map[i].name);
-                    maps_removed++;
-                }
-            }
-            else
-            {
-                sprintf (fn, "data\\%s", map[i].name);
-                if (map_readmap (i, fn, NULL) == -1)
-                {
-                    map_delmap (map[i].name);
-                    maps_removed++;
-                }
-            }
-        }
-    }
-
-    free (waterlist);
-    printf ("\rMaps Loaded: %d %60s\n", map_num, "");
-    printf ("\rMaps Removed: %d \n", maps_removed);
-    return 0;
-}
-
-/*==========================================
- * 読み込むmapを追加する
- *------------------------------------------
- */
-int map_addmap (char *mapname)
-{
-    if (strcasecmp (mapname, "clear") == 0)
-    {
-        map_num = 0;
-        return 0;
-    }
-
-    if (map_num >= MAX_MAP_PER_SERVER - 1)
-    {
-        printf ("too many map\n");
-        return 1;
-    }
-    memcpy (map[map_num].name, mapname, 24);
-    map_num++;
-    return 0;
-}
-
-/*==========================================
- * 読み込むmapを削除する
- *------------------------------------------
- */
-int map_delmap (char *mapname)
-{
-    int  i;
-
-    if (strcasecmp (mapname, "all") == 0)
-    {
-        map_num = 0;
-        return 0;
-    }
-
-    for (i = 0; i < map_num; i++)
-    {
-        if (strcmp (map[i].name, mapname) == 0)
-        {
-            printf ("Removing map [ %s ] from maplist\n", map[i].name);
-            memmove (map + i, map + i + 1,
-                     sizeof (map[0]) * (map_num - i - 1));
-            map_num--;
-        }
-    }
-    return 0;
-}
-
-extern char *gm_logfile_name;
-
-#define LOGFILE_SECONDS_PER_CHUNK_SHIFT 10
-
-FILE *map_logfile = NULL;
-char *map_logfile_name = NULL;
-static long map_logfile_index;
-
-static void map_close_logfile (void)
-{
-    if (map_logfile)
-    {
-        char *filenameop_buf = (char*)malloc (strlen (map_logfile_name) + 50);
-        sprintf (filenameop_buf, "gzip -f %s.%ld", map_logfile_name,
-                 map_logfile_index);
-
-        fclose (map_logfile);
-
-        if (!system (filenameop_buf))
-            perror (filenameop_buf);
-
-        free (filenameop_buf);
-    }
-}
-
-static void map_start_logfile (long suffix)
-{
-    char *filename_buf = (char*)malloc (strlen (map_logfile_name) + 50);
-    map_logfile_index = suffix >> LOGFILE_SECONDS_PER_CHUNK_SHIFT;
-
-    sprintf (filename_buf, "%s.%ld", map_logfile_name, map_logfile_index);
-    map_logfile = fopen (filename_buf, "w+");
-    if (!map_logfile)
-        perror (map_logfile_name);
-
-    free (filename_buf);
-}
-
-static void map_set_logfile (char *filename)
-{
-    struct timeval tv;
-
-    map_logfile_name = strdup (filename);
-    gettimeofday (&tv, NULL);
-
-    map_start_logfile (tv.tv_sec);
-
-    MAP_LOG ("log-start v3");
-}
-
-void map_write_log (char *format, ...)
-{
-    struct timeval tv;
-    va_list args;
-    va_start (args, format);
-
-    gettimeofday (&tv, NULL);
-
-    if ((tv.tv_sec >> LOGFILE_SECONDS_PER_CHUNK_SHIFT) != map_logfile_index)
-    {
-        map_close_logfile ();
-        map_start_logfile (tv.tv_sec);
-    }
-
-    fprintf (map_logfile, "%ld.%06ld ", (long) tv.tv_sec, (long) tv.tv_usec);
-    vfprintf (map_logfile, format, args);
-    fputc ('\n', map_logfile);
-}
-
-/*==========================================
- * 設定ファイルを読み込む
- *------------------------------------------
- */
-int map_config_read (char *cfgName)
-{
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-    struct hostent *h = NULL;
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        printf ("Map configuration file not found at: %s\n", cfgName);
-        exit (1);
-    }
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
-        {
-            if (strcasecmp (w1, "userid") == 0)
-            {
-                chrif_setuserid (w2);
-            }
-            else if (strcasecmp (w1, "passwd") == 0)
-            {
-                chrif_setpasswd (w2);
-            }
-            else if (strcasecmp (w1, "char_ip") == 0)
-            {
-                h = gethostbyname (w2);
-                if (h != NULL)
-                {
-                    printf
-                        ("Character server IP address : %s -> %d.%d.%d.%d\n",
-                         w2, (unsigned char) h->h_addr[0],
-                         (unsigned char) h->h_addr[1],
-                         (unsigned char) h->h_addr[2],
-                         (unsigned char) h->h_addr[3]);
-                    sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0],
-                             (unsigned char) h->h_addr[1],
-                             (unsigned char) h->h_addr[2],
-                             (unsigned char) h->h_addr[3]);
-                }
-                chrif_setip (w2);
-            }
-            else if (strcasecmp (w1, "char_port") == 0)
-            {
-                chrif_setport (atoi (w2));
-            }
-            else if (strcasecmp (w1, "map_ip") == 0)
-            {
-                h = gethostbyname (w2);
-                if (h != NULL)
-                {
-                    printf ("Map server IP address : %s -> %d.%d.%d.%d\n", w2,
-                            (unsigned char) h->h_addr[0],
-                            (unsigned char) h->h_addr[1],
-                            (unsigned char) h->h_addr[2],
-                            (unsigned char) h->h_addr[3]);
-                    sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0],
-                             (unsigned char) h->h_addr[1],
-                             (unsigned char) h->h_addr[2],
-                             (unsigned char) h->h_addr[3]);
-                }
-                clif_setip (w2);
-            }
-            else if (strcasecmp (w1, "map_port") == 0)
-            {
-                clif_setport (atoi (w2));
-                map_port = (atoi (w2));
-            }
-            else if (strcasecmp (w1, "water_height") == 0)
-            {
-                map_readwater (w2);
-            }
-            else if (strcasecmp (w1, "map") == 0)
-            {
-                map_addmap (w2);
-            }
-            else if (strcasecmp (w1, "delmap") == 0)
-            {
-                map_delmap (w2);
-            }
-            else if (strcasecmp (w1, "npc") == 0)
-            {
-                npc_addsrcfile (w2);
-            }
-            else if (strcasecmp (w1, "delnpc") == 0)
-            {
-                npc_delsrcfile (w2);
-            }
-            else if (strcasecmp (w1, "autosave_time") == 0)
-            {
-                autosave_interval = atoi (w2) * 1000;
-                if (autosave_interval <= 0)
-                    autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
-            }
-            else if (strcasecmp (w1, "motd_txt") == 0)
-            {
-                strcpy (motd_txt, w2);
-            }
-            else if (strcasecmp (w1, "help_txt") == 0)
-            {
-                strcpy (help_txt, w2);
-            }
-            else if (strcasecmp (w1, "mapreg_txt") == 0)
-            {
-                strcpy (mapreg_txt, w2);
-            }
-            else if (strcasecmp (w1, "gm_log") == 0)
-            {
-                gm_logfile_name = strdup (w2);
-            }
-            else if (strcasecmp (w1, "log_file") == 0)
-            {
-                map_set_logfile (w2);
-            }
-            else if (strcasecmp (w1, "import") == 0)
-            {
-                map_config_read (w2);
-            }
-        }
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-static int cleanup_sub (struct block_list *bl, va_list ap)
-{
-    nullpo_retr (0, bl);
-
-    switch (bl->type)
-    {
-        case BL_PC:
-            map_delblock (bl);  // There is something better...
-            break;
-        case BL_NPC:
-            npc_delete ((struct npc_data *) bl);
-            break;
-        case BL_MOB:
-            mob_delete ((struct mob_data *) bl);
-            break;
-        case BL_ITEM:
-            map_clearflooritem (bl->id);
-            break;
-        case BL_SKILL:
-            skill_delunit ((struct skill_unit *) bl);
-            break;
-        case BL_SPELL:
-            spell_free_invocation ((struct invocation *) bl);
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * map鯖終了時処理
- *------------------------------------------
- */
-void term_func (void)
-{
-    map_close_logfile ();
-
-    int  map_id, i;
-
-    for (map_id = 0; map_id < map_num; map_id++)
-    {
-        if (map[map_id].m)
-            map_foreachinarea (cleanup_sub, map_id, 0, 0, map[map_id].xs,
-                               map[map_id].ys, 0, 0);
-    }
-
-    for (i = 0; i < fd_max; i++)
-        delete_session (i);
-
-    map_removenpc ();
-
-    numdb_final (id_db, NULL);
-    strdb_final (map_db, NULL);
-    strdb_final (nick_db, NULL);
-    numdb_final (charid_db, NULL);
-
-    for (i = 0; i <= map_num; i++)
-    {
-        if (map[i].gat)
-            free (map[i].gat);
-        if (map[i].block)
-            free (map[i].block);
-        if (map[i].block_mob)
-            free (map[i].block_mob);
-        if (map[i].block_count)
-            free (map[i].block_count);
-        if (map[i].block_mob_count)
-            free (map[i].block_mob_count);
-    }
-    do_final_script ();
-    do_final_itemdb ();
-    do_final_storage ();
-    do_final_guild ();
-}
-
-/// --help was passed
-// FIXME this should produce output
-void map_helpscreen (void)
-{
-    exit (1);
-}
-
-int compare_item (struct item *a, struct item *b)
-{
-    return ((a->nameid == b->nameid) &&
-            (a->identify == b->identify) &&
-            (a->refine == b->refine) &&
-            (a->attribute == b->attribute) &&
-            (a->card[0] == b->card[0]) &&
-            (a->card[1] == b->card[1]) &&
-            (a->card[2] == b->card[2]) && (a->card[3] == b->card[3]));
-}
-
-/*======================================================
- * Map-Server Init and Command-line Arguments [Valaris]
- *------------------------------------------------------
- */
-int do_init (int argc, char *argv[])
-{
-    int  i;
-
-    unsigned char *MAP_CONF_NAME = "conf/map_athena.conf";
-    unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
-    unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
-    unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf";
-    unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf";
-
-    for (i = 1; i < argc; i++)
-    {
-
-        if (strcmp (argv[i], "--help") == 0 || strcmp (argv[i], "--h") == 0
-            || strcmp (argv[i], "--?") == 0 || strcmp (argv[i], "/?") == 0)
-            map_helpscreen ();
-        else if (strcmp (argv[i], "--map_config") == 0)
-            MAP_CONF_NAME = argv[i + 1];
-        else if (strcmp (argv[i], "--battle_config") == 0)
-            BATTLE_CONF_FILENAME = argv[i + 1];
-        else if (strcmp (argv[i], "--atcommand_config") == 0)
-            ATCOMMAND_CONF_FILENAME = argv[i + 1];
-        else if (strcmp (argv[i], "--script_config") == 0)
-            SCRIPT_CONF_NAME = argv[i + 1];
-        else if (strcmp (argv[i], "--msg_config") == 0)
-            MSG_CONF_NAME = argv[i + 1];
-    }
-
-    map_config_read (MAP_CONF_NAME);
-    battle_config_read (BATTLE_CONF_FILENAME);
-    atcommand_config_read (ATCOMMAND_CONF_FILENAME);
-    script_config_read (SCRIPT_CONF_NAME);
-    msg_config_read (MSG_CONF_NAME);
-
-    id_db = numdb_init ();
-    map_db = strdb_init (16);
-    nick_db = strdb_init (24);
-    charid_db = numdb_init ();
-
-    map_readallmap ();
-
-//    add_timer_func_list (map_clearflooritem_timer, "map_clearflooritem_timer");
-
-    do_init_chrif ();
-    do_init_clif ();
-    do_init_itemdb ();
-    do_init_mob ();             // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先
-    do_init_script ();
-    do_init_npc ();
-    do_init_pc ();
-    do_init_party ();
-    do_init_guild ();
-    do_init_storage ();
-    do_init_skill ();
-    do_init_magic ();
-
-    npc_event_do_oninit ();     // npcのOnInitイベント実行
-
-    if (battle_config.pk_mode == 1)
-        printf ("The server is running in \033[1;31mPK Mode\033[0m.\n");
-
-    printf
-        ("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
-         map_port);
-
-    return 0;
-}
-
-int map_scriptcont (struct map_session_data *sd, int id)
-{
-    struct block_list *bl = map_id2bl (id);
-
-    if (!bl)
-        return 0;
-
-    switch (bl->type)
-    {
-        case BL_NPC:
-            return npc_scriptcont (sd, id);
-        case BL_SPELL:
-            spell_execute_script ((struct invocation *) bl);
-            break;
-    }
-
-    return 0;
-}
diff --git a/src/map/map.cpp b/src/map/map.cpp
new file mode 100644
index 0000000..3c778df
--- /dev/null
+++ b/src/map/map.cpp
@@ -0,0 +1,2215 @@
+// $Id: map.c,v 1.6 2004/09/25 17:37:01 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef LCCWIN32
+#include <winsock.h>
+#else
+#include <netdb.h>
+#endif
+
+#include "../common/core.hpp"
+#include "../common/timer.hpp"
+#include "../common/db.hpp"
+#include "../common/grfio.hpp"
+#include "../common/mt_rand.hpp"
+#include "map.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "mob.hpp"
+#include "chat.hpp"
+#include "itemdb.hpp"
+#include "storage.hpp"
+#include "skill.hpp"
+#include "trade.hpp"
+#include "party.hpp"
+#include "battle.hpp"
+#include "script.hpp"
+#include "guild.hpp"
+#include "atcommand.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/socket.hpp"
+#include "magic.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+// 極力 staticでローカルに収める
+static struct dbt *id_db = NULL;
+static struct dbt *map_db = NULL;
+static struct dbt *nick_db = NULL;
+static struct dbt *charid_db = NULL;
+
+static int users = 0;
+static struct block_list *object[MAX_FLOORITEM];
+static int first_free_object_id = 0, last_object_id = 0;
+
+#define block_free_max 1048576
+static void *block_free[block_free_max];
+static int block_free_count = 0, block_free_lock = 0;
+
+#define BL_LIST_MAX 1048576
+static struct block_list *bl_list[BL_LIST_MAX];
+static int bl_list_count = 0;
+
+struct map_data map[MAX_MAP_PER_SERVER];
+int  map_num = 0;
+
+int  map_port = 0;
+
+int  autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+int  save_settings = 0xFFFF;
+int  agit_flag = 0;
+int  night_flag = 0;            // 0=day, 1=night [Yor]
+
+struct charid2nick
+{
+    char nick[24];
+    int  req_id;
+};
+
+char motd_txt[256] = "conf/motd.txt";
+char help_txt[256] = "conf/help.txt";
+
+char wisp_server_name[24] = "Server";   // can be modified in char-server configuration file
+
+/*==========================================
+ * 全map鯖総計での接続数設定
+ * (char鯖から送られてくる)
+ *------------------------------------------
+ */
+void map_setusers (int n)
+{
+    users = n;
+}
+
+/*==========================================
+ * 全map鯖総計での接続数取得 (/wへの応答用)
+ *------------------------------------------
+ */
+int map_getusers (void)
+{
+    return users;
+}
+
+//
+// block削除の安全性確保処理
+//
+
+/*==========================================
+ * blockをfreeするときfreeの変わりに呼ぶ
+ * ロックされているときはバッファにためる
+ *------------------------------------------
+ */
+int map_freeblock (void *bl)
+{
+    if (block_free_lock == 0)
+    {
+        free (bl);
+        bl = NULL;
+    }
+    else
+    {
+        if (block_free_count >= block_free_max)
+        {
+            if (battle_config.error_log)
+                printf
+                    ("map_freeblock: *WARNING* too many free block! %d %d\n",
+                     block_free_count, block_free_lock);
+        }
+        else
+            block_free[block_free_count++] = bl;
+    }
+    return block_free_lock;
+}
+
+/*==========================================
+ * blockのfreeを一時的に禁止する
+ *------------------------------------------
+ */
+int map_freeblock_lock (void)
+{
+    return ++block_free_lock;
+}
+
+/*==========================================
+ * blockのfreeのロックを解除する
+ * このとき、ロックが完全になくなると
+ * バッファにたまっていたblockを全部削除
+ *------------------------------------------
+ */
+int map_freeblock_unlock (void)
+{
+    if ((--block_free_lock) == 0)
+    {
+        int  i;
+//      if(block_free_count>0) {
+//          if(battle_config.error_log)
+//              printf("map_freeblock_unlock: free %d object\n",block_free_count);
+//      }
+        for (i = 0; i < block_free_count; i++)
+        {
+            free (block_free[i]);
+            block_free[i] = NULL;
+        }
+        block_free_count = 0;
+    }
+    else if (block_free_lock < 0)
+    {
+        if (battle_config.error_log)
+            printf ("map_freeblock_unlock: lock count < 0 !\n");
+    }
+    return block_free_lock;
+}
+
+//
+// block化処理
+//
+/*==========================================
+ * map[]のblock_listから繋がっている場合に
+ * bl->prevにbl_headのアドレスを入れておく
+ *------------------------------------------
+ */
+static struct block_list bl_head;
+
+/*==========================================
+ * map[]のblock_listに追加
+ * mobは数が多いので別リスト
+ *
+ * 既にlink済みかの確認が無い。危険かも
+ *------------------------------------------
+ */
+int map_addblock (struct block_list *bl)
+{
+    int  m, x, y;
+
+    nullpo_retr (0, bl);
+
+    if (bl->prev != NULL)
+    {
+        if (battle_config.error_log)
+            printf ("map_addblock error : bl->prev!=NULL\n");
+        return 0;
+    }
+
+    m = bl->m;
+    x = bl->x;
+    y = bl->y;
+    if (m < 0 || m >= map_num ||
+        x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
+        return 1;
+
+    if (bl->type == BL_MOB)
+    {
+        bl->next =
+            map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs];
+        bl->prev = &bl_head;
+        if (bl->next)
+            bl->next->prev = bl;
+        map[m].block_mob[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl;
+        map[m].block_mob_count[x / BLOCK_SIZE +
+                               (y / BLOCK_SIZE) * map[m].bxs]++;
+    }
+    else
+    {
+        bl->next =
+            map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs];
+        bl->prev = &bl_head;
+        if (bl->next)
+            bl->next->prev = bl;
+        map[m].block[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs] = bl;
+        map[m].block_count[x / BLOCK_SIZE + (y / BLOCK_SIZE) * map[m].bxs]++;
+        if (bl->type == BL_PC)
+            map[m].users++;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * map[]のblock_listから外す
+ * prevがNULLの場合listに繋がってない
+ *------------------------------------------
+ */
+int map_delblock (struct block_list *bl)
+{
+    int  b;
+    nullpo_retr (0, bl);
+
+    // 既にblocklistから抜けている
+    if (bl->prev == NULL)
+    {
+        if (bl->next != NULL)
+        {
+            // prevがNULLでnextがNULLでないのは有ってはならない
+            if (battle_config.error_log)
+                printf ("map_delblock error : bl->next!=NULL\n");
+        }
+        return 0;
+    }
+
+    b = bl->x / BLOCK_SIZE + (bl->y / BLOCK_SIZE) * map[bl->m].bxs;
+
+    if (bl->type == BL_PC)
+        map[bl->m].users--;
+
+    if (bl->next)
+        bl->next->prev = bl->prev;
+    if (bl->prev == &bl_head)
+    {
+        // リストの頭なので、map[]のblock_listを更新する
+        if (bl->type == BL_MOB)
+        {
+            map[bl->m].block_mob[b] = bl->next;
+            if ((map[bl->m].block_mob_count[b]--) < 0)
+                map[bl->m].block_mob_count[b] = 0;
+        }
+        else
+        {
+            map[bl->m].block[b] = bl->next;
+            if ((map[bl->m].block_count[b]--) < 0)
+                map[bl->m].block_count[b] = 0;
+        }
+    }
+    else
+    {
+        bl->prev->next = bl->next;
+    }
+    bl->next = NULL;
+    bl->prev = NULL;
+
+    return 0;
+}
+
+/*==========================================
+ * 周囲のPC人数を数える (現在未使用)
+ *------------------------------------------
+ */
+int map_countnearpc (int m, int x, int y)
+{
+    int  bx, by, c = 0;
+    struct block_list *bl = NULL;
+
+    if (map[m].users == 0)
+        return 0;
+    for (by = y / BLOCK_SIZE - AREA_SIZE / BLOCK_SIZE - 1;
+         by <= y / BLOCK_SIZE + AREA_SIZE / BLOCK_SIZE + 1; by++)
+    {
+        if (by < 0 || by >= map[m].bys)
+            continue;
+        for (bx = x / BLOCK_SIZE - AREA_SIZE / BLOCK_SIZE - 1;
+             bx <= x / BLOCK_SIZE + AREA_SIZE / BLOCK_SIZE + 1; bx++)
+        {
+            if (bx < 0 || bx >= map[m].bxs)
+                continue;
+            bl = map[m].block[bx + by * map[m].bxs];
+            for (; bl; bl = bl->next)
+            {
+                if (bl->type == BL_PC)
+                    c++;
+            }
+        }
+    }
+    return c;
+}
+
+/*==========================================
+ * セル上のPCとMOBの数を数える (グランドクロス用)
+ *------------------------------------------
+ */
+int map_count_oncell (int m, int x, int y)
+{
+    int  bx, by;
+    struct block_list *bl = NULL;
+    int  i, c;
+    int  count = 0;
+
+    if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
+        return 1;
+    bx = x / BLOCK_SIZE;
+    by = y / BLOCK_SIZE;
+
+    bl = map[m].block[bx + by * map[m].bxs];
+    c = map[m].block_count[bx + by * map[m].bxs];
+    for (i = 0; i < c && bl; i++, bl = bl->next)
+    {
+        if (bl->x == x && bl->y == y && bl->type == BL_PC)
+            count++;
+    }
+    bl = map[m].block_mob[bx + by * map[m].bxs];
+    c = map[m].block_mob_count[bx + by * map[m].bxs];
+    for (i = 0; i < c && bl; i++, bl = bl->next)
+    {
+        if (bl->x == x && bl->y == y)
+            count++;
+    }
+    if (!count)
+        count = 1;
+    return count;
+}
+
+/*==========================================
+ * map m (x0,y0)-(x1,y1)内の全objに対して
+ * funcを呼ぶ
+ * type!=0 ならその種類のみ
+ *------------------------------------------
+ */
+void map_foreachinarea (int (*func) (struct block_list *, va_list), int m,
+                        int x0, int y0, int x1, int y1, int type, ...)
+{
+    int  bx, by;
+    struct block_list *bl = NULL;
+    va_list ap = NULL;
+    int  blockcount = bl_list_count, i, c;
+
+    if (m < 0)
+        return;
+    va_start (ap, type);
+    if (x0 < 0)
+        x0 = 0;
+    if (y0 < 0)
+        y0 = 0;
+    if (x1 >= map[m].xs)
+        x1 = map[m].xs - 1;
+    if (y1 >= map[m].ys)
+        y1 = map[m].ys - 1;
+    if (type == 0 || type != BL_MOB)
+        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
+        {
+            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
+            {
+                bl = map[m].block[bx + by * map[m].bxs];
+                c = map[m].block_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && type && bl->type != type)
+                        continue;
+                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+            }
+        }
+    if (type == 0 || type == BL_MOB)
+        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
+        {
+            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
+            {
+                bl = map[m].block_mob[bx + by * map[m].bxs];
+                c = map[m].block_mob_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+            }
+        }
+
+    if (bl_list_count >= BL_LIST_MAX)
+    {
+        if (battle_config.error_log)
+            printf ("map_foreachinarea: *WARNING* block count too many!\n");
+    }
+
+    map_freeblock_lock ();      // メモリからの解放を禁止する
+
+    for (i = blockcount; i < bl_list_count; i++)
+        if (bl_list[i]->prev)   // 有効かどうかチェック
+            func (bl_list[i], ap);
+
+    map_freeblock_unlock ();    // 解放を許可する
+
+    va_end (ap);
+    bl_list_count = blockcount;
+}
+
+/*==========================================
+ * 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した時の
+ * 領域外になる領域(矩形かL字形)内のobjに
+ * 対してfuncを呼ぶ
+ *
+ * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
+ *------------------------------------------
+ */
+void map_foreachinmovearea (int (*func) (struct block_list *, va_list), int m,
+                            int x0, int y0, int x1, int y1, int dx, int dy,
+                            int type, ...)
+{
+    int  bx, by;
+    struct block_list *bl = NULL;
+    va_list ap = NULL;
+    int  blockcount = bl_list_count, i, c;
+
+    va_start (ap, type);
+    if (dx == 0 || dy == 0)
+    {
+        // 矩形領域の場合
+        if (dx == 0)
+        {
+            if (dy < 0)
+            {
+                y0 = y1 + dy + 1;
+            }
+            else
+            {
+                y1 = y0 + dy - 1;
+            }
+        }
+        else if (dy == 0)
+        {
+            if (dx < 0)
+            {
+                x0 = x1 + dx + 1;
+            }
+            else
+            {
+                x1 = x0 + dx - 1;
+            }
+        }
+        if (x0 < 0)
+            x0 = 0;
+        if (y0 < 0)
+            y0 = 0;
+        if (x1 >= map[m].xs)
+            x1 = map[m].xs - 1;
+        if (y1 >= map[m].ys)
+            y1 = map[m].ys - 1;
+        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
+        {
+            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
+            {
+                bl = map[m].block[bx + by * map[m].bxs];
+                c = map[m].block_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && type && bl->type != type)
+                        continue;
+                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+                bl = map[m].block_mob[bx + by * map[m].bxs];
+                c = map[m].block_mob_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && type && bl->type != type)
+                        continue;
+                    if (bl && bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                        && bl->y <= y1 && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+            }
+        }
+    }
+    else
+    {
+        // L字領域の場合
+
+        if (x0 < 0)
+            x0 = 0;
+        if (y0 < 0)
+            y0 = 0;
+        if (x1 >= map[m].xs)
+            x1 = map[m].xs - 1;
+        if (y1 >= map[m].ys)
+            y1 = map[m].ys - 1;
+        for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++)
+        {
+            for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++)
+            {
+                bl = map[m].block[bx + by * map[m].bxs];
+                c = map[m].block_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && type && bl->type != type)
+                        continue;
+                    if ((bl)
+                        && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                             && bl->y <= y1))
+                        continue;
+                    if ((bl)
+                        && ((dx > 0 && bl->x < x0 + dx)
+                            || (dx < 0 && bl->x > x1 + dx) || (dy > 0
+                                                               && bl->y <
+                                                               y0 + dy)
+                            || (dy < 0 && bl->y > y1 + dy))
+                        && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+                bl = map[m].block_mob[bx + by * map[m].bxs];
+                c = map[m].block_mob_count[bx + by * map[m].bxs];
+                for (i = 0; i < c && bl; i++, bl = bl->next)
+                {
+                    if (bl && type && bl->type != type)
+                        continue;
+                    if ((bl)
+                        && !(bl->x >= x0 && bl->x <= x1 && bl->y >= y0
+                             && bl->y <= y1))
+                        continue;
+                    if ((bl)
+                        && ((dx > 0 && bl->x < x0 + dx)
+                            || (dx < 0 && bl->x > x1 + dx) || (dy > 0
+                                                               && bl->y <
+                                                               y0 + dy)
+                            || (dy < 0 && bl->y > y1 + dy))
+                        && bl_list_count < BL_LIST_MAX)
+                        bl_list[bl_list_count++] = bl;
+                }
+            }
+        }
+
+    }
+
+    if (bl_list_count >= BL_LIST_MAX)
+    {
+        if (battle_config.error_log)
+            printf ("map_foreachinarea: *WARNING* block count too many!\n");
+    }
+
+    map_freeblock_lock ();      // メモリからの解放を禁止する
+
+    for (i = blockcount; i < bl_list_count; i++)
+        if (bl_list[i]->prev)   // 有効かどうかチェック
+            func (bl_list[i], ap);
+
+    map_freeblock_unlock ();    // 解放を許可する
+
+    va_end (ap);
+    bl_list_count = blockcount;
+}
+
+// -- moonsoul  (added map_foreachincell which is a rework of map_foreachinarea but
+//           which only checks the exact single x/y passed to it rather than an
+//           area radius - may be more useful in some instances)
+//
+void map_foreachincell (int (*func) (struct block_list *, va_list), int m,
+                        int x, int y, int type, ...)
+{
+    int  bx, by;
+    struct block_list *bl = NULL;
+    va_list ap = NULL;
+    int  blockcount = bl_list_count, i, c;
+
+    va_start (ap, type);
+
+    by = y / BLOCK_SIZE;
+    bx = x / BLOCK_SIZE;
+
+    if (type == 0 || type != BL_MOB)
+    {
+        bl = map[m].block[bx + by * map[m].bxs];
+        c = map[m].block_count[bx + by * map[m].bxs];
+        for (i = 0; i < c && bl; i++, bl = bl->next)
+        {
+            if (type && bl && bl->type != type)
+                continue;
+            if (bl && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX)
+                bl_list[bl_list_count++] = bl;
+        }
+    }
+
+    if (type == 0 || type == BL_MOB)
+    {
+        bl = map[m].block_mob[bx + by * map[m].bxs];
+        c = map[m].block_mob_count[bx + by * map[m].bxs];
+        for (i = 0; i < c && bl; i++, bl = bl->next)
+        {
+            if (bl && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX)
+                bl_list[bl_list_count++] = bl;
+        }
+    }
+
+    if (bl_list_count >= BL_LIST_MAX)
+    {
+        if (battle_config.error_log)
+            printf ("map_foreachincell: *WARNING* block count too many!\n");
+    }
+
+    map_freeblock_lock ();      // メモリからの解放を禁止する
+
+    for (i = blockcount; i < bl_list_count; i++)
+        if (bl_list[i]->prev)   // 有効かどうかチェック
+            func (bl_list[i], ap);
+
+    map_freeblock_unlock ();    // 解放を許可する
+
+    va_end (ap);
+    bl_list_count = blockcount;
+}
+
+/*==========================================
+ * 床アイテムやエフェクト用の一時obj割り当て
+ * object[]への保存とid_db登録まで
+ *
+ * bl->idもこの中で設定して問題無い?
+ *------------------------------------------
+ */
+int map_addobject (struct block_list *bl)
+{
+    int  i;
+    if (bl == NULL)
+    {
+        printf ("map_addobject nullpo?\n");
+        return 0;
+    }
+    if (first_free_object_id < 2 || first_free_object_id >= MAX_FLOORITEM)
+        first_free_object_id = 2;
+    for (i = first_free_object_id; i < MAX_FLOORITEM; i++)
+        if (object[i] == NULL)
+            break;
+    if (i >= MAX_FLOORITEM)
+    {
+        if (battle_config.error_log)
+            printf ("no free object id\n");
+        return 0;
+    }
+    first_free_object_id = i;
+    if (last_object_id < i)
+        last_object_id = i;
+    object[i] = bl;
+    numdb_insert (id_db, i, bl);
+    return i;
+}
+
+/*==========================================
+ * 一時objectの解放
+ *	map_delobjectのfreeしないバージョン
+ *------------------------------------------
+ */
+int map_delobjectnofree (int id, int type)
+{
+    if (object[id] == NULL)
+        return 0;
+
+    if (object[id]->type != type)
+    {
+        fprintf (stderr, "Incorrect type: expected %d, got %d\n", type,
+                 object[id]->type);
+        *((char *) 0) = 0;      // break for backtrace
+    }
+
+    map_delblock (object[id]);
+    numdb_erase (id_db, id);
+//  map_freeblock(object[id]);
+    object[id] = NULL;
+
+    if (first_free_object_id > id)
+        first_free_object_id = id;
+
+    while (last_object_id > 2 && object[last_object_id] == NULL)
+        last_object_id--;
+
+    return 0;
+}
+
+/*==========================================
+ * 一時objectの解放
+ * block_listからの削除、id_dbからの削除
+ * object dataのfree、object[]へのNULL代入
+ *
+ * addとの対称性が無いのが気になる
+ *------------------------------------------
+ */
+int map_delobject (int id, int type)
+{
+    struct block_list *obj = object[id];
+
+    if (obj == NULL)
+        return 0;
+
+    map_delobjectnofree (id, type);
+    if (obj->type == BL_PC)     // [Fate] Not sure where else to put this... I'm not sure where delobject for PCs is called from
+        pc_cleanup ((struct map_session_data *) obj);
+
+    map_freeblock (obj);
+
+    return 0;
+}
+
+/*==========================================
+ * 全一時obj相手にfuncを呼ぶ
+ *
+ *------------------------------------------
+ */
+void map_foreachobject (int (*func) (struct block_list *, va_list), int type,
+                        ...)
+{
+    int  i;
+    int  blockcount = bl_list_count;
+    va_list ap = NULL;
+
+    va_start (ap, type);
+
+    for (i = 2; i <= last_object_id; i++)
+    {
+        if (object[i])
+        {
+            if (type && object[i]->type != type)
+                continue;
+            if (bl_list_count >= BL_LIST_MAX)
+            {
+                if (battle_config.error_log)
+                    printf ("map_foreachobject: too many block !\n");
+            }
+            else
+                bl_list[bl_list_count++] = object[i];
+        }
+    }
+
+    map_freeblock_lock ();
+
+    for (i = blockcount; i < bl_list_count; i++)
+        if (bl_list[i]->prev || bl_list[i]->next)
+            func (bl_list[i], ap);
+
+    map_freeblock_unlock ();
+
+    va_end (ap);
+    bl_list_count = blockcount;
+}
+
+/*==========================================
+ * 床アイテムを消す
+ *
+ * data==0の時はtimerで消えた時
+ * data!=0の時は拾う等で消えた時として動作
+ *
+ * 後者は、map_clearflooritem(id)へ
+ * map.h内で#defineしてある
+ *------------------------------------------
+ */
+void map_clearflooritem_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct flooritem_data *fitem = NULL;
+
+    fitem = (struct flooritem_data *) object[id];
+    if (fitem == NULL || fitem->bl.type != BL_ITEM
+        || (!data && fitem->cleartimer != tid))
+    {
+        if (battle_config.error_log)
+            printf ("map_clearflooritem_timer : error\n");
+        return;
+    }
+    if (data)
+        delete_timer (fitem->cleartimer, map_clearflooritem_timer);
+    clif_clearflooritem (fitem, 0);
+    map_delobject (fitem->bl.id, BL_ITEM);
+}
+
+/*==========================================
+ * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの
+ * 内から適当なマス目の座標をx+(y<<16)で返す
+ *
+ * 現状range=1でアイテムドロップ用途のみ
+ *------------------------------------------
+ */
+int map_searchrandfreecell (int m, int x, int y, int range)
+{
+    int  free_cell, i, j, c;
+
+    for (free_cell = 0, i = -range; i <= range; i++)
+    {
+        if (i + y < 0 || i + y >= map[m].ys)
+            continue;
+        for (j = -range; j <= range; j++)
+        {
+            if (j + x < 0 || j + x >= map[m].xs)
+                continue;
+            if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5)
+                continue;
+            free_cell++;
+        }
+    }
+    if (free_cell == 0)
+        return -1;
+    free_cell = MRAND (free_cell);
+    for (i = -range; i <= range; i++)
+    {
+        if (i + y < 0 || i + y >= map[m].ys)
+            continue;
+        for (j = -range; j <= range; j++)
+        {
+            if (j + x < 0 || j + x >= map[m].xs)
+                continue;
+            if ((c = read_gat (m, j + x, i + y)) == 1 || c == 5)
+                continue;
+            if (free_cell == 0)
+            {
+                x += j;
+                y += i;
+                i = range + 1;
+                break;
+            }
+            free_cell--;
+        }
+    }
+
+    return x + (y << 16);
+}
+
+/*==========================================
+ * (m,x,y)を中心に3x3以内に床アイテム設置
+ *
+ * item_dataはamount以外をcopyする
+ *------------------------------------------
+ */
+int map_addflooritem_any (struct item *item_data, int amount, int m, int x,
+                          int y, struct map_session_data **owners,
+                          int *owner_protection, int lifetime, int dispersal)
+{
+    int  xy, r;
+    unsigned int tick;
+    struct flooritem_data *fitem = NULL;
+
+    nullpo_retr (0, item_data);
+
+    if ((xy = map_searchrandfreecell (m, x, y, dispersal)) < 0)
+        return 0;
+    r = mt_random ();
+
+    CREATE (fitem, struct flooritem_data, 1);
+    fitem->bl.type = BL_ITEM;
+    fitem->bl.prev = fitem->bl.next = NULL;
+    fitem->bl.m = m;
+    fitem->bl.x = xy & 0xffff;
+    fitem->bl.y = (xy >> 16) & 0xffff;
+    fitem->first_get_id = 0;
+    fitem->first_get_tick = 0;
+    fitem->second_get_id = 0;
+    fitem->second_get_tick = 0;
+    fitem->third_get_id = 0;
+    fitem->third_get_tick = 0;
+
+    fitem->bl.id = map_addobject (&fitem->bl);
+    if (fitem->bl.id == 0)
+    {
+        free (fitem);
+        return 0;
+    }
+
+    tick = gettick ();
+
+    if (owners[0])
+        fitem->first_get_id = owners[0]->bl.id;
+    fitem->first_get_tick = tick + owner_protection[0];
+
+    if (owners[1])
+        fitem->second_get_id = owners[1]->bl.id;
+    fitem->second_get_tick = tick + owner_protection[1];
+
+    if (owners[2])
+        fitem->third_get_id = owners[2]->bl.id;
+    fitem->third_get_tick = tick + owner_protection[2];
+
+    memcpy (&fitem->item_data, item_data, sizeof (*item_data));
+    fitem->item_data.amount = amount;
+    fitem->subx = (r & 3) * 3 + 3;
+    fitem->suby = ((r >> 2) & 3) * 3 + 3;
+    fitem->cleartimer =
+        add_timer (gettick () + lifetime, map_clearflooritem_timer,
+                   fitem->bl.id, 0);
+
+    map_addblock (&fitem->bl);
+    clif_dropflooritem (fitem);
+
+    return fitem->bl.id;
+}
+
+int map_addflooritem (struct item *item_data, int amount, int m, int x, int y,
+                      struct map_session_data *first_sd,
+                      struct map_session_data *second_sd,
+                      struct map_session_data *third_sd, int type)
+{
+    struct map_session_data *owners[3] = { first_sd, second_sd, third_sd };
+    int  owner_protection[3];
+
+    if (type)
+    {
+        owner_protection[0] = battle_config.mvp_item_first_get_time;
+        owner_protection[1] =
+            owner_protection[0] + battle_config.mvp_item_second_get_time;
+        owner_protection[2] =
+            owner_protection[1] + battle_config.mvp_item_third_get_time;
+    }
+    else
+    {
+        owner_protection[0] = battle_config.item_first_get_time;
+        owner_protection[1] =
+            owner_protection[0] + battle_config.item_second_get_time;
+        owner_protection[2] =
+            owner_protection[1] + battle_config.item_third_get_time;
+    }
+
+    return map_addflooritem_any (item_data, amount, m, x, y,
+                                 owners, owner_protection,
+                                 battle_config.flooritem_lifetime, 1);
+}
+
+/* 	int xy,r; */
+/* 	unsigned int tick; */
+/* 	struct flooritem_data *fitem=NULL; */
+
+/* 	nullpo_retr(0, item_data); */
+
+/* 	if((xy=map_searchrandfreecell(m,x,y,1))<0) */
+/* 		return 0; */
+/* 	r=rand(); */
+
+/* 	fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem)); */
+/* 	fitem->bl.type=BL_ITEM; */
+/* 	fitem->bl.prev = fitem->bl.next = NULL; */
+/* 	fitem->bl.m=m; */
+/* 	fitem->bl.x=xy&0xffff; */
+/* 	fitem->bl.y=(xy>>16)&0xffff; */
+/* 	fitem->first_get_id = 0; */
+/* 	fitem->first_get_tick = 0; */
+/* 	fitem->second_get_id = 0; */
+/* 	fitem->second_get_tick = 0; */
+/* 	fitem->third_get_id = 0; */
+/* 	fitem->third_get_tick = 0; */
+
+/* 	fitem->bl.id = map_addobject(&fitem->bl); */
+/* 	if(fitem->bl.id==0){ */
+/* 		free(fitem); */
+/* 		return 0; */
+/* 	} */
+
+/* 	tick = gettick(); */
+/* 	if(first_sd) { */
+/* 		fitem->first_get_id = first_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time; */
+/* 		else */
+/* 			fitem->first_get_tick = tick + battle_config.item_first_get_time; */
+/* 	} */
+/* 	if(second_sd) { */
+/* 		fitem->second_get_id = second_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time; */
+/* 		else */
+/* 			fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time; */
+/* 	} */
+/* 	if(third_sd) { */
+/* 		fitem->third_get_id = third_sd->bl.id; */
+/* 		if(type) */
+/* 			fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time; */
+/* 		else */
+/* 			fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time; */
+/* 	} */
+
+/* 	memcpy(&fitem->item_data,item_data,sizeof(*item_data)); */
+/* 	fitem->item_data.amount=amount; */
+/* 	fitem->subx=(r&3)*3+3; */
+/* 	fitem->suby=((r>>2)&3)*3+3; */
+/* 	fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); */
+
+/* 	map_addblock(&fitem->bl); */
+/* 	clif_dropflooritem(fitem); */
+
+/* 	return fitem->bl.id; */
+/* } */
+
+/*==========================================
+ * charid_dbへ追加(返信待ちがあれば返信)
+ *------------------------------------------
+ */
+void map_addchariddb (int charid, char *name)
+{
+    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid);
+    if (p == NULL)
+    {                           // データベースにない
+        CREATE (p, struct charid2nick, 1);
+        p->req_id = 0;
+    }
+    else
+        numdb_erase (charid_db, charid);
+
+    int req = p->req_id;
+    memcpy (p->nick, name, 24);
+    p->req_id = 0;
+    numdb_insert (charid_db, charid, p);
+    if (req)
+    {                           // 返信待ちがあれば返信
+        struct map_session_data *sd = map_id2sd (req);
+        if (sd != NULL)
+            clif_solved_charname (sd, charid);
+    }
+}
+
+/*==========================================
+ * charid_dbへ追加(返信要求のみ)
+ *------------------------------------------
+ */
+int map_reqchariddb (struct map_session_data *sd, int charid)
+{
+    nullpo_retr (0, sd);
+
+    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, charid);
+    if (p != NULL)              // データベースにすでにある
+        return 0;
+    CREATE (p, struct charid2nick, 1);
+    p->req_id = sd->bl.id;
+    numdb_insert (charid_db, charid, p);
+    return 0;
+}
+
+/*==========================================
+ * id_dbへblを追加
+ *------------------------------------------
+ */
+void map_addiddb (struct block_list *bl)
+{
+    nullpo_retv (bl);
+
+    numdb_insert (id_db, bl->id, bl);
+}
+
+/*==========================================
+ * id_dbからblを削除
+ *------------------------------------------
+ */
+void map_deliddb (struct block_list *bl)
+{
+    nullpo_retv (bl);
+
+    numdb_erase (id_db, bl->id);
+}
+
+/*==========================================
+ * nick_dbへsdを追加
+ *------------------------------------------
+ */
+void map_addnickdb (struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    strdb_insert (nick_db, sd->status.name, sd);
+}
+
+/*==========================================
+ * PCのquit処理 map.c内分
+ *
+ * quit処理の主体が違うような気もしてきた
+ *------------------------------------------
+ */
+int map_quit (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->chatID)             // チャットから出る
+        chat_leavechat (sd);
+
+    if (sd->trade_partner)      // 取引を中断する
+        trade_tradecancel (sd);
+
+    if (sd->party_invite > 0)   // パーティ勧誘を拒否する
+        party_reply_invite (sd, sd->party_invite_account, 0);
+
+    if (sd->guild_invite > 0)   // ギルド勧誘を拒否する
+        guild_reply_invite (sd, sd->guild_invite, 0);
+    if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する
+        guild_reply_reqalliance (sd, sd->guild_alliance_account, 0);
+
+    party_send_logout (sd);     // パーティのログアウトメッセージ送信
+
+    guild_send_memberinfoshort (sd, 0); // ギルドのログアウトメッセージ送信
+
+    pc_cleareventtimer (sd);    // イベントタイマを破棄する
+
+    skill_castcancel (&sd->bl, 0);  // 詠唱を中断する
+    skill_stop_dancing (&sd->bl, 1);    // ダンス/演奏中断
+
+    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中の終了はHPを100に
+        sd->status.hp = 100;
+
+    skill_status_change_clear (&sd->bl, 1); // ステータス異常を解除する
+    skill_clear_unitgroup (&sd->bl);    // スキルユニットグループの削除
+    skill_cleartimerskill (&sd->bl);
+    pc_stop_walking (sd, 0);
+    pc_stopattack (sd);
+    pc_delinvincibletimer (sd);
+    pc_delspiritball (sd, sd->spiritball, 1);
+    skill_gangsterparadise (sd, 0);
+
+    pc_calcstatus (sd, 4);
+
+    clif_clearchar_area (&sd->bl, 2);
+
+    if (pc_isdead (sd))
+        pc_setrestartvalue (sd, 2);
+    pc_makesavestatus (sd);
+    //クローンスキルで覚えたスキルは消す
+
+    //The storage closing routines will save the char if needed. [Skotlex]
+    if (!sd->state.storage_flag)
+        chrif_save (sd);
+    else if (sd->state.storage_flag == 1)
+        storage_storage_quit (sd);
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storage_quit (sd, 1);
+
+    if (sd->npc_stackbuf && sd->npc_stackbuf != NULL)
+        free (sd->npc_stackbuf);
+
+    map_delblock (&sd->bl);
+
+    numdb_erase (id_db, sd->bl.id);
+    strdb_erase (nick_db, sd->status.name);
+    numdb_erase (charid_db, sd->status.char_id);
+
+    return 0;
+}
+
+/*==========================================
+ * id番号のPCを探す。居なければNULL
+ *------------------------------------------
+ */
+struct map_session_data *map_id2sd (int id)
+{
+// remove search from db, because:
+// 1 - all players, npc, items and mob are in this db (to search, it's not speed, and search in session is more sure)
+// 2 - DB seems not always correct. Sometimes, when a player disconnects, its id (account value) is not removed and structure
+//     point to a memory area that is not more a session_data and value are incorrect (or out of available memory) -> crash
+// replaced by searching in all session.
+// by searching in session, we are sure that fd, session, and account exist.
+/*
+	struct block_list *bl;
+
+	bl=numdb_search(id_db,id);
+	if(bl && bl->type==BL_PC)
+		return (struct map_session_data*)bl;
+	return NULL;
+*/
+    int  i;
+    struct map_session_data *sd = NULL;
+
+    for (i = 0; i < fd_max; i++)
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->bl.id == id)
+            return sd;
+
+    return NULL;
+}
+
+/*==========================================
+ * char_id番号の名前を探す
+ *------------------------------------------
+ */
+char *map_charid2nick (int id)
+{
+    struct charid2nick *p = (struct charid2nick *)numdb_search (charid_db, id);
+
+    if (p == NULL)
+        return NULL;
+    if (p->req_id != 0)
+        return NULL;
+    return p->nick;
+}
+
+/*========================================*/
+/* [Fate] Operations to iterate over active map sessions */
+
+static struct map_session_data *map_get_session (int i)
+{
+    struct map_session_data *d;
+
+    if (i >= 0 && i < fd_max
+        && session[i] && (d = (struct map_session_data *)session[i]->session_data) && d->state.auth)
+        return d;
+
+    return NULL;
+}
+
+static struct map_session_data *map_get_session_forward (int start)
+{
+    int  i;
+    for (i = start; i < fd_max; i++)
+    {
+        struct map_session_data *d = map_get_session (i);
+        if (d)
+            return d;
+    }
+
+    return NULL;
+}
+
+static struct map_session_data *map_get_session_backward (int start)
+{
+    int  i;
+    for (i = start; i >= 0; i--)
+    {
+        struct map_session_data *d = map_get_session (i);
+        if (d)
+            return d;
+    }
+
+    return NULL;
+}
+
+struct map_session_data *map_get_first_session (void)
+{
+    return map_get_session_forward (0);
+}
+
+struct map_session_data *map_get_next_session (struct map_session_data *d)
+{
+    return map_get_session_forward (d->fd + 1);
+}
+
+struct map_session_data *map_get_last_session (void)
+{
+    return map_get_session_backward (fd_max);
+}
+
+struct map_session_data *map_get_prev_session (struct map_session_data *d)
+{
+    return map_get_session_backward (d->fd - 1);
+}
+
+/*==========================================
+ * Search session data from a nick name
+ * (without sensitive case if necessary)
+ * return map_session_data pointer or NULL
+ *------------------------------------------
+ */
+struct map_session_data *map_nick2sd (char *nick)
+{
+    int  i, quantity = 0, nicklen;
+    struct map_session_data *sd = NULL;
+    struct map_session_data *pl_sd = NULL;
+
+    if (nick == NULL)
+        return NULL;
+
+    nicklen = strlen (nick);
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+            && pl_sd->state.auth)
+        {
+            // Without case sensitive check (increase the number of similar character names found)
+            if (strncasecmp (pl_sd->status.name, nick, nicklen) == 0)
+            {
+                // Strict comparison (if found, we finish the function immediatly with correct value)
+                if (strcmp (pl_sd->status.name, nick) == 0)
+                    return pl_sd;
+                quantity++;
+                sd = pl_sd;
+            }
+        }
+    }
+    // Here, the exact character name is not found
+    // We return the found index of a similar account ONLY if there is 1 similar character
+    if (quantity == 1)
+        return sd;
+
+    // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
+    return NULL;
+}
+
+/*==========================================
+ * id番号の物を探す
+ * 一時objectの場合は配列を引くのみ
+ *------------------------------------------
+ */
+struct block_list *map_id2bl (int id)
+{
+    struct block_list *bl = NULL;
+    if (id < sizeof (object) / sizeof (object[0]))
+        bl = object[id];
+    else
+        bl = (struct block_list *)numdb_search (id_db, id);
+
+    return bl;
+}
+
+/*==========================================
+ * id_db内の全てにfuncを実行
+ *------------------------------------------
+ */
+int map_foreachiddb (db_func_t func, ...)
+{
+    va_list ap = NULL;
+
+    va_start (ap, func);
+    numdb_foreach (id_db, func, ap);
+    va_end (ap);
+    return 0;
+}
+
+/*==========================================
+ * map.npcへ追加 (warp等の領域持ちのみ)
+ *------------------------------------------
+ */
+int map_addnpc (int m, struct npc_data *nd)
+{
+    int  i;
+    if (m < 0 || m >= map_num)
+        return -1;
+    for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++)
+        if (map[m].npc[i] == NULL)
+            break;
+    if (i == MAX_NPC_PER_MAP)
+    {
+        if (battle_config.error_log)
+            printf ("too many NPCs in one map %s\n", map[m].name);
+        return -1;
+    }
+    if (i == map[m].npc_num)
+    {
+        map[m].npc_num++;
+    }
+
+    nullpo_retr (0, nd);
+
+    map[m].npc[i] = nd;
+    nd->n = i;
+    numdb_insert (id_db, nd->bl.id, nd);
+
+    return i;
+}
+
+void map_removenpc (void)
+{
+    int  i, m, n = 0;
+
+    for (m = 0; m < map_num; m++)
+    {
+        for (i = 0; i < map[m].npc_num && i < MAX_NPC_PER_MAP; i++)
+        {
+            if (map[m].npc[i] != NULL)
+            {
+                clif_clearchar_area (&map[m].npc[i]->bl, 2);
+                map_delblock (&map[m].npc[i]->bl);
+                numdb_erase (id_db, map[m].npc[i]->bl.id);
+                if (map[m].npc[i]->bl.subtype == SCRIPT)
+                {
+//                    free(map[m].npc[i]->u.scr.script);
+//                    free(map[m].npc[i]->u.scr.label_list);
+                }
+                free (map[m].npc[i]);
+                map[m].npc[i] = NULL;
+                n++;
+            }
+        }
+    }
+    printf ("%d NPCs removed.\n", n);
+}
+
+/*==========================================
+ * map名からmap番号へ変換
+ *------------------------------------------
+ */
+int map_mapname2mapid (char *name)
+{
+    struct map_data *md = (struct map_data *)strdb_search (map_db, name);
+    if (md == NULL || md->gat == NULL)
+        return -1;
+    return md->m;
+}
+
+/*==========================================
+ * 他鯖map名からip,port変換
+ *------------------------------------------
+ */
+int map_mapname2ipport (char *name, int *ip, int *port)
+{
+    struct map_data_other_server *mdos = (struct map_data_other_server *)strdb_search (map_db, name);
+    if (mdos == NULL || mdos->gat)
+        return -1;
+    *ip = mdos->ip;
+    *port = mdos->port;
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int map_check_dir (int s_dir, int t_dir)
+{
+    if (s_dir == t_dir)
+        return 0;
+    switch (s_dir)
+    {
+        case 0:
+            if (t_dir == 7 || t_dir == 1 || t_dir == 0)
+                return 0;
+            break;
+        case 1:
+            if (t_dir == 0 || t_dir == 2 || t_dir == 1)
+                return 0;
+            break;
+        case 2:
+            if (t_dir == 1 || t_dir == 3 || t_dir == 2)
+                return 0;
+            break;
+        case 3:
+            if (t_dir == 2 || t_dir == 4 || t_dir == 3)
+                return 0;
+            break;
+        case 4:
+            if (t_dir == 3 || t_dir == 5 || t_dir == 4)
+                return 0;
+            break;
+        case 5:
+            if (t_dir == 4 || t_dir == 6 || t_dir == 5)
+                return 0;
+            break;
+        case 6:
+            if (t_dir == 5 || t_dir == 7 || t_dir == 6)
+                return 0;
+            break;
+        case 7:
+            if (t_dir == 6 || t_dir == 0 || t_dir == 7)
+                return 0;
+            break;
+    }
+    return 1;
+}
+
+/*==========================================
+ * 彼我の方向を計算
+ *------------------------------------------
+ */
+int map_calc_dir (struct block_list *src, int x, int y)
+{
+    int  dir = 0;
+    int  dx, dy;
+
+    nullpo_retr (0, src);
+
+    dx = x - src->x;
+    dy = y - src->y;
+    if (dx == 0 && dy == 0)
+    {                           // 彼我の場所一致
+        dir = 0;                // 上
+    }
+    else if (dx >= 0 && dy >= 0)
+    {                           // 方向的に右上
+        dir = 7;                // 右上
+        if (dx * 3 - 1 < dy)
+            dir = 0;            // 上
+        if (dx > dy * 3)
+            dir = 6;            // 右
+    }
+    else if (dx >= 0 && dy <= 0)
+    {                           // 方向的に右下
+        dir = 5;                // 右下
+        if (dx * 3 - 1 < -dy)
+            dir = 4;            // 下
+        if (dx > -dy * 3)
+            dir = 6;            // 右
+    }
+    else if (dx <= 0 && dy <= 0)
+    {                           // 方向的に左下
+        dir = 3;                // 左下
+        if (dx * 3 + 1 > dy)
+            dir = 4;            // 下
+        if (dx < dy * 3)
+            dir = 2;            // 左
+    }
+    else
+    {                           // 方向的に左上
+        dir = 1;                // 左上
+        if (-dx * 3 - 1 < dy)
+            dir = 0;            // 上
+        if (-dx > dy * 3)
+            dir = 2;            // 左
+    }
+    return dir;
+}
+
+// gat系
+/*==========================================
+ * (m,x,y)の状態を調べる
+ *------------------------------------------
+ */
+int map_getcell (int m, int x, int y)
+{
+    if (x < 0 || x >= map[m].xs - 1 || y < 0 || y >= map[m].ys - 1)
+        return 1;
+    return map[m].gat[x + y * map[m].xs];
+}
+
+/*==========================================
+ * (m,x,y)の状態をtにする
+ *------------------------------------------
+ */
+int map_setcell (int m, int x, int y, int t)
+{
+    if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
+        return t;
+    return map[m].gat[x + y * map[m].xs] = t;
+}
+
+/*==========================================
+ * 他鯖管理のマップをdbに追加
+ *------------------------------------------
+ */
+int map_setipport (char *name, unsigned long ip, int port)
+{
+    struct map_data_other_server *mdos = NULL;
+
+    struct map_data *md = (struct map_data *)strdb_search (map_db, name);
+    if (md == NULL)
+    {                           // not exist -> add new data
+        CREATE (mdos, struct map_data_other_server, 1);
+        memcpy (mdos->name, name, 24);
+        mdos->gat = NULL;
+        mdos->ip = ip;
+        mdos->port = port;
+        strdb_insert (map_db, mdos->name, mdos);
+    }
+    else
+    {
+        if (md->gat)
+        {                       // local -> check data
+            if (ip != clif_getip () || port != clif_getport ())
+            {
+                printf ("from char server : %s -> %08lx:%d\n", name, ip,
+                        port);
+                return 1;
+            }
+        }
+        else
+        {                       // update
+            mdos = (struct map_data_other_server *) md;
+            mdos->ip = ip;
+            mdos->port = port;
+        }
+    }
+    return 0;
+}
+
+// 初期化周り
+/*==========================================
+ * 水場高さ設定
+ *------------------------------------------
+ */
+static struct Waterlist
+{
+    char mapname[24];
+    int  waterheight;
+}   *waterlist = NULL;
+
+#define NO_WATER 1000000
+
+static int map_waterheight (char *mapname)
+{
+    if (waterlist)
+    {
+        int  i;
+        for (i = 0; waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER; i++)
+            if (strcmp (waterlist[i].mapname, mapname) == 0)
+                return waterlist[i].waterheight;
+    }
+    return NO_WATER;
+}
+
+static void map_readwater (char *watertxt)
+{
+    char line[1024], w1[1024];
+    FILE *fp = NULL;
+    int  n = 0;
+
+    fp = fopen_ (watertxt, "r");
+    if (fp == NULL)
+    {
+        printf ("file not found: %s\n", watertxt);
+        return;
+    }
+    if (waterlist == NULL)
+    {
+        CREATE (waterlist, struct Waterlist, MAX_MAP_PER_SERVER);
+    }
+    while (fgets (line, 1020, fp) && n < MAX_MAP_PER_SERVER)
+    {
+        int  wh, count;
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if ((count = sscanf (line, "%s%d", w1, &wh)) < 1)
+        {
+            continue;
+        }
+        strcpy (waterlist[n].mapname, w1);
+        if (count >= 2)
+            waterlist[n].waterheight = wh;
+        else
+            waterlist[n].waterheight = 3;
+        n++;
+    }
+    fclose_ (fp);
+}
+
+/*==========================================
+ * マップ1枚読み込み
+ *------------------------------------------
+ */
+static int map_readmap (int m, char *fn, char *alias)
+{
+    int  s;
+    int  x, y, xs, ys;
+    struct gat_1cell
+    {
+        char type;
+    }   *p;
+    int  wh;
+    size_t size;
+
+    // read & convert fn
+    uint8_t *gat = (uint8_t *)grfio_read (fn);
+    if (gat == NULL)
+        return -1;
+
+    printf ("\rLoading Maps [%d/%d]: %-50s  ", m, map_num, fn);
+    fflush (stdout);
+
+    map[m].m = m;
+    xs = map[m].xs = *(short *) (gat);
+    ys = map[m].ys = *(short *) (gat + 2);
+    printf ("\n%i %i\n", xs, ys);
+    map[m].gat = (uint8_t *)calloc (s = map[m].xs * map[m].ys, 1);
+    if (map[m].gat == NULL)
+    {
+        printf ("out of memory : map_readmap gat\n");
+        exit (1);
+    }
+
+    map[m].npc_num = 0;
+    map[m].users = 0;
+    memset (&map[m].flag, 0, sizeof (map[m].flag));
+    if (battle_config.pk_mode)
+        map[m].flag.pvp = 1;    // make all maps pvp for pk_mode [Valaris]
+    wh = map_waterheight (map[m].name);
+    for (y = 0; y < ys; y++)
+    {
+        p = (struct gat_1cell *) (gat + y * xs + 4);
+        for (x = 0; x < xs; x++)
+        {
+            /*if(wh!=NO_WATER && p->type==0){
+             * // 水場判定
+             * map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
+             * } else { */
+            map[m].gat[x + y * xs] = p->type;
+            //}
+            p++;
+        }
+    }
+    free (gat);
+
+    map[m].bxs = (xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    map[m].bys = (ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
+    size = map[m].bxs * map[m].bys;
+
+    CREATE (map[m].block, struct block_list *, size);
+
+    CREATE (map[m].block_mob, struct block_list *, size);
+
+    CREATE (map[m].block_count, int, size);
+
+    CREATE (map[m].block_mob_count, int, size);
+
+    strdb_insert (map_db, map[m].name, &map[m]);
+
+//  printf("%s read done\n",fn);
+
+    return 0;
+}
+
+/*==========================================
+ * 全てのmapデータを読み込む
+ *------------------------------------------
+ */
+int map_readallmap (void)
+{
+    int  i, maps_removed = 0;
+    char fn[256] = "";
+
+    // 先に全部のャbプの存在を確認
+    for (i = 0; i < map_num; i++)
+    {
+        if (strstr (map[i].name, ".gat") == NULL)
+            continue;
+        sprintf (fn, "data\\%s", map[i].name);
+        // TODO - remove this, it is the last call to grfio_size, which is deprecated
+        if (!grfio_size (fn))
+        {
+            map_delmap (map[i].name);
+            maps_removed++;
+        }
+    }
+    for (i = 0; i < map_num; i++)
+    {
+        if (strstr (map[i].name, ".gat") != NULL)
+        {
+            char *p = strstr (map[i].name, ">");    // [MouseJstr]
+            if (p != NULL)
+            {
+                char alias[64];
+                *p = '\0';
+                strcpy (alias, map[i].name);
+                strcpy (map[i].name, p + 1);
+                sprintf (fn, "data\\%s", map[i].name);
+                if (map_readmap (i, fn, alias) == -1)
+                {
+                    map_delmap (map[i].name);
+                    maps_removed++;
+                }
+            }
+            else
+            {
+                sprintf (fn, "data\\%s", map[i].name);
+                if (map_readmap (i, fn, NULL) == -1)
+                {
+                    map_delmap (map[i].name);
+                    maps_removed++;
+                }
+            }
+        }
+    }
+
+    free (waterlist);
+    printf ("\rMaps Loaded: %d %60s\n", map_num, "");
+    printf ("\rMaps Removed: %d \n", maps_removed);
+    return 0;
+}
+
+/*==========================================
+ * 読み込むmapを追加する
+ *------------------------------------------
+ */
+int map_addmap (char *mapname)
+{
+    if (strcasecmp (mapname, "clear") == 0)
+    {
+        map_num = 0;
+        return 0;
+    }
+
+    if (map_num >= MAX_MAP_PER_SERVER - 1)
+    {
+        printf ("too many map\n");
+        return 1;
+    }
+    memcpy (map[map_num].name, mapname, 24);
+    map_num++;
+    return 0;
+}
+
+/*==========================================
+ * 読み込むmapを削除する
+ *------------------------------------------
+ */
+int map_delmap (char *mapname)
+{
+    int  i;
+
+    if (strcasecmp (mapname, "all") == 0)
+    {
+        map_num = 0;
+        return 0;
+    }
+
+    for (i = 0; i < map_num; i++)
+    {
+        if (strcmp (map[i].name, mapname) == 0)
+        {
+            printf ("Removing map [ %s ] from maplist\n", map[i].name);
+            memmove (map + i, map + i + 1,
+                     sizeof (map[0]) * (map_num - i - 1));
+            map_num--;
+        }
+    }
+    return 0;
+}
+
+extern char *gm_logfile_name;
+
+#define LOGFILE_SECONDS_PER_CHUNK_SHIFT 10
+
+FILE *map_logfile = NULL;
+char *map_logfile_name = NULL;
+static long map_logfile_index;
+
+static void map_close_logfile (void)
+{
+    if (map_logfile)
+    {
+        char *filenameop_buf = (char*)malloc (strlen (map_logfile_name) + 50);
+        sprintf (filenameop_buf, "gzip -f %s.%ld", map_logfile_name,
+                 map_logfile_index);
+
+        fclose (map_logfile);
+
+        if (!system (filenameop_buf))
+            perror (filenameop_buf);
+
+        free (filenameop_buf);
+    }
+}
+
+static void map_start_logfile (long suffix)
+{
+    char *filename_buf = (char*)malloc (strlen (map_logfile_name) + 50);
+    map_logfile_index = suffix >> LOGFILE_SECONDS_PER_CHUNK_SHIFT;
+
+    sprintf (filename_buf, "%s.%ld", map_logfile_name, map_logfile_index);
+    map_logfile = fopen (filename_buf, "w+");
+    if (!map_logfile)
+        perror (map_logfile_name);
+
+    free (filename_buf);
+}
+
+static void map_set_logfile (char *filename)
+{
+    struct timeval tv;
+
+    map_logfile_name = strdup (filename);
+    gettimeofday (&tv, NULL);
+
+    map_start_logfile (tv.tv_sec);
+
+    MAP_LOG ("log-start v3");
+}
+
+void map_write_log (char *format, ...)
+{
+    struct timeval tv;
+    va_list args;
+    va_start (args, format);
+
+    gettimeofday (&tv, NULL);
+
+    if ((tv.tv_sec >> LOGFILE_SECONDS_PER_CHUNK_SHIFT) != map_logfile_index)
+    {
+        map_close_logfile ();
+        map_start_logfile (tv.tv_sec);
+    }
+
+    fprintf (map_logfile, "%ld.%06ld ", (long) tv.tv_sec, (long) tv.tv_usec);
+    vfprintf (map_logfile, format, args);
+    fputc ('\n', map_logfile);
+}
+
+/*==========================================
+ * 設定ファイルを読み込む
+ *------------------------------------------
+ */
+int map_config_read (char *cfgName)
+{
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+    struct hostent *h = NULL;
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        printf ("Map configuration file not found at: %s\n", cfgName);
+        exit (1);
+    }
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (sscanf (line, "%[^:]: %[^\r\n]", w1, w2) == 2)
+        {
+            if (strcasecmp (w1, "userid") == 0)
+            {
+                chrif_setuserid (w2);
+            }
+            else if (strcasecmp (w1, "passwd") == 0)
+            {
+                chrif_setpasswd (w2);
+            }
+            else if (strcasecmp (w1, "char_ip") == 0)
+            {
+                h = gethostbyname (w2);
+                if (h != NULL)
+                {
+                    printf
+                        ("Character server IP address : %s -> %d.%d.%d.%d\n",
+                         w2, (unsigned char) h->h_addr[0],
+                         (unsigned char) h->h_addr[1],
+                         (unsigned char) h->h_addr[2],
+                         (unsigned char) h->h_addr[3]);
+                    sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0],
+                             (unsigned char) h->h_addr[1],
+                             (unsigned char) h->h_addr[2],
+                             (unsigned char) h->h_addr[3]);
+                }
+                chrif_setip (w2);
+            }
+            else if (strcasecmp (w1, "char_port") == 0)
+            {
+                chrif_setport (atoi (w2));
+            }
+            else if (strcasecmp (w1, "map_ip") == 0)
+            {
+                h = gethostbyname (w2);
+                if (h != NULL)
+                {
+                    printf ("Map server IP address : %s -> %d.%d.%d.%d\n", w2,
+                            (unsigned char) h->h_addr[0],
+                            (unsigned char) h->h_addr[1],
+                            (unsigned char) h->h_addr[2],
+                            (unsigned char) h->h_addr[3]);
+                    sprintf (w2, "%d.%d.%d.%d", (unsigned char) h->h_addr[0],
+                             (unsigned char) h->h_addr[1],
+                             (unsigned char) h->h_addr[2],
+                             (unsigned char) h->h_addr[3]);
+                }
+                clif_setip (w2);
+            }
+            else if (strcasecmp (w1, "map_port") == 0)
+            {
+                clif_setport (atoi (w2));
+                map_port = (atoi (w2));
+            }
+            else if (strcasecmp (w1, "water_height") == 0)
+            {
+                map_readwater (w2);
+            }
+            else if (strcasecmp (w1, "map") == 0)
+            {
+                map_addmap (w2);
+            }
+            else if (strcasecmp (w1, "delmap") == 0)
+            {
+                map_delmap (w2);
+            }
+            else if (strcasecmp (w1, "npc") == 0)
+            {
+                npc_addsrcfile (w2);
+            }
+            else if (strcasecmp (w1, "delnpc") == 0)
+            {
+                npc_delsrcfile (w2);
+            }
+            else if (strcasecmp (w1, "autosave_time") == 0)
+            {
+                autosave_interval = atoi (w2) * 1000;
+                if (autosave_interval <= 0)
+                    autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
+            }
+            else if (strcasecmp (w1, "motd_txt") == 0)
+            {
+                strcpy (motd_txt, w2);
+            }
+            else if (strcasecmp (w1, "help_txt") == 0)
+            {
+                strcpy (help_txt, w2);
+            }
+            else if (strcasecmp (w1, "mapreg_txt") == 0)
+            {
+                strcpy (mapreg_txt, w2);
+            }
+            else if (strcasecmp (w1, "gm_log") == 0)
+            {
+                gm_logfile_name = strdup (w2);
+            }
+            else if (strcasecmp (w1, "log_file") == 0)
+            {
+                map_set_logfile (w2);
+            }
+            else if (strcasecmp (w1, "import") == 0)
+            {
+                map_config_read (w2);
+            }
+        }
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+static int cleanup_sub (struct block_list *bl, va_list ap)
+{
+    nullpo_retr (0, bl);
+
+    switch (bl->type)
+    {
+        case BL_PC:
+            map_delblock (bl);  // There is something better...
+            break;
+        case BL_NPC:
+            npc_delete ((struct npc_data *) bl);
+            break;
+        case BL_MOB:
+            mob_delete ((struct mob_data *) bl);
+            break;
+        case BL_ITEM:
+            map_clearflooritem (bl->id);
+            break;
+        case BL_SKILL:
+            skill_delunit ((struct skill_unit *) bl);
+            break;
+        case BL_SPELL:
+            spell_free_invocation ((struct invocation *) bl);
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * map鯖終了時処理
+ *------------------------------------------
+ */
+void term_func (void)
+{
+    map_close_logfile ();
+
+    int  map_id, i;
+
+    for (map_id = 0; map_id < map_num; map_id++)
+    {
+        if (map[map_id].m)
+            map_foreachinarea (cleanup_sub, map_id, 0, 0, map[map_id].xs,
+                               map[map_id].ys, 0, 0);
+    }
+
+    for (i = 0; i < fd_max; i++)
+        delete_session (i);
+
+    map_removenpc ();
+
+    numdb_final (id_db, NULL);
+    strdb_final (map_db, NULL);
+    strdb_final (nick_db, NULL);
+    numdb_final (charid_db, NULL);
+
+    for (i = 0; i <= map_num; i++)
+    {
+        if (map[i].gat)
+            free (map[i].gat);
+        if (map[i].block)
+            free (map[i].block);
+        if (map[i].block_mob)
+            free (map[i].block_mob);
+        if (map[i].block_count)
+            free (map[i].block_count);
+        if (map[i].block_mob_count)
+            free (map[i].block_mob_count);
+    }
+    do_final_script ();
+    do_final_itemdb ();
+    do_final_storage ();
+    do_final_guild ();
+}
+
+/// --help was passed
+// FIXME this should produce output
+void map_helpscreen (void)
+{
+    exit (1);
+}
+
+int compare_item (struct item *a, struct item *b)
+{
+    return ((a->nameid == b->nameid) &&
+            (a->identify == b->identify) &&
+            (a->refine == b->refine) &&
+            (a->attribute == b->attribute) &&
+            (a->card[0] == b->card[0]) &&
+            (a->card[1] == b->card[1]) &&
+            (a->card[2] == b->card[2]) && (a->card[3] == b->card[3]));
+}
+
+/*======================================================
+ * Map-Server Init and Command-line Arguments [Valaris]
+ *------------------------------------------------------
+ */
+int do_init (int argc, char *argv[])
+{
+    int  i;
+
+    unsigned char *MAP_CONF_NAME = "conf/map_athena.conf";
+    unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
+    unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
+    unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf";
+    unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf";
+
+    for (i = 1; i < argc; i++)
+    {
+
+        if (strcmp (argv[i], "--help") == 0 || strcmp (argv[i], "--h") == 0
+            || strcmp (argv[i], "--?") == 0 || strcmp (argv[i], "/?") == 0)
+            map_helpscreen ();
+        else if (strcmp (argv[i], "--map_config") == 0)
+            MAP_CONF_NAME = argv[i + 1];
+        else if (strcmp (argv[i], "--battle_config") == 0)
+            BATTLE_CONF_FILENAME = argv[i + 1];
+        else if (strcmp (argv[i], "--atcommand_config") == 0)
+            ATCOMMAND_CONF_FILENAME = argv[i + 1];
+        else if (strcmp (argv[i], "--script_config") == 0)
+            SCRIPT_CONF_NAME = argv[i + 1];
+        else if (strcmp (argv[i], "--msg_config") == 0)
+            MSG_CONF_NAME = argv[i + 1];
+    }
+
+    map_config_read (MAP_CONF_NAME);
+    battle_config_read (BATTLE_CONF_FILENAME);
+    atcommand_config_read (ATCOMMAND_CONF_FILENAME);
+    script_config_read (SCRIPT_CONF_NAME);
+    msg_config_read (MSG_CONF_NAME);
+
+    id_db = numdb_init ();
+    map_db = strdb_init (16);
+    nick_db = strdb_init (24);
+    charid_db = numdb_init ();
+
+    map_readallmap ();
+
+//    add_timer_func_list (map_clearflooritem_timer, "map_clearflooritem_timer");
+
+    do_init_chrif ();
+    do_init_clif ();
+    do_init_itemdb ();
+    do_init_mob ();             // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先
+    do_init_script ();
+    do_init_npc ();
+    do_init_pc ();
+    do_init_party ();
+    do_init_guild ();
+    do_init_storage ();
+    do_init_skill ();
+    do_init_magic ();
+
+    npc_event_do_oninit ();     // npcのOnInitイベント実行
+
+    if (battle_config.pk_mode == 1)
+        printf ("The server is running in \033[1;31mPK Mode\033[0m.\n");
+
+    printf
+        ("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n",
+         map_port);
+
+    return 0;
+}
+
+int map_scriptcont (struct map_session_data *sd, int id)
+{
+    struct block_list *bl = map_id2bl (id);
+
+    if (!bl)
+        return 0;
+
+    switch (bl->type)
+    {
+        case BL_NPC:
+            return npc_scriptcont (sd, id);
+        case BL_SPELL:
+            spell_execute_script ((struct invocation *) bl);
+            break;
+    }
+
+    return 0;
+}
diff --git a/src/map/map.h b/src/map/map.h
deleted file mode 100644
index a480cd0..0000000
--- a/src/map/map.h
+++ /dev/null
@@ -1,822 +0,0 @@
-// $Id: map.h,v 1.8 2004/09/25 11:39:17 MouseJstr Exp $
-#ifndef _MAP_H_
-#define _MAP_H_
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include "../common/mmo.h"
-#include "../common/timer.h"
-#include "../common/db.h"
-
-#ifndef MAX
-#  define MAX(x,y) (((x)>(y)) ? (x) : (y))
-#endif
-#ifndef MIN
-#  define MIN(x,y) (((x)<(y)) ? (x) : (y))
-#endif
-
-#define MAX_PC_CLASS (1+6+6+1+6+1+1+1+1+4023)
-#define PC_CLASS_BASE 0
-#define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001)
-#define PC_CLASS_BASE3 (PC_CLASS_BASE2 + 22)
-#define MAX_NPC_PER_MAP 512
-#define BLOCK_SIZE 8
-#define AREA_SIZE battle_config.area_size
-#define LOCAL_REG_NUM 16
-#define LIFETIME_FLOORITEM 60
-#define DAMAGELOG_SIZE 30
-#define LOOTITEM_SIZE 10
-#define MAX_SKILL_LEVEL 100
-#define MAX_STATUSCHANGE 200
-#define MAX_SKILLUNITGROUP 32
-#define MAX_MOBSKILLUNITGROUP 8
-#define MAX_SKILLUNITGROUPTICKSET 128
-#define MAX_SKILLTIMERSKILL 32
-#define MAX_MOBSKILLTIMERSKILL 10
-#define MAX_MOBSKILL 32
-#define MAX_EVENTQUEUE 2
-#define MAX_EVENTTIMER 32
-#define NATURAL_HEAL_INTERVAL 500
-#define MAX_FLOORITEM 500000
-#define MAX_LEVEL 255
-#define MAX_WALKPATH 48
-#define MAX_DROP_PER_MAP 48
-
-#define DEFAULT_AUTOSAVE_INTERVAL 60*1000
-
-// [Fate] status.option properties.  These are persistent status changes.
-// IDs that are not listed are not used in the code (to the best of my knowledge)
-#define OPTION_HIDE2		0x0002  // apparently some weaker non-GM hide
-#define OPTION_CLOAK		0x0004
-#define OPTION_10		0x0010
-#define OPTION_20		0x0020
-#define OPTION_HIDE		0x0040  // [Fate] This is the GM `@hide' flag
-#define OPTION_800		0x0800
-#define OPTION_INVISIBILITY	0x1000  // [Fate] Complete invisibility to other clients
-#define OPTION_SCRIBE		0x2000  // [Fate] Auto-logging of nearby comments
-#define OPTION_CHASEWALK	0x4000
-
-//  Below are special clif_changestatus() IDs reserved for option updates
-#define CLIF_OPTION_SC_BASE		0x1000
-#define CLIF_OPTION_SC_INVISIBILITY	(CLIF_OPTION_SC_BASE)
-#define CLIF_OPTION_SC_SCRIBE		(CLIF_OPTION_SC_BASE + 1)
-
-enum
-{ BL_NUL, BL_PC, BL_NPC, BL_MOB, BL_ITEM, BL_CHAT, BL_SKILL, BL_SPELL };
-enum
-{ WARP, SHOP, SCRIPT, MONS, MESSAGE };
-struct block_list
-{
-    struct block_list *next, *prev;
-    int  id;
-    short m, x, y;
-    unsigned char type;
-    unsigned char subtype;
-};
-
-struct walkpath_data
-{
-    unsigned char path_len, path_pos, path_half;
-    unsigned char path[MAX_WALKPATH];
-};
-struct script_reg
-{
-    int  index;
-    int  data;
-};
-struct script_regstr
-{
-    int  index;
-    char data[256];
-};
-struct status_change
-{
-    int  timer;
-    int  val1, val2, val3, val4;
-    int  spell_invocation;      /* [Fate] If triggered by a spell, record here */
-};
-
-struct invocation;
-
-struct skill_unit_group;
-struct skill_unit
-{
-    struct block_list bl;
-
-    struct skill_unit_group *group;
-
-    int  limit;
-    int  val1, val2;
-    short alive, range;
-};
-struct skill_unit_group
-{
-    int  src_id;
-    int  party_id;
-    int  guild_id;
-    int  map, range;
-    int  target_flag;
-    unsigned int tick;
-    int  limit, interval;
-
-    int  skill_id, skill_lv;
-    int  val1, val2;
-    char *valstr;
-    int  unit_id;
-    int  group_id;
-    int  unit_count, alive_count;
-    struct skill_unit *unit;
-};
-struct skill_unit_group_tickset
-{
-    unsigned int tick;
-    int  group_id;
-};
-struct skill_timerskill
-{
-    int  timer;
-    int  src_id;
-    int  target_id;
-    int  map;
-    short x, y;
-    short skill_id, skill_lv;
-    int  type;
-    int  flag;
-};
-
-struct npc_data;
-struct item_data;
-struct square;
-
-struct quick_regeneration
-{                               // [Fate]
-    int  amount;                // Amount of HP/SP left to regenerate
-    unsigned char speed;        // less is faster (number of half-second ticks to wait between updates)
-    unsigned char tickdelay;    // number of ticks to next update
-};
-
-#define VERSION_2_SKILLINFO  0x02   // client supports full skillinfo blocks
-
-struct map_session_data
-{
-    struct block_list bl;
-    struct
-    {
-        unsigned auth:1;
-        unsigned change_walk_target:1;
-        unsigned attack_continue:1;
-        unsigned menu_or_input:1;
-        unsigned dead_sit:2;
-        unsigned skillcastcancel:1;
-        unsigned waitingdisconnect:1;
-        unsigned lr_flag:2;
-        unsigned connect_new:1;
-        unsigned arrow_atk:1;
-        unsigned attack_type:3;
-        unsigned skill_flag:1;
-        unsigned gangsterparadise:1;
-        unsigned produce_flag:1;
-        unsigned make_arrow_flag:1;
-        unsigned potionpitcher_flag:1;
-        unsigned storage_flag:2;    //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex]
-        unsigned shroud_active:1;
-        unsigned shroud_hides_name_talking:1;
-        unsigned shroud_disappears_on_pickup:1;
-        unsigned shroud_disappears_on_talk:1;
-    } state;
-    struct
-    {
-        unsigned killer:1;
-        unsigned killable:1;
-        unsigned restart_full_recover:1;
-        unsigned no_castcancel:1;
-        unsigned no_castcancel2:1;
-        unsigned no_sizefix:1;
-        unsigned no_magic_damage:1;
-        unsigned no_weapon_damage:1;
-        unsigned no_gemstone:1;
-        unsigned infinite_endure:1;
-        unsigned unbreakable_weapon:1;
-        unsigned unbreakable_armor:1;
-        unsigned infinite_autospell:1;
-        unsigned deaf:1;
-    } special_state;
-    int  char_id, login_id1, login_id2, sex;
-    unsigned char tmw_version;  // tmw client version
-    struct mmo_charstatus status;
-    struct item_data *inventory_data[MAX_INVENTORY];
-    short equip_index[11];
-    int  weight, max_weight;
-    int  cart_weight, cart_max_weight, cart_num, cart_max_num;
-    char mapname[24];
-    int  fd, new_fd;
-    short to_x, to_y;
-    short speed, prev_speed;
-    short opt1, opt2, opt3;
-    char dir, head_dir;
-    unsigned int client_tick, server_tick;
-    struct walkpath_data walkpath;
-    int  walktimer;
-    int  npc_id, areanpc_id, npc_shopid;
-    int  npc_pos;
-    int  npc_menu;
-    int  npc_amount;
-    int  npc_stack, npc_stackmax;
-    char *npc_script, *npc_scriptroot;
-    char *npc_stackbuf;
-    char npc_str[256];
-    struct
-    {
-        unsigned storage:1;
-        unsigned divorce:1;
-    } npc_flags;
-    unsigned int chatID;
-
-    int  attacktimer;
-    int  attacktarget;
-    short attacktarget_lv;
-    unsigned int attackabletime;
-
-    int  followtimer;           // [MouseJstr]
-    int  followtarget;
-
-    unsigned int cast_tick;     // [Fate] Next tick at which spellcasting is allowed
-    struct invocation *active_spells;   // [Fate] Singly-linked list of active spells linked to this PC
-    int  attack_spell_override; // [Fate] When an attack spell is active for this player, they trigger it
-    // like a weapon.  Check pc_attack_timer() for details.
-    short attack_spell_icon_override;   // Weapon equipment slot (slot 4) item override
-    short attack_spell_look_override;   // Weapon `look' (attack animation) override
-    short attack_spell_charges; // [Fate] Remaining number of charges for the attack spell
-    short attack_spell_delay;   // [Fate] ms delay after spell attack
-    short attack_spell_range;   // [Fate] spell range
-    short spellpower_bonus_target, spellpower_bonus_current;    // [Fate] Spellpower boni.  _current is the active one.
-    //_current slowly approximates _target, and _target is determined by equipment.
-
-    short attackrange, attackrange_;
-    int  skilltimer;
-    int  skilltarget;
-    short skillx, skilly;
-    short skillid, skilllv;
-    short skillitem, skillitemlv;
-    short skillid_old, skilllv_old;
-    short skillid_dance, skilllv_dance;
-    struct skill_unit_group skillunit[MAX_SKILLUNITGROUP];
-    struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
-    struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL];
-    int  cloneskill_id, cloneskill_lv;
-    int  potion_hp, potion_sp, potion_per_hp, potion_per_sp;
-
-    // [Fate] Used for gradual healing; amount of enqueued regeneration
-    struct quick_regeneration quick_regeneration_hp, quick_regeneration_sp;
-    // [Fate] XP that can be extracted from this player by healing
-    int  heal_xp;               // i.e., OTHER players (healers) can partake in this player's XP
-
-    int  invincible_timer;
-    unsigned int canact_tick;
-    unsigned int canmove_tick;
-    unsigned int canlog_tick;
-    int  hp_sub, sp_sub;
-    int  inchealhptick, inchealsptick, inchealspirithptick,
-        inchealspiritsptick;
-// -- moonsoul (new tick for berserk self-damage)
-    int  berserkdamagetick;
-    int  fame;
-
-    short view_class;
-    short weapontype1, weapontype2;
-    short disguiseflag, disguise;   // [Valaris]
-    int  paramb[6], paramc[6], parame[6], paramcard[6];
-    int  hit, flee, flee2, aspd, amotion, dmotion;
-    int  watk, watk2, atkmods[3];
-    int  def, def2, mdef, mdef2, critical, matk1, matk2;
-    int  atk_ele, def_ele, star, overrefine;
-    int  castrate, hprate, sprate, dsprate;
-    int  addele[10], addrace[12], addsize[3], subele[10], subrace[12];
-    int  addeff[10], addeff2[10], reseff[10];
-    int  watk_, watk_2, atkmods_[3], addele_[10], addrace_[12], addsize_[3];    //二刀流のために追加
-    int  atk_ele_, star_, overrefine_;  //二刀流のために追加
-    int  base_atk, atk_rate;
-    int  arrow_atk, arrow_ele, arrow_cri, arrow_hit, arrow_range;
-    int  arrow_addele[10], arrow_addrace[12], arrow_addsize[3],
-        arrow_addeff[10], arrow_addeff2[10];
-    int  nhealhp, nhealsp, nshealhp, nshealsp, nsshealhp, nsshealsp;
-    int  aspd_rate, speed_rate, hprecov_rate, sprecov_rate, critical_def,
-        double_rate;
-    int  near_attack_def_rate, long_attack_def_rate, magic_def_rate,
-        misc_def_rate;
-    int  matk_rate, ignore_def_ele, ignore_def_race, ignore_def_ele_,
-        ignore_def_race_;
-    int  ignore_mdef_ele, ignore_mdef_race;
-    int  magic_addele[10], magic_addrace[12], magic_subrace[12];
-    int  perfect_hit, get_zeny_num;
-    int  critical_rate, hit_rate, flee_rate, flee2_rate, def_rate, def2_rate,
-        mdef_rate, mdef2_rate;
-    int  def_ratio_atk_ele, def_ratio_atk_ele_, def_ratio_atk_race,
-        def_ratio_atk_race_;
-    int  add_damage_class_count, add_damage_class_count_,
-        add_magic_damage_class_count;
-    short add_damage_classid[10], add_damage_classid_[10],
-        add_magic_damage_classid[10];
-    int  add_damage_classrate[10], add_damage_classrate_[10],
-        add_magic_damage_classrate[10];
-    short add_def_class_count, add_mdef_class_count;
-    short add_def_classid[10], add_mdef_classid[10];
-    int  add_def_classrate[10], add_mdef_classrate[10];
-    short monster_drop_item_count;
-    short monster_drop_itemid[10];
-    int  monster_drop_race[10], monster_drop_itemrate[10];
-    int  double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add,
-        get_zeny_add_num;
-    short splash_range, splash_add_range;
-    short autospell_id, autospell_lv, autospell_rate;
-    short hp_drain_rate, hp_drain_per, sp_drain_rate, sp_drain_per;
-    short hp_drain_rate_, hp_drain_per_, sp_drain_rate_, sp_drain_per_;
-    int  short_weapon_damage_return, long_weapon_damage_return;
-    int  weapon_coma_ele[10], weapon_coma_race[12];
-    short break_weapon_rate, break_armor_rate;
-    short add_steal_rate;
-
-    short spiritball, spiritball_old;
-    int  spirit_timer[MAX_SKILL_LEVEL];
-    int  magic_damage_return;   // AppleGirl Was Here
-    int  random_attack_increase_add, random_attack_increase_per;    // [Valaris]
-    int  perfect_hiding;        // [Valaris]
-    int  unbreakable;
-
-    int  die_counter;
-    short doridori_counter;
-
-    int  reg_num;
-    struct script_reg *reg;
-    int  regstr_num;
-    struct script_regstr *regstr;
-
-    struct status_change sc_data[MAX_STATUSCHANGE];
-    short sc_count;
-    struct square dev;
-
-    int  trade_partner;
-    int  deal_item_index[10];
-    int  deal_item_amount[10];
-    int  deal_zeny;
-    short deal_locked;
-
-    int  party_sended, party_invite, party_invite_account;
-    int  party_hp, party_x, party_y;
-
-    int  guild_sended, guild_invite, guild_invite_account;
-    int  guild_emblem_id, guild_alliance, guild_alliance_account;
-    int  guildspy;              // [Syrus22]
-    int  partyspy;              // [Syrus22]
-
-    char message[80];
-
-    int  catch_target_class;
-
-    int  pvp_point, pvp_rank, pvp_timer, pvp_lastusers;
-
-    char eventqueue[MAX_EVENTQUEUE][50];
-    int  eventtimer[MAX_EVENTTIMER];
-
-    int  last_skillid, last_skilllv;    // Added by RoVeRT
-    struct
-    {
-        char name[24];
-    } ignore[80];
-    int  ignoreAll;
-    short sg_count;
-
-    struct
-    {
-        unsigned in_progress:1;
-    } auto_ban_info;
-
-    time_t chat_reset_due;
-    time_t chat_repeat_reset_due;
-    int  chat_lines_in;
-    int  chat_total_repeats;
-    char chat_lastmsg[513];
-
-    unsigned int flood_rates[0x220];
-    time_t packet_flood_reset_due;
-    int packet_flood_in;
-
-    in_addr_t ip;
-};
-
-struct npc_timerevent_list
-{
-    int  timer, pos;
-};
-struct npc_label_list
-{
-    char name[24];
-    int  pos;
-};
-struct npc_item_list
-{
-    int  nameid, value;
-};
-struct npc_data
-{
-    struct block_list bl;
-    short n;
-    short npc_class, dir;
-    short speed;
-    char name[24];
-    char exname[24];
-    int  chat_id;
-    short opt1, opt2, opt3, option;
-    short flag;
-    union
-    {
-        struct
-        {
-            char *script;
-            short xs, ys;
-            int  guild_id;
-            int  timer, timerid, timeramount, nexttimer;
-            unsigned int timertick;
-            struct npc_timerevent_list *timer_event;
-            int  label_list_num;
-            struct npc_label_list *label_list;
-            int  src_id;
-        } scr;
-        struct npc_item_list shop_item[1];
-        struct
-        {
-            short xs, ys;
-            short x, y;
-            char name[16];
-        } warp;
-        char *message;          // for MESSAGE: only send this message
-    } u;
-    // ここにメンバを追加してはならない(shop_itemが可変長の為)
-
-    char eventqueue[MAX_EVENTQUEUE][50];
-    int  eventtimer[MAX_EVENTTIMER];
-    short arenaflag;
-};
-
-#define MOB_MODE_SUMMONED			0x1000
-#define MOB_MODE_TURNS_AGAINST_BAD_MASTER	0x2000
-
-#define MOB_SENSIBLE_MASK 0xf000    // fate: mob mode flags that I actually understand
-
-enum mob_stat
-{
-    MOB_LV,
-    MOB_MAX_HP,
-    MOB_STR, MOB_AGI, MOB_VIT, MOB_INT, MOB_DEX, MOB_LUK,
-    MOB_ATK1, MOB_ATK2,         // low and high attacks
-    MOB_ADELAY,                 // attack delay
-    MOB_DEF, MOB_MDEF,
-    MOB_SPEED,
-    // These must come last:
-    MOB_XP_BONUS,               /* [Fate] Encoded as base to 1024: 1024 means 100% */
-    MOB_LAST
-};
-
-#define MOB_XP_BONUS_BASE  1024
-#define MOB_XP_BONUS_SHIFT 10
-
-struct mob_data
-{
-    struct block_list bl;
-    short n;
-    short base_class, mob_class, dir, mode;
-    short m, x0, y0, xs, ys;
-    char name[24];
-    int  spawndelay1, spawndelay2;
-    struct
-    {
-        unsigned state:8;
-        unsigned skillstate:8;
-        unsigned targettype:1;
-        unsigned steal_flag:1;
-        unsigned steal_coin_flag:1;
-        unsigned skillcastcancel:1;
-        unsigned master_check:1;
-        unsigned change_walk_target:1;
-        unsigned walk_easy:1;
-        unsigned special_mob_ai:3;
-    } state;
-    int  timer;
-    short to_x, to_y;
-    int  hp;
-    int  target_id, attacked_id;
-    short target_lv;
-    struct walkpath_data walkpath;
-    unsigned int next_walktime;
-    unsigned int attackabletime;
-    unsigned int last_deadtime, last_spawntime, last_thinktime;
-    unsigned int canmove_tick;
-    short move_fail_count;
-    struct
-    {
-        int  id;
-        int  dmg;
-    } dmglog[DAMAGELOG_SIZE];
-    struct item *lootitem;
-    short lootitem_count;
-
-    struct status_change sc_data[MAX_STATUSCHANGE];
-    short sc_count;
-    short opt1, opt2, opt3, option;
-    short min_chase;
-    short sg_count;
-    int  guild_id;
-    int  deletetimer;
-
-    int  skilltimer;
-    int  skilltarget;
-    short skillx, skilly;
-    short skillid, skilllv, skillidx;
-    unsigned int skilldelay[MAX_MOBSKILL];
-    int  def_ele;
-    int  master_id, master_dist;
-    int  exclusion_src, exclusion_party, exclusion_guild;
-    struct skill_timerskill skilltimerskill[MAX_MOBSKILLTIMERSKILL];
-    struct skill_unit_group skillunit[MAX_MOBSKILLUNITGROUP];
-    struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
-    char npc_event[50];
-    unsigned short stats[MOB_LAST]; // [Fate] mob-specific stats
-    short size;
-};
-
-enum
-{ MS_IDLE, MS_WALK, MS_ATTACK, MS_DEAD, MS_DELAY };
-
-enum
-{ NONE_ATTACKABLE, ATTACKABLE };
-
-enum
-{ ATK_LUCKY = 1, ATK_FLEE, ATK_DEF };   // 囲まれペナルティ計算用
-
-struct map_data
-{
-    char name[24];
-    char alias[24];             // [MouseJstr]
-    unsigned char *gat;         // NULLなら下のmap_data_other_serverとして扱う
-    struct block_list **block;
-    struct block_list **block_mob;
-    int *block_count, *block_mob_count;
-    int  m;
-    short xs, ys;
-    short bxs, bys;
-    int  npc_num;
-    int  users;
-    struct
-    {
-        unsigned alias:1;
-        unsigned nomemo:1;
-        unsigned noteleport:1;
-        unsigned noreturn:1;
-        unsigned monster_noteleport:1;
-        unsigned nosave:1;
-        unsigned nobranch:1;
-        unsigned nopenalty:1;
-        unsigned pvp:1;
-        unsigned pvp_noparty:1;
-        unsigned pvp_noguild:1;
-        unsigned pvp_nightmaredrop:1;
-        unsigned pvp_nocalcrank:1;
-        unsigned gvg:1;
-        unsigned gvg_noparty:1;
-        unsigned nozenypenalty:1;
-        unsigned notrade:1;
-        unsigned noskill:1;
-        unsigned nowarp:1;
-        unsigned nowarpto:1;
-        unsigned nopvp:1;       // [Valaris]
-        unsigned noicewall:1;   // [Valaris]
-        unsigned snow:1;        // [Valaris]
-        unsigned fog:1;         // [Valaris]
-        unsigned sakura:1;      // [Valaris]
-        unsigned leaves:1;      // [Valaris]
-        unsigned rain:1;        // [Valaris]
-        unsigned no_player_drops:1; // [Jaxad0127]
-        unsigned town:1;        // [remoitnane]
-    } flag;
-    struct point save;
-    struct npc_data *npc[MAX_NPC_PER_MAP];
-    struct
-    {
-        int  drop_id;
-        int  drop_type;
-        int  drop_per;
-    } drop_list[MAX_DROP_PER_MAP];
-};
-struct map_data_other_server
-{
-    char name[24];
-    unsigned char *gat;         // NULL固定にして判断
-    unsigned long ip;
-    unsigned int port;
-};
-#define read_gat(m,x,y) (map[m].gat[(x)+(y)*map[m].xs])
-#define read_gatp(m,x,y) (m->gat[(x)+(y)*m->xs])
-
-struct flooritem_data
-{
-    struct block_list bl;
-    short subx, suby;
-    int  cleartimer;
-    int  first_get_id, second_get_id, third_get_id;
-    unsigned int first_get_tick, second_get_tick, third_get_tick;
-    struct item item_data;
-};
-
-enum
-{
-    SP_SPEED, SP_BASEEXP, SP_JOBEXP, SP_KARMA, SP_MANNER, SP_HP, SP_MAXHP, SP_SP,   // 0-7
-    SP_MAXSP, SP_STATUSPOINT, SP_0a, SP_BASELEVEL, SP_SKILLPOINT, SP_STR, SP_AGI, SP_VIT,   // 8-15
-    SP_INT, SP_DEX, SP_LUK, SP_CLASS, SP_ZENY, SP_SEX, SP_NEXTBASEEXP, SP_NEXTJOBEXP,   // 16-23
-    SP_WEIGHT, SP_MAXWEIGHT, SP_1a, SP_1b, SP_1c, SP_1d, SP_1e, SP_1f,  // 24-31
-    SP_USTR, SP_UAGI, SP_UVIT, SP_UINT, SP_UDEX, SP_ULUK, SP_26, SP_27, // 32-39
-    SP_28, SP_ATK1, SP_ATK2, SP_MATK1, SP_MATK2, SP_DEF1, SP_DEF2, SP_MDEF1,    // 40-47
-    SP_MDEF2, SP_HIT, SP_FLEE1, SP_FLEE2, SP_CRITICAL, SP_ASPD, SP_36, SP_JOBLEVEL, // 48-55
-    SP_UPPER, SP_PARTNER, SP_CART, SP_FAME, SP_UNBREAKABLE, //56-58
-    SP_DEAF = 70,
-    SP_CARTINFO = 99,           // 99
-    SP_GM = 500,
-
-    // original 1000-
-    SP_ATTACKRANGE = 1000, SP_ATKELE, SP_DEFELE,    // 1000-1002
-    SP_CASTRATE, SP_MAXHPRATE, SP_MAXSPRATE, SP_SPRATE, // 1003-1006
-    SP_ADDELE, SP_ADDRACE, SP_ADDSIZE, SP_SUBELE, SP_SUBRACE,   // 1007-1011
-    SP_ADDEFF, SP_RESEFF,       // 1012-1013
-    SP_BASE_ATK, SP_ASPD_RATE, SP_HP_RECOV_RATE, SP_SP_RECOV_RATE, SP_SPEED_RATE,   // 1014-1018
-    SP_CRITICAL_DEF, SP_NEAR_ATK_DEF, SP_LONG_ATK_DEF,  // 1019-1021
-    SP_DOUBLE_RATE, SP_DOUBLE_ADD_RATE, SP_MATK, SP_MATK_RATE,  // 1022-1025
-    SP_IGNORE_DEF_ELE, SP_IGNORE_DEF_RACE,  // 1026-1027
-    SP_ATK_RATE, SP_SPEED_ADDRATE, SP_ASPD_ADDRATE, // 1028-1030
-    SP_MAGIC_ATK_DEF, SP_MISC_ATK_DEF,  // 1031-1032
-    SP_IGNORE_MDEF_ELE, SP_IGNORE_MDEF_RACE,    // 1033-1034
-    SP_MAGIC_ADDELE, SP_MAGIC_ADDRACE, SP_MAGIC_SUBRACE,    // 1035-1037
-    SP_PERFECT_HIT_RATE, SP_PERFECT_HIT_ADD_RATE, SP_CRITICAL_RATE, SP_GET_ZENY_NUM, SP_ADD_GET_ZENY_NUM,   // 1038-1042
-    SP_ADD_DAMAGE_CLASS, SP_ADD_MAGIC_DAMAGE_CLASS, SP_ADD_DEF_CLASS, SP_ADD_MDEF_CLASS,    // 1043-1046
-    SP_ADD_MONSTER_DROP_ITEM, SP_DEF_RATIO_ATK_ELE, SP_DEF_RATIO_ATK_RACE, SP_ADD_SPEED,    // 1047-1050
-    SP_HIT_RATE, SP_FLEE_RATE, SP_FLEE2_RATE, SP_DEF_RATE, SP_DEF2_RATE, SP_MDEF_RATE, SP_MDEF2_RATE,   // 1051-1057
-    SP_SPLASH_RANGE, SP_SPLASH_ADD_RANGE, SP_AUTOSPELL, SP_HP_DRAIN_RATE, SP_SP_DRAIN_RATE, // 1058-1062
-    SP_SHORT_WEAPON_DAMAGE_RETURN, SP_LONG_WEAPON_DAMAGE_RETURN, SP_WEAPON_COMA_ELE, SP_WEAPON_COMA_RACE,   // 1063-1066
-    SP_ADDEFF2, SP_BREAK_WEAPON_RATE, SP_BREAK_ARMOR_RATE, SP_ADD_STEAL_RATE,   // 1067-1070
-    SP_MAGIC_DAMAGE_RETURN, SP_RANDOM_ATTACK_INCREASE, SP_ALL_STATS, SP_AGI_VIT, SP_AGI_DEX_STR, SP_PERFECT_HIDE,   // 1071-1077
-    SP_DISGUISE,                // 1077
-
-    SP_RESTART_FULL_RECORVER = 2000, SP_NO_CASTCANCEL, SP_NO_SIZEFIX, SP_NO_MAGIC_DAMAGE, SP_NO_WEAPON_DAMAGE, SP_NO_GEMSTONE,  // 2000-2005
-    SP_NO_CASTCANCEL2, SP_INFINITE_ENDURE, SP_UNBREAKABLE_WEAPON, SP_UNBREAKABLE_ARMOR  // 2006-2009
-};
-
-enum
-{
-    LOOK_BASE,
-    LOOK_HAIR,
-    LOOK_WEAPON,
-    LOOK_HEAD_BOTTOM,
-    LOOK_HEAD_TOP,
-    LOOK_HEAD_MID,
-    LOOK_HAIR_COLOR,
-    LOOK_CLOTHES_COLOR,
-    LOOK_SHIELD,
-    LOOK_SHOES,                 /* 9 */
-    LOOK_GLOVES,
-    LOOK_CAPE,
-    LOOK_MISC1,
-    LOOK_MISC2
-};
-
-enum
-{
-    EQUIP_SHIELD = 8,
-    EQUIP_WEAPON = 9
-};
-
-#define LOOK_LAST LOOK_MISC2
-
-struct chat_data
-{
-    struct block_list bl;
-
-    unsigned char pass[8];      /* password */
-    unsigned char title[61];    /* room title MAX 60 */
-    unsigned char limit;        /* join limit */
-    unsigned char trigger;
-    unsigned char users;        /* current users */
-    unsigned char pub;          /* room attribute */
-    struct map_session_data *usersd[20];
-    struct block_list *owner_;
-    struct block_list **owner;
-    char npc_event[50];
-};
-
-extern struct map_data map[];
-extern int map_num;
-extern int autosave_interval;
-extern int save_settings;
-extern int agit_flag;
-extern int night_flag;          // 0=day, 1=night [Yor]
-
-extern char motd_txt[];
-extern char help_txt[];
-
-extern char talkie_mes[];
-
-extern char wisp_server_name[];
-
-// 鯖全体情報
-void map_setusers (int);
-int  map_getusers (void);
-// block削除関連
-int  map_freeblock (void *bl);
-int  map_freeblock_lock (void);
-int  map_freeblock_unlock (void);
-// block関連
-int  map_addblock (struct block_list *);
-int  map_delblock (struct block_list *);
-void map_foreachinarea (int (*)(struct block_list *, va_list), int, int, int,
-                        int, int, int, ...);
-// -- moonsoul (added map_foreachincell)
-void map_foreachincell (int (*)(struct block_list *, va_list), int, int, int,
-                        int, ...);
-void map_foreachinmovearea (int (*)(struct block_list *, va_list), int, int,
-                            int, int, int, int, int, int, ...);
-int  map_countnearpc (int, int, int);
-//block関連に追加
-int  map_count_oncell (int m, int x, int y);
-// 一時的object関連
-int  map_addobject (struct block_list *);
-int  map_delobject (int, int type);
-int  map_delobjectnofree (int id, int type);
-void map_foreachobject (int (*)(struct block_list *, va_list), int, ...);
-//
-int  map_quit (struct map_session_data *);
-// npc
-int  map_addnpc (int, struct npc_data *);
-
-extern FILE *map_logfile;
-void map_write_log (char *format, ...);
-#define MAP_LOG(format, args...) {if (map_logfile) map_write_log(format, ##args);}
-
-#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
-
-// 床アイテム関連
-void map_clearflooritem_timer (timer_id, tick_t, custom_id_t, custom_data_t);
-#define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1)
-int  map_addflooritem_any (struct item *, int amount, int m, int x, int y,
-                           struct map_session_data **owners,
-                           int *owner_protection,
-                           int lifetime, int dispersal);
-int  map_addflooritem (struct item *, int, int, int, int,
-                       struct map_session_data *, struct map_session_data *,
-                       struct map_session_data *, int);
-int  map_searchrandfreecell (int, int, int, int);
-
-// キャラid=>キャラ名 変換関連
-void map_addchariddb (int charid, char *name);
-void map_delchariddb (int charid);
-int  map_reqchariddb (struct map_session_data *sd, int charid);
-char *map_charid2nick (int);
-
-struct map_session_data *map_id2sd (int);
-struct block_list *map_id2bl (int);
-int  map_mapname2mapid (char *);
-int  map_mapname2ipport (char *, int *, int *);
-int  map_setipport (char *name, unsigned long ip, int port);
-int  map_eraseipport (char *name, unsigned long ip, int port);
-void map_addiddb (struct block_list *);
-void map_deliddb (struct block_list *bl);
-int  map_foreachiddb (db_func_t, ...);
-void map_addnickdb (struct map_session_data *);
-int  map_scriptcont (struct map_session_data *sd, int id);  /* Continues a script either on a spell or on an NPC */
-struct map_session_data *map_nick2sd (char *);
-int  compare_item (struct item *a, struct item *b);
-
-struct map_session_data *map_get_first_session (void);
-struct map_session_data *map_get_last_session (void);
-struct map_session_data *map_get_next_session (struct map_session_data
-                                               *current);
-struct map_session_data *map_get_prev_session (struct map_session_data
-                                               *current);
-
-// gat関連
-int  map_getcell (int, int, int);
-int  map_setcell (int, int, int, int);
-
-// その他
-int  map_check_dir (int s_dir, int t_dir);
-int  map_calc_dir (struct block_list *src, int x, int y);
-
-// path.cより
-int  path_search (struct walkpath_data *, int, int, int, int, int, int);
-int  path_blownpos (int m, int x0, int y0, int dx, int dy, int count);
-
-int  map_who (int fd);
-
-void map_helpscreen (void);         // [Valaris]
-int  map_delmap (char *mapname);
-
-#endif
diff --git a/src/map/map.hpp b/src/map/map.hpp
new file mode 100644
index 0000000..5d3e0a2
--- /dev/null
+++ b/src/map/map.hpp
@@ -0,0 +1,822 @@
+// $Id: map.h,v 1.8 2004/09/25 11:39:17 MouseJstr Exp $
+#ifndef MAP_HPP
+#define MAP_HPP
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include "../common/mmo.hpp"
+#include "../common/timer.hpp"
+#include "../common/db.hpp"
+
+#ifndef MAX
+#  define MAX(x,y) (((x)>(y)) ? (x) : (y))
+#endif
+#ifndef MIN
+#  define MIN(x,y) (((x)<(y)) ? (x) : (y))
+#endif
+
+#define MAX_PC_CLASS (1+6+6+1+6+1+1+1+1+4023)
+#define PC_CLASS_BASE 0
+#define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001)
+#define PC_CLASS_BASE3 (PC_CLASS_BASE2 + 22)
+#define MAX_NPC_PER_MAP 512
+#define BLOCK_SIZE 8
+#define AREA_SIZE battle_config.area_size
+#define LOCAL_REG_NUM 16
+#define LIFETIME_FLOORITEM 60
+#define DAMAGELOG_SIZE 30
+#define LOOTITEM_SIZE 10
+#define MAX_SKILL_LEVEL 100
+#define MAX_STATUSCHANGE 200
+#define MAX_SKILLUNITGROUP 32
+#define MAX_MOBSKILLUNITGROUP 8
+#define MAX_SKILLUNITGROUPTICKSET 128
+#define MAX_SKILLTIMERSKILL 32
+#define MAX_MOBSKILLTIMERSKILL 10
+#define MAX_MOBSKILL 32
+#define MAX_EVENTQUEUE 2
+#define MAX_EVENTTIMER 32
+#define NATURAL_HEAL_INTERVAL 500
+#define MAX_FLOORITEM 500000
+#define MAX_LEVEL 255
+#define MAX_WALKPATH 48
+#define MAX_DROP_PER_MAP 48
+
+#define DEFAULT_AUTOSAVE_INTERVAL 60*1000
+
+// [Fate] status.option properties.  These are persistent status changes.
+// IDs that are not listed are not used in the code (to the best of my knowledge)
+#define OPTION_HIDE2		0x0002  // apparently some weaker non-GM hide
+#define OPTION_CLOAK		0x0004
+#define OPTION_10		0x0010
+#define OPTION_20		0x0020
+#define OPTION_HIDE		0x0040  // [Fate] This is the GM `@hide' flag
+#define OPTION_800		0x0800
+#define OPTION_INVISIBILITY	0x1000  // [Fate] Complete invisibility to other clients
+#define OPTION_SCRIBE		0x2000  // [Fate] Auto-logging of nearby comments
+#define OPTION_CHASEWALK	0x4000
+
+//  Below are special clif_changestatus() IDs reserved for option updates
+#define CLIF_OPTION_SC_BASE		0x1000
+#define CLIF_OPTION_SC_INVISIBILITY	(CLIF_OPTION_SC_BASE)
+#define CLIF_OPTION_SC_SCRIBE		(CLIF_OPTION_SC_BASE + 1)
+
+enum
+{ BL_NUL, BL_PC, BL_NPC, BL_MOB, BL_ITEM, BL_CHAT, BL_SKILL, BL_SPELL };
+enum
+{ WARP, SHOP, SCRIPT, MONS, MESSAGE };
+struct block_list
+{
+    struct block_list *next, *prev;
+    int  id;
+    short m, x, y;
+    unsigned char type;
+    unsigned char subtype;
+};
+
+struct walkpath_data
+{
+    unsigned char path_len, path_pos, path_half;
+    unsigned char path[MAX_WALKPATH];
+};
+struct script_reg
+{
+    int  index;
+    int  data;
+};
+struct script_regstr
+{
+    int  index;
+    char data[256];
+};
+struct status_change
+{
+    int  timer;
+    int  val1, val2, val3, val4;
+    int  spell_invocation;      /* [Fate] If triggered by a spell, record here */
+};
+
+struct invocation;
+
+struct skill_unit_group;
+struct skill_unit
+{
+    struct block_list bl;
+
+    struct skill_unit_group *group;
+
+    int  limit;
+    int  val1, val2;
+    short alive, range;
+};
+struct skill_unit_group
+{
+    int  src_id;
+    int  party_id;
+    int  guild_id;
+    int  map, range;
+    int  target_flag;
+    unsigned int tick;
+    int  limit, interval;
+
+    int  skill_id, skill_lv;
+    int  val1, val2;
+    char *valstr;
+    int  unit_id;
+    int  group_id;
+    int  unit_count, alive_count;
+    struct skill_unit *unit;
+};
+struct skill_unit_group_tickset
+{
+    unsigned int tick;
+    int  group_id;
+};
+struct skill_timerskill
+{
+    int  timer;
+    int  src_id;
+    int  target_id;
+    int  map;
+    short x, y;
+    short skill_id, skill_lv;
+    int  type;
+    int  flag;
+};
+
+struct npc_data;
+struct item_data;
+struct square;
+
+struct quick_regeneration
+{                               // [Fate]
+    int  amount;                // Amount of HP/SP left to regenerate
+    unsigned char speed;        // less is faster (number of half-second ticks to wait between updates)
+    unsigned char tickdelay;    // number of ticks to next update
+};
+
+#define VERSION_2_SKILLINFO  0x02   // client supports full skillinfo blocks
+
+struct map_session_data
+{
+    struct block_list bl;
+    struct
+    {
+        unsigned auth:1;
+        unsigned change_walk_target:1;
+        unsigned attack_continue:1;
+        unsigned menu_or_input:1;
+        unsigned dead_sit:2;
+        unsigned skillcastcancel:1;
+        unsigned waitingdisconnect:1;
+        unsigned lr_flag:2;
+        unsigned connect_new:1;
+        unsigned arrow_atk:1;
+        unsigned attack_type:3;
+        unsigned skill_flag:1;
+        unsigned gangsterparadise:1;
+        unsigned produce_flag:1;
+        unsigned make_arrow_flag:1;
+        unsigned potionpitcher_flag:1;
+        unsigned storage_flag:2;    //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex]
+        unsigned shroud_active:1;
+        unsigned shroud_hides_name_talking:1;
+        unsigned shroud_disappears_on_pickup:1;
+        unsigned shroud_disappears_on_talk:1;
+    } state;
+    struct
+    {
+        unsigned killer:1;
+        unsigned killable:1;
+        unsigned restart_full_recover:1;
+        unsigned no_castcancel:1;
+        unsigned no_castcancel2:1;
+        unsigned no_sizefix:1;
+        unsigned no_magic_damage:1;
+        unsigned no_weapon_damage:1;
+        unsigned no_gemstone:1;
+        unsigned infinite_endure:1;
+        unsigned unbreakable_weapon:1;
+        unsigned unbreakable_armor:1;
+        unsigned infinite_autospell:1;
+        unsigned deaf:1;
+    } special_state;
+    int  char_id, login_id1, login_id2, sex;
+    unsigned char tmw_version;  // tmw client version
+    struct mmo_charstatus status;
+    struct item_data *inventory_data[MAX_INVENTORY];
+    short equip_index[11];
+    int  weight, max_weight;
+    int  cart_weight, cart_max_weight, cart_num, cart_max_num;
+    char mapname[24];
+    int  fd, new_fd;
+    short to_x, to_y;
+    short speed, prev_speed;
+    short opt1, opt2, opt3;
+    char dir, head_dir;
+    unsigned int client_tick, server_tick;
+    struct walkpath_data walkpath;
+    int  walktimer;
+    int  npc_id, areanpc_id, npc_shopid;
+    int  npc_pos;
+    int  npc_menu;
+    int  npc_amount;
+    int  npc_stack, npc_stackmax;
+    char *npc_script, *npc_scriptroot;
+    char *npc_stackbuf;
+    char npc_str[256];
+    struct
+    {
+        unsigned storage:1;
+        unsigned divorce:1;
+    } npc_flags;
+    unsigned int chatID;
+
+    int  attacktimer;
+    int  attacktarget;
+    short attacktarget_lv;
+    unsigned int attackabletime;
+
+    int  followtimer;           // [MouseJstr]
+    int  followtarget;
+
+    unsigned int cast_tick;     // [Fate] Next tick at which spellcasting is allowed
+    struct invocation *active_spells;   // [Fate] Singly-linked list of active spells linked to this PC
+    int  attack_spell_override; // [Fate] When an attack spell is active for this player, they trigger it
+    // like a weapon.  Check pc_attack_timer() for details.
+    short attack_spell_icon_override;   // Weapon equipment slot (slot 4) item override
+    short attack_spell_look_override;   // Weapon `look' (attack animation) override
+    short attack_spell_charges; // [Fate] Remaining number of charges for the attack spell
+    short attack_spell_delay;   // [Fate] ms delay after spell attack
+    short attack_spell_range;   // [Fate] spell range
+    short spellpower_bonus_target, spellpower_bonus_current;    // [Fate] Spellpower boni.  _current is the active one.
+    //_current slowly approximates _target, and _target is determined by equipment.
+
+    short attackrange, attackrange_;
+    int  skilltimer;
+    int  skilltarget;
+    short skillx, skilly;
+    short skillid, skilllv;
+    short skillitem, skillitemlv;
+    short skillid_old, skilllv_old;
+    short skillid_dance, skilllv_dance;
+    struct skill_unit_group skillunit[MAX_SKILLUNITGROUP];
+    struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
+    struct skill_timerskill skilltimerskill[MAX_SKILLTIMERSKILL];
+    int  cloneskill_id, cloneskill_lv;
+    int  potion_hp, potion_sp, potion_per_hp, potion_per_sp;
+
+    // [Fate] Used for gradual healing; amount of enqueued regeneration
+    struct quick_regeneration quick_regeneration_hp, quick_regeneration_sp;
+    // [Fate] XP that can be extracted from this player by healing
+    int  heal_xp;               // i.e., OTHER players (healers) can partake in this player's XP
+
+    int  invincible_timer;
+    unsigned int canact_tick;
+    unsigned int canmove_tick;
+    unsigned int canlog_tick;
+    int  hp_sub, sp_sub;
+    int  inchealhptick, inchealsptick, inchealspirithptick,
+        inchealspiritsptick;
+// -- moonsoul (new tick for berserk self-damage)
+    int  berserkdamagetick;
+    int  fame;
+
+    short view_class;
+    short weapontype1, weapontype2;
+    short disguiseflag, disguise;   // [Valaris]
+    int  paramb[6], paramc[6], parame[6], paramcard[6];
+    int  hit, flee, flee2, aspd, amotion, dmotion;
+    int  watk, watk2, atkmods[3];
+    int  def, def2, mdef, mdef2, critical, matk1, matk2;
+    int  atk_ele, def_ele, star, overrefine;
+    int  castrate, hprate, sprate, dsprate;
+    int  addele[10], addrace[12], addsize[3], subele[10], subrace[12];
+    int  addeff[10], addeff2[10], reseff[10];
+    int  watk_, watk_2, atkmods_[3], addele_[10], addrace_[12], addsize_[3];    //二刀流のために追加
+    int  atk_ele_, star_, overrefine_;  //二刀流のために追加
+    int  base_atk, atk_rate;
+    int  arrow_atk, arrow_ele, arrow_cri, arrow_hit, arrow_range;
+    int  arrow_addele[10], arrow_addrace[12], arrow_addsize[3],
+        arrow_addeff[10], arrow_addeff2[10];
+    int  nhealhp, nhealsp, nshealhp, nshealsp, nsshealhp, nsshealsp;
+    int  aspd_rate, speed_rate, hprecov_rate, sprecov_rate, critical_def,
+        double_rate;
+    int  near_attack_def_rate, long_attack_def_rate, magic_def_rate,
+        misc_def_rate;
+    int  matk_rate, ignore_def_ele, ignore_def_race, ignore_def_ele_,
+        ignore_def_race_;
+    int  ignore_mdef_ele, ignore_mdef_race;
+    int  magic_addele[10], magic_addrace[12], magic_subrace[12];
+    int  perfect_hit, get_zeny_num;
+    int  critical_rate, hit_rate, flee_rate, flee2_rate, def_rate, def2_rate,
+        mdef_rate, mdef2_rate;
+    int  def_ratio_atk_ele, def_ratio_atk_ele_, def_ratio_atk_race,
+        def_ratio_atk_race_;
+    int  add_damage_class_count, add_damage_class_count_,
+        add_magic_damage_class_count;
+    short add_damage_classid[10], add_damage_classid_[10],
+        add_magic_damage_classid[10];
+    int  add_damage_classrate[10], add_damage_classrate_[10],
+        add_magic_damage_classrate[10];
+    short add_def_class_count, add_mdef_class_count;
+    short add_def_classid[10], add_mdef_classid[10];
+    int  add_def_classrate[10], add_mdef_classrate[10];
+    short monster_drop_item_count;
+    short monster_drop_itemid[10];
+    int  monster_drop_race[10], monster_drop_itemrate[10];
+    int  double_add_rate, speed_add_rate, aspd_add_rate, perfect_hit_add,
+        get_zeny_add_num;
+    short splash_range, splash_add_range;
+    short autospell_id, autospell_lv, autospell_rate;
+    short hp_drain_rate, hp_drain_per, sp_drain_rate, sp_drain_per;
+    short hp_drain_rate_, hp_drain_per_, sp_drain_rate_, sp_drain_per_;
+    int  short_weapon_damage_return, long_weapon_damage_return;
+    int  weapon_coma_ele[10], weapon_coma_race[12];
+    short break_weapon_rate, break_armor_rate;
+    short add_steal_rate;
+
+    short spiritball, spiritball_old;
+    int  spirit_timer[MAX_SKILL_LEVEL];
+    int  magic_damage_return;   // AppleGirl Was Here
+    int  random_attack_increase_add, random_attack_increase_per;    // [Valaris]
+    int  perfect_hiding;        // [Valaris]
+    int  unbreakable;
+
+    int  die_counter;
+    short doridori_counter;
+
+    int  reg_num;
+    struct script_reg *reg;
+    int  regstr_num;
+    struct script_regstr *regstr;
+
+    struct status_change sc_data[MAX_STATUSCHANGE];
+    short sc_count;
+    struct square dev;
+
+    int  trade_partner;
+    int  deal_item_index[10];
+    int  deal_item_amount[10];
+    int  deal_zeny;
+    short deal_locked;
+
+    int  party_sended, party_invite, party_invite_account;
+    int  party_hp, party_x, party_y;
+
+    int  guild_sended, guild_invite, guild_invite_account;
+    int  guild_emblem_id, guild_alliance, guild_alliance_account;
+    int  guildspy;              // [Syrus22]
+    int  partyspy;              // [Syrus22]
+
+    char message[80];
+
+    int  catch_target_class;
+
+    int  pvp_point, pvp_rank, pvp_timer, pvp_lastusers;
+
+    char eventqueue[MAX_EVENTQUEUE][50];
+    int  eventtimer[MAX_EVENTTIMER];
+
+    int  last_skillid, last_skilllv;    // Added by RoVeRT
+    struct
+    {
+        char name[24];
+    } ignore[80];
+    int  ignoreAll;
+    short sg_count;
+
+    struct
+    {
+        unsigned in_progress:1;
+    } auto_ban_info;
+
+    time_t chat_reset_due;
+    time_t chat_repeat_reset_due;
+    int  chat_lines_in;
+    int  chat_total_repeats;
+    char chat_lastmsg[513];
+
+    unsigned int flood_rates[0x220];
+    time_t packet_flood_reset_due;
+    int packet_flood_in;
+
+    in_addr_t ip;
+};
+
+struct npc_timerevent_list
+{
+    int  timer, pos;
+};
+struct npc_label_list
+{
+    char name[24];
+    int  pos;
+};
+struct npc_item_list
+{
+    int  nameid, value;
+};
+struct npc_data
+{
+    struct block_list bl;
+    short n;
+    short npc_class, dir;
+    short speed;
+    char name[24];
+    char exname[24];
+    int  chat_id;
+    short opt1, opt2, opt3, option;
+    short flag;
+    union
+    {
+        struct
+        {
+            char *script;
+            short xs, ys;
+            int  guild_id;
+            int  timer, timerid, timeramount, nexttimer;
+            unsigned int timertick;
+            struct npc_timerevent_list *timer_event;
+            int  label_list_num;
+            struct npc_label_list *label_list;
+            int  src_id;
+        } scr;
+        struct npc_item_list shop_item[1];
+        struct
+        {
+            short xs, ys;
+            short x, y;
+            char name[16];
+        } warp;
+        char *message;          // for MESSAGE: only send this message
+    } u;
+    // ここにメンバを追加してはならない(shop_itemが可変長の為)
+
+    char eventqueue[MAX_EVENTQUEUE][50];
+    int  eventtimer[MAX_EVENTTIMER];
+    short arenaflag;
+};
+
+#define MOB_MODE_SUMMONED			0x1000
+#define MOB_MODE_TURNS_AGAINST_BAD_MASTER	0x2000
+
+#define MOB_SENSIBLE_MASK 0xf000    // fate: mob mode flags that I actually understand
+
+enum mob_stat
+{
+    MOB_LV,
+    MOB_MAX_HP,
+    MOB_STR, MOB_AGI, MOB_VIT, MOB_INT, MOB_DEX, MOB_LUK,
+    MOB_ATK1, MOB_ATK2,         // low and high attacks
+    MOB_ADELAY,                 // attack delay
+    MOB_DEF, MOB_MDEF,
+    MOB_SPEED,
+    // These must come last:
+    MOB_XP_BONUS,               /* [Fate] Encoded as base to 1024: 1024 means 100% */
+    MOB_LAST
+};
+
+#define MOB_XP_BONUS_BASE  1024
+#define MOB_XP_BONUS_SHIFT 10
+
+struct mob_data
+{
+    struct block_list bl;
+    short n;
+    short base_class, mob_class, dir, mode;
+    short m, x0, y0, xs, ys;
+    char name[24];
+    int  spawndelay1, spawndelay2;
+    struct
+    {
+        unsigned state:8;
+        unsigned skillstate:8;
+        unsigned targettype:1;
+        unsigned steal_flag:1;
+        unsigned steal_coin_flag:1;
+        unsigned skillcastcancel:1;
+        unsigned master_check:1;
+        unsigned change_walk_target:1;
+        unsigned walk_easy:1;
+        unsigned special_mob_ai:3;
+    } state;
+    int  timer;
+    short to_x, to_y;
+    int  hp;
+    int  target_id, attacked_id;
+    short target_lv;
+    struct walkpath_data walkpath;
+    unsigned int next_walktime;
+    unsigned int attackabletime;
+    unsigned int last_deadtime, last_spawntime, last_thinktime;
+    unsigned int canmove_tick;
+    short move_fail_count;
+    struct
+    {
+        int  id;
+        int  dmg;
+    } dmglog[DAMAGELOG_SIZE];
+    struct item *lootitem;
+    short lootitem_count;
+
+    struct status_change sc_data[MAX_STATUSCHANGE];
+    short sc_count;
+    short opt1, opt2, opt3, option;
+    short min_chase;
+    short sg_count;
+    int  guild_id;
+    int  deletetimer;
+
+    int  skilltimer;
+    int  skilltarget;
+    short skillx, skilly;
+    short skillid, skilllv, skillidx;
+    unsigned int skilldelay[MAX_MOBSKILL];
+    int  def_ele;
+    int  master_id, master_dist;
+    int  exclusion_src, exclusion_party, exclusion_guild;
+    struct skill_timerskill skilltimerskill[MAX_MOBSKILLTIMERSKILL];
+    struct skill_unit_group skillunit[MAX_MOBSKILLUNITGROUP];
+    struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
+    char npc_event[50];
+    unsigned short stats[MOB_LAST]; // [Fate] mob-specific stats
+    short size;
+};
+
+enum
+{ MS_IDLE, MS_WALK, MS_ATTACK, MS_DEAD, MS_DELAY };
+
+enum
+{ NONE_ATTACKABLE, ATTACKABLE };
+
+enum
+{ ATK_LUCKY = 1, ATK_FLEE, ATK_DEF };   // 囲まれペナルティ計算用
+
+struct map_data
+{
+    char name[24];
+    char alias[24];             // [MouseJstr]
+    unsigned char *gat;         // NULLなら下のmap_data_other_serverとして扱う
+    struct block_list **block;
+    struct block_list **block_mob;
+    int *block_count, *block_mob_count;
+    int  m;
+    short xs, ys;
+    short bxs, bys;
+    int  npc_num;
+    int  users;
+    struct
+    {
+        unsigned alias:1;
+        unsigned nomemo:1;
+        unsigned noteleport:1;
+        unsigned noreturn:1;
+        unsigned monster_noteleport:1;
+        unsigned nosave:1;
+        unsigned nobranch:1;
+        unsigned nopenalty:1;
+        unsigned pvp:1;
+        unsigned pvp_noparty:1;
+        unsigned pvp_noguild:1;
+        unsigned pvp_nightmaredrop:1;
+        unsigned pvp_nocalcrank:1;
+        unsigned gvg:1;
+        unsigned gvg_noparty:1;
+        unsigned nozenypenalty:1;
+        unsigned notrade:1;
+        unsigned noskill:1;
+        unsigned nowarp:1;
+        unsigned nowarpto:1;
+        unsigned nopvp:1;       // [Valaris]
+        unsigned noicewall:1;   // [Valaris]
+        unsigned snow:1;        // [Valaris]
+        unsigned fog:1;         // [Valaris]
+        unsigned sakura:1;      // [Valaris]
+        unsigned leaves:1;      // [Valaris]
+        unsigned rain:1;        // [Valaris]
+        unsigned no_player_drops:1; // [Jaxad0127]
+        unsigned town:1;        // [remoitnane]
+    } flag;
+    struct point save;
+    struct npc_data *npc[MAX_NPC_PER_MAP];
+    struct
+    {
+        int  drop_id;
+        int  drop_type;
+        int  drop_per;
+    } drop_list[MAX_DROP_PER_MAP];
+};
+struct map_data_other_server
+{
+    char name[24];
+    unsigned char *gat;         // NULL固定にして判断
+    unsigned long ip;
+    unsigned int port;
+};
+#define read_gat(m,x,y) (map[m].gat[(x)+(y)*map[m].xs])
+#define read_gatp(m,x,y) (m->gat[(x)+(y)*m->xs])
+
+struct flooritem_data
+{
+    struct block_list bl;
+    short subx, suby;
+    int  cleartimer;
+    int  first_get_id, second_get_id, third_get_id;
+    unsigned int first_get_tick, second_get_tick, third_get_tick;
+    struct item item_data;
+};
+
+enum
+{
+    SP_SPEED, SP_BASEEXP, SP_JOBEXP, SP_KARMA, SP_MANNER, SP_HP, SP_MAXHP, SP_SP,   // 0-7
+    SP_MAXSP, SP_STATUSPOINT, SP_0a, SP_BASELEVEL, SP_SKILLPOINT, SP_STR, SP_AGI, SP_VIT,   // 8-15
+    SP_INT, SP_DEX, SP_LUK, SP_CLASS, SP_ZENY, SP_SEX, SP_NEXTBASEEXP, SP_NEXTJOBEXP,   // 16-23
+    SP_WEIGHT, SP_MAXWEIGHT, SP_1a, SP_1b, SP_1c, SP_1d, SP_1e, SP_1f,  // 24-31
+    SP_USTR, SP_UAGI, SP_UVIT, SP_UINT, SP_UDEX, SP_ULUK, SP_26, SP_27, // 32-39
+    SP_28, SP_ATK1, SP_ATK2, SP_MATK1, SP_MATK2, SP_DEF1, SP_DEF2, SP_MDEF1,    // 40-47
+    SP_MDEF2, SP_HIT, SP_FLEE1, SP_FLEE2, SP_CRITICAL, SP_ASPD, SP_36, SP_JOBLEVEL, // 48-55
+    SP_UPPER, SP_PARTNER, SP_CART, SP_FAME, SP_UNBREAKABLE, //56-58
+    SP_DEAF = 70,
+    SP_CARTINFO = 99,           // 99
+    SP_GM = 500,
+
+    // original 1000-
+    SP_ATTACKRANGE = 1000, SP_ATKELE, SP_DEFELE,    // 1000-1002
+    SP_CASTRATE, SP_MAXHPRATE, SP_MAXSPRATE, SP_SPRATE, // 1003-1006
+    SP_ADDELE, SP_ADDRACE, SP_ADDSIZE, SP_SUBELE, SP_SUBRACE,   // 1007-1011
+    SP_ADDEFF, SP_RESEFF,       // 1012-1013
+    SP_BASE_ATK, SP_ASPD_RATE, SP_HP_RECOV_RATE, SP_SP_RECOV_RATE, SP_SPEED_RATE,   // 1014-1018
+    SP_CRITICAL_DEF, SP_NEAR_ATK_DEF, SP_LONG_ATK_DEF,  // 1019-1021
+    SP_DOUBLE_RATE, SP_DOUBLE_ADD_RATE, SP_MATK, SP_MATK_RATE,  // 1022-1025
+    SP_IGNORE_DEF_ELE, SP_IGNORE_DEF_RACE,  // 1026-1027
+    SP_ATK_RATE, SP_SPEED_ADDRATE, SP_ASPD_ADDRATE, // 1028-1030
+    SP_MAGIC_ATK_DEF, SP_MISC_ATK_DEF,  // 1031-1032
+    SP_IGNORE_MDEF_ELE, SP_IGNORE_MDEF_RACE,    // 1033-1034
+    SP_MAGIC_ADDELE, SP_MAGIC_ADDRACE, SP_MAGIC_SUBRACE,    // 1035-1037
+    SP_PERFECT_HIT_RATE, SP_PERFECT_HIT_ADD_RATE, SP_CRITICAL_RATE, SP_GET_ZENY_NUM, SP_ADD_GET_ZENY_NUM,   // 1038-1042
+    SP_ADD_DAMAGE_CLASS, SP_ADD_MAGIC_DAMAGE_CLASS, SP_ADD_DEF_CLASS, SP_ADD_MDEF_CLASS,    // 1043-1046
+    SP_ADD_MONSTER_DROP_ITEM, SP_DEF_RATIO_ATK_ELE, SP_DEF_RATIO_ATK_RACE, SP_ADD_SPEED,    // 1047-1050
+    SP_HIT_RATE, SP_FLEE_RATE, SP_FLEE2_RATE, SP_DEF_RATE, SP_DEF2_RATE, SP_MDEF_RATE, SP_MDEF2_RATE,   // 1051-1057
+    SP_SPLASH_RANGE, SP_SPLASH_ADD_RANGE, SP_AUTOSPELL, SP_HP_DRAIN_RATE, SP_SP_DRAIN_RATE, // 1058-1062
+    SP_SHORT_WEAPON_DAMAGE_RETURN, SP_LONG_WEAPON_DAMAGE_RETURN, SP_WEAPON_COMA_ELE, SP_WEAPON_COMA_RACE,   // 1063-1066
+    SP_ADDEFF2, SP_BREAK_WEAPON_RATE, SP_BREAK_ARMOR_RATE, SP_ADD_STEAL_RATE,   // 1067-1070
+    SP_MAGIC_DAMAGE_RETURN, SP_RANDOM_ATTACK_INCREASE, SP_ALL_STATS, SP_AGI_VIT, SP_AGI_DEX_STR, SP_PERFECT_HIDE,   // 1071-1077
+    SP_DISGUISE,                // 1077
+
+    SP_RESTART_FULL_RECORVER = 2000, SP_NO_CASTCANCEL, SP_NO_SIZEFIX, SP_NO_MAGIC_DAMAGE, SP_NO_WEAPON_DAMAGE, SP_NO_GEMSTONE,  // 2000-2005
+    SP_NO_CASTCANCEL2, SP_INFINITE_ENDURE, SP_UNBREAKABLE_WEAPON, SP_UNBREAKABLE_ARMOR  // 2006-2009
+};
+
+enum
+{
+    LOOK_BASE,
+    LOOK_HAIR,
+    LOOK_WEAPON,
+    LOOK_HEAD_BOTTOM,
+    LOOK_HEAD_TOP,
+    LOOK_HEAD_MID,
+    LOOK_HAIR_COLOR,
+    LOOK_CLOTHES_COLOR,
+    LOOK_SHIELD,
+    LOOK_SHOES,                 /* 9 */
+    LOOK_GLOVES,
+    LOOK_CAPE,
+    LOOK_MISC1,
+    LOOK_MISC2
+};
+
+enum
+{
+    EQUIP_SHIELD = 8,
+    EQUIP_WEAPON = 9
+};
+
+#define LOOK_LAST LOOK_MISC2
+
+struct chat_data
+{
+    struct block_list bl;
+
+    unsigned char pass[8];      /* password */
+    unsigned char title[61];    /* room title MAX 60 */
+    unsigned char limit;        /* join limit */
+    unsigned char trigger;
+    unsigned char users;        /* current users */
+    unsigned char pub;          /* room attribute */
+    struct map_session_data *usersd[20];
+    struct block_list *owner_;
+    struct block_list **owner;
+    char npc_event[50];
+};
+
+extern struct map_data map[];
+extern int map_num;
+extern int autosave_interval;
+extern int save_settings;
+extern int agit_flag;
+extern int night_flag;          // 0=day, 1=night [Yor]
+
+extern char motd_txt[];
+extern char help_txt[];
+
+extern char talkie_mes[];
+
+extern char wisp_server_name[];
+
+// 鯖全体情報
+void map_setusers (int);
+int  map_getusers (void);
+// block削除関連
+int  map_freeblock (void *bl);
+int  map_freeblock_lock (void);
+int  map_freeblock_unlock (void);
+// block関連
+int  map_addblock (struct block_list *);
+int  map_delblock (struct block_list *);
+void map_foreachinarea (int (*)(struct block_list *, va_list), int, int, int,
+                        int, int, int, ...);
+// -- moonsoul (added map_foreachincell)
+void map_foreachincell (int (*)(struct block_list *, va_list), int, int, int,
+                        int, ...);
+void map_foreachinmovearea (int (*)(struct block_list *, va_list), int, int,
+                            int, int, int, int, int, int, ...);
+int  map_countnearpc (int, int, int);
+//block関連に追加
+int  map_count_oncell (int m, int x, int y);
+// 一時的object関連
+int  map_addobject (struct block_list *);
+int  map_delobject (int, int type);
+int  map_delobjectnofree (int id, int type);
+void map_foreachobject (int (*)(struct block_list *, va_list), int, ...);
+//
+int  map_quit (struct map_session_data *);
+// npc
+int  map_addnpc (int, struct npc_data *);
+
+extern FILE *map_logfile;
+void map_write_log (char *format, ...);
+#define MAP_LOG(format, args...) {if (map_logfile) map_write_log(format, ##args);}
+
+#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
+
+// 床アイテム関連
+void map_clearflooritem_timer (timer_id, tick_t, custom_id_t, custom_data_t);
+#define map_clearflooritem(id) map_clearflooritem_timer(0,0,id,1)
+int  map_addflooritem_any (struct item *, int amount, int m, int x, int y,
+                           struct map_session_data **owners,
+                           int *owner_protection,
+                           int lifetime, int dispersal);
+int  map_addflooritem (struct item *, int, int, int, int,
+                       struct map_session_data *, struct map_session_data *,
+                       struct map_session_data *, int);
+int  map_searchrandfreecell (int, int, int, int);
+
+// キャラid=>キャラ名 変換関連
+void map_addchariddb (int charid, char *name);
+void map_delchariddb (int charid);
+int  map_reqchariddb (struct map_session_data *sd, int charid);
+char *map_charid2nick (int);
+
+struct map_session_data *map_id2sd (int);
+struct block_list *map_id2bl (int);
+int  map_mapname2mapid (char *);
+int  map_mapname2ipport (char *, int *, int *);
+int  map_setipport (char *name, unsigned long ip, int port);
+int  map_eraseipport (char *name, unsigned long ip, int port);
+void map_addiddb (struct block_list *);
+void map_deliddb (struct block_list *bl);
+int  map_foreachiddb (db_func_t, ...);
+void map_addnickdb (struct map_session_data *);
+int  map_scriptcont (struct map_session_data *sd, int id);  /* Continues a script either on a spell or on an NPC */
+struct map_session_data *map_nick2sd (char *);
+int  compare_item (struct item *a, struct item *b);
+
+struct map_session_data *map_get_first_session (void);
+struct map_session_data *map_get_last_session (void);
+struct map_session_data *map_get_next_session (struct map_session_data
+                                               *current);
+struct map_session_data *map_get_prev_session (struct map_session_data
+                                               *current);
+
+// gat関連
+int  map_getcell (int, int, int);
+int  map_setcell (int, int, int, int);
+
+// その他
+int  map_check_dir (int s_dir, int t_dir);
+int  map_calc_dir (struct block_list *src, int x, int y);
+
+// path.cより
+int  path_search (struct walkpath_data *, int, int, int, int, int, int);
+int  path_blownpos (int m, int x0, int y0, int dx, int dy, int count);
+
+int  map_who (int fd);
+
+void map_helpscreen (void);         // [Valaris]
+int  map_delmap (char *mapname);
+
+#endif
diff --git a/src/map/mob.c b/src/map/mob.c
deleted file mode 100644
index 7be069e..0000000
--- a/src/map/mob.c
+++ /dev/null
@@ -1,5070 +0,0 @@
-// $Id: mob.c,v 1.7 2004/09/25 05:32:18 MouseJstr Exp $
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "../common/timer.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/nullpo.h"
-#include "../common/mt_rand.h"
-#include "map.h"
-#include "clif.h"
-#include "intif.h"
-#include "pc.h"
-#include "mob.h"
-#include "guild.h"
-#include "itemdb.h"
-#include "skill.h"
-#include "battle.h"
-#include "party.h"
-#include "npc.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#ifndef max
-#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
-#endif
-
-#define MIN_MOBTHINKTIME 100
-
-#define MOB_LAZYMOVEPERC 50     // Move probability in the negligent mode MOB (rate of 1000 minute)
-#define MOB_LAZYWARPPERC 20     // Warp probability in the negligent mode MOB (rate of 1000 minute)
-
-struct mob_db mob_db[2001];
-
-/*==========================================
- * Local prototype declaration   (only required thing)
- *------------------------------------------
- */
-static int distance (int, int, int, int);
-static int mob_makedummymobdb (int);
-static void mob_timer (timer_id, tick_t, custom_id_t, custom_data_t);
-int  mobskill_use (struct mob_data *md, unsigned int tick, int event);
-int  mobskill_deltimer (struct mob_data *md);
-int  mob_skillid2skillidx (int mob_class, int skillid);
-int  mobskill_use_id (struct mob_data *md, struct block_list *target,
-                      int skill_idx);
-static int mob_unlocktarget (struct mob_data *md, int tick);
-
-/*==========================================
- * Mob is searched with a name.
- *------------------------------------------
- */
-int mobdb_searchname (const char *str)
-{
-    int  i;
-
-    for (i = 0; i < sizeof (mob_db) / sizeof (mob_db[0]); i++)
-    {
-        if (strcasecmp (mob_db[i].name, str) == 0
-            || strcmp (mob_db[i].jname, str) == 0
-            || memcmp (mob_db[i].name, str, 24) == 0
-            || memcmp (mob_db[i].jname, str, 24) == 0)
-            return i;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Id Mob is checked.
- *------------------------------------------
- */
-int mobdb_checkid (const int id)
-{
-    if (id <= 0 || id >= (sizeof (mob_db) / sizeof (mob_db[0]))
-        || mob_db[id].name[0] == '\0')
-        return 0;
-
-    return id;
-}
-
-static void mob_init (struct mob_data *md);
-
-/*==========================================
- * The minimum data set for MOB spawning
- *------------------------------------------
- */
-int mob_spawn_dataset (struct mob_data *md, const char *mobname, int mob_class)
-{
-    nullpo_retr (0, md);
-
-    if (strcmp (mobname, "--en--") == 0)
-        memcpy (md->name, mob_db[mob_class].name, 24);
-    else if (strcmp (mobname, "--ja--") == 0)
-        memcpy (md->name, mob_db[mob_class].jname, 24);
-    else
-        memcpy (md->name, mobname, 24);
-
-    md->bl.prev = NULL;
-    md->bl.next = NULL;
-    md->n = 0;
-    md->base_class = md->mob_class = mob_class;
-    md->bl.id = npc_get_new_npc_id ();
-
-    memset (&md->state, 0, sizeof (md->state));
-    md->timer = -1;
-    md->target_id = 0;
-    md->attacked_id = 0;
-
-    mob_init (md);
-
-    return 0;
-}
-
-// Mutation values indicate how `valuable' a change to each stat is, XP wise.
-// For one 256th of change, we give out that many 1024th fractions of XP change
-// (i.e., 1024 means a 100% XP increase for a single point of adjustment, 4 means 100% XP bonus for doubling the value)
-static int mutation_value[MOB_XP_BONUS] = {
-    2,                          // MOB_LV
-    3,                          // MOB_MAX_HP
-    1,                          // MOB_STR
-    2,                          // MOB_AGI
-    1,                          // MOB_VIT
-    0,                          // MOB_INT
-    2,                          // MOB_DEX
-    2,                          // MOB_LUK
-    1,                          // MOB_ATK1
-    1,                          // MOB_ATK2
-    2,                          // MOB_ADELAY
-    2,                          // MOB_DEF
-    2,                          // MOB_MDEF
-    2,                          // MOB_SPEED
-};
-
-// The mutation scale indicates how far `up' we can go, with 256 indicating 100%  Note that this may stack with multiple
-// calls to `mutate'.
-static int mutation_scale[MOB_XP_BONUS] = {
-    16,                         // MOB_LV
-    256,                        // MOB_MAX_HP
-    32,                         // MOB_STR
-    48,                         // MOB_AGI
-    48,                         // MOB_VIT
-    48,                         // MOB_INT
-    48,                         // MOB_DEX
-    64,                         // MOB_LUK
-    48,                         // MOB_ATK1
-    48,                         // MOB_ATK2
-    80,                         // MOB_ADELAY
-    48,                         // MOB_DEF
-    48,                         // MOB_MDEF
-    80,                         // MOB_SPEED
-};
-
-// The table below indicates the `average' value for each of the statistics, or -1 if there is none.
-// This average is used to determine XP modifications for mutations.  The experience point bonus is
-// based on mutation_value and mutation_base as follows:
-// (1) first, compute the percentage change of the attribute (p0)
-// (2) second, determine the absolute stat change
-// (3) third, compute the percentage stat change relative to mutation_base (p1)
-// (4) fourth, compute the XP mofication based on the smaller of (p0, p1).
-static int mutation_base[MOB_XP_BONUS] = {
-    30,                         // MOB_LV
-    -1,                         // MOB_MAX_HP
-    20,                         // MOB_STR
-    20,                         // MOB_AGI
-    20,                         // MOB_VIT
-    20,                         // MOB_INT
-    20,                         // MOB_DEX
-    20,                         // MOB_LUK
-    -1,                         // MOB_ATK1
-    -1,                         // MOB_ATK2
-    -1,                         // MOB_ADELAY
-    -1,                         // MOB_DEF
-    20,                         // MOB_MDEF
-    -1,                         // MOB_SPEED
-};
-
-/*========================================
- * Mutates a MOB.  For large `direction' values, calling this multiple times will give bigger XP boni.
- *----------------------------------------
- */
-static void mob_mutate (struct mob_data *md, int stat, int intensity)   // intensity: positive: strengthen, negative: weaken.  256 = 100%.
-{
-    int  old_stat;
-    int  new_stat;
-    int  real_intensity;        // relative intensity
-    const int mut_base = mutation_base[stat];
-    int  sign = 1;
-
-    if (!md || stat < 0 || stat >= MOB_XP_BONUS || intensity == 0)
-        return;
-
-    while (intensity > mutation_scale[stat])
-    {
-        mob_mutate (md, stat, mutation_scale[stat]);    // give better XP assignments
-        intensity -= mutation_scale[stat];
-    }
-    while (intensity < -mutation_scale[stat])
-    {
-        mob_mutate (md, stat, mutation_scale[stat]);    // give better XP assignments
-        intensity += mutation_scale[stat];
-    }
-
-    if (!intensity)
-        return;
-
-    // MOB_ADELAY and MOB_SPEED are special because going DOWN is good here.
-    if (stat == MOB_ADELAY || stat == MOB_SPEED)
-        sign = -1;
-
-    // Now compute the new stat
-    old_stat = md->stats[stat];
-    new_stat = old_stat + ((old_stat * sign * intensity) / 256);
-
-    if (new_stat < 0)
-        new_stat = 0;
-
-    if (old_stat == 0)
-        real_intensity = 0;
-    else
-        real_intensity = (((new_stat - old_stat) << 8) / old_stat);
-
-    if (mut_base != -1)
-    {
-        // Now compute the mutation intensity relative to an absolute value.
-        // Take the lesser of the two effects.
-        int  real_intensity2 = (((new_stat - old_stat) << 8) / mut_base);
-
-        if (real_intensity < 0)
-            if (real_intensity2 > real_intensity)
-                real_intensity = real_intensity2;
-
-        if (real_intensity > 0)
-            if (real_intensity2 < real_intensity)
-                real_intensity = real_intensity2;
-    }
-
-    real_intensity *= sign;
-
-    md->stats[stat] = new_stat;
-
-    // Adjust XP value
-    md->stats[MOB_XP_BONUS] += mutation_value[stat] * real_intensity;
-    if (md->stats[MOB_XP_BONUS] <= 0)
-        md->stats[MOB_XP_BONUS] = 1;
-
-    // Sanitise
-    if (md->stats[MOB_ATK1] > md->stats[MOB_ATK2])
-    {
-        int  swap = md->stats[MOB_ATK2];
-        md->stats[MOB_ATK2] = md->stats[MOB_ATK1];
-        md->stats[MOB_ATK1] = swap;
-    }
-}
-
-// This calculates the exp of a given mob
-int mob_gen_exp (struct mob_db *mob)
-{
-    if (mob->max_hp <= 1)
-        return 1;
-    double mod_def = 100 - mob->def;
-    if (mod_def == 0)
-        mod_def = 1;
-    double effective_hp =
-        ((50 - mob->luk) * mob->max_hp / 50.0) +
-        (2 * mob->luk * mob->max_hp / mod_def);
-    double attack_factor =
-        (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 +
-         mob->luk) * (1872.0 / mob->adelay) / 4;
-    double dodge_factor =
-        pow (mob->lv + mob->agi + mob->luk / 2.0, 4.0 / 3.0);
-    double persuit_factor =
-        (3 + mob->range) * (mob->mode % 2) * 1000 / mob->speed;
-    double aggression_factor = (mob->mode & 4) == 4 ? 10.0 / 9.0 : 1.0;
-    int  xp =
-        (int) floor (effective_hp *
-                     pow (sqrt (attack_factor) + sqrt (dodge_factor) +
-                          sqrt (persuit_factor) + 55,
-                          3) * aggression_factor / 2000000.0 *
-                     (double) battle_config.base_exp_rate / 100.);
-    if (xp < 1)
-        xp = 1;
-    printf ("Exp for mob '%s' generated: %d\n", mob->name, xp);
-    return xp;
-}
-
-static void mob_init (struct mob_data *md)
-{
-    int  i;
-    const int mob_class = md->mob_class;
-    const int mutations_nr = mob_db[mob_class].mutations_nr;
-    const int mutation_power = mob_db[mob_class].mutation_power;
-
-    md->stats[MOB_LV] = mob_db[mob_class].lv;
-    md->stats[MOB_MAX_HP] = mob_db[mob_class].max_hp;
-    md->stats[MOB_STR] = mob_db[mob_class].str;
-    md->stats[MOB_AGI] = mob_db[mob_class].agi;
-    md->stats[MOB_VIT] = mob_db[mob_class].vit;
-    md->stats[MOB_INT] = mob_db[mob_class].int_;
-    md->stats[MOB_DEX] = mob_db[mob_class].dex;
-    md->stats[MOB_LUK] = mob_db[mob_class].luk;
-    md->stats[MOB_ATK1] = mob_db[mob_class].atk1;
-    md->stats[MOB_ATK2] = mob_db[mob_class].atk2;
-    md->stats[MOB_ADELAY] = mob_db[mob_class].adelay;
-    md->stats[MOB_DEF] = mob_db[mob_class].def;
-    md->stats[MOB_MDEF] = mob_db[mob_class].mdef;
-    md->stats[MOB_SPEED] = mob_db[mob_class].speed;
-    md->stats[MOB_XP_BONUS] = MOB_XP_BONUS_BASE;
-
-    for (i = 0; i < mutations_nr; i++)
-    {
-        int  stat_nr = MRAND (MOB_XP_BONUS + 1);
-        int  strength;
-
-        if (stat_nr >= MOB_XP_BONUS)
-            stat_nr = MOB_MAX_HP;
-
-        strength =
-            ((MRAND ((mutation_power >> 1)) +
-              (MRAND ((mutation_power >> 1))) +
-              2) * mutation_scale[stat_nr]) / 100;
-
-        strength = MRAND (2) ? strength : -strength;
-
-        if (strength < -240)
-            strength = -240;    /* Don't go too close to zero */
-
-        mob_mutate (md, stat_nr, strength);
-    }
-}
-
-/*==========================================
- * The MOB appearance for one time (for scripts)
- *------------------------------------------
- */
-int mob_once_spawn (struct map_session_data *sd, char *mapname,
-                    int x, int y, const char *mobname, int mob_class, int amount,
-                    const char *event)
-{
-    struct mob_data *md = NULL;
-    int  m, count, lv = 255, r = mob_class;
-
-    if (sd)
-        lv = sd->status.base_level;
-
-    if (sd && strcmp (mapname, "this") == 0)
-        m = sd->bl.m;
-    else
-        m = map_mapname2mapid (mapname);
-
-    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // 値が異常なら召喚を止める
-        return 0;
-
-    if (mob_class < 0)
-    {                           // ランダムに召喚
-        int  i = 0;
-        int  j = -mob_class - 1;
-        int  k;
-        if (j >= 0 && j < MAX_RANDOMMONSTER)
-        {
-            do
-            {
-                mob_class = MPRAND (1001, 1000);
-                k = MRAND (1000000);
-            }
-            while ((mob_db[mob_class].max_hp <= 0
-                    || mob_db[mob_class].summonper[j] <= k
-                    || (lv < mob_db[mob_class].lv
-                        && battle_config.random_monster_checklv == 1))
-                   && (i++) < 2000);
-            if (i >= 2000)
-            {
-                mob_class = mob_db[0].summonper[j];
-            }
-        }
-        else
-        {
-            return 0;
-        }
-//      if(battle_config.etc_log==1)
-//          printf("mobmob_class=%d try=%d\n",mob_class,i);
-    }
-    if (sd)
-    {
-        if (x <= 0)
-            x = sd->bl.x;
-        if (y <= 0)
-            y = sd->bl.y;
-    }
-    else if (x <= 0 || y <= 0)
-    {
-        printf ("mob_once_spawn: ??\n");
-    }
-
-    for (count = 0; count < amount; count++)
-    {
-        md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
-        if (mob_db[mob_class].mode & 0x02)
-            md->lootitem =
-                (struct item *) calloc (LOOTITEM_SIZE, sizeof (struct item));
-        else
-            md->lootitem = NULL;
-
-        mob_spawn_dataset (md, mobname, mob_class);
-        md->bl.m = m;
-        md->bl.x = x;
-        md->bl.y = y;
-        if (r < 0 && battle_config.dead_branch_active == 1)
-            md->mode = 0x1 + 0x4 + 0x80;    //移動してアクティブで反撃する
-        md->m = m;
-        md->x0 = x;
-        md->y0 = y;
-        md->xs = 0;
-        md->ys = 0;
-        md->spawndelay1 = -1;   // Only once is a flag.
-        md->spawndelay2 = -1;   // Only once is a flag.
-
-        memcpy (md->npc_event, event, sizeof (md->npc_event));
-
-        md->bl.type = BL_MOB;
-        map_addiddb (&md->bl);
-        mob_spawn (md->bl.id);
-
-        if (mob_class == 1288)
-        {                       // emperium hp based on defense level [Valaris]
-            struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
-            if (gc)
-            {
-                mob_db[mob_class].max_hp += 2000 * gc->defense;
-                md->hp = mob_db[mob_class].max_hp;
-            }
-        }                       // end addition [Valaris]
-
-    }
-    return (amount > 0) ? md->bl.id : 0;
-}
-
-/*==========================================
- * The MOB appearance for one time (& area specification for scripts)
- *------------------------------------------
- */
-int mob_once_spawn_area (struct map_session_data *sd, char *mapname,
-                         int x0, int y0, int x1, int y1,
-                         const char *mobname, int mob_class, int amount,
-                         const char *event)
-{
-    int  x, y, i, c, max, lx = -1, ly = -1, id = 0;
-    int  m;
-
-    if (strcmp (mapname, "this") == 0)
-        m = sd->bl.m;
-    else
-        m = map_mapname2mapid (mapname);
-
-    max = (y1 - y0 + 1) * (x1 - x0 + 1) * 3;
-    if (max > 1000)
-        max = 1000;
-
-    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // A summon is stopped if a value is unusual
-        return 0;
-
-    for (i = 0; i < amount; i++)
-    {
-        int  j = 0;
-        do
-        {
-            x = MPRAND (x0, (x1 - x0 + 1));
-            y = MPRAND (y0, (y1 - y0 + 1));
-        }
-        while (((c = map_getcell (m, x, y)) == 1 || c == 5) && (++j) < max);
-        if (j >= max)
-        {
-            if (lx >= 0)
-            {                   // Since reference went wrong, the place which boiled before is used.
-                x = lx;
-                y = ly;
-            }
-            else
-                return 0;       // Since reference of the place which boils first went wrong, it stops.
-        }
-        id = mob_once_spawn (sd, mapname, x, y, mobname, mob_class, 1, event);
-        lx = x;
-        ly = y;
-    }
-    return id;
-}
-
-/*==========================================
- * Summoning Guardians [Valaris]
- *------------------------------------------
- */
-int mob_spawn_guardian (struct map_session_data *sd, char *mapname,
-                        int x, int y, const char *mobname, int mob_class,
-                        int amount, const char *event, int guardian)
-{
-    struct mob_data *md = NULL;
-    int  m, count = 1, lv = 255;
-
-    if (sd)
-        lv = sd->status.base_level;
-
-    if (sd && strcmp (mapname, "this") == 0)
-        m = sd->bl.m;
-    else
-        m = map_mapname2mapid (mapname);
-
-    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // 値が異常なら召喚を止める
-        return 0;
-
-    if (mob_class < 0)
-        return 0;
-
-    if (sd)
-    {
-        if (x <= 0)
-            x = sd->bl.x;
-        if (y <= 0)
-            y = sd->bl.y;
-    }
-
-    else if (x <= 0 || y <= 0)
-        printf ("mob_spawn_guardian: ??\n");
-
-    for (count = 0; count < amount; count++)
-    {
-        struct guild_castle *gc;
-        CREATE (md, struct mob_data, 1);
-
-        mob_spawn_dataset (md, mobname, mob_class);
-        md->bl.m = m;
-        md->bl.x = x;
-        md->bl.y = y;
-        md->m = m;
-        md->x0 = x;
-        md->y0 = y;
-        md->xs = 0;
-        md->ys = 0;
-        md->spawndelay1 = -1;   // Only once is a flag.
-        md->spawndelay2 = -1;   // Only once is a flag.
-
-        memcpy (md->npc_event, event, sizeof (md->npc_event));
-
-        md->bl.type = BL_MOB;
-        map_addiddb (&md->bl);
-        mob_spawn (md->bl.id);
-
-        gc = guild_mapname2gc (map[md->bl.m].name);
-        if (gc)
-        {
-            mob_db[mob_class].max_hp += 2000 * gc->defense;
-            if (guardian == 0)
-            {
-                md->hp = gc->Ghp0;
-                gc->GID0 = md->bl.id;
-            }
-            if (guardian == 1)
-            {
-                md->hp = gc->Ghp1;
-                gc->GID1 = md->bl.id;
-            }
-            if (guardian == 2)
-            {
-                md->hp = gc->Ghp2;
-                gc->GID2 = md->bl.id;
-            }
-            if (guardian == 3)
-            {
-                md->hp = gc->Ghp3;
-                gc->GID3 = md->bl.id;
-            }
-            if (guardian == 4)
-            {
-                md->hp = gc->Ghp4;
-                gc->GID4 = md->bl.id;
-            }
-            if (guardian == 5)
-            {
-                md->hp = gc->Ghp5;
-                gc->GID5 = md->bl.id;
-            }
-            if (guardian == 6)
-            {
-                md->hp = gc->Ghp6;
-                gc->GID6 = md->bl.id;
-            }
-            if (guardian == 7)
-            {
-                md->hp = gc->Ghp7;
-                gc->GID7 = md->bl.id;
-            }
-
-        }
-    }
-
-    return (amount > 0) ? md->bl.id : 0;
-}
-
-/*==========================================
- * Appearance income of mob
- *------------------------------------------
- */
-int mob_get_viewclass (int mob_class)
-{
-    return mob_db[mob_class].view_class;
-}
-
-int mob_get_sex (int mob_class)
-{
-    return mob_db[mob_class].sex;
-}
-
-short mob_get_hair (int mob_class)
-{
-    return mob_db[mob_class].hair;
-}
-
-short mob_get_hair_color (int mob_class)
-{
-    return mob_db[mob_class].hair_color;
-}
-
-short mob_get_weapon (int mob_class)
-{
-    return mob_db[mob_class].weapon;
-}
-
-short mob_get_shield (int mob_class)
-{
-    return mob_db[mob_class].shield;
-}
-
-short mob_get_head_top (int mob_class)
-{
-    return mob_db[mob_class].head_top;
-}
-
-short mob_get_head_mid (int mob_class)
-{
-    return mob_db[mob_class].head_mid;
-}
-
-short mob_get_head_buttom (int mob_class)
-{
-    return mob_db[mob_class].head_buttom;
-}
-
-short mob_get_clothes_color (int mob_class) // Add for player monster dye - Valaris
-{
-    return mob_db[mob_class].clothes_color; // End
-}
-
-int mob_get_equip (int mob_class)   // mob equip [Valaris]
-{
-    return mob_db[mob_class].equip;
-}
-
-/*==========================================
- * Is MOB in the state in which the present movement is possible or not?
- *------------------------------------------
- */
-int mob_can_move (struct mob_data *md)
-{
-    nullpo_retr (0, md);
-
-    if (md->canmove_tick > gettick () || (md->opt1 > 0 && md->opt1 != 6)
-        || md->option & 2)
-        return 0;
-    // アンクル中で動けないとか
-    if (md->sc_data[SC_ANKLE].timer != -1 ||    //アンクルスネア
-        md->sc_data[SC_AUTOCOUNTER].timer != -1 ||  //オートカウンター
-        md->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
-        md->sc_data[SC_SPIDERWEB].timer != -1   //スパイダーウェッブ
-        )
-        return 0;
-
-    return 1;
-}
-
-/*==========================================
- * Time calculation concerning one step next to mob
- *------------------------------------------
- */
-static int calc_next_walk_step (struct mob_data *md)
-{
-    nullpo_retr (0, md);
-
-    if (md->walkpath.path_pos >= md->walkpath.path_len)
-        return -1;
-    if (md->walkpath.path[md->walkpath.path_pos] & 1)
-        return battle_get_speed (&md->bl) * 14 / 10;
-    return battle_get_speed (&md->bl);
-}
-
-static int mob_walktoxy_sub (struct mob_data *md);
-
-/*==========================================
- * Mob Walk processing
- *------------------------------------------
- */
-static int mob_walk (struct mob_data *md, unsigned int tick, int data)
-{
-    int  moveblock;
-    int  i, ctype;
-    static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-    static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-    int  x, y, dx, dy;
-
-    nullpo_retr (0, md);
-
-    md->state.state = MS_IDLE;
-    if (md->walkpath.path_pos >= md->walkpath.path_len
-        || md->walkpath.path_pos != data)
-        return 0;
-
-    md->walkpath.path_half ^= 1;
-    if (md->walkpath.path_half == 0)
-    {
-        md->walkpath.path_pos++;
-        if (md->state.change_walk_target)
-        {
-            mob_walktoxy_sub (md);
-            return 0;
-        }
-    }
-    else
-    {
-        if (md->walkpath.path[md->walkpath.path_pos] >= 8)
-            return 1;
-
-        x = md->bl.x;
-        y = md->bl.y;
-        ctype = map_getcell (md->bl.m, x, y);
-        if (ctype == 1 || ctype == 5)
-        {
-            mob_stop_walking (md, 1);
-            return 0;
-        }
-        md->dir = md->walkpath.path[md->walkpath.path_pos];
-        dx = dirx[md->dir];
-        dy = diry[md->dir];
-
-        ctype = map_getcell (md->bl.m, x + dx, y + dy);
-        if (ctype == 1 || ctype == 5)
-        {
-            mob_walktoxy_sub (md);
-            return 0;
-        }
-
-        moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
-                     || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
-
-        md->state.state = MS_WALK;
-        map_foreachinmovearea (clif_moboutsight, md->bl.m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               dx, dy, BL_PC, md);
-
-        x += dx;
-        y += dy;
-        if (md->min_chase > 13)
-            md->min_chase--;
-
-        if (moveblock)
-            map_delblock (&md->bl);
-        md->bl.x = x;
-        md->bl.y = y;
-        if (moveblock)
-            map_addblock (&md->bl);
-
-        map_foreachinmovearea (clif_mobinsight, md->bl.m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               -dx, -dy, BL_PC, md);
-        md->state.state = MS_IDLE;
-
-        if (md->option & 4)
-            skill_check_cloaking (&md->bl);
-
-        skill_unit_move (&md->bl, tick, 1); // Inspection of a skill unit
-    }
-    if ((i = calc_next_walk_step (md)) > 0)
-    {
-        i = i >> 1;
-        if (i < 1 && md->walkpath.path_half == 0)
-            i = 1;
-        md->timer =
-            add_timer (tick + i, mob_timer, md->bl.id, md->walkpath.path_pos);
-        md->state.state = MS_WALK;
-
-        if (md->walkpath.path_pos >= md->walkpath.path_len)
-            clif_fixmobpos (md);    // When mob stops, retransmission current of a position.
-    }
-    return 0;
-}
-
-/*==========================================
- * Check if mob should be attempting to attack
- *------------------------------------------
- */
-static int mob_check_attack (struct mob_data *md)
-{
-    struct block_list *tbl = NULL;
-    struct map_session_data *tsd = NULL;
-    struct mob_data *tmd = NULL;
-
-    int  mode, race, range;
-
-    nullpo_retr (0, md);
-
-    md->min_chase = 13;
-    md->state.state = MS_IDLE;
-    md->state.skillstate = MSS_IDLE;
-
-    if (md->skilltimer != -1)
-        return 0;
-
-    if (md->opt1 > 0 || md->option & 2)
-        return 0;
-
-    if (md->sc_data[SC_AUTOCOUNTER].timer != -1)
-        return 0;
-
-    if (md->sc_data[SC_BLADESTOP].timer != -1)
-        return 0;
-
-    if ((tbl = map_id2bl (md->target_id)) == NULL)
-    {
-        md->target_id = 0;
-        md->state.targettype = NONE_ATTACKABLE;
-        return 0;
-    }
-
-    if (tbl->type == BL_PC)
-        tsd = (struct map_session_data *) tbl;
-    else if (tbl->type == BL_MOB)
-        tmd = (struct mob_data *) tbl;
-    else
-        return 0;
-
-    if (tsd)
-    {
-        if (pc_isdead (tsd) || tsd->invincible_timer != -1
-            || pc_isinvisible (tsd) || md->bl.m != tbl->m || tbl->prev == NULL
-            || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
-        {
-            md->target_id = 0;
-            md->state.targettype = NONE_ATTACKABLE;
-            return 0;
-        }
-    }
-    if (tmd)
-    {
-        if (md->bl.m != tbl->m || tbl->prev == NULL
-            || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
-        {
-            md->target_id = 0;
-            md->state.targettype = NONE_ATTACKABLE;
-            return 0;
-        }
-    }
-
-    if (!md->mode)
-        mode = mob_db[md->mob_class].mode;
-    else
-        mode = md->mode;
-
-    race = mob_db[md->mob_class].race;
-    if (!(mode & 0x80))
-    {
-        md->target_id = 0;
-        md->state.targettype = NONE_ATTACKABLE;
-        return 0;
-    }
-    if (tsd && !(mode & 0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 ||
-                                  ((pc_ishiding (tsd)
-                                    || tsd->state.gangsterparadise)
-                                   && race != 4 && race != 6)))
-    {
-        md->target_id = 0;
-        md->state.targettype = NONE_ATTACKABLE;
-        return 0;
-    }
-
-    range = mob_db[md->mob_class].range;
-    if (mode & 1)
-        range++;
-    if (distance (md->bl.x, md->bl.y, tbl->x, tbl->y) > range)
-        return 0;
-
-    return 1;
-}
-
-static int mob_ancillary_attack(struct block_list *bl, va_list ap)
-{
-    struct block_list *mdbl = va_arg(ap, struct block_list *);
-    struct block_list *tbl = va_arg(ap, struct block_list *);
-    unsigned int tick = va_arg(ap, unsigned int);
-    if (bl != tbl)
-        battle_weapon_attack(mdbl, bl, tick, 0);
-    return 0;
-}
-
-/*==========================================
- * Attack processing of mob
- *------------------------------------------
- */
-static int mob_attack (struct mob_data *md, unsigned int tick, int data)
-{
-    struct block_list *tbl = NULL;
-
-    nullpo_retr (0, md);
-
-    if ((tbl = map_id2bl (md->target_id)) == NULL)
-        return 0;
-
-    if (!mob_check_attack (md))
-        return 0;
-
-    if (battle_config.monster_attack_direction_change)
-        md->dir = map_calc_dir (&md->bl, tbl->x, tbl->y);   // 向き設定
-
-    //clif_fixmobpos(md);
-
-    md->state.skillstate = MSS_ATTACK;
-    if (mobskill_use (md, tick, -2))    // スキル使用
-        return 0;
-
-    md->target_lv = battle_weapon_attack (&md->bl, tbl, tick, 0);
-    // If you are reading this, please note:
-    // it is highly platform-specific that this even works at all.
-    int radius = battle_config.mob_splash_radius;
-    if (radius >= 0 && tbl->type == BL_PC && !map[tbl->m].flag.town)
-        map_foreachinarea(mob_ancillary_attack,
-            tbl->m, tbl->x - radius, tbl->y - radius, tbl->x + radius, tbl->y + radius,
-            BL_PC,
-            &md->bl, tbl, tick);
-
-    if (!(battle_config.monster_cloak_check_type & 2)
-        && md->sc_data[SC_CLOAKING].timer != -1)
-        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
-
-    md->attackabletime = tick + battle_get_adelay (&md->bl);
-
-    md->timer = add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
-    md->state.state = MS_ATTACK;
-
-    return 0;
-}
-
-/*==========================================
- * The attack of PC which is attacking id is stopped.
- * The callback function of clif_foreachclient
- *------------------------------------------
- */
-int mob_stopattacked (struct map_session_data *sd, va_list ap)
-{
-    int  id;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, ap);
-
-    id = va_arg (ap, int);
-    if (sd->attacktarget == id)
-        pc_stopattack (sd);
-    return 0;
-}
-
-/*==========================================
- * The timer in which the mob's states changes
- *------------------------------------------
- */
-int mob_changestate (struct mob_data *md, int state, int type)
-{
-    unsigned int tick;
-    int  i;
-
-    nullpo_retr (0, md);
-
-    if (md->timer != -1)
-        delete_timer (md->timer, mob_timer);
-    md->timer = -1;
-    md->state.state = state;
-
-    switch (state)
-    {
-        case MS_WALK:
-            if ((i = calc_next_walk_step (md)) > 0)
-            {
-                i = i >> 2;
-                md->timer =
-                    add_timer (gettick () + i, mob_timer, md->bl.id, 0);
-            }
-            else
-                md->state.state = MS_IDLE;
-            break;
-        case MS_ATTACK:
-            tick = gettick ();
-            i = DIFF_TICK (md->attackabletime, tick);
-            if (i > 0 && i < 2000)
-                md->timer =
-                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
-            else if (type)
-            {
-                md->attackabletime = tick + battle_get_amotion (&md->bl);
-                md->timer =
-                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
-            }
-            else
-            {
-                md->attackabletime = tick + 1;
-                md->timer =
-                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
-            }
-            break;
-        case MS_DELAY:
-            md->timer =
-                add_timer (gettick () + type, mob_timer, md->bl.id, 0);
-            break;
-        case MS_DEAD:
-            skill_castcancel (&md->bl, 0);
-//      mobskill_deltimer(md);
-            md->state.skillstate = MSS_DEAD;
-            md->last_deadtime = gettick ();
-            // Since it died, all aggressors' attack to this mob is stopped.
-            clif_foreachclient (mob_stopattacked, md->bl.id);
-            skill_unit_out_all (&md->bl, gettick (), 1);
-            skill_status_change_clear (&md->bl, 2); // The abnormalities in status are canceled.
-            skill_clear_unitgroup (&md->bl);    // All skill unit groups are deleted.
-            skill_cleartimerskill (&md->bl);
-            if (md->deletetimer != -1)
-                delete_timer (md->deletetimer, mob_timer_delete);
-            md->deletetimer = -1;
-            md->hp = md->target_id = md->attacked_id = 0;
-            md->state.targettype = NONE_ATTACKABLE;
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * timer processing of mob (timer function)
- * It branches to a walk and an attack.
- *------------------------------------------
- */
-static void mob_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct mob_data *md;
-    struct block_list *bl;
-
-    if ((bl = map_id2bl (id)) == NULL)
-    {                           //攻撃してきた敵がもういないのは正常のようだ
-        return;
-    }
-
-    if (!bl || !bl->type || bl->type != BL_MOB)
-        return;
-
-    nullpo_retv (md = (struct mob_data *) bl);
-
-    if (!md->bl.type || md->bl.type != BL_MOB)
-        return;
-
-    if (md->timer != tid)
-    {
-        if (battle_config.error_log == 1)
-            printf ("mob_timer %d != %d\n", md->timer, tid);
-        return;
-    }
-    md->timer = -1;
-    if (md->bl.prev == NULL || md->state.state == MS_DEAD)
-        return;
-
-    map_freeblock_lock ();
-    switch (md->state.state)
-    {
-        case MS_WALK:
-            mob_check_attack (md);
-            mob_walk (md, tick, data);
-            break;
-        case MS_ATTACK:
-            mob_attack (md, tick, data);
-            break;
-        case MS_DELAY:
-            mob_changestate (md, MS_IDLE, 0);
-            break;
-        default:
-            if (battle_config.error_log == 1)
-                printf ("mob_timer : %d ?\n", md->state.state);
-            break;
-    }
-    map_freeblock_unlock ();
-    return;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int mob_walktoxy_sub (struct mob_data *md)
-{
-    struct walkpath_data wpd;
-
-    nullpo_retr (0, md);
-
-    if (path_search
-        (&wpd, md->bl.m, md->bl.x, md->bl.y, md->to_x, md->to_y,
-         md->state.walk_easy))
-        return 1;
-    memcpy (&md->walkpath, &wpd, sizeof (wpd));
-
-    md->state.change_walk_target = 0;
-    mob_changestate (md, MS_WALK, 0);
-    clif_movemob (md);
-
-    return 0;
-}
-
-/*==========================================
- * mob move start
- *------------------------------------------
- */
-int mob_walktoxy (struct mob_data *md, int x, int y, int easy)
-{
-    struct walkpath_data wpd;
-
-    nullpo_retr (0, md);
-
-    if (md->state.state == MS_WALK
-        && path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, x, y, easy))
-        return 1;
-
-    md->state.walk_easy = easy;
-    md->to_x = x;
-    md->to_y = y;
-    if (md->state.state == MS_WALK)
-    {
-        md->state.change_walk_target = 1;
-    }
-    else
-    {
-        return mob_walktoxy_sub (md);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * mob spawn with delay (timer function)
- *------------------------------------------
- */
-static void mob_delayspawn (timer_id tid, tick_t tick, custom_id_t m, custom_data_t n)
-{
-    mob_spawn (m);
-}
-
-/*==========================================
- * spawn timing calculation
- *------------------------------------------
- */
-int mob_setdelayspawn (int id)
-{
-    unsigned int spawntime, spawntime1, spawntime2, spawntime3;
-    struct mob_data *md;
-    struct block_list *bl;
-
-    if ((bl = map_id2bl (id)) == NULL)
-        return -1;
-
-    if (!bl || !bl->type || bl->type != BL_MOB)
-        return -1;
-
-    nullpo_retr (-1, md = (struct mob_data *) bl);
-
-    if (!md || md->bl.type != BL_MOB)
-        return -1;
-
-    // Processing of MOB which is not revitalized
-    if (md->spawndelay1 == -1 && md->spawndelay2 == -1 && md->n == 0)
-    {
-        map_deliddb (&md->bl);
-        if (md->lootitem)
-        {
-            map_freeblock (md->lootitem);
-            md->lootitem = NULL;
-        }
-        map_freeblock (md);     // Instead of [ of free ]
-        return 0;
-    }
-
-    spawntime1 = md->last_spawntime + md->spawndelay1;
-    spawntime2 = md->last_deadtime + md->spawndelay2;
-    spawntime3 = gettick () + 5000;
-    // spawntime = max(spawntime1,spawntime2,spawntime3);
-    if (DIFF_TICK (spawntime1, spawntime2) > 0)
-    {
-        spawntime = spawntime1;
-    }
-    else
-    {
-        spawntime = spawntime2;
-    }
-    if (DIFF_TICK (spawntime3, spawntime) > 0)
-    {
-        spawntime = spawntime3;
-    }
-
-    add_timer (spawntime, mob_delayspawn, id, 0);
-    return 0;
-}
-
-/*==========================================
- * Mob spawning. Initialization is also variously here.
- *------------------------------------------
- */
-int mob_spawn (int id)
-{
-    int  x = 0, y = 0, i = 0, c;
-    unsigned int tick = gettick ();
-    struct mob_data *md;
-    struct block_list *bl;
-
-    nullpo_retr (-1, bl = map_id2bl (id));
-
-    if (!bl || !bl->type || bl->type != BL_MOB)
-        return -1;
-
-    nullpo_retr (-1, md = (struct mob_data *) bl);
-
-    if (!md || !md->bl.type || md->bl.type != BL_MOB)
-        return -1;
-
-    md->last_spawntime = tick;
-    if (md->bl.prev != NULL)
-    {
-//      clif_clearchar_area(&md->bl,3);
-        skill_unit_out_all (&md->bl, gettick (), 1);
-        map_delblock (&md->bl);
-    }
-    else
-        md->mob_class = md->base_class;
-
-    md->bl.m = md->m;
-    do
-    {
-        if (md->x0 == 0 && md->y0 == 0)
-        {
-            x = MPRAND (1, (map[md->bl.m].xs - 2));
-            y = MPRAND (1, (map[md->bl.m].ys - 2));
-        }
-        else
-        {
-            x = MPRAND (md->x0, (md->xs + 1)) - md->xs / 2;
-            y = MPRAND (md->y0, (md->ys + 1)) - md->ys / 2;
-        }
-        i++;
-    }
-    while (((c = map_getcell (md->bl.m, x, y)) == 1 || c == 5) && i < 50);
-
-    if (i >= 50)
-    {
-//      if(battle_config.error_log==1)
-//          printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
-        add_timer (tick + 5000, mob_delayspawn, id, 0);
-        return 1;
-    }
-
-    md->to_x = md->bl.x = x;
-    md->to_y = md->bl.y = y;
-    md->dir = 0;
-
-    map_addblock (&md->bl);
-
-    memset (&md->state, 0, sizeof (md->state));
-    md->attacked_id = 0;
-    md->target_id = 0;
-    md->move_fail_count = 0;
-    mob_init (md);
-
-    if (!md->stats[MOB_SPEED])
-        md->stats[MOB_SPEED] = mob_db[md->mob_class].speed;
-    md->def_ele = mob_db[md->mob_class].element;
-    md->master_id = 0;
-    md->master_dist = 0;
-
-    md->state.state = MS_IDLE;
-    md->state.skillstate = MSS_IDLE;
-    md->timer = -1;
-    md->last_thinktime = tick;
-    md->next_walktime = tick + MPRAND (5000, 50);
-    md->attackabletime = tick;
-    md->canmove_tick = tick;
-
-    md->sg_count = 0;
-    md->deletetimer = -1;
-
-    md->skilltimer = -1;
-    for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
-        md->skilldelay[i] = c;
-    md->skillid = 0;
-    md->skilllv = 0;
-
-    memset (md->dmglog, 0, sizeof (md->dmglog));
-    if (md->lootitem)
-        memset (md->lootitem, 0, sizeof (md->lootitem));
-    md->lootitem_count = 0;
-
-    for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
-        md->skilltimerskill[i].timer = -1;
-
-    for (i = 0; i < MAX_STATUSCHANGE; i++)
-    {
-        md->sc_data[i].timer = -1;
-        md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 =
-            md->sc_data[i].val4 = 0;
-    }
-    md->sc_count = 0;
-    md->opt1 = md->opt2 = md->opt3 = md->option = 0;
-
-    memset (md->skillunit, 0, sizeof (md->skillunit));
-    memset (md->skillunittick, 0, sizeof (md->skillunittick));
-
-    md->hp = battle_get_max_hp (&md->bl);
-    if (md->hp <= 0)
-    {
-        mob_makedummymobdb (md->mob_class);
-        md->hp = battle_get_max_hp (&md->bl);
-    }
-
-    clif_spawnmob (md);
-
-    return 0;
-}
-
-/*==========================================
- * Distance calculation between two points
- *------------------------------------------
- */
-static int distance (int x0, int y0, int x1, int y1)
-{
-    int  dx, dy;
-
-    dx = abs (x0 - x1);
-    dy = abs (y0 - y1);
-    return dx > dy ? dx : dy;
-}
-
-/*==========================================
- * The stop of MOB's attack
- *------------------------------------------
- */
-int mob_stopattack (struct mob_data *md)
-{
-    md->target_id = 0;
-    md->state.targettype = NONE_ATTACKABLE;
-    md->attacked_id = 0;
-    return 0;
-}
-
-/*==========================================
- * The stop of MOB's walking
- *------------------------------------------
- */
-int mob_stop_walking (struct mob_data *md, int type)
-{
-    nullpo_retr (0, md);
-
-    if (md->state.state == MS_WALK || md->state.state == MS_IDLE)
-    {
-        int  dx = 0, dy = 0;
-
-        md->walkpath.path_len = 0;
-        if (type & 4)
-        {
-            dx = md->to_x - md->bl.x;
-            if (dx < 0)
-                dx = -1;
-            else if (dx > 0)
-                dx = 1;
-            dy = md->to_y - md->bl.y;
-            if (dy < 0)
-                dy = -1;
-            else if (dy > 0)
-                dy = 1;
-        }
-        md->to_x = md->bl.x + dx;
-        md->to_y = md->bl.y + dy;
-        if (dx != 0 || dy != 0)
-        {
-            mob_walktoxy_sub (md);
-            return 0;
-        }
-        mob_changestate (md, MS_IDLE, 0);
-    }
-    if (type & 0x01)
-        clif_fixmobpos (md);
-    if (type & 0x02)
-    {
-        int  delay = battle_get_dmotion (&md->bl);
-        unsigned int tick = gettick ();
-        if (md->canmove_tick < tick)
-            md->canmove_tick = tick + delay;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Reachability to a Specification ID existence place
- *------------------------------------------
- */
-int mob_can_reach (struct mob_data *md, struct block_list *bl, int range)
-{
-    int  dx, dy;
-    struct walkpath_data wpd;
-    int  i;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, bl);
-
-    dx = abs (bl->x - md->bl.x);
-    dy = abs (bl->y - md->bl.y);
-
-    //=========== guildcastle guardian no search start===========
-    //when players are the guild castle member not attack them !
-    if (md->mob_class == 1285 || md->mob_class == 1286 || md->mob_class == 1287)
-    {
-        struct map_session_data *sd;
-        struct guild *g = NULL;
-        struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
-
-        if (gc && agit_flag == 0)   // Guardians will not attack during non-woe time [Valaris]
-            return 0;           // end addition [Valaris]
-
-        if (bl && bl->type == BL_PC)
-        {
-            if ((sd = (struct map_session_data *) bl) == NULL)
-            {
-                printf ("mob_can_reach nullpo\n");
-                return 0;
-            }
-
-            if (gc && sd && sd->status.guild_id && sd->status.guild_id > 0)
-            {
-                g = guild_search (sd->status.guild_id); // don't attack guild members [Valaris]
-                if (g && g->guild_id > 0 && g->guild_id == gc->guild_id)
-                    return 0;
-                if (g && gc && guild_isallied (g, gc))
-                    return 0;
-
-            }
-        }
-    }
-    //========== guildcastle guardian no search eof==============
-
-    if (bl && bl->type == BL_PC && battle_config.monsters_ignore_gm == 1)
-    {                           // option to have monsters ignore GMs [Valaris]
-        struct map_session_data *sd;
-        if ((sd = (struct map_session_data *) bl) != NULL && pc_isGM (sd))
-            return 0;
-    }
-
-    if (md->bl.m != bl->m)      // 違うャbプ
-        return 0;
-
-    if (range > 0 && range < ((dx > dy) ? dx : dy)) // 遠すぎる
-        return 0;
-
-    if (md->bl.x == bl->x && md->bl.y == bl->y) // 同じャX
-        return 1;
-
-    // Obstacle judging
-    wpd.path_len = 0;
-    wpd.path_pos = 0;
-    wpd.path_half = 0;
-    if (path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0) !=
-        -1)
-        return 1;
-
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-        return 0;
-
-    // It judges whether it can adjoin or not.
-    dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
-    dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
-    if (path_search
-        (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - dx, bl->y - dy, 0) != -1)
-        return 1;
-    for (i = 0; i < 9; i++)
-    {
-        if (path_search
-            (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - 1 + i / 3,
-             bl->y - 1 + i % 3, 0) != -1)
-            return 1;
-    }
-    return 0;
-}
-
-/*==========================================
- * Determination for an attack of a monster
- *------------------------------------------
- */
-int mob_target (struct mob_data *md, struct block_list *bl, int dist)
-{
-    struct map_session_data *sd;
-    struct status_change *sc_data;
-    short *option;
-    int  mode, race;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, bl);
-
-    sc_data = battle_get_sc_data (bl);
-    option = battle_get_option (bl);
-    race = mob_db[md->mob_class].race;
-
-    if (!md->mode)
-    {
-        mode = mob_db[md->mob_class].mode;
-    }
-    else
-    {
-        mode = md->mode;
-    }
-    if (!(mode & 0x80))
-    {
-        md->target_id = 0;
-        return 0;
-    }
-    // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
-    if ((md->target_id > 0 && md->state.targettype == ATTACKABLE)
-        && (!(mode & 0x04) || MRAND (100) > 25))
-        return 0;
-
-    if (mode & 0x20 ||          // Coercion is exerted if it is MVPMOB.
-        (sc_data && sc_data[SC_TRICKDEAD].timer == -1 &&
-         ((option && !(*option & 0x06)) || race == 4 || race == 6)))
-    {
-        if (bl->type == BL_PC)
-        {
-            nullpo_retr (0, sd = (struct map_session_data *) bl);
-            if (sd->invincible_timer != -1 || pc_isinvisible (sd))
-                return 0;
-            if (!(mode & 0x20) && race != 4 && race != 6
-                && sd->state.gangsterparadise)
-                return 0;
-        }
-
-        md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
-        if (bl->type == BL_PC || bl->type == BL_MOB)
-            md->state.targettype = ATTACKABLE;
-        else
-            md->state.targettype = NONE_ATTACKABLE;
-        md->min_chase = dist + 13;
-        if (md->min_chase > 26)
-            md->min_chase = 26;
-    }
-    return 0;
-}
-
-/*==========================================
- * The ?? routine of an active monster
- *------------------------------------------
- */
-static int mob_ai_sub_hard_activesearch (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *tsd = NULL;
-    struct mob_data *smd, *tmd = NULL;
-    int  mode, race, dist, *pcc;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, smd = va_arg (ap, struct mob_data *));
-    nullpo_retr (0, pcc = va_arg (ap, int *));
-
-    if (bl->type == BL_PC)
-        tsd = (struct map_session_data *) bl;
-    else if (bl->type == BL_MOB)
-        tmd = (struct mob_data *) bl;
-    else
-        return 0;
-
-    //敵味方判定
-    if (battle_check_target (&smd->bl, bl, BCT_ENEMY) == 0)
-        return 0;
-
-    if (!smd->mode)
-        mode = mob_db[smd->mob_class].mode;
-    else
-        mode = smd->mode;
-
-    // アクティブでターゲット射程内にいるなら、ロックする
-    if (mode & 0x04)
-    {
-        race = mob_db[smd->mob_class].race;
-        //対象がPCの場合
-        if (tsd &&
-            !pc_isdead (tsd) &&
-            tsd->bl.m == smd->bl.m &&
-            tsd->invincible_timer == -1 &&
-            !pc_isinvisible (tsd) &&
-            (dist =
-             distance (smd->bl.x, smd->bl.y, tsd->bl.x, tsd->bl.y)) < 9)
-        {
-            if (mode & 0x20 ||
-                (tsd->sc_data[SC_TRICKDEAD].timer == -1 &&
-                 ((!pc_ishiding (tsd) && !tsd->state.gangsterparadise)
-                  || race == 4 || race == 6)))
-            {                   // 妨害がないか判定
-                if (mob_can_reach (smd, bl, 12) &&  // 到達可能性判定
-                    MRAND (1000) < 1000 / (++(*pcc)))
-                {               // 範囲内PCで等確率にする
-                    smd->target_id = tsd->bl.id;
-                    smd->state.targettype = ATTACKABLE;
-                    smd->min_chase = 13;
-                }
-            }
-        }
-        //対象がMobの場合
-        else if (tmd &&
-                 tmd->bl.m == smd->bl.m &&
-                 (dist =
-                  distance (smd->bl.x, smd->bl.y, tmd->bl.x, tmd->bl.y)) < 9)
-        {
-            if (mob_can_reach (smd, bl, 12) &&  // 到達可能性判定
-                MRAND (1000) < 1000 / (++(*pcc)))
-            {                   // 範囲内で等確率にする
-                smd->target_id = bl->id;
-                smd->state.targettype = ATTACKABLE;
-                smd->min_chase = 13;
-            }
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * loot monster item search
- *------------------------------------------
- */
-static int mob_ai_sub_hard_lootsearch (struct block_list *bl, va_list ap)
-{
-    struct mob_data *md;
-    int  mode, dist, *itc;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
-    nullpo_retr (0, itc = va_arg (ap, int *));
-
-    if (!md->mode)
-    {
-        mode = mob_db[md->mob_class].mode;
-    }
-    else
-    {
-        mode = md->mode;
-    }
-
-    if (!md->target_id && mode & 0x02)
-    {
-        if (!md->lootitem
-            || (battle_config.monster_loot_type == 1
-                && md->lootitem_count >= LOOTITEM_SIZE))
-            return 0;
-        if (bl->m == md->bl.m
-            && (dist = distance (md->bl.x, md->bl.y, bl->x, bl->y)) < 9)
-        {
-            if (mob_can_reach (md, bl, 12) &&   // Reachability judging
-                MRAND (1000) < 1000 / (++(*itc)))
-            {                   // It is made a probability, such as within the limits PC.
-                md->target_id = bl->id;
-                md->state.targettype = NONE_ATTACKABLE;
-                md->min_chase = 13;
-            }
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * The ?? routine of a link monster
- *------------------------------------------
- */
-static int mob_ai_sub_hard_linksearch (struct block_list *bl, va_list ap)
-{
-    struct mob_data *tmd;
-    struct mob_data *md;
-    struct block_list *target;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, tmd = (struct mob_data *) bl);
-    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
-    nullpo_retr (0, target = va_arg (ap, struct block_list *));
-
-    // same family free in a range at a link monster -- it will be made to lock if MOB is
-/*	if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->mob_class].mode&0x08){
-		if( tmd->mob_class==md->mob_class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
-			if( mob_can_reach(tmd,target,12) ){	// Reachability judging
-				tmd->target_id=md->target_id;
-				tmd->state.targettype = ATTACKABLE;
-				tmd->min_chase=13;
-			}
-		}
-	}*/
-    if (md->attacked_id > 0 && mob_db[md->mob_class].mode & 0x08)
-    {
-        if (tmd->mob_class == md->mob_class && tmd->bl.m == md->bl.m
-            && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE))
-        {
-            if (mob_can_reach (tmd, target, 12))
-            {                   // Reachability judging
-                tmd->target_id = md->attacked_id;
-                tmd->state.targettype = ATTACKABLE;
-                tmd->min_chase = 13;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Processing of slave monsters
- *------------------------------------------
- */
-static int mob_ai_sub_hard_slavemob (struct mob_data *md, unsigned int tick)
-{
-    struct mob_data *mmd = NULL;
-    struct block_list *bl;
-    int  mode, race, old_dist;
-
-    nullpo_retr (0, md);
-
-    if ((bl = map_id2bl (md->master_id)) != NULL)
-        mmd = (struct mob_data *) bl;
-
-    mode = mob_db[md->mob_class].mode;
-
-    // It is not main monster/leader.
-    if (!mmd || mmd->bl.type != BL_MOB || mmd->bl.id != md->master_id)
-        return 0;
-
-    // Since it is in the map on which the master is not, teleport is carried out and it pursues.
-    if (mmd->bl.m != md->bl.m)
-    {
-        mob_warp (md, mmd->bl.m, mmd->bl.x, mmd->bl.y, 3);
-        md->state.master_check = 1;
-        return 0;
-    }
-
-    // Distance with between slave and master is measured.
-    old_dist = md->master_dist;
-    md->master_dist = distance (md->bl.x, md->bl.y, mmd->bl.x, mmd->bl.y);
-
-    // Since the master was in near immediately before, teleport is carried out and it pursues.
-    if (old_dist < 10 && md->master_dist > 18)
-    {
-        mob_warp (md, -1, mmd->bl.x, mmd->bl.y, 3);
-        md->state.master_check = 1;
-        return 0;
-    }
-
-    // Although there is the master, since it is somewhat far, it approaches.
-    if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
-        && mob_can_move (md)
-        && (md->walkpath.path_pos >= md->walkpath.path_len
-            || md->walkpath.path_len == 0) && md->master_dist < 15)
-    {
-        int  i = 0, dx, dy, ret;
-        if (md->master_dist > 4)
-        {
-            do
-            {
-                if (i <= 5)
-                {
-                    dx = mmd->bl.x - md->bl.x;
-                    dy = mmd->bl.y - md->bl.y;
-                    if (dx < 0)
-                        dx += (MPRAND (1, ((dx < -3) ? 3 : -dx)));
-                    else if (dx > 0)
-                        dx -= (MPRAND (1, ((dx > 3) ? 3 : dx)));
-                    if (dy < 0)
-                        dy += (MPRAND (1, ((dy < -3) ? 3 : -dy)));
-                    else if (dy > 0)
-                        dy -= (MPRAND (1, ((dy > 3) ? 3 : dy)));
-                }
-                else
-                {
-                    dx = mmd->bl.x - md->bl.x + MRAND (7) - 3;
-                    dy = mmd->bl.y - md->bl.y + MRAND (7) - 3;
-                }
-
-                ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
-                i++;
-            }
-            while (ret && i < 10);
-        }
-        else
-        {
-            do
-            {
-                dx = MRAND (9) - 5;
-                dy = MRAND (9) - 5;
-                if (dx == 0 && dy == 0)
-                {
-                    dx = (MRAND (1)) ? 1 : -1;
-                    dy = (MRAND (1)) ? 1 : -1;
-                }
-                dx += mmd->bl.x;
-                dy += mmd->bl.y;
-
-                ret = mob_walktoxy (md, mmd->bl.x + dx, mmd->bl.y + dy, 0);
-                i++;
-            }
-            while (ret && i < 10);
-        }
-
-        md->next_walktime = tick + 500;
-        md->state.master_check = 1;
-    }
-
-    // There is the master, the master locks a target and he does not lock.
-    if ((mmd->target_id > 0 && mmd->state.targettype == ATTACKABLE)
-        && (!md->target_id || md->state.targettype == NONE_ATTACKABLE))
-    {
-        struct map_session_data *sd = map_id2sd (mmd->target_id);
-        if (sd != NULL && !pc_isdead (sd) && sd->invincible_timer == -1
-            && !pc_isinvisible (sd))
-        {
-
-            race = mob_db[md->mob_class].race;
-            if (mode & 0x20 ||
-                (sd->sc_data[SC_TRICKDEAD].timer == -1 &&
-                 ((!pc_ishiding (sd) && !sd->state.gangsterparadise)
-                  || race == 4 || race == 6)))
-            {                   // 妨害がないか判定
-
-                md->target_id = sd->bl.id;
-                md->state.targettype = ATTACKABLE;
-                md->min_chase =
-                    5 + distance (md->bl.x, md->bl.y, sd->bl.x, sd->bl.y);
-                md->state.master_check = 1;
-            }
-        }
-    }
-
-    // There is the master, the master locks a target and he does not lock.
-/*	if( (md->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!mmd->target_id || mmd->state.targettype == NONE_ATTACKABLE) ){
-		struct map_session_data *sd=map_id2sd(md->target_id);
-		if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
-
-			race=mob_db[mmd->mob_class].race;
-			if(mode&0x20 ||
-				(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
-				(!(sd->status.option&0x06) || race==4 || race==6)
-				) ){	// It judges whether there is any disturbance.
-
-				mmd->target_id=sd->bl.id;
-				mmd->state.targettype = ATTACKABLE;
-				mmd->min_chase=5+distance(mmd->bl.x,mmd->bl.y,sd->bl.x,sd->bl.y);
-			}
-		}
-	}*/
-
-    return 0;
-}
-
-/*==========================================
- * A lock of target is stopped and mob moves to a standby state.
- *------------------------------------------
- */
-static int mob_unlocktarget (struct mob_data *md, int tick)
-{
-    nullpo_retr (0, md);
-
-    md->target_id = 0;
-    md->state.targettype = NONE_ATTACKABLE;
-    md->state.skillstate = MSS_IDLE;
-    md->next_walktime = tick + MPRAND (3000, 3000);
-    return 0;
-}
-
-/*==========================================
- * Random walk
- *------------------------------------------
- */
-static int mob_randomwalk (struct mob_data *md, int tick)
-{
-    const int retrycount = 20;
-    int  speed;
-
-    nullpo_retr (0, md);
-
-    speed = battle_get_speed (&md->bl);
-    if (DIFF_TICK (md->next_walktime, tick) < 0)
-    {
-        int  i, x, y, c, d = 12 - md->move_fail_count;
-        if (d < 5)
-            d = 5;
-        for (i = 0; i < retrycount; i++)
-        {                       // Search of a movable place
-            int  r = mt_random ();
-            x = md->bl.x + r % (d * 2 + 1) - d;
-            y = md->bl.y + r / (d * 2 + 1) % (d * 2 + 1) - d;
-            if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5
-                && mob_walktoxy (md, x, y, 1) == 0)
-            {
-                md->move_fail_count = 0;
-                break;
-            }
-            if (i + 1 >= retrycount)
-            {
-                md->move_fail_count++;
-                if (md->move_fail_count > 1000)
-                {
-                    if (battle_config.error_log == 1)
-                        printf
-                            ("MOB cant move. random spawn %d, mob_class = %d\n",
-                             md->bl.id, md->mob_class);
-                    md->move_fail_count = 0;
-                    mob_spawn (md->bl.id);
-                }
-            }
-        }
-        for (i = c = 0; i < md->walkpath.path_len; i++)
-        {                       // The next walk start time is calculated.
-            if (md->walkpath.path[i] & 1)
-                c += speed * 14 / 10;
-            else
-                c += speed;
-        }
-        md->next_walktime = tick + MPRAND (3000, 3000) + c;
-        md->state.skillstate = MSS_WALK;
-        return 1;
-    }
-    return 0;
-}
-
-/*==========================================
- * AI of MOB whose is near a Player
- *------------------------------------------
- */
-static int mob_ai_sub_hard (struct block_list *bl, va_list ap)
-{
-    struct mob_data *md, *tmd = NULL;
-    struct map_session_data *tsd = NULL;
-    struct block_list *tbl = NULL;
-    struct flooritem_data *fitem;
-    unsigned int tick;
-    int  i, dx, dy, ret, dist;
-    int  attack_type = 0;
-    int  mode, race;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = (struct mob_data *) bl);
-
-    tick = va_arg (ap, unsigned int);
-
-    if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME)
-        return 0;
-    md->last_thinktime = tick;
-
-    if (md->skilltimer != -1 || md->bl.prev == NULL)
-    {                           // Under a skill aria and death
-        if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME)
-            md->next_walktime = tick;
-        return 0;
-    }
-
-    if (!md->mode)
-        mode = mob_db[md->mob_class].mode;
-    else
-        mode = md->mode;
-
-    race = mob_db[md->mob_class].race;
-
-    // Abnormalities
-    if ((md->opt1 > 0 && md->opt1 != 6) || md->state.state == MS_DELAY
-        || md->sc_data[SC_BLADESTOP].timer != -1)
-        return 0;
-
-    if (!(mode & 0x80) && md->target_id > 0)
-        md->target_id = 0;
-
-    if (md->attacked_id > 0 && mode & 0x08)
-    {                           // Link monster
-        struct map_session_data *asd = map_id2sd (md->attacked_id);
-        if (asd)
-        {
-            if (asd->invincible_timer == -1 && !pc_isinvisible (asd))
-            {
-                map_foreachinarea (mob_ai_sub_hard_linksearch, md->bl.m,
-                                   md->bl.x - 13, md->bl.y - 13,
-                                   md->bl.x + 13, md->bl.y + 13,
-                                   BL_MOB, md, &asd->bl);
-            }
-        }
-    }
-
-    // It checks to see it was attacked first (if active, it is target change at 25% of probability).
-    if (mode > 0 && md->attacked_id > 0
-        && (!md->target_id || md->state.targettype == NONE_ATTACKABLE
-            || (mode & 0x04 && MRAND (100) < 25)))
-    {
-        struct block_list *abl = map_id2bl (md->attacked_id);
-        struct map_session_data *asd = NULL;
-        if (abl)
-        {
-            if (abl->type == BL_PC)
-                asd = (struct map_session_data *) abl;
-            if (asd == NULL || md->bl.m != abl->m || abl->prev == NULL
-                || asd->invincible_timer != -1 || pc_isinvisible (asd)
-                || (dist =
-                    distance (md->bl.x, md->bl.y, abl->x, abl->y)) >= 32
-                || battle_check_target (bl, abl, BCT_ENEMY) == 0)
-                md->attacked_id = 0;
-            else
-            {
-                md->target_id = md->attacked_id;    // set target
-                md->state.targettype = ATTACKABLE;
-                attack_type = 1;
-                md->attacked_id = 0;
-                md->min_chase = dist + 13;
-                if (md->min_chase > 26)
-                    md->min_chase = 26;
-            }
-        }
-    }
-
-    md->state.master_check = 0;
-    // Processing of slave monster
-    if (md->master_id > 0 && md->state.special_mob_ai == 0)
-        mob_ai_sub_hard_slavemob (md, tick);
-
-    // アクティヴモンスターの策敵 (?? of a bitter taste TIVU monster)
-    if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
-        && mode & 0x04 && !md->state.master_check
-        && battle_config.monster_active_enable == 1)
-    {
-        i = 0;
-        if (md->state.special_mob_ai)
-        {
-            map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
-                               md->bl.x - AREA_SIZE * 2,
-                               md->bl.y - AREA_SIZE * 2,
-                               md->bl.x + AREA_SIZE * 2,
-                               md->bl.y + AREA_SIZE * 2, 0, md, &i);
-        }
-        else
-        {
-            map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
-                               md->bl.x - AREA_SIZE * 2,
-                               md->bl.y - AREA_SIZE * 2,
-                               md->bl.x + AREA_SIZE * 2,
-                               md->bl.y + AREA_SIZE * 2, BL_PC, md, &i);
-        }
-    }
-
-    // The item search of a route monster
-    if (!md->target_id && mode & 0x02 && !md->state.master_check)
-    {
-        i = 0;
-        map_foreachinarea (mob_ai_sub_hard_lootsearch, md->bl.m,
-                           md->bl.x - AREA_SIZE * 2, md->bl.y - AREA_SIZE * 2,
-                           md->bl.x + AREA_SIZE * 2, md->bl.y + AREA_SIZE * 2,
-                           BL_ITEM, md, &i);
-    }
-
-    // It will attack, if the candidate for an attack is.
-    if (md->target_id > 0)
-    {
-        if ((tbl = map_id2bl (md->target_id)))
-        {
-            if (tbl->type == BL_PC)
-                tsd = (struct map_session_data *) tbl;
-            else if (tbl->type == BL_MOB)
-                tmd = (struct mob_data *) tbl;
-            if (tsd || tmd)
-            {
-                if (tbl->m != md->bl.m || tbl->prev == NULL
-                    || (dist =
-                        distance (md->bl.x, md->bl.y, tbl->x,
-                                  tbl->y)) >= md->min_chase)
-                    mob_unlocktarget (md, tick);    // 別マップか、視界外
-                else if (tsd && !(mode & 0x20)
-                         && (tsd->sc_data[SC_TRICKDEAD].timer != -1
-                             ||
-                             ((pc_ishiding (tsd)
-                               || tsd->state.gangsterparadise) && race != 4
-                              && race != 6)))
-                    mob_unlocktarget (md, tick);    // スキルなどによる策敵妨害
-                else if (!battle_check_range
-                         (&md->bl, tbl, mob_db[md->mob_class].range))
-                {
-                    // 攻撃範囲外なので移動
-                    if (!(mode & 1))
-                    {           // 移動しないモード
-                        mob_unlocktarget (md, tick);
-                        return 0;
-                    }
-                    if (!mob_can_move (md)) // 動けない状態にある
-                        return 0;
-                    md->state.skillstate = MSS_CHASE;   // 突撃時スキル
-                    mobskill_use (md, tick, -1);
-//                  if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
-                    if (md->timer != -1 && md->state.state != MS_ATTACK
-                        && (DIFF_TICK (md->next_walktime, tick) < 0
-                            || distance (md->to_x, md->to_y, tbl->x,
-                                         tbl->y) < 2))
-                        return 0;   // 既に移動中
-                    if (!mob_can_reach
-                        (md, tbl, (md->min_chase > 13) ? md->min_chase : 13))
-                        mob_unlocktarget (md, tick);    // 移動できないのでタゲ解除(IWとか?)
-                    else
-                    {
-                        // 追跡
-                        md->next_walktime = tick + 500;
-                        i = 0;
-                        do
-                        {
-                            if (i == 0)
-                            {   // 最初はAEGISと同じ方法で検索
-                                dx = tbl->x - md->bl.x;
-                                dy = tbl->y - md->bl.y;
-                                if (dx < 0)
-                                    dx++;
-                                else if (dx > 0)
-                                    dx--;
-                                if (dy < 0)
-                                    dy++;
-                                else if (dy > 0)
-                                    dy--;
-                            }
-                            else
-                            {   // だめならAthena式(ランダム)
-                                dx = tbl->x - md->bl.x + MRAND (3) - 1;
-                                dy = tbl->y - md->bl.y + MRAND (3) - 1;
-                            }
-                            /*                      if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
-                             * dx=tsd->bl.x - md->bl.x;
-                             * dy=tsd->bl.y - md->bl.y;
-                             * if(dx<0) dx--;
-                             * else if(dx>0) dx++;
-                             * if(dy<0) dy--;
-                             * else if(dy>0) dy++;
-                             * } */
-                            ret =
-                                mob_walktoxy (md, md->bl.x + dx,
-                                              md->bl.y + dy, 0);
-                            i++;
-                        }
-                        while (ret && i < 5);
-
-                        if (ret)
-                        {       // 移動不可能な所からの攻撃なら2歩下る
-                            if (dx < 0)
-                                dx = 2;
-                            else if (dx > 0)
-                                dx = -2;
-                            if (dy < 0)
-                                dy = 2;
-                            else if (dy > 0)
-                                dy = -2;
-                            mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy,
-                                          0);
-                        }
-                    }
-                }
-                else
-                {               // 攻撃射程範囲内
-                    md->state.skillstate = MSS_ATTACK;
-                    if (md->state.state == MS_WALK)
-                        mob_stop_walking (md, 1);   // 歩行中なら停止
-                    if (md->state.state == MS_ATTACK)
-                        return 0;   // 既に攻撃中
-                    mob_changestate (md, MS_ATTACK, attack_type);
-
-/*					if(mode&0x08){	// リンクモンスター
-					map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
-						md->bl.x-13,md->bl.y-13,
-						md->bl.x+13,md->bl.y+13,
-							BL_MOB,md,&tsd->bl);
-				}*/
-                }
-                return 0;
-            }
-            else
-            {                   // ルートモンスター処理
-                if (tbl == NULL || tbl->type != BL_ITEM || tbl->m != md->bl.m
-                    || (dist =
-                        distance (md->bl.x, md->bl.y, tbl->x,
-                                  tbl->y)) >= md->min_chase || !md->lootitem)
-                {
-                    // 遠すぎるかアイテムがなくなった
-                    mob_unlocktarget (md, tick);
-                    if (md->state.state == MS_WALK)
-                        mob_stop_walking (md, 1);   // 歩行中なら停止
-                }
-                else if (dist)
-                {
-                    if (!(mode & 1))
-                    {           // 移動しないモード
-                        mob_unlocktarget (md, tick);
-                        return 0;
-                    }
-                    if (!mob_can_move (md)) // 動けない状態にある
-                        return 0;
-                    md->state.skillstate = MSS_LOOT;    // ルート時スキル使用
-                    mobskill_use (md, tick, -1);
-//                  if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
-                    if (md->timer != -1 && md->state.state != MS_ATTACK
-                        && (DIFF_TICK (md->next_walktime, tick) < 0
-                            || distance (md->to_x, md->to_y, tbl->x,
-                                         tbl->y) <= 0))
-                        return 0;   // 既に移動中
-                    md->next_walktime = tick + 500;
-                    dx = tbl->x - md->bl.x;
-                    dy = tbl->y - md->bl.y;
-/*				if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
-						dx=tbl->x - md->bl.x;
-						dy=tbl->y - md->bl.y;
-				}*/
-                    ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
-                    if (ret)
-                        mob_unlocktarget (md, tick);    // 移動できないのでタゲ解除(IWとか?)
-                }
-                else
-                {               // アイテムまでたどり着いた
-                    if (md->state.state == MS_ATTACK)
-                        return 0;   // 攻撃中
-                    if (md->state.state == MS_WALK)
-                        mob_stop_walking (md, 1);   // 歩行中なら停止
-                    fitem = (struct flooritem_data *) tbl;
-                    if (md->lootitem_count < LOOTITEM_SIZE)
-                        memcpy (&md->lootitem[md->lootitem_count++],
-                                &fitem->item_data, sizeof (md->lootitem[0]));
-                    else if (battle_config.monster_loot_type == 1
-                             && md->lootitem_count >= LOOTITEM_SIZE)
-                    {
-                        mob_unlocktarget (md, tick);
-                        return 0;
-                    }
-                    else
-                    {
-                        for (i = 0; i < LOOTITEM_SIZE - 1; i++)
-                            memcpy (&md->lootitem[i], &md->lootitem[i + 1],
-                                    sizeof (md->lootitem[0]));
-                        memcpy (&md->lootitem[LOOTITEM_SIZE - 1],
-                                &fitem->item_data, sizeof (md->lootitem[0]));
-                    }
-                    map_clearflooritem (tbl->id);
-                    mob_unlocktarget (md, tick);
-                }
-                return 0;
-            }
-        }
-        else
-        {
-            mob_unlocktarget (md, tick);
-            if (md->state.state == MS_WALK)
-                mob_stop_walking (md, 4);   // 歩行中なら停止
-            return 0;
-        }
-    }
-
-    // It is skill use at the time of /standby at the time of a walk.
-    if (mobskill_use (md, tick, -1))
-        return 0;
-
-    // 歩行処理
-    if (mode & 1 && mob_can_move (md) &&    // 移動可能MOB&動ける状態にある
-        (md->master_id == 0 || md->state.special_mob_ai
-         || md->master_dist > 10))
-    {                           //取り巻きMOBじゃない
-
-        if (DIFF_TICK (md->next_walktime, tick) > +7000 &&
-            (md->walkpath.path_len == 0
-             || md->walkpath.path_pos >= md->walkpath.path_len))
-        {
-            md->next_walktime = tick + 3000 * MRAND (2000);
-        }
-
-        // Random movement
-        if (mob_randomwalk (md, tick))
-            return 0;
-    }
-
-    // Since he has finished walking, it stands by.
-    if (md->walkpath.path_len == 0
-        || md->walkpath.path_pos >= md->walkpath.path_len)
-        md->state.skillstate = MSS_IDLE;
-    return 0;
-}
-
-/*==========================================
- * Serious processing for mob in PC field of view (foreachclient)
- *------------------------------------------
- */
-static int mob_ai_sub_foreachclient (struct map_session_data *sd, va_list ap)
-{
-    unsigned int tick;
-    nullpo_retr (0, sd);
-    nullpo_retr (0, ap);
-
-    tick = va_arg (ap, unsigned int);
-    map_foreachinarea (mob_ai_sub_hard, sd->bl.m,
-                       sd->bl.x - AREA_SIZE * 2, sd->bl.y - AREA_SIZE * 2,
-                       sd->bl.x + AREA_SIZE * 2, sd->bl.y + AREA_SIZE * 2,
-                       BL_MOB, tick);
-
-    return 0;
-}
-
-/*==========================================
- * Serious processing for mob in PC field of view   (interval timer function)
- *------------------------------------------
- */
-static void mob_ai_hard (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    clif_foreachclient (mob_ai_sub_foreachclient, tick);
-}
-
-/*==========================================
- * Negligent mode MOB AI (PC is not in near)
- *------------------------------------------
- */
-static void mob_ai_sub_lazy (db_key_t key, db_val_t data, va_list app)
-{
-    struct mob_data *md = (struct mob_data *)data;
-    unsigned int tick;
-    va_list ap;
-
-    nullpo_retv (md);
-    nullpo_retv (app);
-    nullpo_retv (ap = va_arg (app, va_list));
-
-    if (md == NULL)
-        return;
-
-    if (!md->bl.type || md->bl.type != BL_MOB)
-        return;
-
-    tick = va_arg (ap, unsigned int);
-
-    if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME * 10)
-        return;
-    md->last_thinktime = tick;
-
-    if (md->bl.prev == NULL || md->skilltimer != -1)
-    {
-        if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME * 10)
-            md->next_walktime = tick;
-        return;
-    }
-
-    if (DIFF_TICK (md->next_walktime, tick) < 0 &&
-        (mob_db[md->mob_class].mode & 1) && mob_can_move (md))
-    {
-
-        if (map[md->bl.m].users > 0)
-        {
-            // Since PC is in the same map, somewhat better negligent processing is carried out.
-
-            // It sometimes moves.
-            if (MRAND (1000) < MOB_LAZYMOVEPERC)
-                mob_randomwalk (md, tick);
-
-            // MOB which is not not the summons MOB but BOSS, either sometimes reboils.
-            else if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
-                     && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0
-                     && !(mob_db[md->mob_class].mode & 0x20))
-                mob_spawn (md->bl.id);
-
-        }
-        else
-        {
-            // Since PC is not even in the same map, suitable processing is carried out even if it takes.
-
-            // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
-            if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
-                && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0
-                && !(mob_db[md->mob_class].mode & 0x20))
-                mob_warp (md, -1, -1, -1, -1);
-        }
-
-        md->next_walktime = tick + MPRAND (5000, 10000);
-    }
-}
-
-/*==========================================
- * Negligent processing for mob outside PC field of view   (interval timer function)
- *------------------------------------------
- */
-static void mob_ai_lazy (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    map_foreachiddb (mob_ai_sub_lazy, tick);
-}
-
-/*==========================================
- * The structure object for item drop with delay
- * Since it is only two being able to pass [ int ] a timer function
- * Data is put in and passed to this structure object.
- *------------------------------------------
- */
-struct delay_item_drop
-{
-    int  m, x, y;
-    int  nameid, amount;
-    struct map_session_data *first_sd, *second_sd, *third_sd;
-};
-
-struct delay_item_drop2
-{
-    int  m, x, y;
-    struct item item_data;
-    struct map_session_data *first_sd, *second_sd, *third_sd;
-};
-
-/*==========================================
- * item drop with delay (timer function)
- *------------------------------------------
- */
-static void mob_delay_item_drop (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct delay_item_drop *ditem;
-    struct item temp_item;
-    int  flag;
-
-    nullpo_retv (ditem = (struct delay_item_drop *) id);
-
-    memset (&temp_item, 0, sizeof (temp_item));
-    temp_item.nameid = ditem->nameid;
-    temp_item.amount = ditem->amount;
-    temp_item.identify = !itemdb_isequip3 (temp_item.nameid);
-
-    if (battle_config.item_auto_get == 1)
-    {
-        if (ditem->first_sd
-            && (flag =
-                pc_additem (ditem->first_sd, &temp_item, ditem->amount)))
-        {
-            clif_additem (ditem->first_sd, 0, 0, flag);
-            map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
-                              ditem->first_sd, ditem->second_sd,
-                              ditem->third_sd, 0);
-        }
-        free (ditem);
-        return;
-    }
-
-    map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
-                      ditem->first_sd, ditem->second_sd, ditem->third_sd, 0);
-
-    free (ditem);
-}
-
-/*==========================================
- * item drop (timer function)-lootitem with delay
- *------------------------------------------
- */
-static void mob_delay_item_drop2 (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct delay_item_drop2 *ditem;
-    int  flag;
-
-    nullpo_retv (ditem = (struct delay_item_drop2 *) id);
-
-    if (battle_config.item_auto_get == 1)
-    {
-        if (ditem->first_sd
-            && (flag =
-                pc_additem (ditem->first_sd, &ditem->item_data,
-                            ditem->item_data.amount)))
-        {
-            clif_additem (ditem->first_sd, 0, 0, flag);
-            map_addflooritem (&ditem->item_data, ditem->item_data.amount,
-                              ditem->m, ditem->x, ditem->y, ditem->first_sd,
-                              ditem->second_sd, ditem->third_sd, 0);
-        }
-        free (ditem);
-        return;
-    }
-
-    map_addflooritem (&ditem->item_data, ditem->item_data.amount, ditem->m,
-                      ditem->x, ditem->y, ditem->first_sd, ditem->second_sd,
-                      ditem->third_sd, 0);
-
-    free (ditem);
-}
-
-/*==========================================
- * mob data is erased.
- *------------------------------------------
- */
-int mob_delete (struct mob_data *md)
-{
-    nullpo_retr (1, md);
-
-    if (md->bl.prev == NULL)
-        return 1;
-    mob_changestate (md, MS_DEAD, 0);
-    clif_clearchar_area (&md->bl, 1);
-    map_delblock (&md->bl);
-    if (mob_get_viewclass (md->mob_class) <= 1000)
-        clif_clearchar_delay (gettick () + 3000, &md->bl, 0);
-    mob_deleteslave (md);
-    mob_setdelayspawn (md->bl.id);
-    return 0;
-}
-
-int mob_catch_delete (struct mob_data *md, int type)
-{
-    nullpo_retr (1, md);
-
-    if (md->bl.prev == NULL)
-        return 1;
-    mob_changestate (md, MS_DEAD, 0);
-    clif_clearchar_area (&md->bl, type);
-    map_delblock (&md->bl);
-    mob_setdelayspawn (md->bl.id);
-    return 0;
-}
-
-void mob_timer_delete (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct block_list *bl = map_id2bl (id);
-    struct mob_data *md;
-
-    nullpo_retv (bl);
-
-    md = (struct mob_data *) bl;
-    mob_catch_delete (md, 3);
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int mob_deleteslave_sub (struct block_list *bl, va_list ap)
-{
-    struct mob_data *md;
-    int  id;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = (struct mob_data *) bl);
-
-    id = va_arg (ap, int);
-    if (md->master_id > 0 && md->master_id == id)
-        mob_damage (NULL, md, md->hp, 1);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int mob_deleteslave (struct mob_data *md)
-{
-    nullpo_retr (0, md);
-
-    map_foreachinarea (mob_deleteslave_sub, md->bl.m,
-                       0, 0, map[md->bl.m].xs, map[md->bl.m].ys,
-                       BL_MOB, md->bl.id);
-    return 0;
-}
-
-#define DAMAGE_BONUS_COUNT 6    // max. number of players to account for
-const static double damage_bonus_factor[DAMAGE_BONUS_COUNT + 1] = {
-    1.0, 1.0, 2.0, 2.5, 2.75, 2.9, 3.0
-};
-
-/*==========================================
- * It is the damage of sd to damage to md.
- *------------------------------------------
- */
-int mob_damage (struct block_list *src, struct mob_data *md, int damage,
-                int type)
-{
-    int  i, count, minpos, mindmg;
-    struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE];
-    struct
-    {
-        struct party *p;
-        int  id, base_exp, job_exp;
-    } pt[DAMAGELOG_SIZE];
-    int  pnum = 0;
-    int  mvp_damage, max_hp;
-    unsigned int tick = gettick ();
-    struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd =
-        NULL;
-    double dmg_rate, tdmg, temp;
-    struct item item;
-    int  ret;
-    int  drop_rate;
-    int  skill, sp;
-
-    nullpo_retr (0, md);        //srcはNULLで呼ばれる場合もあるので、他でチェック
-
-    if (src && src->id == md->master_id
-        && md->mode & MOB_MODE_TURNS_AGAINST_BAD_MASTER)
-    {
-        /* If the master hits a monster, have the monster turn against him */
-        md->master_id = 0;
-        md->mode = 0x85;        /* Regular war mode */
-        md->target_id = src->id;
-        md->attacked_id = src->id;
-    }
-
-    max_hp = battle_get_max_hp (&md->bl);
-
-    if (src && src->type == BL_PC)
-    {
-        sd = (struct map_session_data *) src;
-        mvp_sd = sd;
-    }
-
-//  if(battle_config.battle_log)
-//      printf("mob_damage %d %d %d\n",md->hp,max_hp,damage);
-    if (md->bl.prev == NULL)
-    {
-        if (battle_config.error_log == 1)
-            printf ("mob_damage : BlockError!!\n");
-        return 0;
-    }
-
-    if (md->state.state == MS_DEAD || md->hp <= 0)
-    {
-        if (md->bl.prev != NULL)
-        {
-            mob_changestate (md, MS_DEAD, 0);
-            mobskill_use (md, tick, -1);    // It is skill at the time of death.
-            clif_clearchar_area (&md->bl, 1);
-            map_delblock (&md->bl);
-            mob_setdelayspawn (md->bl.id);
-        }
-        return 0;
-    }
-
-    if (md->sc_data[SC_ENDURE].timer == -1)
-        mob_stop_walking (md, 3);
-    if (damage > max_hp >> 2)
-        skill_stop_dancing (&md->bl, 0);
-
-    if (md->hp > max_hp)
-        md->hp = max_hp;
-
-    // The amount of overkill rounds to hp.
-    if (damage > md->hp)
-        damage = md->hp;
-
-    if (!(type & 2))
-    {
-        if (sd != NULL)
-        {
-            for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
-                 i++)
-            {
-                if (md->dmglog[i].id == sd->bl.id)
-                    break;
-                if (md->dmglog[i].id == 0)
-                {
-                    minpos = i;
-                    mindmg = 0;
-                }
-                else if (md->dmglog[i].dmg < mindmg)
-                {
-                    minpos = i;
-                    mindmg = md->dmglog[i].dmg;
-                }
-            }
-            if (i < DAMAGELOG_SIZE)
-                md->dmglog[i].dmg += damage;
-            else
-            {
-                md->dmglog[minpos].id = sd->bl.id;
-                md->dmglog[minpos].dmg = damage;
-            }
-
-            if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
-                md->attacked_id = sd->bl.id;
-        }
-        if (src && src->type == BL_MOB
-            && ((struct mob_data *) src)->state.special_mob_ai)
-        {
-            struct mob_data *md2 = (struct mob_data *) src;
-            struct block_list *master_bl = map_id2bl (md2->master_id);
-            if (master_bl && master_bl->type == BL_PC)
-            {
-                MAP_LOG_PC (((struct map_session_data *) master_bl),
-                            "MOB-TO-MOB-DMG FROM MOB%d %d TO MOB%d %d FOR %d",
-                            md2->bl.id, md2->mob_class, md->bl.id, md->mob_class,
-                            damage);
-            }
-
-            nullpo_retr (0, md2);
-            for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
-                 i++)
-            {
-                if (md->dmglog[i].id == md2->master_id)
-                    break;
-                if (md->dmglog[i].id == 0)
-                {
-                    minpos = i;
-                    mindmg = 0;
-                }
-                else if (md->dmglog[i].dmg < mindmg)
-                {
-                    minpos = i;
-                    mindmg = md->dmglog[i].dmg;
-                }
-            }
-            if (i < DAMAGELOG_SIZE)
-                md->dmglog[i].dmg += damage;
-            else
-            {
-                md->dmglog[minpos].id = md2->master_id;
-                md->dmglog[minpos].dmg = damage;
-
-                if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
-                    md->attacked_id = md2->master_id;
-            }
-        }
-
-    }
-
-    md->hp -= damage;
-
-    if (md->mob_class >= 1285 && md->mob_class <= 1287)
-    {                           // guardian hp update [Valaris]
-        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
-        if (gc)
-        {
-
-            if (md->bl.id == gc->GID0)
-            {
-                gc->Ghp0 = md->hp;
-                if (gc->Ghp0 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 10, 0);
-                    guild_castledatasave (gc->castle_id, 18, 0);
-                }
-            }
-            if (md->bl.id == gc->GID1)
-            {
-                gc->Ghp1 = md->hp;
-                if (gc->Ghp1 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 11, 0);
-                    guild_castledatasave (gc->castle_id, 19, 0);
-                }
-            }
-            if (md->bl.id == gc->GID2)
-            {
-                gc->Ghp2 = md->hp;
-                if (gc->Ghp2 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 12, 0);
-                    guild_castledatasave (gc->castle_id, 20, 0);
-                }
-            }
-            if (md->bl.id == gc->GID3)
-            {
-                gc->Ghp3 = md->hp;
-                if (gc->Ghp3 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 13, 0);
-                    guild_castledatasave (gc->castle_id, 21, 0);
-                }
-            }
-            if (md->bl.id == gc->GID4)
-            {
-                gc->Ghp4 = md->hp;
-                if (gc->Ghp4 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 14, 0);
-                    guild_castledatasave (gc->castle_id, 22, 0);
-                }
-            }
-            if (md->bl.id == gc->GID5)
-            {
-                gc->Ghp5 = md->hp;
-                if (gc->Ghp5 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 15, 0);
-                    guild_castledatasave (gc->castle_id, 23, 0);
-                }
-            }
-            if (md->bl.id == gc->GID6)
-            {
-                gc->Ghp6 = md->hp;
-                if (gc->Ghp6 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 16, 0);
-                    guild_castledatasave (gc->castle_id, 24, 0);
-                }
-            }
-            if (md->bl.id == gc->GID7)
-            {
-                gc->Ghp7 = md->hp;
-                if (gc->Ghp7 <= 0)
-                {
-                    guild_castledatasave (gc->castle_id, 17, 0);
-                    guild_castledatasave (gc->castle_id, 25, 0);
-
-                }
-            }
-        }
-    }                           // end addition [Valaris]
-
-    if (md->option & 2)
-        skill_status_change_end (&md->bl, SC_HIDING, -1);
-    if (md->option & 4)
-        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
-
-    if (md->state.special_mob_ai == 2)
-    {                           //スフィアーマイン
-        int  skillidx = 0;
-
-        if ((skillidx =
-             mob_skillid2skillidx (md->mob_class, NPC_SELFDESTRUCTION2)) >= 0)
-        {
-            md->mode |= 0x1;
-            md->next_walktime = tick;
-            mobskill_use_id (md, &md->bl, skillidx);    //自爆詠唱開始
-            md->state.special_mob_ai++;
-        }
-    }
-
-    if (md->hp > 0)
-    {
-        return 0;
-    }
-
-    MAP_LOG ("MOB%d DEAD", md->bl.id);
-
-    // ----- ここから死亡処理 -----
-
-    map_freeblock_lock ();
-    mob_changestate (md, MS_DEAD, 0);
-    mobskill_use (md, tick, -1);    // 死亡時スキル
-
-    memset (tmpsd, 0, sizeof (tmpsd));
-    memset (pt, 0, sizeof (pt));
-
-    max_hp = battle_get_max_hp (&md->bl);
-
-    if (src && src->type == BL_MOB)
-        mob_unlocktarget ((struct mob_data *) src, tick);
-
-    /* ソウルドレイン */
-    if (sd && (skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0)
-    {
-        clif_skill_nodamage (src, &md->bl, HW_SOULDRAIN, skill, 1);
-        sp = (battle_get_lv (&md->bl)) * (65 + 15 * skill) / 100;
-        if (sd->status.sp + sp > sd->status.max_sp)
-            sp = sd->status.max_sp - sd->status.sp;
-        sd->status.sp += sp;
-        clif_heal (sd->fd, SP_SP, sp);
-    }
-
-    // map外に消えた人は計算から除くので
-    // overkill分は無いけどsumはmax_hpとは違う
-
-    tdmg = 0;
-    for (i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE; i++)
-    {
-        if (md->dmglog[i].id == 0)
-            continue;
-        tmpsd[i] = map_id2sd (md->dmglog[i].id);
-        if (tmpsd[i] == NULL)
-            continue;
-        count++;
-        if (tmpsd[i]->bl.m != md->bl.m || pc_isdead (tmpsd[i]))
-            continue;
-
-        tdmg += (double) md->dmglog[i].dmg;
-        if (mvp_damage < md->dmglog[i].dmg)
-        {
-            third_sd = second_sd;
-            second_sd = mvp_sd;
-            mvp_sd = tmpsd[i];
-            mvp_damage = md->dmglog[i].dmg;
-        }
-    }
-
-    // [MouseJstr]
-    if ((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1))
-    {
-
-        if ((double) max_hp < tdmg)
-            dmg_rate = ((double) max_hp) / tdmg;
-        else
-            dmg_rate = 1;
-
-        // 経験値の分配
-        for (i = 0; i < DAMAGELOG_SIZE; i++)
-        {
-
-            int  pid, base_exp, job_exp, flag = 1;
-            double per;
-            struct party *p;
-            if (tmpsd[i] == NULL || tmpsd[i]->bl.m != md->bl.m)
-                continue;
-/* jAthena's exp formula
-		per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
-		temp = ((double)mob_db[md->mob_class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
-		base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
-		if(mob_db[md->mob_class].base_exp > 0 && base_exp < 1) base_exp = 1;
-		if(base_exp < 0) base_exp = 0;
-		temp = ((double)mob_db[md->mob_class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
-		job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
-		if(mob_db[md->mob_class].job_exp > 0 && job_exp < 1) job_exp = 1;
-		if(job_exp < 0) job_exp = 0;
-*/
-//eAthena's exp formula rather than jAthena's
-//      per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
-            // [Fate] The above is the old formula.  We do a more involved computation below.
-            per = (double) md->dmglog[i].dmg * 256 / (double) max_hp;   // 256 = 100% of the score
-            per *= damage_bonus_factor[count > DAMAGE_BONUS_COUNT ? DAMAGE_BONUS_COUNT : count];    // Bonus for party attack
-            if (per > 512)
-                per = 512;      // [Fate] Retained from before.  The maximum a single individual can get is double the original value.
-            if (per < 1)
-                per = 1;
-
-            base_exp =
-                ((mob_db[md->mob_class].base_exp *
-                  md->stats[MOB_XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256;
-            if (base_exp < 1)
-                base_exp = 1;
-            if (sd && md && battle_config.pk_mode == 1
-                && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
-            {
-                base_exp *= 1.15;   // pk_mode additional exp if monster >20 levels [Valaris]
-            }
-            if (md->state.special_mob_ai >= 1
-                && battle_config.alchemist_summon_reward != 1)
-                base_exp = 0;   // Added [Valaris]
-            job_exp = mob_db[md->mob_class].job_exp * per / 256;
-            if (job_exp < 1)
-                job_exp = 1;
-            if (sd && md && battle_config.pk_mode == 1
-                && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
-            {
-                job_exp *= 1.15;    // pk_mode additional exp if monster >20 levels [Valaris]
-            }
-            if (md->state.special_mob_ai >= 1
-                && battle_config.alchemist_summon_reward != 1)
-                job_exp = 0;    // Added [Valaris]
-
-            if ((pid = tmpsd[i]->status.party_id) > 0)
-            {                   // パーティに入っている
-                int  j = 0;
-                for (j = 0; j < pnum; j++)  // 公平パーティリストにいるかどうか
-                    if (pt[j].id == pid)
-                        break;
-                if (j == pnum)
-                {               // いないときは公平かどうか確認
-                    if ((p = party_search (pid)) != NULL && p->exp != 0)
-                    {
-                        pt[pnum].id = pid;
-                        pt[pnum].p = p;
-                        pt[pnum].base_exp = base_exp;
-                        pt[pnum].job_exp = job_exp;
-                        pnum++;
-                        flag = 0;
-                    }
-                }
-                else
-                {               // いるときは公平
-                    pt[j].base_exp += base_exp;
-                    pt[j].job_exp += job_exp;
-                    flag = 0;
-                }
-            }
-            if (flag)           // 各自所得
-                pc_gainexp (tmpsd[i], base_exp, job_exp);
-        }
-        // 公平分配
-        for (i = 0; i < pnum; i++)
-            party_exp_share (pt[i].p, md->bl.m, pt[i].base_exp,
-                             pt[i].job_exp);
-
-        // item drop
-        if (!(type & 1))
-        {
-            for (i = 0; i < 8; i++)
-            {
-                struct delay_item_drop *ditem;
-                int  drop_rate;
-
-                if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)    // Added [Valaris]
-                    break;      // End
-
-                if (mob_db[md->mob_class].dropitem[i].nameid <= 0)
-                    continue;
-                drop_rate = mob_db[md->mob_class].dropitem[i].p;
-                if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
-                    drop_rate = 1;
-                if (battle_config.drops_by_luk > 0 && sd && md)
-                    drop_rate += (sd->status.luk * battle_config.drops_by_luk) / 100;   // drops affected by luk [Valaris]
-                if (sd && md && battle_config.pk_mode == 1
-                    && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
-                    drop_rate *= 1.25;  // pk_mode increase drops if 20 level difference [Valaris]
-                if (drop_rate <= MRAND (10000))
-                    continue;
-
-                ditem = (struct delay_item_drop *)
-                    calloc (1, sizeof (struct delay_item_drop));
-                ditem->nameid = mob_db[md->mob_class].dropitem[i].nameid;
-                ditem->amount = 1;
-                ditem->m = md->bl.m;
-                ditem->x = md->bl.x;
-                ditem->y = md->bl.y;
-                ditem->first_sd = mvp_sd;
-                ditem->second_sd = second_sd;
-                ditem->third_sd = third_sd;
-                add_timer (tick + 500 + i, mob_delay_item_drop, (int) ditem, 0);
-            }
-            if (sd && sd->state.attack_type == BF_WEAPON)
-            {
-                for (i = 0; i < sd->monster_drop_item_count; i++)
-                {
-                    struct delay_item_drop *ditem;
-                    int  race = battle_get_race (&md->bl);
-                    if (sd->monster_drop_itemid[i] <= 0)
-                        continue;
-                    if (sd->monster_drop_race[i] & (1 << race) ||
-                        (mob_db[md->mob_class].mode & 0x20
-                         && sd->monster_drop_race[i] & 1 << 10)
-                        || (!(mob_db[md->mob_class].mode & 0x20)
-                            && sd->monster_drop_race[i] & 1 << 11))
-                    {
-                        if (sd->monster_drop_itemrate[i] <= MRAND (10000))
-                            continue;
-
-                        ditem = (struct delay_item_drop *)
-                            calloc (1, sizeof (struct delay_item_drop));
-                        ditem->nameid = sd->monster_drop_itemid[i];
-                        ditem->amount = 1;
-                        ditem->m = md->bl.m;
-                        ditem->x = md->bl.x;
-                        ditem->y = md->bl.y;
-                        ditem->first_sd = mvp_sd;
-                        ditem->second_sd = second_sd;
-                        ditem->third_sd = third_sd;
-                        add_timer (tick + 520 + i, mob_delay_item_drop,
-                                   (int) ditem, 0);
-                    }
-                }
-                if (sd->get_zeny_num > 0)
-                    pc_getzeny (sd,
-                                mob_db[md->mob_class].lv * 10 +
-                                MRAND ((sd->get_zeny_num + 1)));
-            }
-            if (md->lootitem)
-            {
-                for (i = 0; i < md->lootitem_count; i++)
-                {
-                    struct delay_item_drop2 *ditem;
-
-                    ditem = (struct delay_item_drop2 *)
-                        calloc (1, sizeof (struct delay_item_drop2));
-                    memcpy (&ditem->item_data, &md->lootitem[i],
-                            sizeof (md->lootitem[0]));
-                    ditem->m = md->bl.m;
-                    ditem->x = md->bl.x;
-                    ditem->y = md->bl.y;
-                    ditem->first_sd = mvp_sd;
-                    ditem->second_sd = second_sd;
-                    ditem->third_sd = third_sd;
-                    add_timer (tick + 540 + i, mob_delay_item_drop2,
-                               (int) ditem, 0);
-                }
-            }
-        }
-
-        // mvp処理
-        if (mvp_sd && mob_db[md->mob_class].mexp > 0)
-        {
-            int  j;
-            int  mexp = battle_get_mexp (&md->bl);
-            temp =
-                ((double) mexp * (double) battle_config.mvp_exp_rate *
-                 (9. + (double) count) / 1000.);
-            mexp = (temp > 2147483647.) ? 0x7fffffff : (int) temp;
-            if (mexp < 1)
-                mexp = 1;
-            clif_mvp_effect (mvp_sd);   // エフェクト
-            clif_mvp_exp (mvp_sd, mexp);
-            pc_gainexp (mvp_sd, mexp, 0);
-            for (j = 0; j < 3; j++)
-            {
-                i = MRAND (3);
-                if (mob_db[md->mob_class].mvpitem[i].nameid <= 0)
-                    continue;
-                drop_rate = mob_db[md->mob_class].mvpitem[i].p;
-                if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
-                    drop_rate = 1;
-                if (drop_rate < battle_config.item_drop_mvp_min)
-                    drop_rate = battle_config.item_drop_mvp_min;
-                if (drop_rate > battle_config.item_drop_mvp_max)
-                    drop_rate = battle_config.item_drop_mvp_max;
-                if (drop_rate <= MRAND (10000))
-                    continue;
-                memset (&item, 0, sizeof (item));
-                item.nameid = mob_db[md->mob_class].mvpitem[i].nameid;
-                item.identify = !itemdb_isequip3 (item.nameid);
-                clif_mvp_item (mvp_sd, item.nameid);
-                if (mvp_sd->weight * 2 > mvp_sd->max_weight)
-                    map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
-                                      mvp_sd->bl.y, mvp_sd, second_sd,
-                                      third_sd, 1);
-                else if ((ret = pc_additem (mvp_sd, &item, 1)))
-                {
-                    clif_additem (sd, 0, 0, ret);
-                    map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
-                                      mvp_sd->bl.y, mvp_sd, second_sd,
-                                      third_sd, 1);
-                }
-                break;
-            }
-        }
-
-    }                           // [MouseJstr]
-
-    // <Agit> NPC Event [OnAgitBreak]
-    if (md->npc_event[0]
-        && strcmp (((md->npc_event) + strlen (md->npc_event) - 13),
-                   "::OnAgitBreak") == 0)
-    {
-        printf ("MOB.C: Run NPC_Event[OnAgitBreak].\n");
-        if (agit_flag == 1)     //Call to Run NPC_Event[OnAgitBreak]
-            guild_agit_break (md);
-    }
-
-    // SCRIPT実行
-    if (md->npc_event[0])
-    {
-        if (sd == NULL)
-        {
-            if (mvp_sd != NULL)
-                sd = mvp_sd;
-            else
-            {
-                struct map_session_data *tmpsd;
-                int  i;
-                for (i = 0; i < fd_max; i++)
-                {
-                    if (session[i] && (tmpsd = (struct map_session_data *)session[i]->session_data)
-                        && tmpsd->state.auth)
-                    {
-                        if (md->bl.m == tmpsd->bl.m)
-                        {
-                            sd = tmpsd;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        if (sd)
-            npc_event (sd, md->npc_event, 0);
-    }
-
-    clif_clearchar_area (&md->bl, 1);
-    map_delblock (&md->bl);
-    if (mob_get_viewclass (md->mob_class) <= 1000)
-        clif_clearchar_delay (tick + 3000, &md->bl, 0);
-    mob_deleteslave (md);
-    mob_setdelayspawn (md->bl.id);
-    map_freeblock_unlock ();
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int mob_class_change (struct mob_data *md, int *value)
-{
-    unsigned int tick = gettick ();
-    int  i, c, hp_rate, max_hp, mob_class, count = 0;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, value);
-
-    if (value[0] <= 1000 || value[0] > 2000)
-        return 0;
-    if (md->bl.prev == NULL)
-        return 0;
-
-    while (count < 5 && value[count] > 1000 && value[count] <= 2000)
-        count++;
-    if (count < 1)
-        return 0;
-
-    mob_class = value[MRAND (count)];
-    if (mob_class <= 1000 || mob_class > 2000)
-        return 0;
-
-    max_hp = battle_get_max_hp (&md->bl);
-    hp_rate = md->hp * 100 / max_hp;
-    clif_mob_class_change (md, mob_class);
-    md->mob_class = mob_class;
-    max_hp = battle_get_max_hp (&md->bl);
-    if (battle_config.monster_class_change_full_recover == 1)
-    {
-        md->hp = max_hp;
-        memset (md->dmglog, 0, sizeof (md->dmglog));
-    }
-    else
-        md->hp = max_hp * hp_rate / 100;
-    if (md->hp > max_hp)
-        md->hp = max_hp;
-    else if (md->hp < 1)
-        md->hp = 1;
-
-    memcpy (md->name, mob_db[mob_class].jname, 24);
-    memset (&md->state, 0, sizeof (md->state));
-    md->attacked_id = 0;
-    md->target_id = 0;
-    md->move_fail_count = 0;
-
-    md->stats[MOB_SPEED] = mob_db[md->mob_class].speed;
-    md->def_ele = mob_db[md->mob_class].element;
-
-    mob_changestate (md, MS_IDLE, 0);
-    skill_castcancel (&md->bl, 0);
-    md->state.skillstate = MSS_IDLE;
-    md->last_thinktime = tick;
-    md->next_walktime = tick + MPRAND (5000, 50);
-    md->attackabletime = tick;
-    md->canmove_tick = tick;
-    md->sg_count = 0;
-
-    for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
-        md->skilldelay[i] = c;
-    md->skillid = 0;
-    md->skilllv = 0;
-
-    if (md->lootitem == NULL && mob_db[mob_class].mode & 0x02)
-        md->lootitem = (struct item *)
-            calloc (LOOTITEM_SIZE, sizeof (struct item));
-
-    skill_clear_unitgroup (&md->bl);
-    skill_cleartimerskill (&md->bl);
-
-    clif_clearchar_area (&md->bl, 0);
-    clif_spawnmob (md);
-
-    return 0;
-}
-
-/*==========================================
- * mob回復
- *------------------------------------------
- */
-int mob_heal (struct mob_data *md, int heal)
-{
-    int  max_hp = battle_get_max_hp (&md->bl);
-
-    nullpo_retr (0, md);
-
-    md->hp += heal;
-    if (max_hp < md->hp)
-        md->hp = max_hp;
-
-    if (md->mob_class >= 1285 && md->mob_class <= 1287)
-    {                           // guardian hp update [Valaris]
-        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
-        if (gc)
-        {
-            if (md->bl.id == gc->GID0)
-                gc->Ghp0 = md->hp;
-            if (md->bl.id == gc->GID1)
-                gc->Ghp1 = md->hp;
-            if (md->bl.id == gc->GID2)
-                gc->Ghp2 = md->hp;
-            if (md->bl.id == gc->GID3)
-                gc->Ghp3 = md->hp;
-            if (md->bl.id == gc->GID4)
-                gc->Ghp4 = md->hp;
-            if (md->bl.id == gc->GID5)
-                gc->Ghp5 = md->hp;
-            if (md->bl.id == gc->GID6)
-                gc->Ghp6 = md->hp;
-            if (md->bl.id == gc->GID7)
-                gc->Ghp7 = md->hp;
-        }
-    }                           // end addition [Valaris]
-
-    return 0;
-}
-
-/*==========================================
- * Added by RoVeRT
- *------------------------------------------
- */
-int mob_warpslave_sub (struct block_list *bl, va_list ap)
-{
-    struct mob_data *md = (struct mob_data *) bl;
-    int  id, x, y;
-    id = va_arg (ap, int);
-    x = va_arg (ap, int);
-    y = va_arg (ap, int);
-    if (md->master_id == id)
-    {
-        mob_warp (md, -1, x, y, 2);
-    }
-    return 0;
-}
-
-/*==========================================
- * Added by RoVeRT
- *------------------------------------------
- */
-int mob_warpslave (struct mob_data *md, int x, int y)
-{
-//printf("warp slave\n");
-    map_foreachinarea (mob_warpslave_sub, md->bl.m,
-                       x - AREA_SIZE, y - AREA_SIZE,
-                       x + AREA_SIZE, y + AREA_SIZE, BL_MOB,
-                       md->bl.id, md->bl.x, md->bl.y);
-    return 0;
-}
-
-/*==========================================
- * mobワープ
- *------------------------------------------
- */
-int mob_warp (struct mob_data *md, int m, int x, int y, int type)
-{
-    int  i = 0, c, xs = 0, ys = 0, bx = x, by = y;
-
-    nullpo_retr (0, md);
-
-    if (md->bl.prev == NULL)
-        return 0;
-
-    if (m < 0)
-        m = md->bl.m;
-
-    if (type >= 0)
-    {
-        if (map[md->bl.m].flag.monster_noteleport)
-            return 0;
-        clif_clearchar_area (&md->bl, type);
-    }
-    skill_unit_out_all (&md->bl, gettick (), 1);
-    map_delblock (&md->bl);
-
-    if (bx > 0 && by > 0)
-    {                           // 位置指定の場合周囲9セルを探索
-        xs = ys = 9;
-    }
-
-    while ((x < 0 || y < 0 || ((c = read_gat (m, x, y)) == 1 || c == 5))
-           && (i++) < 1000)
-    {
-        if (xs > 0 && ys > 0 && i < 250)
-        {                       // 指定位置付近の探索
-            x = MPRAND (bx, xs) - xs / 2;
-            y = MPRAND (by, ys) - ys / 2;
-        }
-        else
-        {                       // 完全ランダム探索
-            x = MPRAND (1, (map[m].xs - 2));
-            y = MPRAND (1, (map[m].ys - 2));
-        }
-    }
-    md->dir = 0;
-    if (i < 1000)
-    {
-        md->bl.x = md->to_x = x;
-        md->bl.y = md->to_y = y;
-        md->bl.m = m;
-    }
-    else
-    {
-        m = md->bl.m;
-        if (battle_config.error_log == 1)
-            printf ("MOB %d warp failed, mob_class = %d\n", md->bl.id, md->mob_class);
-    }
-
-    md->target_id = 0;          // タゲを解除する
-    md->state.targettype = NONE_ATTACKABLE;
-    md->attacked_id = 0;
-    md->state.skillstate = MSS_IDLE;
-    mob_changestate (md, MS_IDLE, 0);
-
-    if (type > 0 && i == 1000)
-    {
-        if (battle_config.battle_log == 1)
-            printf ("MOB %d warp to (%d,%d), mob_class = %d\n", md->bl.id, x, y,
-                    md->mob_class);
-    }
-
-    map_addblock (&md->bl);
-    if (type > 0)
-    {
-        clif_spawnmob (md);
-        mob_warpslave (md, md->bl.x, md->bl.y);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 画面内の取り巻きの数計算用(foreachinarea)
- *------------------------------------------
- */
-int mob_countslave_sub (struct block_list *bl, va_list ap)
-{
-    int  id, *c;
-    struct mob_data *md;
-
-    id = va_arg (ap, int);
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, c = va_arg (ap, int *));
-    nullpo_retr (0, md = (struct mob_data *) bl);
-
-    if (md->master_id == id)
-        (*c)++;
-    return 0;
-}
-
-/*==========================================
- * 画面内の取り巻きの数計算
- *------------------------------------------
- */
-int mob_countslave (struct mob_data *md)
-{
-    int  c = 0;
-
-    nullpo_retr (0, md);
-
-    map_foreachinarea (mob_countslave_sub, md->bl.m,
-                       0, 0, map[md->bl.m].xs - 1, map[md->bl.m].ys - 1,
-                       BL_MOB, md->bl.id, &c);
-    return c;
-}
-
-/*==========================================
- * 手下MOB召喚
- *------------------------------------------
- */
-int mob_summonslave (struct mob_data *md2, int *value, int amount, int flag)
-{
-    struct mob_data *md;
-    int  bx, by, m, count = 0, mob_class, k, a = amount;
-
-    nullpo_retr (0, md2);
-    nullpo_retr (0, value);
-
-    bx = md2->bl.x;
-    by = md2->bl.y;
-    m = md2->bl.m;
-
-    if (value[0] <= 1000 || value[0] > 2000)    // 値が異常なら召喚を止める
-        return 0;
-    while (count < 5 && value[count] > 1000 && value[count] <= 2000)
-        count++;
-    if (count < 1)
-        return 0;
-
-    for (k = 0; k < count; k++)
-    {
-        amount = a;
-        mob_class = value[k];
-        if (mob_class <= 1000 || mob_class > 2000)
-            continue;
-        for (; amount > 0; amount--)
-        {
-            int  x = 0, y = 0, c = 0, i = 0;
-            md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
-            if (mob_db[mob_class].mode & 0x02)
-                md->lootitem = (struct item *)
-                    calloc (LOOTITEM_SIZE, sizeof (struct item));
-            else
-                md->lootitem = NULL;
-
-            while ((x <= 0 || y <= 0 || (c = map_getcell (m, x, y)) == 1
-                    || c == 5) && (i++) < 100)
-            {
-                x = MPRAND (bx, 9) - 4;
-                y = MPRAND (by, 9) - 4;
-            }
-            if (i >= 100)
-            {
-                x = bx;
-                y = by;
-            }
-
-            mob_spawn_dataset (md, "--ja--", mob_class);
-            md->bl.prev = NULL;
-            md->bl.next = NULL;
-            md->bl.m = m;
-            md->bl.x = x;
-            md->bl.y = y;
-
-            md->m = m;
-            md->x0 = x;
-            md->y0 = y;
-            md->xs = 0;
-            md->ys = 0;
-            md->stats[MOB_SPEED] = md2->stats[MOB_SPEED];
-            md->spawndelay1 = -1;   // 一度のみフラグ
-            md->spawndelay2 = -1;   // 一度のみフラグ
-
-            memset (md->npc_event, 0, sizeof (md->npc_event));
-            md->bl.type = BL_MOB;
-            map_addiddb (&md->bl);
-            mob_spawn (md->bl.id);
-            clif_skill_nodamage (&md->bl, &md->bl,
-                                 (flag) ? NPC_SUMMONSLAVE : NPC_SUMMONMONSTER,
-                                 a, 1);
-
-            if (flag)
-                md->master_id = md2->bl.id;
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * 自分をロックしているPCの数を数える(foreachclient)
- *------------------------------------------
- */
-static int mob_counttargeted_sub (struct block_list *bl, va_list ap)
-{
-    int  id, *c, target_lv;
-    struct block_list *src;
-
-    id = va_arg (ap, int);
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, c = va_arg (ap, int *));
-
-    src = va_arg (ap, struct block_list *);
-    target_lv = va_arg (ap, int);
-    if (id == bl->id || (src && id == src->id))
-        return 0;
-    if (bl->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) bl;
-        if (sd && sd->attacktarget == id && sd->attacktimer != -1
-            && sd->attacktarget_lv >= target_lv)
-            (*c)++;
-    }
-    else if (bl->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) bl;
-        if (md && md->target_id == id && md->timer != -1
-            && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
-            (*c)++;
-    }
-    return 0;
-}
-
-/*==========================================
- * 自分をロックしているPCの数を数える
- *------------------------------------------
- */
-int mob_counttargeted (struct mob_data *md, struct block_list *src,
-                       int target_lv)
-{
-    int  c = 0;
-
-    nullpo_retr (0, md);
-
-    map_foreachinarea (mob_counttargeted_sub, md->bl.m,
-                       md->bl.x - AREA_SIZE, md->bl.y - AREA_SIZE,
-                       md->bl.x + AREA_SIZE, md->bl.y + AREA_SIZE, 0,
-                       md->bl.id, &c, src, target_lv);
-    return c;
-}
-
-/*==========================================
- *MOBskillから該当skillidのskillidxを返す
- *------------------------------------------
- */
-int mob_skillid2skillidx (int mob_class, int skillid)
-{
-    int  i;
-    struct mob_skill *ms = mob_db[mob_class].skill;
-
-    if (ms == NULL)
-        return -1;
-
-    for (i = 0; i < mob_db[mob_class].maxskill; i++)
-    {
-        if (ms[i].skill_id == skillid)
-            return i;
-    }
-    return -1;
-
-}
-
-//
-// MOBスキル
-//
-
-/*==========================================
- * スキル使用(詠唱完了、ID指定)
- *------------------------------------------
- */
-void mobskill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct mob_data *md = NULL;
-    struct block_list *bl;
-    struct block_list *mbl;
-    int  range;
-
-    if ((mbl = map_id2bl (id)) == NULL) //詠唱したMobがもういないというのは良くある正常処理
-        return;
-    if ((md = (struct mob_data *) mbl) == NULL)
-    {
-        printf ("mobskill_castend_id nullpo mbl->id:%d\n", mbl->id);
-        return;
-    }
-    if (md->bl.type != BL_MOB || md->bl.prev == NULL)
-        return;
-    if (md->skilltimer != tid)  // タイマIDの確認
-        return;
-
-    md->skilltimer = -1;
-    //沈黙や状態異常など
-    if (md->sc_data)
-    {
-        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
-            || md->sc_data[SC_ROKISWEIL].timer != -1
-            || md->sc_data[SC_STEELBODY].timer != -1)
-            return;
-        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
-            return;
-        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
-            return;
-        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
-            return;
-    }
-    if (md->skillid != NPC_EMOTION)
-        md->last_thinktime = tick + battle_get_adelay (&md->bl);
-
-    if ((bl = map_id2bl (md->skilltarget)) == NULL || bl->prev == NULL)
-    {                           //スキルターゲットが存在しない
-        //printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
-        return;
-    }
-    if (md->bl.m != bl->m)
-        return;
-
-    if (md->skillid == PR_LEXAETERNA)
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        if (sc_data
-            && (sc_data[SC_FREEZE].timer != -1
-                || (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0)))
-            return;
-    }
-    else if (md->skillid == RG_BACKSTAP)
-    {
-        int  dir = map_calc_dir (&md->bl, bl->x, bl->y), t_dir =
-            battle_get_dir (bl);
-        int  dist = distance (md->bl.x, md->bl.y, bl->x, bl->y);
-        if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir)))
-            return;
-    }
-    if (((skill_get_inf (md->skillid) & 1) || (skill_get_inf2 (md->skillid) & 4)) &&    // 彼我敵対関係チェック
-        battle_check_target (&md->bl, bl, BCT_ENEMY) <= 0)
-        return;
-    range = skill_get_range (md->skillid, md->skilllv);
-    if (range < 0)
-        range = battle_get_range (&md->bl) - (range + 1);
-    if (range + battle_config.mob_skill_add_range <
-        distance (md->bl.x, md->bl.y, bl->x, bl->y))
-        return;
-
-    md->skilldelay[md->skillidx] = tick;
-
-    if (battle_config.mob_skill_log == 1)
-        printf ("MOB skill castend skill=%d, mob_class = %d\n", md->skillid,
-                md->mob_class);
-    mob_stop_walking (md, 0);
-
-    switch (skill_get_nk (md->skillid))
-    {
-            // 攻撃系/吹き飛ばし系
-        case 0:
-        case 2:
-            skill_castend_damage_id (&md->bl, bl, md->skillid, md->skilllv,
-                                     tick, 0);
-            break;
-        case 1:                // 支援系
-            if (!mob_db[md->mob_class].skill[md->skillidx].val[0] &&
-                (md->skillid == AL_HEAL
-                 || (md->skillid == ALL_RESURRECTION && bl->type != BL_PC))
-                && battle_check_undead (battle_get_race (bl),
-                                        battle_get_elem_type (bl)))
-                skill_castend_damage_id (&md->bl, bl, md->skillid,
-                                         md->skilllv, tick, 0);
-            else
-                skill_castend_nodamage_id (&md->bl, bl, md->skillid,
-                                           md->skilllv, tick, 0);
-            break;
-    }
-}
-
-/*==========================================
- * スキル使用(詠唱完了、場所指定)
- *------------------------------------------
- */
-void mobskill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct mob_data *md = NULL;
-    struct block_list *bl;
-    int  range, maxcount;
-
-    //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
-    if ((bl = map_id2bl (id)) == NULL)
-        return;
-
-    nullpo_retv (md = (struct mob_data *) bl);
-
-    if (md->bl.type != BL_MOB || md->bl.prev == NULL)
-        return;
-
-    if (md->skilltimer != tid)  // タイマIDの確認
-        return;
-
-    md->skilltimer = -1;
-    if (md->sc_data)
-    {
-        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
-            || md->sc_data[SC_ROKISWEIL].timer != -1
-            || md->sc_data[SC_STEELBODY].timer != -1)
-            return;
-        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
-            return;
-        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
-            return;
-        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
-            return;
-    }
-
-    if (battle_config.monster_skill_reiteration == 0)
-    {
-        range = -1;
-        switch (md->skillid)
-        {
-            case MG_SAFETYWALL:
-            case WZ_FIREPILLAR:
-            case HT_SKIDTRAP:
-            case HT_LANDMINE:
-            case HT_ANKLESNARE:
-            case HT_SHOCKWAVE:
-            case HT_SANDMAN:
-            case HT_FLASHER:
-            case HT_FREEZINGTRAP:
-            case HT_BLASTMINE:
-            case HT_CLAYMORETRAP:
-            case PF_SPIDERWEB: /* スパイダーウェッブ */
-                range = 0;
-                break;
-            case AL_PNEUMA:
-            case AL_WARP:
-                range = 1;
-                break;
-        }
-        if (range >= 0)
-        {
-            if (skill_check_unit_range
-                (md->bl.m, md->skillx, md->skilly, range, md->skillid) > 0)
-                return;
-        }
-    }
-    if (battle_config.monster_skill_nofootset == 1)
-    {
-        range = -1;
-        switch (md->skillid)
-        {
-            case WZ_FIREPILLAR:
-            case HT_SKIDTRAP:
-            case HT_LANDMINE:
-            case HT_ANKLESNARE:
-            case HT_SHOCKWAVE:
-            case HT_SANDMAN:
-            case HT_FLASHER:
-            case HT_FREEZINGTRAP:
-            case HT_BLASTMINE:
-            case HT_CLAYMORETRAP:
-            case AM_DEMONSTRATION:
-            case PF_SPIDERWEB: /* スパイダーウェッブ */
-                range = 1;
-                break;
-            case AL_WARP:
-                range = 0;
-                break;
-        }
-        if (range >= 0)
-        {
-            if (skill_check_unit_range2
-                (md->bl.m, md->skillx, md->skilly, range) > 0)
-                return;
-        }
-    }
-
-    if (battle_config.monster_land_skill_limit == 1)
-    {
-        maxcount = skill_get_maxcount (md->skillid);
-        if (maxcount > 0)
-        {
-            int  i, c;
-            for (i = c = 0; i < MAX_MOBSKILLUNITGROUP; i++)
-            {
-                if (md->skillunit[i].alive_count > 0
-                    && md->skillunit[i].skill_id == md->skillid)
-                    c++;
-            }
-            if (c >= maxcount)
-                return;
-        }
-    }
-
-    range = skill_get_range (md->skillid, md->skilllv);
-    if (range < 0)
-        range = battle_get_range (&md->bl) - (range + 1);
-    if (range + battle_config.mob_skill_add_range <
-        distance (md->bl.x, md->bl.y, md->skillx, md->skilly))
-        return;
-    md->skilldelay[md->skillidx] = tick;
-
-    if (battle_config.mob_skill_log == 1)
-        printf ("MOB skill castend skill=%d, mob_class = %d\n", md->skillid,
-                md->mob_class);
-    mob_stop_walking (md, 0);
-
-    skill_castend_pos2 (&md->bl, md->skillx, md->skilly, md->skillid,
-                        md->skilllv, tick, 0);
-
-    return;
-}
-
-/*==========================================
- * Skill use (an aria start, ID specification)
- *------------------------------------------
- */
-int mobskill_use_id (struct mob_data *md, struct block_list *target,
-                     int skill_idx)
-{
-    int  casttime, range;
-    struct mob_skill *ms;
-    int  skill_id, skill_lv, forcecast = 0;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, ms = &mob_db[md->mob_class].skill[skill_idx]);
-
-    if (target == NULL && (target = map_id2bl (md->target_id)) == NULL)
-        return 0;
-
-    if (target->prev == NULL || md->bl.prev == NULL)
-        return 0;
-
-    skill_id = ms->skill_id;
-    skill_lv = ms->skill_lv;
-
-    // 沈黙や異常
-    if (md->sc_data)
-    {
-        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
-            || md->sc_data[SC_ROKISWEIL].timer != -1
-            || md->sc_data[SC_STEELBODY].timer != -1)
-            return 0;
-        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
-            return 0;
-        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
-            return 0;
-        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
-            return 0;
-    }
-
-    if (md->option & 4 && skill_id == TF_HIDING)
-        return 0;
-    if (md->option & 2 && skill_id != TF_HIDING && skill_id != AS_GRIMTOOTH
-        && skill_id != RG_BACKSTAP && skill_id != RG_RAID)
-        return 0;
-
-    if (map[md->bl.m].flag.gvg
-        && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
-            || skill_id == AL_WARP || skill_id == WZ_ICEWALL
-            || skill_id == TF_BACKSLIDING))
-        return 0;
-
-    if (skill_get_inf2 (skill_id) & 0x200 && md->bl.id == target->id)
-        return 0;
-
-    // 射程と障害物チェック
-    range = skill_get_range (skill_id, skill_lv);
-    if (range < 0)
-        range = battle_get_range (&md->bl) - (range + 1);
-
-    if (!battle_check_range (&md->bl, target, range))
-        return 0;
-
-//  delay=skill_delayfix(&md->bl, skill_get_delay( skill_id,skill_lv) );
-
-    casttime = skill_castfix (&md->bl, ms->casttime);
-    md->state.skillcastcancel = ms->cancel;
-    md->skilldelay[skill_idx] = gettick ();
-
-    switch (skill_id)
-    {                           /* 何か特殊な処理が必要 */
-        case ALL_RESURRECTION: /* リザレクション */
-            if (target->type != BL_PC
-                && battle_check_undead (battle_get_race (target),
-                                        battle_get_elem_type (target)))
-            {                   /* 敵がアンデッドなら */
-                forcecast = 1;  /* ターンアンデットと同じ詠唱時間 */
-                casttime =
-                    skill_castfix (&md->bl,
-                                   skill_get_cast (PR_TURNUNDEAD, skill_lv));
-            }
-            break;
-        case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */
-        case SA_MAGICROD:
-        case SA_SPELLBREAKER:
-            forcecast = 1;
-            break;
-    }
-
-    if (battle_config.mob_skill_log == 1)
-        printf
-            ("MOB skill use target_id=%d skill=%d lv=%d cast=%d, mob_class = %d\n",
-             target->id, skill_id, skill_lv, casttime, md->mob_class);
-
-    if (casttime > 0 || forcecast)
-    {                           // 詠唱が必要
-//      struct mob_data *md2;
-        clif_skillcasting (&md->bl,
-                           md->bl.id, target->id, 0, 0, skill_id, casttime);
-
-        // 詠唱反応モンスター
-/*		if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->mob_class].mode&0x10 &&
-			md2->state.state!=MS_ATTACK){
-				md2->target_id=md->bl.id;
-				md->state.targettype = ATTACKABLE;
-				md2->min_chase=13;
-		}*/
-    }
-
-    if (casttime <= 0)          // 詠唱の無いものはキャンセルされない
-        md->state.skillcastcancel = 0;
-
-    md->skilltarget = target->id;
-    md->skillx = 0;
-    md->skilly = 0;
-    md->skillid = skill_id;
-    md->skilllv = skill_lv;
-    md->skillidx = skill_idx;
-
-    if (!(battle_config.monster_cloak_check_type & 2)
-        && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
-        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
-
-    if (casttime > 0)
-    {
-        md->skilltimer =
-            add_timer (gettick () + casttime, mobskill_castend_id, md->bl.id,
-                       0);
-    }
-    else
-    {
-        md->skilltimer = -1;
-        mobskill_castend_id (md->skilltimer, gettick (), md->bl.id, 0);
-    }
-
-    return 1;
-}
-
-/*==========================================
- * スキル使用(場所指定)
- *------------------------------------------
- */
-int mobskill_use_pos (struct mob_data *md,
-                      int skill_x, int skill_y, int skill_idx)
-{
-    int  casttime = 0, range;
-    struct mob_skill *ms;
-    struct block_list bl;
-    int  skill_id, skill_lv;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, ms = &mob_db[md->mob_class].skill[skill_idx]);
-
-    if (md->bl.prev == NULL)
-        return 0;
-
-    skill_id = ms->skill_id;
-    skill_lv = ms->skill_lv;
-
-    //沈黙や状態異常など
-    if (md->sc_data)
-    {
-        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
-            || md->sc_data[SC_ROKISWEIL].timer != -1
-            || md->sc_data[SC_STEELBODY].timer != -1)
-            return 0;
-        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
-            return 0;
-        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
-            return 0;
-        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
-            return 0;
-    }
-
-    if (md->option & 2)
-        return 0;
-
-    if (map[md->bl.m].flag.gvg
-        && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
-            || skill_id == AL_WARP || skill_id == WZ_ICEWALL
-            || skill_id == TF_BACKSLIDING))
-        return 0;
-
-    // 射程と障害物チェック
-    bl.type = BL_NUL;
-    bl.m = md->bl.m;
-    bl.x = skill_x;
-    bl.y = skill_y;
-    range = skill_get_range (skill_id, skill_lv);
-    if (range < 0)
-        range = battle_get_range (&md->bl) - (range + 1);
-    if (!battle_check_range (&md->bl, &bl, range))
-        return 0;
-
-//  delay=skill_delayfix(&sd->bl, skill_get_delay( skill_id,skill_lv) );
-    casttime = skill_castfix (&md->bl, ms->casttime);
-    md->skilldelay[skill_idx] = gettick ();
-    md->state.skillcastcancel = ms->cancel;
-
-    if (battle_config.mob_skill_log == 1)
-        printf
-            ("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, mob_class = %d\n",
-             skill_x, skill_y, skill_id, skill_lv, casttime, md->mob_class);
-
-    if (casttime > 0)           // A cast time is required.
-        clif_skillcasting (&md->bl,
-                           md->bl.id, 0, skill_x, skill_y, skill_id,
-                           casttime);
-
-    if (casttime <= 0)          // A skill without a cast time wont be cancelled.
-        md->state.skillcastcancel = 0;
-
-    md->skillx = skill_x;
-    md->skilly = skill_y;
-    md->skilltarget = 0;
-    md->skillid = skill_id;
-    md->skilllv = skill_lv;
-    md->skillidx = skill_idx;
-    if (!(battle_config.monster_cloak_check_type & 2)
-        && md->sc_data[SC_CLOAKING].timer != -1)
-        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
-    if (casttime > 0)
-    {
-        md->skilltimer =
-            add_timer (gettick () + casttime, mobskill_castend_pos, md->bl.id,
-                       0);
-    }
-    else
-    {
-        md->skilltimer = -1;
-        mobskill_castend_pos (md->skilltimer, gettick (), md->bl.id, 0);
-    }
-
-    return 1;
-}
-
-/*==========================================
- * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
- *------------------------------------------
- */
-int mob_getfriendhpltmaxrate_sub (struct block_list *bl, va_list ap)
-{
-    int  rate;
-    struct mob_data **fr, *md, *mmd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
-
-    md = (struct mob_data *) bl;
-
-    if (mmd->bl.id == bl->id)
-        return 0;
-    rate = va_arg (ap, int);
-    fr = va_arg (ap, struct mob_data **);
-    if (md->hp < mob_db[md->mob_class].max_hp * rate / 100)
-        (*fr) = md;
-    return 0;
-}
-
-struct mob_data *mob_getfriendhpltmaxrate (struct mob_data *md, int rate)
-{
-    struct mob_data *fr = NULL;
-    const int r = 8;
-
-    nullpo_retr (NULL, md);
-
-    map_foreachinarea (mob_getfriendhpltmaxrate_sub, md->bl.m,
-                       md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
-                       BL_MOB, md, rate, &fr);
-    return fr;
-}
-
-/*==========================================
- * What a status state suits by nearby MOB is looked for.
- *------------------------------------------
- */
-int mob_getfriendstatus_sub (struct block_list *bl, va_list ap)
-{
-    int  cond1, cond2;
-    struct mob_data **fr, *md, *mmd;
-    int  flag = 0;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = (struct mob_data *) bl);
-    nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
-
-    if (mmd->bl.id == bl->id)
-        return 0;
-    cond1 = va_arg (ap, int);
-    cond2 = va_arg (ap, int);
-    fr = va_arg (ap, struct mob_data **);
-    if (cond2 == -1)
-    {
-        int  j;
-        for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
-        {
-            flag = (md->sc_data[j].timer != -1);
-        }
-    }
-    else
-        flag = (md->sc_data[cond2].timer != -1);
-    if (flag ^ (cond1 == MSC_FRIENDSTATUSOFF))
-        (*fr) = md;
-
-    return 0;
-}
-
-struct mob_data *mob_getfriendstatus (struct mob_data *md, int cond1,
-                                      int cond2)
-{
-    struct mob_data *fr = NULL;
-    const int r = 8;
-
-    nullpo_retr (0, md);
-
-    map_foreachinarea (mob_getfriendstatus_sub, md->bl.m,
-                       md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
-                       BL_MOB, md, cond1, cond2, &fr);
-    return fr;
-}
-
-/*==========================================
- * Skill use judging
- *------------------------------------------
- */
-int mobskill_use (struct mob_data *md, unsigned int tick, int event)
-{
-    struct mob_skill *ms;
-//  struct block_list *target=NULL;
-    int  i, max_hp;
-
-    nullpo_retr (0, md);
-    nullpo_retr (0, ms = mob_db[md->mob_class].skill);
-
-    max_hp = battle_get_max_hp (&md->bl);
-
-    if (battle_config.mob_skill_use == 0 || md->skilltimer != -1)
-        return 0;
-
-    if (md->state.special_mob_ai)
-        return 0;
-
-    if (md->sc_data[SC_SELFDESTRUCTION].timer != -1)    //自爆中はスキルを使わない
-        return 0;
-
-    for (i = 0; i < mob_db[md->mob_class].maxskill; i++)
-    {
-        int  c2 = ms[i].cond2, flag = 0;
-        struct mob_data *fmd = NULL;
-
-        // ディレイ中
-        if (DIFF_TICK (tick, md->skilldelay[i]) < ms[i].delay)
-            continue;
-
-        // 状態判定
-        if (ms[i].state >= 0 && ms[i].state != md->state.skillstate)
-            continue;
-
-        // 条件判定
-        flag = (event == ms[i].cond1);
-        if (!flag)
-        {
-            switch (ms[i].cond1)
-            {
-                case MSC_ALWAYS:
-                    flag = 1;
-                    break;
-                case MSC_MYHPLTMAXRATE:    // HP< maxhp%
-                    flag = (md->hp < max_hp * c2 / 100);
-                    break;
-                case MSC_MYSTATUSON:   // status[num] on
-                case MSC_MYSTATUSOFF:  // status[num] off
-                    if (ms[i].cond2 == -1)
-                    {
-                        int  j;
-                        for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
-                        {
-                            flag = (md->sc_data[j].timer != -1);
-                        }
-                    }
-                    else
-                        flag = (md->sc_data[ms[i].cond2].timer != -1);
-                    flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF);
-                    break;
-                case MSC_FRIENDHPLTMAXRATE:    // friend HP < maxhp%
-                    flag =
-                        ((fmd =
-                          mob_getfriendhpltmaxrate (md,
-                                                    ms[i].cond2)) != NULL);
-                    break;
-                case MSC_FRIENDSTATUSON:   // friend status[num] on
-                case MSC_FRIENDSTATUSOFF:  // friend status[num] off
-                    flag =
-                        ((fmd =
-                          mob_getfriendstatus (md, ms[i].cond1,
-                                               ms[i].cond2)) != NULL);
-                    break;
-                case MSC_NOTINTOWN:     // Only outside of towns.
-                    flag = !map[md->bl.m].flag.town;
-                    break;
-                case MSC_SLAVELT:  // slave < num
-                    flag = (mob_countslave (md) < c2);
-                    break;
-                case MSC_ATTACKPCGT:   // attack pc > num
-                    flag = (mob_counttargeted (md, NULL, 0) > c2);
-                    break;
-                case MSC_SLAVELE:  // slave <= num
-                    flag = (mob_countslave (md) <= c2);
-                    break;
-                case MSC_ATTACKPCGE:   // attack pc >= num
-                    flag = (mob_counttargeted (md, NULL, 0) >= c2);
-                    break;
-                case MSC_SKILLUSED:    // specificated skill used
-                    flag = ((event & 0xffff) == MSC_SKILLUSED
-                            && ((event >> 16) == c2 || c2 == 0));
-                    break;
-            }
-        }
-
-        // 確率判定
-        if (flag && MRAND (10000) < ms[i].permillage)
-        {
-
-            if (skill_get_inf (ms[i].skill_id) & 2)
-            {
-                // 場所指定
-                struct block_list *bl = NULL;
-                int  x = 0, y = 0;
-                if (ms[i].target <= MST_AROUND)
-                {
-                    if (ms[i].target == MST_MASTER)
-                    {
-                        bl = &md->bl;
-                        if (md->master_id)
-                            bl = map_id2bl (md->master_id);
-                    }
-                    else
-                    {
-                        bl = ((ms[i].target == MST_TARGET
-                               || ms[i].target ==
-                               MST_AROUND5) ? map_id2bl (md->
-                                                         target_id)
-                              : (ms[i].target ==
-                                 MST_FRIEND) ? &fmd->bl : &md->bl);
-                    }
-
-                    if (bl)
-                    {
-                        x = bl->x;
-                        y = bl->y;
-                    }
-                }
-                if (x <= 0 || y <= 0)
-                    continue;
-                // 自分の周囲
-                if (ms[i].target >= MST_AROUND1)
-                {
-                    int  bx = x, by = y, i = 0, c, m = bl->m, r =
-                        ms[i].target - MST_AROUND1;
-                    do
-                    {
-                        bx = x + MRAND ((r * 2 + 3)) - r;
-                        by = y + MRAND ((r * 2 + 3)) - r;
-                    }
-                    while ((bx <= 0 || by <= 0 || bx >= map[m].xs
-                            || by >= map[m].ys
-                            || ((c = read_gat (m, bx, by)) == 1 || c == 5))
-                           && (i++) < 1000);
-                    if (i < 1000)
-                    {
-                        x = bx;
-                        y = by;
-                    }
-                }
-                // 相手の周囲
-                if (ms[i].target >= MST_AROUND5)
-                {
-                    int  bx = x, by = y, i = 0, c, m = bl->m, r =
-                        (ms[i].target - MST_AROUND5) + 1;
-                    do
-                    {
-                        bx = x + MRAND ((r * 2 + 1)) - r;
-                        by = y + MRAND ((r * 2 + 1)) - r;
-                    }
-                    while ((bx <= 0 || by <= 0 || bx >= map[m].xs
-                            || by >= map[m].ys
-                            || ((c = read_gat (m, bx, by)) == 1 || c == 5))
-                           && (i++) < 1000);
-                    if (i < 1000)
-                    {
-                        x = bx;
-                        y = by;
-                    }
-                }
-                if (!mobskill_use_pos (md, x, y, i))
-                    return 0;
-
-            }
-            else
-            {
-                if (ms[i].target == MST_MASTER)
-                {
-                    struct block_list *bl = &md->bl;
-                    if (md->master_id)
-                        bl = map_id2bl (md->master_id);
-
-                    if (bl && !mobskill_use_id (md, bl, i))
-                        return 0;
-                }
-                // ID指定
-                if (ms[i].target <= MST_FRIEND)
-                {
-                    struct block_list *bl = NULL;
-                    bl = ((ms[i].target ==
-                           MST_TARGET) ? map_id2bl (md->
-                                                    target_id) : (ms[i].target
-                                                                  ==
-                                                                  MST_FRIEND)
-                          ? &fmd->bl : &md->bl);
-                    if (bl && !mobskill_use_id (md, bl, i))
-                        return 0;
-                }
-            }
-            if (ms[i].emotion >= 0)
-                clif_emotion (&md->bl, ms[i].emotion);
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Skill use event processing
- *------------------------------------------
- */
-int mobskill_event (struct mob_data *md, int flag)
-{
-    nullpo_retr (0, md);
-
-    if (flag == -1 && mobskill_use (md, gettick (), MSC_CASTTARGETED))
-        return 1;
-    if ((flag & BF_SHORT)
-        && mobskill_use (md, gettick (), MSC_CLOSEDATTACKED))
-        return 1;
-    if ((flag & BF_LONG)
-        && mobskill_use (md, gettick (), MSC_LONGRANGEATTACKED))
-        return 1;
-    return 0;
-}
-
-/*==========================================
- * Mobがエンペリウムなどの場合の判定
- *------------------------------------------
- */
-int mob_gvmobcheck (struct map_session_data *sd, struct block_list *bl)
-{
-    struct mob_data *md = NULL;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_MOB && (md = (struct mob_data *) bl) &&
-        (md->mob_class == 1288 || md->mob_class == 1287 || md->mob_class == 1286
-         || md->mob_class == 1285))
-    {
-        struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
-        struct guild *g = guild_search (sd->status.guild_id);
-
-        if (g == NULL && md->mob_class == 1288)
-            return 0;           //ギルド未加入ならダメージ無し
-        else if (gc != NULL && !map[sd->bl.m].flag.gvg)
-            return 0;           //砦内でGvじゃないときはダメージなし
-        else if (g && gc != NULL && g->guild_id == gc->guild_id)
-            return 0;           //自占領ギルドのエンペならダメージ無し
-        else if (g && guild_checkskill (g, GD_APPROVAL) <= 0
-                 && md->mob_class == 1288)
-            return 0;           //正規ギルド承認がないとダメージ無し
-
-    }
-
-    return 1;
-}
-
-/*==========================================
- * スキル用タイマー削除
- *------------------------------------------
- */
-int mobskill_deltimer (struct mob_data *md)
-{
-    nullpo_retr (0, md);
-
-    if (md->skilltimer != -1)
-    {
-        if (skill_get_inf (md->skillid) & 2)
-            delete_timer (md->skilltimer, mobskill_castend_pos);
-        else
-            delete_timer (md->skilltimer, mobskill_castend_id);
-        md->skilltimer = -1;
-    }
-    return 0;
-}
-
-//
-// 初期化
-//
-/*==========================================
- * Since un-setting [ mob ] up was used, it is an initial provisional value setup.
- *------------------------------------------
- */
-static int mob_makedummymobdb (int mob_class)
-{
-    int  i;
-
-    sprintf (mob_db[mob_class].name, "mob%d", mob_class);
-    sprintf (mob_db[mob_class].jname, "mob%d", mob_class);
-    mob_db[mob_class].lv = 1;
-    mob_db[mob_class].max_hp = 1000;
-    mob_db[mob_class].max_sp = 1;
-    mob_db[mob_class].base_exp = 2;
-    mob_db[mob_class].job_exp = 1;
-    mob_db[mob_class].range = 1;
-    mob_db[mob_class].atk1 = 7;
-    mob_db[mob_class].atk2 = 10;
-    mob_db[mob_class].def = 0;
-    mob_db[mob_class].mdef = 0;
-    mob_db[mob_class].str = 1;
-    mob_db[mob_class].agi = 1;
-    mob_db[mob_class].vit = 1;
-    mob_db[mob_class].int_ = 1;
-    mob_db[mob_class].dex = 6;
-    mob_db[mob_class].luk = 2;
-    mob_db[mob_class].range2 = 10;
-    mob_db[mob_class].range3 = 10;
-    mob_db[mob_class].size = 0;
-    mob_db[mob_class].race = 0;
-    mob_db[mob_class].element = 0;
-    mob_db[mob_class].mode = 0;
-    mob_db[mob_class].speed = 300;
-    mob_db[mob_class].adelay = 1000;
-    mob_db[mob_class].amotion = 500;
-    mob_db[mob_class].dmotion = 500;
-    mob_db[mob_class].dropitem[0].nameid = 909; // Jellopy
-    mob_db[mob_class].dropitem[0].p = 1000;
-    for (i = 1; i < 8; i++)
-    {
-        mob_db[mob_class].dropitem[i].nameid = 0;
-        mob_db[mob_class].dropitem[i].p = 0;
-    }
-    // Item1,Item2
-    mob_db[mob_class].mexp = 0;
-    mob_db[mob_class].mexpper = 0;
-    for (i = 0; i < 3; i++)
-    {
-        mob_db[mob_class].mvpitem[i].nameid = 0;
-        mob_db[mob_class].mvpitem[i].p = 0;
-    }
-    for (i = 0; i < MAX_RANDOMMONSTER; i++)
-        mob_db[mob_class].summonper[i] = 0;
-    return 0;
-}
-
-/*==========================================
- * db/mob_db.txt reading
- *------------------------------------------
- */
-static int mob_readdb (void)
-{
-    FILE *fp;
-    char line[1024];
-    char *filename[] = { "db/mob_db.txt", "db/mob_db2.txt" };
-    int  i;
-
-    memset (mob_db, 0, sizeof (mob_db));
-
-    for (i = 0; i < 2; i++)
-    {
-
-        fp = fopen_ (filename[i], "r");
-        if (fp == NULL)
-        {
-            if (i > 0)
-                continue;
-            return -1;
-        }
-        while (fgets (line, 1020, fp))
-        {
-            int  mob_class, i;
-            char *str[57], *p, *np;
-
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-
-            for (i = 0, p = line; i < 57; i++)
-            {
-                while (*p == '\t' || *p == ' ')
-                    p++;
-                if ((np = strchr (p, ',')) != NULL)
-                {
-                    str[i] = p;
-                    *np = 0;
-                    p = np + 1;
-                }
-                else
-                    str[i] = p;
-            }
-
-            mob_class = atoi (str[0]);
-            if (mob_class <= 1000 || mob_class > 2000)
-                continue;
-
-            mob_db[mob_class].view_class = mob_class;
-            memcpy (mob_db[mob_class].name, str[1], 24);
-            memcpy (mob_db[mob_class].jname, str[2], 24);
-            mob_db[mob_class].lv = atoi (str[3]);
-            mob_db[mob_class].max_hp = atoi (str[4]);
-            mob_db[mob_class].max_sp = atoi (str[5]);
-
-            mob_db[mob_class].base_exp = atoi (str[6]);
-            if (mob_db[mob_class].base_exp < 0)
-                mob_db[mob_class].base_exp = 0;
-            else if (mob_db[mob_class].base_exp > 0
-                     && (mob_db[mob_class].base_exp *
-                         battle_config.base_exp_rate / 100 > 1000000000
-                         || mob_db[mob_class].base_exp *
-                         battle_config.base_exp_rate / 100 < 0))
-                mob_db[mob_class].base_exp = 1000000000;
-            else
-                mob_db[mob_class].base_exp *= battle_config.base_exp_rate / 100;
-
-            mob_db[mob_class].job_exp = atoi (str[7]);
-            if (mob_db[mob_class].job_exp < 0)
-                mob_db[mob_class].job_exp = 0;
-            else if (mob_db[mob_class].job_exp > 0
-                     && (mob_db[mob_class].job_exp * battle_config.job_exp_rate /
-                         100 > 1000000000
-                         || mob_db[mob_class].job_exp *
-                         battle_config.job_exp_rate / 100 < 0))
-                mob_db[mob_class].job_exp = 1000000000;
-            else
-                mob_db[mob_class].job_exp *= battle_config.job_exp_rate / 100;
-
-            mob_db[mob_class].range = atoi (str[8]);
-            mob_db[mob_class].atk1 = atoi (str[9]);
-            mob_db[mob_class].atk2 = atoi (str[10]);
-            mob_db[mob_class].def = atoi (str[11]);
-            mob_db[mob_class].mdef = atoi (str[12]);
-            mob_db[mob_class].str = atoi (str[13]);
-            mob_db[mob_class].agi = atoi (str[14]);
-            mob_db[mob_class].vit = atoi (str[15]);
-            mob_db[mob_class].int_ = atoi (str[16]);
-            mob_db[mob_class].dex = atoi (str[17]);
-            mob_db[mob_class].luk = atoi (str[18]);
-            mob_db[mob_class].range2 = atoi (str[19]);
-            mob_db[mob_class].range3 = atoi (str[20]);
-            mob_db[mob_class].size = atoi (str[21]);
-            mob_db[mob_class].race = atoi (str[22]);
-            mob_db[mob_class].element = atoi (str[23]);
-            mob_db[mob_class].mode = atoi (str[24]);
-            mob_db[mob_class].speed = atoi (str[25]);
-            mob_db[mob_class].adelay = atoi (str[26]);
-            mob_db[mob_class].amotion = atoi (str[27]);
-            mob_db[mob_class].dmotion = atoi (str[28]);
-
-            for (i = 0; i < 8; i++)
-            {
-                int  rate = 0, type, ratemin, ratemax;
-                mob_db[mob_class].dropitem[i].nameid = atoi (str[29 + i * 2]);
-                type = itemdb_type (mob_db[mob_class].dropitem[i].nameid);
-                if (type == 0)
-                {               // Added [Valaris]
-                    rate = battle_config.item_rate_heal;
-                    ratemin = battle_config.item_drop_heal_min;
-                    ratemax = battle_config.item_drop_heal_max;
-                }
-                else if (type == 2)
-                {
-                    rate = battle_config.item_rate_use;
-                    ratemin = battle_config.item_drop_use_min;
-                    ratemax = battle_config.item_drop_use_max;  // End
-                }
-                else if (type == 4 || type == 5 || type == 8)
-                {
-                    rate = battle_config.item_rate_equip;
-                    ratemin = battle_config.item_drop_equip_min;
-                    ratemax = battle_config.item_drop_equip_max;
-                }
-                else if (type == 6)
-                {
-                    rate = battle_config.item_rate_card;
-                    ratemin = battle_config.item_drop_card_min;
-                    ratemax = battle_config.item_drop_card_max;
-                }
-                else
-                {
-                    rate = battle_config.item_rate_common;
-                    ratemin = battle_config.item_drop_common_min;
-                    ratemax = battle_config.item_drop_common_max;
-                }
-                rate = (rate / 100) * atoi (str[30 + i * 2]);
-                rate =
-                    (rate < ratemin) ? ratemin : (rate >
-                                                  ratemax) ? ratemax : rate;
-                mob_db[mob_class].dropitem[i].p = rate;
-            }
-            // Item1,Item2
-            mob_db[mob_class].mexp =
-                atoi (str[45]) * battle_config.mvp_exp_rate / 100;
-            mob_db[mob_class].mexpper = atoi (str[46]);
-            for (i = 0; i < 3; i++)
-            {
-                mob_db[mob_class].mvpitem[i].nameid = atoi (str[47 + i * 2]);
-                mob_db[mob_class].mvpitem[i].p =
-                    atoi (str[48 + i * 2]) * battle_config.mvp_item_rate /
-                    100;
-            }
-            mob_db[mob_class].mutations_nr = atoi (str[55]);
-            mob_db[mob_class].mutation_power = atoi (str[56]);
-
-            for (i = 0; i < MAX_RANDOMMONSTER; i++)
-                mob_db[mob_class].summonper[i] = 0;
-            mob_db[mob_class].maxskill = 0;
-
-            mob_db[mob_class].sex = 0;
-            mob_db[mob_class].hair = 0;
-            mob_db[mob_class].hair_color = 0;
-            mob_db[mob_class].weapon = 0;
-            mob_db[mob_class].shield = 0;
-            mob_db[mob_class].head_top = 0;
-            mob_db[mob_class].head_mid = 0;
-            mob_db[mob_class].head_buttom = 0;
-            mob_db[mob_class].clothes_color = 0;    //Add for player monster dye - Valaris
-
-            if (mob_db[mob_class].base_exp == 0)
-                mob_db[mob_class].base_exp = mob_gen_exp (&mob_db[mob_class]);
-        }
-        fclose_ (fp);
-        printf ("read %s done\n", filename[i]);
-    }
-    return 0;
-}
-
-/*==========================================
- * MOB display graphic change data reading
- *------------------------------------------
- */
-static int mob_readdb_mobavail (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  ln = 0;
-    int  mob_class, j, k;
-    char *str[20], *p, *np;
-
-    if ((fp = fopen_ ("db/mob_avail.txt", "r")) == NULL)
-    {
-        printf ("can't read db/mob_avail.txt\n");
-        return -1;
-    }
-
-    while (fgets (line, 1020, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        memset (str, 0, sizeof (str));
-
-        for (j = 0, p = line; j < 12; j++)
-        {
-            if ((np = strchr (p, ',')) != NULL)
-            {
-                str[j] = p;
-                *np = 0;
-                p = np + 1;
-            }
-            else
-                str[j] = p;
-        }
-
-        if (str[0] == NULL)
-            continue;
-
-        mob_class = atoi (str[0]);
-
-        if (mob_class <= 1000 || mob_class > 2000)  // 値が異常なら処理しない。
-            continue;
-        k = atoi (str[1]);
-        if (k >= 0)
-            mob_db[mob_class].view_class = k;
-
-        if ((mob_db[mob_class].view_class < 24)
-            || (mob_db[mob_class].view_class > 4000))
-        {
-            mob_db[mob_class].sex = atoi (str[2]);
-            mob_db[mob_class].hair = atoi (str[3]);
-            mob_db[mob_class].hair_color = atoi (str[4]);
-            mob_db[mob_class].weapon = atoi (str[5]);
-            mob_db[mob_class].shield = atoi (str[6]);
-            mob_db[mob_class].head_top = atoi (str[7]);
-            mob_db[mob_class].head_mid = atoi (str[8]);
-            mob_db[mob_class].head_buttom = atoi (str[9]);
-            mob_db[mob_class].option = atoi (str[10]) & ~0x46;
-            mob_db[mob_class].clothes_color = atoi (str[11]);   // Monster player dye option - Valaris
-        }
-
-        else if (atoi (str[2]) > 0)
-            mob_db[mob_class].equip = atoi (str[2]);    // mob equipment [Valaris]
-
-        ln++;
-    }
-    fclose_ (fp);
-    printf ("read db/mob_avail.txt done (count=%d)\n", ln);
-    return 0;
-}
-
-/*==========================================
- * Reading of random monster data
- *------------------------------------------
- */
-static int mob_read_randommonster (void)
-{
-    FILE *fp;
-    char line[1024];
-    char *str[10], *p;
-    int  i, j;
-
-    const char *mobfile[] = {
-        "db/mob_branch.txt",
-        "db/mob_poring.txt",
-        "db/mob_boss.txt"
-    };
-
-    for (i = 0; i < MAX_RANDOMMONSTER; i++)
-    {
-        mob_db[0].summonper[i] = 1002;  // 設定し忘れた場合はポリンが出るようにしておく
-        fp = fopen_ (mobfile[i], "r");
-        if (fp == NULL)
-        {
-            printf ("can't read %s\n", mobfile[i]);
-            return -1;
-        }
-        while (fgets (line, 1020, fp))
-        {
-            int  mob_class, per;
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-            memset (str, 0, sizeof (str));
-            for (j = 0, p = line; j < 3 && p; j++)
-            {
-                str[j] = p;
-                p = strchr (p, ',');
-                if (p)
-                    *p++ = 0;
-            }
-
-            if (str[0] == NULL || str[2] == NULL)
-                continue;
-
-            mob_class = atoi (str[0]);
-            per = atoi (str[2]);
-            if ((mob_class > 1000 && mob_class <= 2000) || mob_class == 0)
-                mob_db[mob_class].summonper[i] = per;
-        }
-        fclose_ (fp);
-        printf ("read %s done\n", mobfile[i]);
-    }
-    return 0;
-}
-
-/*==========================================
- * db/mob_skill_db.txt reading
- *------------------------------------------
- */
-static int mob_readskilldb (void)
-{
-    FILE *fp;
-    char line[1024];
-    int  i;
-
-    const struct
-    {
-        char str[32];
-        int  id;
-    } cond1[] =
-    {
-        {
-        "always", MSC_ALWAYS},
-        {
-        "myhpltmaxrate", MSC_MYHPLTMAXRATE},
-        {
-        "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE},
-        {
-        "mystatuson", MSC_MYSTATUSON},
-        {
-        "mystatusoff", MSC_MYSTATUSOFF},
-        {
-        "friendstatuson", MSC_FRIENDSTATUSON},
-        {
-        "friendstatusoff", MSC_FRIENDSTATUSOFF},
-        {
-        "notintown", MSC_NOTINTOWN},
-        {
-        "attackpcgt", MSC_ATTACKPCGT},
-        {
-        "attackpcge", MSC_ATTACKPCGE},
-        {
-        "slavelt", MSC_SLAVELT},
-        {
-        "slavele", MSC_SLAVELE},
-        {
-        "closedattacked", MSC_CLOSEDATTACKED},
-        {
-        "longrangeattacked", MSC_LONGRANGEATTACKED},
-        {
-        "skillused", MSC_SKILLUSED},
-        {
-    "casttargeted", MSC_CASTTARGETED},}, cond2[] =
-    {
-        {
-        "anybad", -1},
-        {
-        "stone", SC_STONE},
-        {
-        "freeze", SC_FREEZE},
-        {
-        "stan", SC_STAN},
-        {
-        "sleep", SC_SLEEP},
-        {
-        "poison", SC_POISON},
-        {
-        "curse", SC_CURSE},
-        {
-        "silence", SC_SILENCE},
-        {
-        "confusion", SC_CONFUSION},
-        {
-        "blind", SC_BLIND},
-        {
-        "hiding", SC_HIDING},
-        {
-    "sight", SC_SIGHT},}, state[] =
-    {
-        {
-        "any", -1},
-        {
-        "idle", MSS_IDLE},
-        {
-        "walk", MSS_WALK},
-        {
-        "attack", MSS_ATTACK},
-        {
-        "dead", MSS_DEAD},
-        {
-        "loot", MSS_LOOT},
-        {
-    "chase", MSS_CHASE},}, target[] =
-    {
-        {
-        "target", MST_TARGET},
-        {
-        "self", MST_SELF},
-        {
-        "friend", MST_FRIEND},
-        {
-        "master", MST_MASTER},
-        {
-        "around5", MST_AROUND5},
-        {
-        "around6", MST_AROUND6},
-        {
-        "around7", MST_AROUND7},
-        {
-        "around8", MST_AROUND8},
-        {
-        "around1", MST_AROUND1},
-        {
-        "around2", MST_AROUND2},
-        {
-        "around3", MST_AROUND3},
-        {
-        "around4", MST_AROUND4},
-        {
-    "around", MST_AROUND},};
-
-    int  x;
-    char *filename[] = { "db/mob_skill_db.txt", "db/mob_skill_db2.txt" };
-
-    for (x = 0; x < 2; x++)
-    {
-
-        fp = fopen_ (filename[x], "r");
-        if (fp == NULL)
-        {
-            if (x == 0)
-                printf ("can't read %s\n", filename[x]);
-            continue;
-        }
-        while (fgets (line, 1020, fp))
-        {
-            char *sp[20], *p;
-            int  mob_id;
-            struct mob_skill *ms;
-            int  j = 0;
-
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-
-            memset (sp, 0, sizeof (sp));
-            for (i = 0, p = line; i < 18 && p; i++)
-            {
-                sp[i] = p;
-                if ((p = strchr (p, ',')) != NULL)
-                    *p++ = 0;
-            }
-            if ((mob_id = atoi (sp[0])) <= 0)
-                continue;
-
-            if (strcmp (sp[1], "clear") == 0)
-            {
-                memset (mob_db[mob_id].skill, 0,
-                        sizeof (mob_db[mob_id].skill));
-                mob_db[mob_id].maxskill = 0;
-                continue;
-            }
-
-            for (i = 0; i < MAX_MOBSKILL; i++)
-                if ((ms = &mob_db[mob_id].skill[i])->skill_id == 0)
-                    break;
-            if (i == MAX_MOBSKILL)
-            {
-                printf
-                    ("mob_skill: readdb: too many skill ! [%s] in %d[%s]\n",
-                     sp[1], mob_id, mob_db[mob_id].jname);
-                continue;
-            }
-
-            ms->state = atoi (sp[2]);
-            for (j = 0; j < sizeof (state) / sizeof (state[0]); j++)
-            {
-                if (strcmp (sp[2], state[j].str) == 0)
-                    ms->state = state[j].id;
-            }
-            ms->skill_id = atoi (sp[3]);
-            ms->skill_lv = atoi (sp[4]);
-
-            ms->permillage = atoi (sp[5]);
-            ms->casttime = atoi (sp[6]);
-            ms->delay = atoi (sp[7]);
-            ms->cancel = atoi (sp[8]);
-            if (strcmp (sp[8], "yes") == 0)
-                ms->cancel = 1;
-            ms->target = atoi (sp[9]);
-            for (j = 0; j < sizeof (target) / sizeof (target[0]); j++)
-            {
-                if (strcmp (sp[9], target[j].str) == 0)
-                    ms->target = target[j].id;
-            }
-            ms->cond1 = -1;
-            for (j = 0; j < sizeof (cond1) / sizeof (cond1[0]); j++)
-            {
-                if (strcmp (sp[10], cond1[j].str) == 0)
-                    ms->cond1 = cond1[j].id;
-            }
-            ms->cond2 = atoi (sp[11]);
-            for (j = 0; j < sizeof (cond2) / sizeof (cond2[0]); j++)
-            {
-                if (strcmp (sp[11], cond2[j].str) == 0)
-                    ms->cond2 = cond2[j].id;
-            }
-            ms->val[0] = atoi (sp[12]);
-            ms->val[1] = atoi (sp[13]);
-            ms->val[2] = atoi (sp[14]);
-            ms->val[3] = atoi (sp[15]);
-            ms->val[4] = atoi (sp[16]);
-            if (sp[17] != NULL && strlen (sp[17]) > 2)
-                ms->emotion = atoi (sp[17]);
-            else
-                ms->emotion = -1;
-            mob_db[mob_id].maxskill = i + 1;
-        }
-        fclose_ (fp);
-        printf ("read %s done\n", filename[x]);
-    }
-    return 0;
-}
-
-void mob_reload (void)
-{
-    /*
-     *
-     * <empty monster database>
-     * mob_read();
-     *
-     */
-
-    do_init_mob ();
-}
-
-/*==========================================
- * Circumference initialization of mob
- *------------------------------------------
- */
-int do_init_mob (void)
-{
-    mob_readdb ();
-
-    mob_readdb_mobavail ();
-    mob_read_randommonster ();
-    mob_readskilldb ();
-
-    add_timer_interval (gettick () + MIN_MOBTHINKTIME, mob_ai_hard, 0, 0,
-                        MIN_MOBTHINKTIME);
-    add_timer_interval (gettick () + MIN_MOBTHINKTIME * 10, mob_ai_lazy, 0, 0,
-                        MIN_MOBTHINKTIME * 10);
-
-    return 0;
-}
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
new file mode 100644
index 0000000..a722920
--- /dev/null
+++ b/src/map/mob.cpp
@@ -0,0 +1,5070 @@
+// $Id: mob.c,v 1.7 2004/09/25 05:32:18 MouseJstr Exp $
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "../common/timer.hpp"
+#include "../common/socket.hpp"
+#include "../common/db.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/mt_rand.hpp"
+#include "map.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "pc.hpp"
+#include "mob.hpp"
+#include "guild.hpp"
+#include "itemdb.hpp"
+#include "skill.hpp"
+#include "battle.hpp"
+#include "party.hpp"
+#include "npc.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#ifndef max
+#define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
+#endif
+
+#define MIN_MOBTHINKTIME 100
+
+#define MOB_LAZYMOVEPERC 50     // Move probability in the negligent mode MOB (rate of 1000 minute)
+#define MOB_LAZYWARPPERC 20     // Warp probability in the negligent mode MOB (rate of 1000 minute)
+
+struct mob_db mob_db[2001];
+
+/*==========================================
+ * Local prototype declaration   (only required thing)
+ *------------------------------------------
+ */
+static int distance (int, int, int, int);
+static int mob_makedummymobdb (int);
+static void mob_timer (timer_id, tick_t, custom_id_t, custom_data_t);
+int  mobskill_use (struct mob_data *md, unsigned int tick, int event);
+int  mobskill_deltimer (struct mob_data *md);
+int  mob_skillid2skillidx (int mob_class, int skillid);
+int  mobskill_use_id (struct mob_data *md, struct block_list *target,
+                      int skill_idx);
+static int mob_unlocktarget (struct mob_data *md, int tick);
+
+/*==========================================
+ * Mob is searched with a name.
+ *------------------------------------------
+ */
+int mobdb_searchname (const char *str)
+{
+    int  i;
+
+    for (i = 0; i < sizeof (mob_db) / sizeof (mob_db[0]); i++)
+    {
+        if (strcasecmp (mob_db[i].name, str) == 0
+            || strcmp (mob_db[i].jname, str) == 0
+            || memcmp (mob_db[i].name, str, 24) == 0
+            || memcmp (mob_db[i].jname, str, 24) == 0)
+            return i;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Id Mob is checked.
+ *------------------------------------------
+ */
+int mobdb_checkid (const int id)
+{
+    if (id <= 0 || id >= (sizeof (mob_db) / sizeof (mob_db[0]))
+        || mob_db[id].name[0] == '\0')
+        return 0;
+
+    return id;
+}
+
+static void mob_init (struct mob_data *md);
+
+/*==========================================
+ * The minimum data set for MOB spawning
+ *------------------------------------------
+ */
+int mob_spawn_dataset (struct mob_data *md, const char *mobname, int mob_class)
+{
+    nullpo_retr (0, md);
+
+    if (strcmp (mobname, "--en--") == 0)
+        memcpy (md->name, mob_db[mob_class].name, 24);
+    else if (strcmp (mobname, "--ja--") == 0)
+        memcpy (md->name, mob_db[mob_class].jname, 24);
+    else
+        memcpy (md->name, mobname, 24);
+
+    md->bl.prev = NULL;
+    md->bl.next = NULL;
+    md->n = 0;
+    md->base_class = md->mob_class = mob_class;
+    md->bl.id = npc_get_new_npc_id ();
+
+    memset (&md->state, 0, sizeof (md->state));
+    md->timer = -1;
+    md->target_id = 0;
+    md->attacked_id = 0;
+
+    mob_init (md);
+
+    return 0;
+}
+
+// Mutation values indicate how `valuable' a change to each stat is, XP wise.
+// For one 256th of change, we give out that many 1024th fractions of XP change
+// (i.e., 1024 means a 100% XP increase for a single point of adjustment, 4 means 100% XP bonus for doubling the value)
+static int mutation_value[MOB_XP_BONUS] = {
+    2,                          // MOB_LV
+    3,                          // MOB_MAX_HP
+    1,                          // MOB_STR
+    2,                          // MOB_AGI
+    1,                          // MOB_VIT
+    0,                          // MOB_INT
+    2,                          // MOB_DEX
+    2,                          // MOB_LUK
+    1,                          // MOB_ATK1
+    1,                          // MOB_ATK2
+    2,                          // MOB_ADELAY
+    2,                          // MOB_DEF
+    2,                          // MOB_MDEF
+    2,                          // MOB_SPEED
+};
+
+// The mutation scale indicates how far `up' we can go, with 256 indicating 100%  Note that this may stack with multiple
+// calls to `mutate'.
+static int mutation_scale[MOB_XP_BONUS] = {
+    16,                         // MOB_LV
+    256,                        // MOB_MAX_HP
+    32,                         // MOB_STR
+    48,                         // MOB_AGI
+    48,                         // MOB_VIT
+    48,                         // MOB_INT
+    48,                         // MOB_DEX
+    64,                         // MOB_LUK
+    48,                         // MOB_ATK1
+    48,                         // MOB_ATK2
+    80,                         // MOB_ADELAY
+    48,                         // MOB_DEF
+    48,                         // MOB_MDEF
+    80,                         // MOB_SPEED
+};
+
+// The table below indicates the `average' value for each of the statistics, or -1 if there is none.
+// This average is used to determine XP modifications for mutations.  The experience point bonus is
+// based on mutation_value and mutation_base as follows:
+// (1) first, compute the percentage change of the attribute (p0)
+// (2) second, determine the absolute stat change
+// (3) third, compute the percentage stat change relative to mutation_base (p1)
+// (4) fourth, compute the XP mofication based on the smaller of (p0, p1).
+static int mutation_base[MOB_XP_BONUS] = {
+    30,                         // MOB_LV
+    -1,                         // MOB_MAX_HP
+    20,                         // MOB_STR
+    20,                         // MOB_AGI
+    20,                         // MOB_VIT
+    20,                         // MOB_INT
+    20,                         // MOB_DEX
+    20,                         // MOB_LUK
+    -1,                         // MOB_ATK1
+    -1,                         // MOB_ATK2
+    -1,                         // MOB_ADELAY
+    -1,                         // MOB_DEF
+    20,                         // MOB_MDEF
+    -1,                         // MOB_SPEED
+};
+
+/*========================================
+ * Mutates a MOB.  For large `direction' values, calling this multiple times will give bigger XP boni.
+ *----------------------------------------
+ */
+static void mob_mutate (struct mob_data *md, int stat, int intensity)   // intensity: positive: strengthen, negative: weaken.  256 = 100%.
+{
+    int  old_stat;
+    int  new_stat;
+    int  real_intensity;        // relative intensity
+    const int mut_base = mutation_base[stat];
+    int  sign = 1;
+
+    if (!md || stat < 0 || stat >= MOB_XP_BONUS || intensity == 0)
+        return;
+
+    while (intensity > mutation_scale[stat])
+    {
+        mob_mutate (md, stat, mutation_scale[stat]);    // give better XP assignments
+        intensity -= mutation_scale[stat];
+    }
+    while (intensity < -mutation_scale[stat])
+    {
+        mob_mutate (md, stat, mutation_scale[stat]);    // give better XP assignments
+        intensity += mutation_scale[stat];
+    }
+
+    if (!intensity)
+        return;
+
+    // MOB_ADELAY and MOB_SPEED are special because going DOWN is good here.
+    if (stat == MOB_ADELAY || stat == MOB_SPEED)
+        sign = -1;
+
+    // Now compute the new stat
+    old_stat = md->stats[stat];
+    new_stat = old_stat + ((old_stat * sign * intensity) / 256);
+
+    if (new_stat < 0)
+        new_stat = 0;
+
+    if (old_stat == 0)
+        real_intensity = 0;
+    else
+        real_intensity = (((new_stat - old_stat) << 8) / old_stat);
+
+    if (mut_base != -1)
+    {
+        // Now compute the mutation intensity relative to an absolute value.
+        // Take the lesser of the two effects.
+        int  real_intensity2 = (((new_stat - old_stat) << 8) / mut_base);
+
+        if (real_intensity < 0)
+            if (real_intensity2 > real_intensity)
+                real_intensity = real_intensity2;
+
+        if (real_intensity > 0)
+            if (real_intensity2 < real_intensity)
+                real_intensity = real_intensity2;
+    }
+
+    real_intensity *= sign;
+
+    md->stats[stat] = new_stat;
+
+    // Adjust XP value
+    md->stats[MOB_XP_BONUS] += mutation_value[stat] * real_intensity;
+    if (md->stats[MOB_XP_BONUS] <= 0)
+        md->stats[MOB_XP_BONUS] = 1;
+
+    // Sanitise
+    if (md->stats[MOB_ATK1] > md->stats[MOB_ATK2])
+    {
+        int  swap = md->stats[MOB_ATK2];
+        md->stats[MOB_ATK2] = md->stats[MOB_ATK1];
+        md->stats[MOB_ATK1] = swap;
+    }
+}
+
+// This calculates the exp of a given mob
+int mob_gen_exp (struct mob_db *mob)
+{
+    if (mob->max_hp <= 1)
+        return 1;
+    double mod_def = 100 - mob->def;
+    if (mod_def == 0)
+        mod_def = 1;
+    double effective_hp =
+        ((50 - mob->luk) * mob->max_hp / 50.0) +
+        (2 * mob->luk * mob->max_hp / mod_def);
+    double attack_factor =
+        (mob->atk1 + mob->atk2 + mob->str / 3.0 + mob->dex / 2.0 +
+         mob->luk) * (1872.0 / mob->adelay) / 4;
+    double dodge_factor =
+        pow (mob->lv + mob->agi + mob->luk / 2.0, 4.0 / 3.0);
+    double persuit_factor =
+        (3 + mob->range) * (mob->mode % 2) * 1000 / mob->speed;
+    double aggression_factor = (mob->mode & 4) == 4 ? 10.0 / 9.0 : 1.0;
+    int  xp =
+        (int) floor (effective_hp *
+                     pow (sqrt (attack_factor) + sqrt (dodge_factor) +
+                          sqrt (persuit_factor) + 55,
+                          3) * aggression_factor / 2000000.0 *
+                     (double) battle_config.base_exp_rate / 100.);
+    if (xp < 1)
+        xp = 1;
+    printf ("Exp for mob '%s' generated: %d\n", mob->name, xp);
+    return xp;
+}
+
+static void mob_init (struct mob_data *md)
+{
+    int  i;
+    const int mob_class = md->mob_class;
+    const int mutations_nr = mob_db[mob_class].mutations_nr;
+    const int mutation_power = mob_db[mob_class].mutation_power;
+
+    md->stats[MOB_LV] = mob_db[mob_class].lv;
+    md->stats[MOB_MAX_HP] = mob_db[mob_class].max_hp;
+    md->stats[MOB_STR] = mob_db[mob_class].str;
+    md->stats[MOB_AGI] = mob_db[mob_class].agi;
+    md->stats[MOB_VIT] = mob_db[mob_class].vit;
+    md->stats[MOB_INT] = mob_db[mob_class].int_;
+    md->stats[MOB_DEX] = mob_db[mob_class].dex;
+    md->stats[MOB_LUK] = mob_db[mob_class].luk;
+    md->stats[MOB_ATK1] = mob_db[mob_class].atk1;
+    md->stats[MOB_ATK2] = mob_db[mob_class].atk2;
+    md->stats[MOB_ADELAY] = mob_db[mob_class].adelay;
+    md->stats[MOB_DEF] = mob_db[mob_class].def;
+    md->stats[MOB_MDEF] = mob_db[mob_class].mdef;
+    md->stats[MOB_SPEED] = mob_db[mob_class].speed;
+    md->stats[MOB_XP_BONUS] = MOB_XP_BONUS_BASE;
+
+    for (i = 0; i < mutations_nr; i++)
+    {
+        int  stat_nr = MRAND (MOB_XP_BONUS + 1);
+        int  strength;
+
+        if (stat_nr >= MOB_XP_BONUS)
+            stat_nr = MOB_MAX_HP;
+
+        strength =
+            ((MRAND ((mutation_power >> 1)) +
+              (MRAND ((mutation_power >> 1))) +
+              2) * mutation_scale[stat_nr]) / 100;
+
+        strength = MRAND (2) ? strength : -strength;
+
+        if (strength < -240)
+            strength = -240;    /* Don't go too close to zero */
+
+        mob_mutate (md, stat_nr, strength);
+    }
+}
+
+/*==========================================
+ * The MOB appearance for one time (for scripts)
+ *------------------------------------------
+ */
+int mob_once_spawn (struct map_session_data *sd, char *mapname,
+                    int x, int y, const char *mobname, int mob_class, int amount,
+                    const char *event)
+{
+    struct mob_data *md = NULL;
+    int  m, count, lv = 255, r = mob_class;
+
+    if (sd)
+        lv = sd->status.base_level;
+
+    if (sd && strcmp (mapname, "this") == 0)
+        m = sd->bl.m;
+    else
+        m = map_mapname2mapid (mapname);
+
+    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // 値が異常なら召喚を止める
+        return 0;
+
+    if (mob_class < 0)
+    {                           // ランダムに召喚
+        int  i = 0;
+        int  j = -mob_class - 1;
+        int  k;
+        if (j >= 0 && j < MAX_RANDOMMONSTER)
+        {
+            do
+            {
+                mob_class = MPRAND (1001, 1000);
+                k = MRAND (1000000);
+            }
+            while ((mob_db[mob_class].max_hp <= 0
+                    || mob_db[mob_class].summonper[j] <= k
+                    || (lv < mob_db[mob_class].lv
+                        && battle_config.random_monster_checklv == 1))
+                   && (i++) < 2000);
+            if (i >= 2000)
+            {
+                mob_class = mob_db[0].summonper[j];
+            }
+        }
+        else
+        {
+            return 0;
+        }
+//      if(battle_config.etc_log==1)
+//          printf("mobmob_class=%d try=%d\n",mob_class,i);
+    }
+    if (sd)
+    {
+        if (x <= 0)
+            x = sd->bl.x;
+        if (y <= 0)
+            y = sd->bl.y;
+    }
+    else if (x <= 0 || y <= 0)
+    {
+        printf ("mob_once_spawn: ??\n");
+    }
+
+    for (count = 0; count < amount; count++)
+    {
+        md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
+        if (mob_db[mob_class].mode & 0x02)
+            md->lootitem =
+                (struct item *) calloc (LOOTITEM_SIZE, sizeof (struct item));
+        else
+            md->lootitem = NULL;
+
+        mob_spawn_dataset (md, mobname, mob_class);
+        md->bl.m = m;
+        md->bl.x = x;
+        md->bl.y = y;
+        if (r < 0 && battle_config.dead_branch_active == 1)
+            md->mode = 0x1 + 0x4 + 0x80;    //移動してアクティブで反撃する
+        md->m = m;
+        md->x0 = x;
+        md->y0 = y;
+        md->xs = 0;
+        md->ys = 0;
+        md->spawndelay1 = -1;   // Only once is a flag.
+        md->spawndelay2 = -1;   // Only once is a flag.
+
+        memcpy (md->npc_event, event, sizeof (md->npc_event));
+
+        md->bl.type = BL_MOB;
+        map_addiddb (&md->bl);
+        mob_spawn (md->bl.id);
+
+        if (mob_class == 1288)
+        {                       // emperium hp based on defense level [Valaris]
+            struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
+            if (gc)
+            {
+                mob_db[mob_class].max_hp += 2000 * gc->defense;
+                md->hp = mob_db[mob_class].max_hp;
+            }
+        }                       // end addition [Valaris]
+
+    }
+    return (amount > 0) ? md->bl.id : 0;
+}
+
+/*==========================================
+ * The MOB appearance for one time (& area specification for scripts)
+ *------------------------------------------
+ */
+int mob_once_spawn_area (struct map_session_data *sd, char *mapname,
+                         int x0, int y0, int x1, int y1,
+                         const char *mobname, int mob_class, int amount,
+                         const char *event)
+{
+    int  x, y, i, c, max, lx = -1, ly = -1, id = 0;
+    int  m;
+
+    if (strcmp (mapname, "this") == 0)
+        m = sd->bl.m;
+    else
+        m = map_mapname2mapid (mapname);
+
+    max = (y1 - y0 + 1) * (x1 - x0 + 1) * 3;
+    if (max > 1000)
+        max = 1000;
+
+    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // A summon is stopped if a value is unusual
+        return 0;
+
+    for (i = 0; i < amount; i++)
+    {
+        int  j = 0;
+        do
+        {
+            x = MPRAND (x0, (x1 - x0 + 1));
+            y = MPRAND (y0, (y1 - y0 + 1));
+        }
+        while (((c = map_getcell (m, x, y)) == 1 || c == 5) && (++j) < max);
+        if (j >= max)
+        {
+            if (lx >= 0)
+            {                   // Since reference went wrong, the place which boiled before is used.
+                x = lx;
+                y = ly;
+            }
+            else
+                return 0;       // Since reference of the place which boils first went wrong, it stops.
+        }
+        id = mob_once_spawn (sd, mapname, x, y, mobname, mob_class, 1, event);
+        lx = x;
+        ly = y;
+    }
+    return id;
+}
+
+/*==========================================
+ * Summoning Guardians [Valaris]
+ *------------------------------------------
+ */
+int mob_spawn_guardian (struct map_session_data *sd, char *mapname,
+                        int x, int y, const char *mobname, int mob_class,
+                        int amount, const char *event, int guardian)
+{
+    struct mob_data *md = NULL;
+    int  m, count = 1, lv = 255;
+
+    if (sd)
+        lv = sd->status.base_level;
+
+    if (sd && strcmp (mapname, "this") == 0)
+        m = sd->bl.m;
+    else
+        m = map_mapname2mapid (mapname);
+
+    if (m < 0 || amount <= 0 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)  // 値が異常なら召喚を止める
+        return 0;
+
+    if (mob_class < 0)
+        return 0;
+
+    if (sd)
+    {
+        if (x <= 0)
+            x = sd->bl.x;
+        if (y <= 0)
+            y = sd->bl.y;
+    }
+
+    else if (x <= 0 || y <= 0)
+        printf ("mob_spawn_guardian: ??\n");
+
+    for (count = 0; count < amount; count++)
+    {
+        struct guild_castle *gc;
+        CREATE (md, struct mob_data, 1);
+
+        mob_spawn_dataset (md, mobname, mob_class);
+        md->bl.m = m;
+        md->bl.x = x;
+        md->bl.y = y;
+        md->m = m;
+        md->x0 = x;
+        md->y0 = y;
+        md->xs = 0;
+        md->ys = 0;
+        md->spawndelay1 = -1;   // Only once is a flag.
+        md->spawndelay2 = -1;   // Only once is a flag.
+
+        memcpy (md->npc_event, event, sizeof (md->npc_event));
+
+        md->bl.type = BL_MOB;
+        map_addiddb (&md->bl);
+        mob_spawn (md->bl.id);
+
+        gc = guild_mapname2gc (map[md->bl.m].name);
+        if (gc)
+        {
+            mob_db[mob_class].max_hp += 2000 * gc->defense;
+            if (guardian == 0)
+            {
+                md->hp = gc->Ghp0;
+                gc->GID0 = md->bl.id;
+            }
+            if (guardian == 1)
+            {
+                md->hp = gc->Ghp1;
+                gc->GID1 = md->bl.id;
+            }
+            if (guardian == 2)
+            {
+                md->hp = gc->Ghp2;
+                gc->GID2 = md->bl.id;
+            }
+            if (guardian == 3)
+            {
+                md->hp = gc->Ghp3;
+                gc->GID3 = md->bl.id;
+            }
+            if (guardian == 4)
+            {
+                md->hp = gc->Ghp4;
+                gc->GID4 = md->bl.id;
+            }
+            if (guardian == 5)
+            {
+                md->hp = gc->Ghp5;
+                gc->GID5 = md->bl.id;
+            }
+            if (guardian == 6)
+            {
+                md->hp = gc->Ghp6;
+                gc->GID6 = md->bl.id;
+            }
+            if (guardian == 7)
+            {
+                md->hp = gc->Ghp7;
+                gc->GID7 = md->bl.id;
+            }
+
+        }
+    }
+
+    return (amount > 0) ? md->bl.id : 0;
+}
+
+/*==========================================
+ * Appearance income of mob
+ *------------------------------------------
+ */
+int mob_get_viewclass (int mob_class)
+{
+    return mob_db[mob_class].view_class;
+}
+
+int mob_get_sex (int mob_class)
+{
+    return mob_db[mob_class].sex;
+}
+
+short mob_get_hair (int mob_class)
+{
+    return mob_db[mob_class].hair;
+}
+
+short mob_get_hair_color (int mob_class)
+{
+    return mob_db[mob_class].hair_color;
+}
+
+short mob_get_weapon (int mob_class)
+{
+    return mob_db[mob_class].weapon;
+}
+
+short mob_get_shield (int mob_class)
+{
+    return mob_db[mob_class].shield;
+}
+
+short mob_get_head_top (int mob_class)
+{
+    return mob_db[mob_class].head_top;
+}
+
+short mob_get_head_mid (int mob_class)
+{
+    return mob_db[mob_class].head_mid;
+}
+
+short mob_get_head_buttom (int mob_class)
+{
+    return mob_db[mob_class].head_buttom;
+}
+
+short mob_get_clothes_color (int mob_class) // Add for player monster dye - Valaris
+{
+    return mob_db[mob_class].clothes_color; // End
+}
+
+int mob_get_equip (int mob_class)   // mob equip [Valaris]
+{
+    return mob_db[mob_class].equip;
+}
+
+/*==========================================
+ * Is MOB in the state in which the present movement is possible or not?
+ *------------------------------------------
+ */
+int mob_can_move (struct mob_data *md)
+{
+    nullpo_retr (0, md);
+
+    if (md->canmove_tick > gettick () || (md->opt1 > 0 && md->opt1 != 6)
+        || md->option & 2)
+        return 0;
+    // アンクル中で動けないとか
+    if (md->sc_data[SC_ANKLE].timer != -1 ||    //アンクルスネア
+        md->sc_data[SC_AUTOCOUNTER].timer != -1 ||  //オートカウンター
+        md->sc_data[SC_BLADESTOP].timer != -1 ||    //白刃取り
+        md->sc_data[SC_SPIDERWEB].timer != -1   //スパイダーウェッブ
+        )
+        return 0;
+
+    return 1;
+}
+
+/*==========================================
+ * Time calculation concerning one step next to mob
+ *------------------------------------------
+ */
+static int calc_next_walk_step (struct mob_data *md)
+{
+    nullpo_retr (0, md);
+
+    if (md->walkpath.path_pos >= md->walkpath.path_len)
+        return -1;
+    if (md->walkpath.path[md->walkpath.path_pos] & 1)
+        return battle_get_speed (&md->bl) * 14 / 10;
+    return battle_get_speed (&md->bl);
+}
+
+static int mob_walktoxy_sub (struct mob_data *md);
+
+/*==========================================
+ * Mob Walk processing
+ *------------------------------------------
+ */
+static int mob_walk (struct mob_data *md, unsigned int tick, int data)
+{
+    int  moveblock;
+    int  i, ctype;
+    static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+    static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+    int  x, y, dx, dy;
+
+    nullpo_retr (0, md);
+
+    md->state.state = MS_IDLE;
+    if (md->walkpath.path_pos >= md->walkpath.path_len
+        || md->walkpath.path_pos != data)
+        return 0;
+
+    md->walkpath.path_half ^= 1;
+    if (md->walkpath.path_half == 0)
+    {
+        md->walkpath.path_pos++;
+        if (md->state.change_walk_target)
+        {
+            mob_walktoxy_sub (md);
+            return 0;
+        }
+    }
+    else
+    {
+        if (md->walkpath.path[md->walkpath.path_pos] >= 8)
+            return 1;
+
+        x = md->bl.x;
+        y = md->bl.y;
+        ctype = map_getcell (md->bl.m, x, y);
+        if (ctype == 1 || ctype == 5)
+        {
+            mob_stop_walking (md, 1);
+            return 0;
+        }
+        md->dir = md->walkpath.path[md->walkpath.path_pos];
+        dx = dirx[md->dir];
+        dy = diry[md->dir];
+
+        ctype = map_getcell (md->bl.m, x + dx, y + dy);
+        if (ctype == 1 || ctype == 5)
+        {
+            mob_walktoxy_sub (md);
+            return 0;
+        }
+
+        moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
+                     || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
+
+        md->state.state = MS_WALK;
+        map_foreachinmovearea (clif_moboutsight, md->bl.m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               dx, dy, BL_PC, md);
+
+        x += dx;
+        y += dy;
+        if (md->min_chase > 13)
+            md->min_chase--;
+
+        if (moveblock)
+            map_delblock (&md->bl);
+        md->bl.x = x;
+        md->bl.y = y;
+        if (moveblock)
+            map_addblock (&md->bl);
+
+        map_foreachinmovearea (clif_mobinsight, md->bl.m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               -dx, -dy, BL_PC, md);
+        md->state.state = MS_IDLE;
+
+        if (md->option & 4)
+            skill_check_cloaking (&md->bl);
+
+        skill_unit_move (&md->bl, tick, 1); // Inspection of a skill unit
+    }
+    if ((i = calc_next_walk_step (md)) > 0)
+    {
+        i = i >> 1;
+        if (i < 1 && md->walkpath.path_half == 0)
+            i = 1;
+        md->timer =
+            add_timer (tick + i, mob_timer, md->bl.id, md->walkpath.path_pos);
+        md->state.state = MS_WALK;
+
+        if (md->walkpath.path_pos >= md->walkpath.path_len)
+            clif_fixmobpos (md);    // When mob stops, retransmission current of a position.
+    }
+    return 0;
+}
+
+/*==========================================
+ * Check if mob should be attempting to attack
+ *------------------------------------------
+ */
+static int mob_check_attack (struct mob_data *md)
+{
+    struct block_list *tbl = NULL;
+    struct map_session_data *tsd = NULL;
+    struct mob_data *tmd = NULL;
+
+    int  mode, race, range;
+
+    nullpo_retr (0, md);
+
+    md->min_chase = 13;
+    md->state.state = MS_IDLE;
+    md->state.skillstate = MSS_IDLE;
+
+    if (md->skilltimer != -1)
+        return 0;
+
+    if (md->opt1 > 0 || md->option & 2)
+        return 0;
+
+    if (md->sc_data[SC_AUTOCOUNTER].timer != -1)
+        return 0;
+
+    if (md->sc_data[SC_BLADESTOP].timer != -1)
+        return 0;
+
+    if ((tbl = map_id2bl (md->target_id)) == NULL)
+    {
+        md->target_id = 0;
+        md->state.targettype = NONE_ATTACKABLE;
+        return 0;
+    }
+
+    if (tbl->type == BL_PC)
+        tsd = (struct map_session_data *) tbl;
+    else if (tbl->type == BL_MOB)
+        tmd = (struct mob_data *) tbl;
+    else
+        return 0;
+
+    if (tsd)
+    {
+        if (pc_isdead (tsd) || tsd->invincible_timer != -1
+            || pc_isinvisible (tsd) || md->bl.m != tbl->m || tbl->prev == NULL
+            || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
+        {
+            md->target_id = 0;
+            md->state.targettype = NONE_ATTACKABLE;
+            return 0;
+        }
+    }
+    if (tmd)
+    {
+        if (md->bl.m != tbl->m || tbl->prev == NULL
+            || distance (md->bl.x, md->bl.y, tbl->x, tbl->y) >= 13)
+        {
+            md->target_id = 0;
+            md->state.targettype = NONE_ATTACKABLE;
+            return 0;
+        }
+    }
+
+    if (!md->mode)
+        mode = mob_db[md->mob_class].mode;
+    else
+        mode = md->mode;
+
+    race = mob_db[md->mob_class].race;
+    if (!(mode & 0x80))
+    {
+        md->target_id = 0;
+        md->state.targettype = NONE_ATTACKABLE;
+        return 0;
+    }
+    if (tsd && !(mode & 0x20) && (tsd->sc_data[SC_TRICKDEAD].timer != -1 ||
+                                  ((pc_ishiding (tsd)
+                                    || tsd->state.gangsterparadise)
+                                   && race != 4 && race != 6)))
+    {
+        md->target_id = 0;
+        md->state.targettype = NONE_ATTACKABLE;
+        return 0;
+    }
+
+    range = mob_db[md->mob_class].range;
+    if (mode & 1)
+        range++;
+    if (distance (md->bl.x, md->bl.y, tbl->x, tbl->y) > range)
+        return 0;
+
+    return 1;
+}
+
+static int mob_ancillary_attack(struct block_list *bl, va_list ap)
+{
+    struct block_list *mdbl = va_arg(ap, struct block_list *);
+    struct block_list *tbl = va_arg(ap, struct block_list *);
+    unsigned int tick = va_arg(ap, unsigned int);
+    if (bl != tbl)
+        battle_weapon_attack(mdbl, bl, tick, 0);
+    return 0;
+}
+
+/*==========================================
+ * Attack processing of mob
+ *------------------------------------------
+ */
+static int mob_attack (struct mob_data *md, unsigned int tick, int data)
+{
+    struct block_list *tbl = NULL;
+
+    nullpo_retr (0, md);
+
+    if ((tbl = map_id2bl (md->target_id)) == NULL)
+        return 0;
+
+    if (!mob_check_attack (md))
+        return 0;
+
+    if (battle_config.monster_attack_direction_change)
+        md->dir = map_calc_dir (&md->bl, tbl->x, tbl->y);   // 向き設定
+
+    //clif_fixmobpos(md);
+
+    md->state.skillstate = MSS_ATTACK;
+    if (mobskill_use (md, tick, -2))    // スキル使用
+        return 0;
+
+    md->target_lv = battle_weapon_attack (&md->bl, tbl, tick, 0);
+    // If you are reading this, please note:
+    // it is highly platform-specific that this even works at all.
+    int radius = battle_config.mob_splash_radius;
+    if (radius >= 0 && tbl->type == BL_PC && !map[tbl->m].flag.town)
+        map_foreachinarea(mob_ancillary_attack,
+            tbl->m, tbl->x - radius, tbl->y - radius, tbl->x + radius, tbl->y + radius,
+            BL_PC,
+            &md->bl, tbl, tick);
+
+    if (!(battle_config.monster_cloak_check_type & 2)
+        && md->sc_data[SC_CLOAKING].timer != -1)
+        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
+
+    md->attackabletime = tick + battle_get_adelay (&md->bl);
+
+    md->timer = add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
+    md->state.state = MS_ATTACK;
+
+    return 0;
+}
+
+/*==========================================
+ * The attack of PC which is attacking id is stopped.
+ * The callback function of clif_foreachclient
+ *------------------------------------------
+ */
+int mob_stopattacked (struct map_session_data *sd, va_list ap)
+{
+    int  id;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, ap);
+
+    id = va_arg (ap, int);
+    if (sd->attacktarget == id)
+        pc_stopattack (sd);
+    return 0;
+}
+
+/*==========================================
+ * The timer in which the mob's states changes
+ *------------------------------------------
+ */
+int mob_changestate (struct mob_data *md, int state, int type)
+{
+    unsigned int tick;
+    int  i;
+
+    nullpo_retr (0, md);
+
+    if (md->timer != -1)
+        delete_timer (md->timer, mob_timer);
+    md->timer = -1;
+    md->state.state = state;
+
+    switch (state)
+    {
+        case MS_WALK:
+            if ((i = calc_next_walk_step (md)) > 0)
+            {
+                i = i >> 2;
+                md->timer =
+                    add_timer (gettick () + i, mob_timer, md->bl.id, 0);
+            }
+            else
+                md->state.state = MS_IDLE;
+            break;
+        case MS_ATTACK:
+            tick = gettick ();
+            i = DIFF_TICK (md->attackabletime, tick);
+            if (i > 0 && i < 2000)
+                md->timer =
+                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
+            else if (type)
+            {
+                md->attackabletime = tick + battle_get_amotion (&md->bl);
+                md->timer =
+                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
+            }
+            else
+            {
+                md->attackabletime = tick + 1;
+                md->timer =
+                    add_timer (md->attackabletime, mob_timer, md->bl.id, 0);
+            }
+            break;
+        case MS_DELAY:
+            md->timer =
+                add_timer (gettick () + type, mob_timer, md->bl.id, 0);
+            break;
+        case MS_DEAD:
+            skill_castcancel (&md->bl, 0);
+//      mobskill_deltimer(md);
+            md->state.skillstate = MSS_DEAD;
+            md->last_deadtime = gettick ();
+            // Since it died, all aggressors' attack to this mob is stopped.
+            clif_foreachclient (mob_stopattacked, md->bl.id);
+            skill_unit_out_all (&md->bl, gettick (), 1);
+            skill_status_change_clear (&md->bl, 2); // The abnormalities in status are canceled.
+            skill_clear_unitgroup (&md->bl);    // All skill unit groups are deleted.
+            skill_cleartimerskill (&md->bl);
+            if (md->deletetimer != -1)
+                delete_timer (md->deletetimer, mob_timer_delete);
+            md->deletetimer = -1;
+            md->hp = md->target_id = md->attacked_id = 0;
+            md->state.targettype = NONE_ATTACKABLE;
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * timer processing of mob (timer function)
+ * It branches to a walk and an attack.
+ *------------------------------------------
+ */
+static void mob_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct mob_data *md;
+    struct block_list *bl;
+
+    if ((bl = map_id2bl (id)) == NULL)
+    {                           //攻撃してきた敵がもういないのは正常のようだ
+        return;
+    }
+
+    if (!bl || !bl->type || bl->type != BL_MOB)
+        return;
+
+    nullpo_retv (md = (struct mob_data *) bl);
+
+    if (!md->bl.type || md->bl.type != BL_MOB)
+        return;
+
+    if (md->timer != tid)
+    {
+        if (battle_config.error_log == 1)
+            printf ("mob_timer %d != %d\n", md->timer, tid);
+        return;
+    }
+    md->timer = -1;
+    if (md->bl.prev == NULL || md->state.state == MS_DEAD)
+        return;
+
+    map_freeblock_lock ();
+    switch (md->state.state)
+    {
+        case MS_WALK:
+            mob_check_attack (md);
+            mob_walk (md, tick, data);
+            break;
+        case MS_ATTACK:
+            mob_attack (md, tick, data);
+            break;
+        case MS_DELAY:
+            mob_changestate (md, MS_IDLE, 0);
+            break;
+        default:
+            if (battle_config.error_log == 1)
+                printf ("mob_timer : %d ?\n", md->state.state);
+            break;
+    }
+    map_freeblock_unlock ();
+    return;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int mob_walktoxy_sub (struct mob_data *md)
+{
+    struct walkpath_data wpd;
+
+    nullpo_retr (0, md);
+
+    if (path_search
+        (&wpd, md->bl.m, md->bl.x, md->bl.y, md->to_x, md->to_y,
+         md->state.walk_easy))
+        return 1;
+    memcpy (&md->walkpath, &wpd, sizeof (wpd));
+
+    md->state.change_walk_target = 0;
+    mob_changestate (md, MS_WALK, 0);
+    clif_movemob (md);
+
+    return 0;
+}
+
+/*==========================================
+ * mob move start
+ *------------------------------------------
+ */
+int mob_walktoxy (struct mob_data *md, int x, int y, int easy)
+{
+    struct walkpath_data wpd;
+
+    nullpo_retr (0, md);
+
+    if (md->state.state == MS_WALK
+        && path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, x, y, easy))
+        return 1;
+
+    md->state.walk_easy = easy;
+    md->to_x = x;
+    md->to_y = y;
+    if (md->state.state == MS_WALK)
+    {
+        md->state.change_walk_target = 1;
+    }
+    else
+    {
+        return mob_walktoxy_sub (md);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * mob spawn with delay (timer function)
+ *------------------------------------------
+ */
+static void mob_delayspawn (timer_id tid, tick_t tick, custom_id_t m, custom_data_t n)
+{
+    mob_spawn (m);
+}
+
+/*==========================================
+ * spawn timing calculation
+ *------------------------------------------
+ */
+int mob_setdelayspawn (int id)
+{
+    unsigned int spawntime, spawntime1, spawntime2, spawntime3;
+    struct mob_data *md;
+    struct block_list *bl;
+
+    if ((bl = map_id2bl (id)) == NULL)
+        return -1;
+
+    if (!bl || !bl->type || bl->type != BL_MOB)
+        return -1;
+
+    nullpo_retr (-1, md = (struct mob_data *) bl);
+
+    if (!md || md->bl.type != BL_MOB)
+        return -1;
+
+    // Processing of MOB which is not revitalized
+    if (md->spawndelay1 == -1 && md->spawndelay2 == -1 && md->n == 0)
+    {
+        map_deliddb (&md->bl);
+        if (md->lootitem)
+        {
+            map_freeblock (md->lootitem);
+            md->lootitem = NULL;
+        }
+        map_freeblock (md);     // Instead of [ of free ]
+        return 0;
+    }
+
+    spawntime1 = md->last_spawntime + md->spawndelay1;
+    spawntime2 = md->last_deadtime + md->spawndelay2;
+    spawntime3 = gettick () + 5000;
+    // spawntime = max(spawntime1,spawntime2,spawntime3);
+    if (DIFF_TICK (spawntime1, spawntime2) > 0)
+    {
+        spawntime = spawntime1;
+    }
+    else
+    {
+        spawntime = spawntime2;
+    }
+    if (DIFF_TICK (spawntime3, spawntime) > 0)
+    {
+        spawntime = spawntime3;
+    }
+
+    add_timer (spawntime, mob_delayspawn, id, 0);
+    return 0;
+}
+
+/*==========================================
+ * Mob spawning. Initialization is also variously here.
+ *------------------------------------------
+ */
+int mob_spawn (int id)
+{
+    int  x = 0, y = 0, i = 0, c;
+    unsigned int tick = gettick ();
+    struct mob_data *md;
+    struct block_list *bl;
+
+    nullpo_retr (-1, bl = map_id2bl (id));
+
+    if (!bl || !bl->type || bl->type != BL_MOB)
+        return -1;
+
+    nullpo_retr (-1, md = (struct mob_data *) bl);
+
+    if (!md || !md->bl.type || md->bl.type != BL_MOB)
+        return -1;
+
+    md->last_spawntime = tick;
+    if (md->bl.prev != NULL)
+    {
+//      clif_clearchar_area(&md->bl,3);
+        skill_unit_out_all (&md->bl, gettick (), 1);
+        map_delblock (&md->bl);
+    }
+    else
+        md->mob_class = md->base_class;
+
+    md->bl.m = md->m;
+    do
+    {
+        if (md->x0 == 0 && md->y0 == 0)
+        {
+            x = MPRAND (1, (map[md->bl.m].xs - 2));
+            y = MPRAND (1, (map[md->bl.m].ys - 2));
+        }
+        else
+        {
+            x = MPRAND (md->x0, (md->xs + 1)) - md->xs / 2;
+            y = MPRAND (md->y0, (md->ys + 1)) - md->ys / 2;
+        }
+        i++;
+    }
+    while (((c = map_getcell (md->bl.m, x, y)) == 1 || c == 5) && i < 50);
+
+    if (i >= 50)
+    {
+//      if(battle_config.error_log==1)
+//          printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
+        add_timer (tick + 5000, mob_delayspawn, id, 0);
+        return 1;
+    }
+
+    md->to_x = md->bl.x = x;
+    md->to_y = md->bl.y = y;
+    md->dir = 0;
+
+    map_addblock (&md->bl);
+
+    memset (&md->state, 0, sizeof (md->state));
+    md->attacked_id = 0;
+    md->target_id = 0;
+    md->move_fail_count = 0;
+    mob_init (md);
+
+    if (!md->stats[MOB_SPEED])
+        md->stats[MOB_SPEED] = mob_db[md->mob_class].speed;
+    md->def_ele = mob_db[md->mob_class].element;
+    md->master_id = 0;
+    md->master_dist = 0;
+
+    md->state.state = MS_IDLE;
+    md->state.skillstate = MSS_IDLE;
+    md->timer = -1;
+    md->last_thinktime = tick;
+    md->next_walktime = tick + MPRAND (5000, 50);
+    md->attackabletime = tick;
+    md->canmove_tick = tick;
+
+    md->sg_count = 0;
+    md->deletetimer = -1;
+
+    md->skilltimer = -1;
+    for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
+        md->skilldelay[i] = c;
+    md->skillid = 0;
+    md->skilllv = 0;
+
+    memset (md->dmglog, 0, sizeof (md->dmglog));
+    if (md->lootitem)
+        memset (md->lootitem, 0, sizeof (md->lootitem));
+    md->lootitem_count = 0;
+
+    for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
+        md->skilltimerskill[i].timer = -1;
+
+    for (i = 0; i < MAX_STATUSCHANGE; i++)
+    {
+        md->sc_data[i].timer = -1;
+        md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 =
+            md->sc_data[i].val4 = 0;
+    }
+    md->sc_count = 0;
+    md->opt1 = md->opt2 = md->opt3 = md->option = 0;
+
+    memset (md->skillunit, 0, sizeof (md->skillunit));
+    memset (md->skillunittick, 0, sizeof (md->skillunittick));
+
+    md->hp = battle_get_max_hp (&md->bl);
+    if (md->hp <= 0)
+    {
+        mob_makedummymobdb (md->mob_class);
+        md->hp = battle_get_max_hp (&md->bl);
+    }
+
+    clif_spawnmob (md);
+
+    return 0;
+}
+
+/*==========================================
+ * Distance calculation between two points
+ *------------------------------------------
+ */
+static int distance (int x0, int y0, int x1, int y1)
+{
+    int  dx, dy;
+
+    dx = abs (x0 - x1);
+    dy = abs (y0 - y1);
+    return dx > dy ? dx : dy;
+}
+
+/*==========================================
+ * The stop of MOB's attack
+ *------------------------------------------
+ */
+int mob_stopattack (struct mob_data *md)
+{
+    md->target_id = 0;
+    md->state.targettype = NONE_ATTACKABLE;
+    md->attacked_id = 0;
+    return 0;
+}
+
+/*==========================================
+ * The stop of MOB's walking
+ *------------------------------------------
+ */
+int mob_stop_walking (struct mob_data *md, int type)
+{
+    nullpo_retr (0, md);
+
+    if (md->state.state == MS_WALK || md->state.state == MS_IDLE)
+    {
+        int  dx = 0, dy = 0;
+
+        md->walkpath.path_len = 0;
+        if (type & 4)
+        {
+            dx = md->to_x - md->bl.x;
+            if (dx < 0)
+                dx = -1;
+            else if (dx > 0)
+                dx = 1;
+            dy = md->to_y - md->bl.y;
+            if (dy < 0)
+                dy = -1;
+            else if (dy > 0)
+                dy = 1;
+        }
+        md->to_x = md->bl.x + dx;
+        md->to_y = md->bl.y + dy;
+        if (dx != 0 || dy != 0)
+        {
+            mob_walktoxy_sub (md);
+            return 0;
+        }
+        mob_changestate (md, MS_IDLE, 0);
+    }
+    if (type & 0x01)
+        clif_fixmobpos (md);
+    if (type & 0x02)
+    {
+        int  delay = battle_get_dmotion (&md->bl);
+        unsigned int tick = gettick ();
+        if (md->canmove_tick < tick)
+            md->canmove_tick = tick + delay;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Reachability to a Specification ID existence place
+ *------------------------------------------
+ */
+int mob_can_reach (struct mob_data *md, struct block_list *bl, int range)
+{
+    int  dx, dy;
+    struct walkpath_data wpd;
+    int  i;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, bl);
+
+    dx = abs (bl->x - md->bl.x);
+    dy = abs (bl->y - md->bl.y);
+
+    //=========== guildcastle guardian no search start===========
+    //when players are the guild castle member not attack them !
+    if (md->mob_class == 1285 || md->mob_class == 1286 || md->mob_class == 1287)
+    {
+        struct map_session_data *sd;
+        struct guild *g = NULL;
+        struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
+
+        if (gc && agit_flag == 0)   // Guardians will not attack during non-woe time [Valaris]
+            return 0;           // end addition [Valaris]
+
+        if (bl && bl->type == BL_PC)
+        {
+            if ((sd = (struct map_session_data *) bl) == NULL)
+            {
+                printf ("mob_can_reach nullpo\n");
+                return 0;
+            }
+
+            if (gc && sd && sd->status.guild_id && sd->status.guild_id > 0)
+            {
+                g = guild_search (sd->status.guild_id); // don't attack guild members [Valaris]
+                if (g && g->guild_id > 0 && g->guild_id == gc->guild_id)
+                    return 0;
+                if (g && gc && guild_isallied (g, gc))
+                    return 0;
+
+            }
+        }
+    }
+    //========== guildcastle guardian no search eof==============
+
+    if (bl && bl->type == BL_PC && battle_config.monsters_ignore_gm == 1)
+    {                           // option to have monsters ignore GMs [Valaris]
+        struct map_session_data *sd;
+        if ((sd = (struct map_session_data *) bl) != NULL && pc_isGM (sd))
+            return 0;
+    }
+
+    if (md->bl.m != bl->m)      // 違うャbプ
+        return 0;
+
+    if (range > 0 && range < ((dx > dy) ? dx : dy)) // 遠すぎる
+        return 0;
+
+    if (md->bl.x == bl->x && md->bl.y == bl->y) // 同じャX
+        return 1;
+
+    // Obstacle judging
+    wpd.path_len = 0;
+    wpd.path_pos = 0;
+    wpd.path_half = 0;
+    if (path_search (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0) !=
+        -1)
+        return 1;
+
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+        return 0;
+
+    // It judges whether it can adjoin or not.
+    dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
+    dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
+    if (path_search
+        (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - dx, bl->y - dy, 0) != -1)
+        return 1;
+    for (i = 0; i < 9; i++)
+    {
+        if (path_search
+            (&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x - 1 + i / 3,
+             bl->y - 1 + i % 3, 0) != -1)
+            return 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ * Determination for an attack of a monster
+ *------------------------------------------
+ */
+int mob_target (struct mob_data *md, struct block_list *bl, int dist)
+{
+    struct map_session_data *sd;
+    struct status_change *sc_data;
+    short *option;
+    int  mode, race;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, bl);
+
+    sc_data = battle_get_sc_data (bl);
+    option = battle_get_option (bl);
+    race = mob_db[md->mob_class].race;
+
+    if (!md->mode)
+    {
+        mode = mob_db[md->mob_class].mode;
+    }
+    else
+    {
+        mode = md->mode;
+    }
+    if (!(mode & 0x80))
+    {
+        md->target_id = 0;
+        return 0;
+    }
+    // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending.
+    if ((md->target_id > 0 && md->state.targettype == ATTACKABLE)
+        && (!(mode & 0x04) || MRAND (100) > 25))
+        return 0;
+
+    if (mode & 0x20 ||          // Coercion is exerted if it is MVPMOB.
+        (sc_data && sc_data[SC_TRICKDEAD].timer == -1 &&
+         ((option && !(*option & 0x06)) || race == 4 || race == 6)))
+    {
+        if (bl->type == BL_PC)
+        {
+            nullpo_retr (0, sd = (struct map_session_data *) bl);
+            if (sd->invincible_timer != -1 || pc_isinvisible (sd))
+                return 0;
+            if (!(mode & 0x20) && race != 4 && race != 6
+                && sd->state.gangsterparadise)
+                return 0;
+        }
+
+        md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
+        if (bl->type == BL_PC || bl->type == BL_MOB)
+            md->state.targettype = ATTACKABLE;
+        else
+            md->state.targettype = NONE_ATTACKABLE;
+        md->min_chase = dist + 13;
+        if (md->min_chase > 26)
+            md->min_chase = 26;
+    }
+    return 0;
+}
+
+/*==========================================
+ * The ?? routine of an active monster
+ *------------------------------------------
+ */
+static int mob_ai_sub_hard_activesearch (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *tsd = NULL;
+    struct mob_data *smd, *tmd = NULL;
+    int  mode, race, dist, *pcc;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, smd = va_arg (ap, struct mob_data *));
+    nullpo_retr (0, pcc = va_arg (ap, int *));
+
+    if (bl->type == BL_PC)
+        tsd = (struct map_session_data *) bl;
+    else if (bl->type == BL_MOB)
+        tmd = (struct mob_data *) bl;
+    else
+        return 0;
+
+    //敵味方判定
+    if (battle_check_target (&smd->bl, bl, BCT_ENEMY) == 0)
+        return 0;
+
+    if (!smd->mode)
+        mode = mob_db[smd->mob_class].mode;
+    else
+        mode = smd->mode;
+
+    // アクティブでターゲット射程内にいるなら、ロックする
+    if (mode & 0x04)
+    {
+        race = mob_db[smd->mob_class].race;
+        //対象がPCの場合
+        if (tsd &&
+            !pc_isdead (tsd) &&
+            tsd->bl.m == smd->bl.m &&
+            tsd->invincible_timer == -1 &&
+            !pc_isinvisible (tsd) &&
+            (dist =
+             distance (smd->bl.x, smd->bl.y, tsd->bl.x, tsd->bl.y)) < 9)
+        {
+            if (mode & 0x20 ||
+                (tsd->sc_data[SC_TRICKDEAD].timer == -1 &&
+                 ((!pc_ishiding (tsd) && !tsd->state.gangsterparadise)
+                  || race == 4 || race == 6)))
+            {                   // 妨害がないか判定
+                if (mob_can_reach (smd, bl, 12) &&  // 到達可能性判定
+                    MRAND (1000) < 1000 / (++(*pcc)))
+                {               // 範囲内PCで等確率にする
+                    smd->target_id = tsd->bl.id;
+                    smd->state.targettype = ATTACKABLE;
+                    smd->min_chase = 13;
+                }
+            }
+        }
+        //対象がMobの場合
+        else if (tmd &&
+                 tmd->bl.m == smd->bl.m &&
+                 (dist =
+                  distance (smd->bl.x, smd->bl.y, tmd->bl.x, tmd->bl.y)) < 9)
+        {
+            if (mob_can_reach (smd, bl, 12) &&  // 到達可能性判定
+                MRAND (1000) < 1000 / (++(*pcc)))
+            {                   // 範囲内で等確率にする
+                smd->target_id = bl->id;
+                smd->state.targettype = ATTACKABLE;
+                smd->min_chase = 13;
+            }
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * loot monster item search
+ *------------------------------------------
+ */
+static int mob_ai_sub_hard_lootsearch (struct block_list *bl, va_list ap)
+{
+    struct mob_data *md;
+    int  mode, dist, *itc;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
+    nullpo_retr (0, itc = va_arg (ap, int *));
+
+    if (!md->mode)
+    {
+        mode = mob_db[md->mob_class].mode;
+    }
+    else
+    {
+        mode = md->mode;
+    }
+
+    if (!md->target_id && mode & 0x02)
+    {
+        if (!md->lootitem
+            || (battle_config.monster_loot_type == 1
+                && md->lootitem_count >= LOOTITEM_SIZE))
+            return 0;
+        if (bl->m == md->bl.m
+            && (dist = distance (md->bl.x, md->bl.y, bl->x, bl->y)) < 9)
+        {
+            if (mob_can_reach (md, bl, 12) &&   // Reachability judging
+                MRAND (1000) < 1000 / (++(*itc)))
+            {                   // It is made a probability, such as within the limits PC.
+                md->target_id = bl->id;
+                md->state.targettype = NONE_ATTACKABLE;
+                md->min_chase = 13;
+            }
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * The ?? routine of a link monster
+ *------------------------------------------
+ */
+static int mob_ai_sub_hard_linksearch (struct block_list *bl, va_list ap)
+{
+    struct mob_data *tmd;
+    struct mob_data *md;
+    struct block_list *target;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, tmd = (struct mob_data *) bl);
+    nullpo_retr (0, md = va_arg (ap, struct mob_data *));
+    nullpo_retr (0, target = va_arg (ap, struct block_list *));
+
+    // same family free in a range at a link monster -- it will be made to lock if MOB is
+/*	if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->mob_class].mode&0x08){
+		if( tmd->mob_class==md->mob_class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
+			if( mob_can_reach(tmd,target,12) ){	// Reachability judging
+				tmd->target_id=md->target_id;
+				tmd->state.targettype = ATTACKABLE;
+				tmd->min_chase=13;
+			}
+		}
+	}*/
+    if (md->attacked_id > 0 && mob_db[md->mob_class].mode & 0x08)
+    {
+        if (tmd->mob_class == md->mob_class && tmd->bl.m == md->bl.m
+            && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE))
+        {
+            if (mob_can_reach (tmd, target, 12))
+            {                   // Reachability judging
+                tmd->target_id = md->attacked_id;
+                tmd->state.targettype = ATTACKABLE;
+                tmd->min_chase = 13;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Processing of slave monsters
+ *------------------------------------------
+ */
+static int mob_ai_sub_hard_slavemob (struct mob_data *md, unsigned int tick)
+{
+    struct mob_data *mmd = NULL;
+    struct block_list *bl;
+    int  mode, race, old_dist;
+
+    nullpo_retr (0, md);
+
+    if ((bl = map_id2bl (md->master_id)) != NULL)
+        mmd = (struct mob_data *) bl;
+
+    mode = mob_db[md->mob_class].mode;
+
+    // It is not main monster/leader.
+    if (!mmd || mmd->bl.type != BL_MOB || mmd->bl.id != md->master_id)
+        return 0;
+
+    // Since it is in the map on which the master is not, teleport is carried out and it pursues.
+    if (mmd->bl.m != md->bl.m)
+    {
+        mob_warp (md, mmd->bl.m, mmd->bl.x, mmd->bl.y, 3);
+        md->state.master_check = 1;
+        return 0;
+    }
+
+    // Distance with between slave and master is measured.
+    old_dist = md->master_dist;
+    md->master_dist = distance (md->bl.x, md->bl.y, mmd->bl.x, mmd->bl.y);
+
+    // Since the master was in near immediately before, teleport is carried out and it pursues.
+    if (old_dist < 10 && md->master_dist > 18)
+    {
+        mob_warp (md, -1, mmd->bl.x, mmd->bl.y, 3);
+        md->state.master_check = 1;
+        return 0;
+    }
+
+    // Although there is the master, since it is somewhat far, it approaches.
+    if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
+        && mob_can_move (md)
+        && (md->walkpath.path_pos >= md->walkpath.path_len
+            || md->walkpath.path_len == 0) && md->master_dist < 15)
+    {
+        int  i = 0, dx, dy, ret;
+        if (md->master_dist > 4)
+        {
+            do
+            {
+                if (i <= 5)
+                {
+                    dx = mmd->bl.x - md->bl.x;
+                    dy = mmd->bl.y - md->bl.y;
+                    if (dx < 0)
+                        dx += (MPRAND (1, ((dx < -3) ? 3 : -dx)));
+                    else if (dx > 0)
+                        dx -= (MPRAND (1, ((dx > 3) ? 3 : dx)));
+                    if (dy < 0)
+                        dy += (MPRAND (1, ((dy < -3) ? 3 : -dy)));
+                    else if (dy > 0)
+                        dy -= (MPRAND (1, ((dy > 3) ? 3 : dy)));
+                }
+                else
+                {
+                    dx = mmd->bl.x - md->bl.x + MRAND (7) - 3;
+                    dy = mmd->bl.y - md->bl.y + MRAND (7) - 3;
+                }
+
+                ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
+                i++;
+            }
+            while (ret && i < 10);
+        }
+        else
+        {
+            do
+            {
+                dx = MRAND (9) - 5;
+                dy = MRAND (9) - 5;
+                if (dx == 0 && dy == 0)
+                {
+                    dx = (MRAND (1)) ? 1 : -1;
+                    dy = (MRAND (1)) ? 1 : -1;
+                }
+                dx += mmd->bl.x;
+                dy += mmd->bl.y;
+
+                ret = mob_walktoxy (md, mmd->bl.x + dx, mmd->bl.y + dy, 0);
+                i++;
+            }
+            while (ret && i < 10);
+        }
+
+        md->next_walktime = tick + 500;
+        md->state.master_check = 1;
+    }
+
+    // There is the master, the master locks a target and he does not lock.
+    if ((mmd->target_id > 0 && mmd->state.targettype == ATTACKABLE)
+        && (!md->target_id || md->state.targettype == NONE_ATTACKABLE))
+    {
+        struct map_session_data *sd = map_id2sd (mmd->target_id);
+        if (sd != NULL && !pc_isdead (sd) && sd->invincible_timer == -1
+            && !pc_isinvisible (sd))
+        {
+
+            race = mob_db[md->mob_class].race;
+            if (mode & 0x20 ||
+                (sd->sc_data[SC_TRICKDEAD].timer == -1 &&
+                 ((!pc_ishiding (sd) && !sd->state.gangsterparadise)
+                  || race == 4 || race == 6)))
+            {                   // 妨害がないか判定
+
+                md->target_id = sd->bl.id;
+                md->state.targettype = ATTACKABLE;
+                md->min_chase =
+                    5 + distance (md->bl.x, md->bl.y, sd->bl.x, sd->bl.y);
+                md->state.master_check = 1;
+            }
+        }
+    }
+
+    // There is the master, the master locks a target and he does not lock.
+/*	if( (md->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!mmd->target_id || mmd->state.targettype == NONE_ATTACKABLE) ){
+		struct map_session_data *sd=map_id2sd(md->target_id);
+		if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
+
+			race=mob_db[mmd->mob_class].race;
+			if(mode&0x20 ||
+				(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
+				(!(sd->status.option&0x06) || race==4 || race==6)
+				) ){	// It judges whether there is any disturbance.
+
+				mmd->target_id=sd->bl.id;
+				mmd->state.targettype = ATTACKABLE;
+				mmd->min_chase=5+distance(mmd->bl.x,mmd->bl.y,sd->bl.x,sd->bl.y);
+			}
+		}
+	}*/
+
+    return 0;
+}
+
+/*==========================================
+ * A lock of target is stopped and mob moves to a standby state.
+ *------------------------------------------
+ */
+static int mob_unlocktarget (struct mob_data *md, int tick)
+{
+    nullpo_retr (0, md);
+
+    md->target_id = 0;
+    md->state.targettype = NONE_ATTACKABLE;
+    md->state.skillstate = MSS_IDLE;
+    md->next_walktime = tick + MPRAND (3000, 3000);
+    return 0;
+}
+
+/*==========================================
+ * Random walk
+ *------------------------------------------
+ */
+static int mob_randomwalk (struct mob_data *md, int tick)
+{
+    const int retrycount = 20;
+    int  speed;
+
+    nullpo_retr (0, md);
+
+    speed = battle_get_speed (&md->bl);
+    if (DIFF_TICK (md->next_walktime, tick) < 0)
+    {
+        int  i, x, y, c, d = 12 - md->move_fail_count;
+        if (d < 5)
+            d = 5;
+        for (i = 0; i < retrycount; i++)
+        {                       // Search of a movable place
+            int  r = mt_random ();
+            x = md->bl.x + r % (d * 2 + 1) - d;
+            y = md->bl.y + r / (d * 2 + 1) % (d * 2 + 1) - d;
+            if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5
+                && mob_walktoxy (md, x, y, 1) == 0)
+            {
+                md->move_fail_count = 0;
+                break;
+            }
+            if (i + 1 >= retrycount)
+            {
+                md->move_fail_count++;
+                if (md->move_fail_count > 1000)
+                {
+                    if (battle_config.error_log == 1)
+                        printf
+                            ("MOB cant move. random spawn %d, mob_class = %d\n",
+                             md->bl.id, md->mob_class);
+                    md->move_fail_count = 0;
+                    mob_spawn (md->bl.id);
+                }
+            }
+        }
+        for (i = c = 0; i < md->walkpath.path_len; i++)
+        {                       // The next walk start time is calculated.
+            if (md->walkpath.path[i] & 1)
+                c += speed * 14 / 10;
+            else
+                c += speed;
+        }
+        md->next_walktime = tick + MPRAND (3000, 3000) + c;
+        md->state.skillstate = MSS_WALK;
+        return 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ * AI of MOB whose is near a Player
+ *------------------------------------------
+ */
+static int mob_ai_sub_hard (struct block_list *bl, va_list ap)
+{
+    struct mob_data *md, *tmd = NULL;
+    struct map_session_data *tsd = NULL;
+    struct block_list *tbl = NULL;
+    struct flooritem_data *fitem;
+    unsigned int tick;
+    int  i, dx, dy, ret, dist;
+    int  attack_type = 0;
+    int  mode, race;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = (struct mob_data *) bl);
+
+    tick = va_arg (ap, unsigned int);
+
+    if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME)
+        return 0;
+    md->last_thinktime = tick;
+
+    if (md->skilltimer != -1 || md->bl.prev == NULL)
+    {                           // Under a skill aria and death
+        if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME)
+            md->next_walktime = tick;
+        return 0;
+    }
+
+    if (!md->mode)
+        mode = mob_db[md->mob_class].mode;
+    else
+        mode = md->mode;
+
+    race = mob_db[md->mob_class].race;
+
+    // Abnormalities
+    if ((md->opt1 > 0 && md->opt1 != 6) || md->state.state == MS_DELAY
+        || md->sc_data[SC_BLADESTOP].timer != -1)
+        return 0;
+
+    if (!(mode & 0x80) && md->target_id > 0)
+        md->target_id = 0;
+
+    if (md->attacked_id > 0 && mode & 0x08)
+    {                           // Link monster
+        struct map_session_data *asd = map_id2sd (md->attacked_id);
+        if (asd)
+        {
+            if (asd->invincible_timer == -1 && !pc_isinvisible (asd))
+            {
+                map_foreachinarea (mob_ai_sub_hard_linksearch, md->bl.m,
+                                   md->bl.x - 13, md->bl.y - 13,
+                                   md->bl.x + 13, md->bl.y + 13,
+                                   BL_MOB, md, &asd->bl);
+            }
+        }
+    }
+
+    // It checks to see it was attacked first (if active, it is target change at 25% of probability).
+    if (mode > 0 && md->attacked_id > 0
+        && (!md->target_id || md->state.targettype == NONE_ATTACKABLE
+            || (mode & 0x04 && MRAND (100) < 25)))
+    {
+        struct block_list *abl = map_id2bl (md->attacked_id);
+        struct map_session_data *asd = NULL;
+        if (abl)
+        {
+            if (abl->type == BL_PC)
+                asd = (struct map_session_data *) abl;
+            if (asd == NULL || md->bl.m != abl->m || abl->prev == NULL
+                || asd->invincible_timer != -1 || pc_isinvisible (asd)
+                || (dist =
+                    distance (md->bl.x, md->bl.y, abl->x, abl->y)) >= 32
+                || battle_check_target (bl, abl, BCT_ENEMY) == 0)
+                md->attacked_id = 0;
+            else
+            {
+                md->target_id = md->attacked_id;    // set target
+                md->state.targettype = ATTACKABLE;
+                attack_type = 1;
+                md->attacked_id = 0;
+                md->min_chase = dist + 13;
+                if (md->min_chase > 26)
+                    md->min_chase = 26;
+            }
+        }
+    }
+
+    md->state.master_check = 0;
+    // Processing of slave monster
+    if (md->master_id > 0 && md->state.special_mob_ai == 0)
+        mob_ai_sub_hard_slavemob (md, tick);
+
+    // アクティヴモンスターの策敵 (?? of a bitter taste TIVU monster)
+    if ((!md->target_id || md->state.targettype == NONE_ATTACKABLE)
+        && mode & 0x04 && !md->state.master_check
+        && battle_config.monster_active_enable == 1)
+    {
+        i = 0;
+        if (md->state.special_mob_ai)
+        {
+            map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
+                               md->bl.x - AREA_SIZE * 2,
+                               md->bl.y - AREA_SIZE * 2,
+                               md->bl.x + AREA_SIZE * 2,
+                               md->bl.y + AREA_SIZE * 2, 0, md, &i);
+        }
+        else
+        {
+            map_foreachinarea (mob_ai_sub_hard_activesearch, md->bl.m,
+                               md->bl.x - AREA_SIZE * 2,
+                               md->bl.y - AREA_SIZE * 2,
+                               md->bl.x + AREA_SIZE * 2,
+                               md->bl.y + AREA_SIZE * 2, BL_PC, md, &i);
+        }
+    }
+
+    // The item search of a route monster
+    if (!md->target_id && mode & 0x02 && !md->state.master_check)
+    {
+        i = 0;
+        map_foreachinarea (mob_ai_sub_hard_lootsearch, md->bl.m,
+                           md->bl.x - AREA_SIZE * 2, md->bl.y - AREA_SIZE * 2,
+                           md->bl.x + AREA_SIZE * 2, md->bl.y + AREA_SIZE * 2,
+                           BL_ITEM, md, &i);
+    }
+
+    // It will attack, if the candidate for an attack is.
+    if (md->target_id > 0)
+    {
+        if ((tbl = map_id2bl (md->target_id)))
+        {
+            if (tbl->type == BL_PC)
+                tsd = (struct map_session_data *) tbl;
+            else if (tbl->type == BL_MOB)
+                tmd = (struct mob_data *) tbl;
+            if (tsd || tmd)
+            {
+                if (tbl->m != md->bl.m || tbl->prev == NULL
+                    || (dist =
+                        distance (md->bl.x, md->bl.y, tbl->x,
+                                  tbl->y)) >= md->min_chase)
+                    mob_unlocktarget (md, tick);    // 別マップか、視界外
+                else if (tsd && !(mode & 0x20)
+                         && (tsd->sc_data[SC_TRICKDEAD].timer != -1
+                             ||
+                             ((pc_ishiding (tsd)
+                               || tsd->state.gangsterparadise) && race != 4
+                              && race != 6)))
+                    mob_unlocktarget (md, tick);    // スキルなどによる策敵妨害
+                else if (!battle_check_range
+                         (&md->bl, tbl, mob_db[md->mob_class].range))
+                {
+                    // 攻撃範囲外なので移動
+                    if (!(mode & 1))
+                    {           // 移動しないモード
+                        mob_unlocktarget (md, tick);
+                        return 0;
+                    }
+                    if (!mob_can_move (md)) // 動けない状態にある
+                        return 0;
+                    md->state.skillstate = MSS_CHASE;   // 突撃時スキル
+                    mobskill_use (md, tick, -1);
+//                  if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tsd->bl.x,tsd->bl.y)<2) )
+                    if (md->timer != -1 && md->state.state != MS_ATTACK
+                        && (DIFF_TICK (md->next_walktime, tick) < 0
+                            || distance (md->to_x, md->to_y, tbl->x,
+                                         tbl->y) < 2))
+                        return 0;   // 既に移動中
+                    if (!mob_can_reach
+                        (md, tbl, (md->min_chase > 13) ? md->min_chase : 13))
+                        mob_unlocktarget (md, tick);    // 移動できないのでタゲ解除(IWとか?)
+                    else
+                    {
+                        // 追跡
+                        md->next_walktime = tick + 500;
+                        i = 0;
+                        do
+                        {
+                            if (i == 0)
+                            {   // 最初はAEGISと同じ方法で検索
+                                dx = tbl->x - md->bl.x;
+                                dy = tbl->y - md->bl.y;
+                                if (dx < 0)
+                                    dx++;
+                                else if (dx > 0)
+                                    dx--;
+                                if (dy < 0)
+                                    dy++;
+                                else if (dy > 0)
+                                    dy--;
+                            }
+                            else
+                            {   // だめならAthena式(ランダム)
+                                dx = tbl->x - md->bl.x + MRAND (3) - 1;
+                                dy = tbl->y - md->bl.y + MRAND (3) - 1;
+                            }
+                            /*                      if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
+                             * dx=tsd->bl.x - md->bl.x;
+                             * dy=tsd->bl.y - md->bl.y;
+                             * if(dx<0) dx--;
+                             * else if(dx>0) dx++;
+                             * if(dy<0) dy--;
+                             * else if(dy>0) dy++;
+                             * } */
+                            ret =
+                                mob_walktoxy (md, md->bl.x + dx,
+                                              md->bl.y + dy, 0);
+                            i++;
+                        }
+                        while (ret && i < 5);
+
+                        if (ret)
+                        {       // 移動不可能な所からの攻撃なら2歩下る
+                            if (dx < 0)
+                                dx = 2;
+                            else if (dx > 0)
+                                dx = -2;
+                            if (dy < 0)
+                                dy = 2;
+                            else if (dy > 0)
+                                dy = -2;
+                            mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy,
+                                          0);
+                        }
+                    }
+                }
+                else
+                {               // 攻撃射程範囲内
+                    md->state.skillstate = MSS_ATTACK;
+                    if (md->state.state == MS_WALK)
+                        mob_stop_walking (md, 1);   // 歩行中なら停止
+                    if (md->state.state == MS_ATTACK)
+                        return 0;   // 既に攻撃中
+                    mob_changestate (md, MS_ATTACK, attack_type);
+
+/*					if(mode&0x08){	// リンクモンスター
+					map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
+						md->bl.x-13,md->bl.y-13,
+						md->bl.x+13,md->bl.y+13,
+							BL_MOB,md,&tsd->bl);
+				}*/
+                }
+                return 0;
+            }
+            else
+            {                   // ルートモンスター処理
+                if (tbl == NULL || tbl->type != BL_ITEM || tbl->m != md->bl.m
+                    || (dist =
+                        distance (md->bl.x, md->bl.y, tbl->x,
+                                  tbl->y)) >= md->min_chase || !md->lootitem)
+                {
+                    // 遠すぎるかアイテムがなくなった
+                    mob_unlocktarget (md, tick);
+                    if (md->state.state == MS_WALK)
+                        mob_stop_walking (md, 1);   // 歩行中なら停止
+                }
+                else if (dist)
+                {
+                    if (!(mode & 1))
+                    {           // 移動しないモード
+                        mob_unlocktarget (md, tick);
+                        return 0;
+                    }
+                    if (!mob_can_move (md)) // 動けない状態にある
+                        return 0;
+                    md->state.skillstate = MSS_LOOT;    // ルート時スキル使用
+                    mobskill_use (md, tick, -1);
+//                  if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,tbl->x,tbl->y)<2) )
+                    if (md->timer != -1 && md->state.state != MS_ATTACK
+                        && (DIFF_TICK (md->next_walktime, tick) < 0
+                            || distance (md->to_x, md->to_y, tbl->x,
+                                         tbl->y) <= 0))
+                        return 0;   // 既に移動中
+                    md->next_walktime = tick + 500;
+                    dx = tbl->x - md->bl.x;
+                    dy = tbl->y - md->bl.y;
+/*				if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
+						dx=tbl->x - md->bl.x;
+						dy=tbl->y - md->bl.y;
+				}*/
+                    ret = mob_walktoxy (md, md->bl.x + dx, md->bl.y + dy, 0);
+                    if (ret)
+                        mob_unlocktarget (md, tick);    // 移動できないのでタゲ解除(IWとか?)
+                }
+                else
+                {               // アイテムまでたどり着いた
+                    if (md->state.state == MS_ATTACK)
+                        return 0;   // 攻撃中
+                    if (md->state.state == MS_WALK)
+                        mob_stop_walking (md, 1);   // 歩行中なら停止
+                    fitem = (struct flooritem_data *) tbl;
+                    if (md->lootitem_count < LOOTITEM_SIZE)
+                        memcpy (&md->lootitem[md->lootitem_count++],
+                                &fitem->item_data, sizeof (md->lootitem[0]));
+                    else if (battle_config.monster_loot_type == 1
+                             && md->lootitem_count >= LOOTITEM_SIZE)
+                    {
+                        mob_unlocktarget (md, tick);
+                        return 0;
+                    }
+                    else
+                    {
+                        for (i = 0; i < LOOTITEM_SIZE - 1; i++)
+                            memcpy (&md->lootitem[i], &md->lootitem[i + 1],
+                                    sizeof (md->lootitem[0]));
+                        memcpy (&md->lootitem[LOOTITEM_SIZE - 1],
+                                &fitem->item_data, sizeof (md->lootitem[0]));
+                    }
+                    map_clearflooritem (tbl->id);
+                    mob_unlocktarget (md, tick);
+                }
+                return 0;
+            }
+        }
+        else
+        {
+            mob_unlocktarget (md, tick);
+            if (md->state.state == MS_WALK)
+                mob_stop_walking (md, 4);   // 歩行中なら停止
+            return 0;
+        }
+    }
+
+    // It is skill use at the time of /standby at the time of a walk.
+    if (mobskill_use (md, tick, -1))
+        return 0;
+
+    // 歩行処理
+    if (mode & 1 && mob_can_move (md) &&    // 移動可能MOB&動ける状態にある
+        (md->master_id == 0 || md->state.special_mob_ai
+         || md->master_dist > 10))
+    {                           //取り巻きMOBじゃない
+
+        if (DIFF_TICK (md->next_walktime, tick) > +7000 &&
+            (md->walkpath.path_len == 0
+             || md->walkpath.path_pos >= md->walkpath.path_len))
+        {
+            md->next_walktime = tick + 3000 * MRAND (2000);
+        }
+
+        // Random movement
+        if (mob_randomwalk (md, tick))
+            return 0;
+    }
+
+    // Since he has finished walking, it stands by.
+    if (md->walkpath.path_len == 0
+        || md->walkpath.path_pos >= md->walkpath.path_len)
+        md->state.skillstate = MSS_IDLE;
+    return 0;
+}
+
+/*==========================================
+ * Serious processing for mob in PC field of view (foreachclient)
+ *------------------------------------------
+ */
+static int mob_ai_sub_foreachclient (struct map_session_data *sd, va_list ap)
+{
+    unsigned int tick;
+    nullpo_retr (0, sd);
+    nullpo_retr (0, ap);
+
+    tick = va_arg (ap, unsigned int);
+    map_foreachinarea (mob_ai_sub_hard, sd->bl.m,
+                       sd->bl.x - AREA_SIZE * 2, sd->bl.y - AREA_SIZE * 2,
+                       sd->bl.x + AREA_SIZE * 2, sd->bl.y + AREA_SIZE * 2,
+                       BL_MOB, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * Serious processing for mob in PC field of view   (interval timer function)
+ *------------------------------------------
+ */
+static void mob_ai_hard (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    clif_foreachclient (mob_ai_sub_foreachclient, tick);
+}
+
+/*==========================================
+ * Negligent mode MOB AI (PC is not in near)
+ *------------------------------------------
+ */
+static void mob_ai_sub_lazy (db_key_t key, db_val_t data, va_list app)
+{
+    struct mob_data *md = (struct mob_data *)data;
+    unsigned int tick;
+    va_list ap;
+
+    nullpo_retv (md);
+    nullpo_retv (app);
+    nullpo_retv (ap = va_arg (app, va_list));
+
+    if (md == NULL)
+        return;
+
+    if (!md->bl.type || md->bl.type != BL_MOB)
+        return;
+
+    tick = va_arg (ap, unsigned int);
+
+    if (DIFF_TICK (tick, md->last_thinktime) < MIN_MOBTHINKTIME * 10)
+        return;
+    md->last_thinktime = tick;
+
+    if (md->bl.prev == NULL || md->skilltimer != -1)
+    {
+        if (DIFF_TICK (tick, md->next_walktime) > MIN_MOBTHINKTIME * 10)
+            md->next_walktime = tick;
+        return;
+    }
+
+    if (DIFF_TICK (md->next_walktime, tick) < 0 &&
+        (mob_db[md->mob_class].mode & 1) && mob_can_move (md))
+    {
+
+        if (map[md->bl.m].users > 0)
+        {
+            // Since PC is in the same map, somewhat better negligent processing is carried out.
+
+            // It sometimes moves.
+            if (MRAND (1000) < MOB_LAZYMOVEPERC)
+                mob_randomwalk (md, tick);
+
+            // MOB which is not not the summons MOB but BOSS, either sometimes reboils.
+            else if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
+                     && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0
+                     && !(mob_db[md->mob_class].mode & 0x20))
+                mob_spawn (md->bl.id);
+
+        }
+        else
+        {
+            // Since PC is not even in the same map, suitable processing is carried out even if it takes.
+
+            // MOB which is not BOSS which is not Summons MOB, either -- a case -- sometimes -- leaping
+            if (MRAND (1000) < MOB_LAZYWARPPERC && md->x0 <= 0
+                && md->master_id != 0 && mob_db[md->mob_class].mexp <= 0
+                && !(mob_db[md->mob_class].mode & 0x20))
+                mob_warp (md, -1, -1, -1, -1);
+        }
+
+        md->next_walktime = tick + MPRAND (5000, 10000);
+    }
+}
+
+/*==========================================
+ * Negligent processing for mob outside PC field of view   (interval timer function)
+ *------------------------------------------
+ */
+static void mob_ai_lazy (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    map_foreachiddb (mob_ai_sub_lazy, tick);
+}
+
+/*==========================================
+ * The structure object for item drop with delay
+ * Since it is only two being able to pass [ int ] a timer function
+ * Data is put in and passed to this structure object.
+ *------------------------------------------
+ */
+struct delay_item_drop
+{
+    int  m, x, y;
+    int  nameid, amount;
+    struct map_session_data *first_sd, *second_sd, *third_sd;
+};
+
+struct delay_item_drop2
+{
+    int  m, x, y;
+    struct item item_data;
+    struct map_session_data *first_sd, *second_sd, *third_sd;
+};
+
+/*==========================================
+ * item drop with delay (timer function)
+ *------------------------------------------
+ */
+static void mob_delay_item_drop (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct delay_item_drop *ditem;
+    struct item temp_item;
+    int  flag;
+
+    nullpo_retv (ditem = (struct delay_item_drop *) id);
+
+    memset (&temp_item, 0, sizeof (temp_item));
+    temp_item.nameid = ditem->nameid;
+    temp_item.amount = ditem->amount;
+    temp_item.identify = !itemdb_isequip3 (temp_item.nameid);
+
+    if (battle_config.item_auto_get == 1)
+    {
+        if (ditem->first_sd
+            && (flag =
+                pc_additem (ditem->first_sd, &temp_item, ditem->amount)))
+        {
+            clif_additem (ditem->first_sd, 0, 0, flag);
+            map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
+                              ditem->first_sd, ditem->second_sd,
+                              ditem->third_sd, 0);
+        }
+        free (ditem);
+        return;
+    }
+
+    map_addflooritem (&temp_item, 1, ditem->m, ditem->x, ditem->y,
+                      ditem->first_sd, ditem->second_sd, ditem->third_sd, 0);
+
+    free (ditem);
+}
+
+/*==========================================
+ * item drop (timer function)-lootitem with delay
+ *------------------------------------------
+ */
+static void mob_delay_item_drop2 (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct delay_item_drop2 *ditem;
+    int  flag;
+
+    nullpo_retv (ditem = (struct delay_item_drop2 *) id);
+
+    if (battle_config.item_auto_get == 1)
+    {
+        if (ditem->first_sd
+            && (flag =
+                pc_additem (ditem->first_sd, &ditem->item_data,
+                            ditem->item_data.amount)))
+        {
+            clif_additem (ditem->first_sd, 0, 0, flag);
+            map_addflooritem (&ditem->item_data, ditem->item_data.amount,
+                              ditem->m, ditem->x, ditem->y, ditem->first_sd,
+                              ditem->second_sd, ditem->third_sd, 0);
+        }
+        free (ditem);
+        return;
+    }
+
+    map_addflooritem (&ditem->item_data, ditem->item_data.amount, ditem->m,
+                      ditem->x, ditem->y, ditem->first_sd, ditem->second_sd,
+                      ditem->third_sd, 0);
+
+    free (ditem);
+}
+
+/*==========================================
+ * mob data is erased.
+ *------------------------------------------
+ */
+int mob_delete (struct mob_data *md)
+{
+    nullpo_retr (1, md);
+
+    if (md->bl.prev == NULL)
+        return 1;
+    mob_changestate (md, MS_DEAD, 0);
+    clif_clearchar_area (&md->bl, 1);
+    map_delblock (&md->bl);
+    if (mob_get_viewclass (md->mob_class) <= 1000)
+        clif_clearchar_delay (gettick () + 3000, &md->bl, 0);
+    mob_deleteslave (md);
+    mob_setdelayspawn (md->bl.id);
+    return 0;
+}
+
+int mob_catch_delete (struct mob_data *md, int type)
+{
+    nullpo_retr (1, md);
+
+    if (md->bl.prev == NULL)
+        return 1;
+    mob_changestate (md, MS_DEAD, 0);
+    clif_clearchar_area (&md->bl, type);
+    map_delblock (&md->bl);
+    mob_setdelayspawn (md->bl.id);
+    return 0;
+}
+
+void mob_timer_delete (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct block_list *bl = map_id2bl (id);
+    struct mob_data *md;
+
+    nullpo_retv (bl);
+
+    md = (struct mob_data *) bl;
+    mob_catch_delete (md, 3);
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int mob_deleteslave_sub (struct block_list *bl, va_list ap)
+{
+    struct mob_data *md;
+    int  id;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = (struct mob_data *) bl);
+
+    id = va_arg (ap, int);
+    if (md->master_id > 0 && md->master_id == id)
+        mob_damage (NULL, md, md->hp, 1);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int mob_deleteslave (struct mob_data *md)
+{
+    nullpo_retr (0, md);
+
+    map_foreachinarea (mob_deleteslave_sub, md->bl.m,
+                       0, 0, map[md->bl.m].xs, map[md->bl.m].ys,
+                       BL_MOB, md->bl.id);
+    return 0;
+}
+
+#define DAMAGE_BONUS_COUNT 6    // max. number of players to account for
+const static double damage_bonus_factor[DAMAGE_BONUS_COUNT + 1] = {
+    1.0, 1.0, 2.0, 2.5, 2.75, 2.9, 3.0
+};
+
+/*==========================================
+ * It is the damage of sd to damage to md.
+ *------------------------------------------
+ */
+int mob_damage (struct block_list *src, struct mob_data *md, int damage,
+                int type)
+{
+    int  i, count, minpos, mindmg;
+    struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE];
+    struct
+    {
+        struct party *p;
+        int  id, base_exp, job_exp;
+    } pt[DAMAGELOG_SIZE];
+    int  pnum = 0;
+    int  mvp_damage, max_hp;
+    unsigned int tick = gettick ();
+    struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd =
+        NULL;
+    double dmg_rate, tdmg, temp;
+    struct item item;
+    int  ret;
+    int  drop_rate;
+    int  skill, sp;
+
+    nullpo_retr (0, md);        //srcはNULLで呼ばれる場合もあるので、他でチェック
+
+    if (src && src->id == md->master_id
+        && md->mode & MOB_MODE_TURNS_AGAINST_BAD_MASTER)
+    {
+        /* If the master hits a monster, have the monster turn against him */
+        md->master_id = 0;
+        md->mode = 0x85;        /* Regular war mode */
+        md->target_id = src->id;
+        md->attacked_id = src->id;
+    }
+
+    max_hp = battle_get_max_hp (&md->bl);
+
+    if (src && src->type == BL_PC)
+    {
+        sd = (struct map_session_data *) src;
+        mvp_sd = sd;
+    }
+
+//  if(battle_config.battle_log)
+//      printf("mob_damage %d %d %d\n",md->hp,max_hp,damage);
+    if (md->bl.prev == NULL)
+    {
+        if (battle_config.error_log == 1)
+            printf ("mob_damage : BlockError!!\n");
+        return 0;
+    }
+
+    if (md->state.state == MS_DEAD || md->hp <= 0)
+    {
+        if (md->bl.prev != NULL)
+        {
+            mob_changestate (md, MS_DEAD, 0);
+            mobskill_use (md, tick, -1);    // It is skill at the time of death.
+            clif_clearchar_area (&md->bl, 1);
+            map_delblock (&md->bl);
+            mob_setdelayspawn (md->bl.id);
+        }
+        return 0;
+    }
+
+    if (md->sc_data[SC_ENDURE].timer == -1)
+        mob_stop_walking (md, 3);
+    if (damage > max_hp >> 2)
+        skill_stop_dancing (&md->bl, 0);
+
+    if (md->hp > max_hp)
+        md->hp = max_hp;
+
+    // The amount of overkill rounds to hp.
+    if (damage > md->hp)
+        damage = md->hp;
+
+    if (!(type & 2))
+    {
+        if (sd != NULL)
+        {
+            for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
+                 i++)
+            {
+                if (md->dmglog[i].id == sd->bl.id)
+                    break;
+                if (md->dmglog[i].id == 0)
+                {
+                    minpos = i;
+                    mindmg = 0;
+                }
+                else if (md->dmglog[i].dmg < mindmg)
+                {
+                    minpos = i;
+                    mindmg = md->dmglog[i].dmg;
+                }
+            }
+            if (i < DAMAGELOG_SIZE)
+                md->dmglog[i].dmg += damage;
+            else
+            {
+                md->dmglog[minpos].id = sd->bl.id;
+                md->dmglog[minpos].dmg = damage;
+            }
+
+            if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
+                md->attacked_id = sd->bl.id;
+        }
+        if (src && src->type == BL_MOB
+            && ((struct mob_data *) src)->state.special_mob_ai)
+        {
+            struct mob_data *md2 = (struct mob_data *) src;
+            struct block_list *master_bl = map_id2bl (md2->master_id);
+            if (master_bl && master_bl->type == BL_PC)
+            {
+                MAP_LOG_PC (((struct map_session_data *) master_bl),
+                            "MOB-TO-MOB-DMG FROM MOB%d %d TO MOB%d %d FOR %d",
+                            md2->bl.id, md2->mob_class, md->bl.id, md->mob_class,
+                            damage);
+            }
+
+            nullpo_retr (0, md2);
+            for (i = 0, minpos = 0, mindmg = 0x7fffffff; i < DAMAGELOG_SIZE;
+                 i++)
+            {
+                if (md->dmglog[i].id == md2->master_id)
+                    break;
+                if (md->dmglog[i].id == 0)
+                {
+                    minpos = i;
+                    mindmg = 0;
+                }
+                else if (md->dmglog[i].dmg < mindmg)
+                {
+                    minpos = i;
+                    mindmg = md->dmglog[i].dmg;
+                }
+            }
+            if (i < DAMAGELOG_SIZE)
+                md->dmglog[i].dmg += damage;
+            else
+            {
+                md->dmglog[minpos].id = md2->master_id;
+                md->dmglog[minpos].dmg = damage;
+
+                if (md->attacked_id <= 0 && md->state.special_mob_ai == 0)
+                    md->attacked_id = md2->master_id;
+            }
+        }
+
+    }
+
+    md->hp -= damage;
+
+    if (md->mob_class >= 1285 && md->mob_class <= 1287)
+    {                           // guardian hp update [Valaris]
+        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
+        if (gc)
+        {
+
+            if (md->bl.id == gc->GID0)
+            {
+                gc->Ghp0 = md->hp;
+                if (gc->Ghp0 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 10, 0);
+                    guild_castledatasave (gc->castle_id, 18, 0);
+                }
+            }
+            if (md->bl.id == gc->GID1)
+            {
+                gc->Ghp1 = md->hp;
+                if (gc->Ghp1 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 11, 0);
+                    guild_castledatasave (gc->castle_id, 19, 0);
+                }
+            }
+            if (md->bl.id == gc->GID2)
+            {
+                gc->Ghp2 = md->hp;
+                if (gc->Ghp2 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 12, 0);
+                    guild_castledatasave (gc->castle_id, 20, 0);
+                }
+            }
+            if (md->bl.id == gc->GID3)
+            {
+                gc->Ghp3 = md->hp;
+                if (gc->Ghp3 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 13, 0);
+                    guild_castledatasave (gc->castle_id, 21, 0);
+                }
+            }
+            if (md->bl.id == gc->GID4)
+            {
+                gc->Ghp4 = md->hp;
+                if (gc->Ghp4 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 14, 0);
+                    guild_castledatasave (gc->castle_id, 22, 0);
+                }
+            }
+            if (md->bl.id == gc->GID5)
+            {
+                gc->Ghp5 = md->hp;
+                if (gc->Ghp5 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 15, 0);
+                    guild_castledatasave (gc->castle_id, 23, 0);
+                }
+            }
+            if (md->bl.id == gc->GID6)
+            {
+                gc->Ghp6 = md->hp;
+                if (gc->Ghp6 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 16, 0);
+                    guild_castledatasave (gc->castle_id, 24, 0);
+                }
+            }
+            if (md->bl.id == gc->GID7)
+            {
+                gc->Ghp7 = md->hp;
+                if (gc->Ghp7 <= 0)
+                {
+                    guild_castledatasave (gc->castle_id, 17, 0);
+                    guild_castledatasave (gc->castle_id, 25, 0);
+
+                }
+            }
+        }
+    }                           // end addition [Valaris]
+
+    if (md->option & 2)
+        skill_status_change_end (&md->bl, SC_HIDING, -1);
+    if (md->option & 4)
+        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
+
+    if (md->state.special_mob_ai == 2)
+    {                           //スフィアーマイン
+        int  skillidx = 0;
+
+        if ((skillidx =
+             mob_skillid2skillidx (md->mob_class, NPC_SELFDESTRUCTION2)) >= 0)
+        {
+            md->mode |= 0x1;
+            md->next_walktime = tick;
+            mobskill_use_id (md, &md->bl, skillidx);    //自爆詠唱開始
+            md->state.special_mob_ai++;
+        }
+    }
+
+    if (md->hp > 0)
+    {
+        return 0;
+    }
+
+    MAP_LOG ("MOB%d DEAD", md->bl.id);
+
+    // ----- ここから死亡処理 -----
+
+    map_freeblock_lock ();
+    mob_changestate (md, MS_DEAD, 0);
+    mobskill_use (md, tick, -1);    // 死亡時スキル
+
+    memset (tmpsd, 0, sizeof (tmpsd));
+    memset (pt, 0, sizeof (pt));
+
+    max_hp = battle_get_max_hp (&md->bl);
+
+    if (src && src->type == BL_MOB)
+        mob_unlocktarget ((struct mob_data *) src, tick);
+
+    /* ソウルドレイン */
+    if (sd && (skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0)
+    {
+        clif_skill_nodamage (src, &md->bl, HW_SOULDRAIN, skill, 1);
+        sp = (battle_get_lv (&md->bl)) * (65 + 15 * skill) / 100;
+        if (sd->status.sp + sp > sd->status.max_sp)
+            sp = sd->status.max_sp - sd->status.sp;
+        sd->status.sp += sp;
+        clif_heal (sd->fd, SP_SP, sp);
+    }
+
+    // map外に消えた人は計算から除くので
+    // overkill分は無いけどsumはmax_hpとは違う
+
+    tdmg = 0;
+    for (i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE; i++)
+    {
+        if (md->dmglog[i].id == 0)
+            continue;
+        tmpsd[i] = map_id2sd (md->dmglog[i].id);
+        if (tmpsd[i] == NULL)
+            continue;
+        count++;
+        if (tmpsd[i]->bl.m != md->bl.m || pc_isdead (tmpsd[i]))
+            continue;
+
+        tdmg += (double) md->dmglog[i].dmg;
+        if (mvp_damage < md->dmglog[i].dmg)
+        {
+            third_sd = second_sd;
+            second_sd = mvp_sd;
+            mvp_sd = tmpsd[i];
+            mvp_damage = md->dmglog[i].dmg;
+        }
+    }
+
+    // [MouseJstr]
+    if ((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1))
+    {
+
+        if ((double) max_hp < tdmg)
+            dmg_rate = ((double) max_hp) / tdmg;
+        else
+            dmg_rate = 1;
+
+        // 経験値の分配
+        for (i = 0; i < DAMAGELOG_SIZE; i++)
+        {
+
+            int  pid, base_exp, job_exp, flag = 1;
+            double per;
+            struct party *p;
+            if (tmpsd[i] == NULL || tmpsd[i]->bl.m != md->bl.m)
+                continue;
+/* jAthena's exp formula
+		per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
+		temp = ((double)mob_db[md->mob_class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
+		base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+		if(mob_db[md->mob_class].base_exp > 0 && base_exp < 1) base_exp = 1;
+		if(base_exp < 0) base_exp = 0;
+		temp = ((double)mob_db[md->mob_class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
+		job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
+		if(mob_db[md->mob_class].job_exp > 0 && job_exp < 1) job_exp = 1;
+		if(job_exp < 0) job_exp = 0;
+*/
+//eAthena's exp formula rather than jAthena's
+//      per=(double)md->dmglog[i].dmg*256*(9+(double)((count > 6)? 6:count))/10/(double)max_hp;
+            // [Fate] The above is the old formula.  We do a more involved computation below.
+            per = (double) md->dmglog[i].dmg * 256 / (double) max_hp;   // 256 = 100% of the score
+            per *= damage_bonus_factor[count > DAMAGE_BONUS_COUNT ? DAMAGE_BONUS_COUNT : count];    // Bonus for party attack
+            if (per > 512)
+                per = 512;      // [Fate] Retained from before.  The maximum a single individual can get is double the original value.
+            if (per < 1)
+                per = 1;
+
+            base_exp =
+                ((mob_db[md->mob_class].base_exp *
+                  md->stats[MOB_XP_BONUS]) >> MOB_XP_BONUS_SHIFT) * per / 256;
+            if (base_exp < 1)
+                base_exp = 1;
+            if (sd && md && battle_config.pk_mode == 1
+                && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
+            {
+                base_exp *= 1.15;   // pk_mode additional exp if monster >20 levels [Valaris]
+            }
+            if (md->state.special_mob_ai >= 1
+                && battle_config.alchemist_summon_reward != 1)
+                base_exp = 0;   // Added [Valaris]
+            job_exp = mob_db[md->mob_class].job_exp * per / 256;
+            if (job_exp < 1)
+                job_exp = 1;
+            if (sd && md && battle_config.pk_mode == 1
+                && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
+            {
+                job_exp *= 1.15;    // pk_mode additional exp if monster >20 levels [Valaris]
+            }
+            if (md->state.special_mob_ai >= 1
+                && battle_config.alchemist_summon_reward != 1)
+                job_exp = 0;    // Added [Valaris]
+
+            if ((pid = tmpsd[i]->status.party_id) > 0)
+            {                   // パーティに入っている
+                int  j = 0;
+                for (j = 0; j < pnum; j++)  // 公平パーティリストにいるかどうか
+                    if (pt[j].id == pid)
+                        break;
+                if (j == pnum)
+                {               // いないときは公平かどうか確認
+                    if ((p = party_search (pid)) != NULL && p->exp != 0)
+                    {
+                        pt[pnum].id = pid;
+                        pt[pnum].p = p;
+                        pt[pnum].base_exp = base_exp;
+                        pt[pnum].job_exp = job_exp;
+                        pnum++;
+                        flag = 0;
+                    }
+                }
+                else
+                {               // いるときは公平
+                    pt[j].base_exp += base_exp;
+                    pt[j].job_exp += job_exp;
+                    flag = 0;
+                }
+            }
+            if (flag)           // 各自所得
+                pc_gainexp (tmpsd[i], base_exp, job_exp);
+        }
+        // 公平分配
+        for (i = 0; i < pnum; i++)
+            party_exp_share (pt[i].p, md->bl.m, pt[i].base_exp,
+                             pt[i].job_exp);
+
+        // item drop
+        if (!(type & 1))
+        {
+            for (i = 0; i < 8; i++)
+            {
+                struct delay_item_drop *ditem;
+                int  drop_rate;
+
+                if (md->state.special_mob_ai >= 1 && battle_config.alchemist_summon_reward != 1)    // Added [Valaris]
+                    break;      // End
+
+                if (mob_db[md->mob_class].dropitem[i].nameid <= 0)
+                    continue;
+                drop_rate = mob_db[md->mob_class].dropitem[i].p;
+                if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
+                    drop_rate = 1;
+                if (battle_config.drops_by_luk > 0 && sd && md)
+                    drop_rate += (sd->status.luk * battle_config.drops_by_luk) / 100;   // drops affected by luk [Valaris]
+                if (sd && md && battle_config.pk_mode == 1
+                    && (mob_db[md->mob_class].lv - sd->status.base_level >= 20))
+                    drop_rate *= 1.25;  // pk_mode increase drops if 20 level difference [Valaris]
+                if (drop_rate <= MRAND (10000))
+                    continue;
+
+                ditem = (struct delay_item_drop *)
+                    calloc (1, sizeof (struct delay_item_drop));
+                ditem->nameid = mob_db[md->mob_class].dropitem[i].nameid;
+                ditem->amount = 1;
+                ditem->m = md->bl.m;
+                ditem->x = md->bl.x;
+                ditem->y = md->bl.y;
+                ditem->first_sd = mvp_sd;
+                ditem->second_sd = second_sd;
+                ditem->third_sd = third_sd;
+                add_timer (tick + 500 + i, mob_delay_item_drop, (int) ditem, 0);
+            }
+            if (sd && sd->state.attack_type == BF_WEAPON)
+            {
+                for (i = 0; i < sd->monster_drop_item_count; i++)
+                {
+                    struct delay_item_drop *ditem;
+                    int  race = battle_get_race (&md->bl);
+                    if (sd->monster_drop_itemid[i] <= 0)
+                        continue;
+                    if (sd->monster_drop_race[i] & (1 << race) ||
+                        (mob_db[md->mob_class].mode & 0x20
+                         && sd->monster_drop_race[i] & 1 << 10)
+                        || (!(mob_db[md->mob_class].mode & 0x20)
+                            && sd->monster_drop_race[i] & 1 << 11))
+                    {
+                        if (sd->monster_drop_itemrate[i] <= MRAND (10000))
+                            continue;
+
+                        ditem = (struct delay_item_drop *)
+                            calloc (1, sizeof (struct delay_item_drop));
+                        ditem->nameid = sd->monster_drop_itemid[i];
+                        ditem->amount = 1;
+                        ditem->m = md->bl.m;
+                        ditem->x = md->bl.x;
+                        ditem->y = md->bl.y;
+                        ditem->first_sd = mvp_sd;
+                        ditem->second_sd = second_sd;
+                        ditem->third_sd = third_sd;
+                        add_timer (tick + 520 + i, mob_delay_item_drop,
+                                   (int) ditem, 0);
+                    }
+                }
+                if (sd->get_zeny_num > 0)
+                    pc_getzeny (sd,
+                                mob_db[md->mob_class].lv * 10 +
+                                MRAND ((sd->get_zeny_num + 1)));
+            }
+            if (md->lootitem)
+            {
+                for (i = 0; i < md->lootitem_count; i++)
+                {
+                    struct delay_item_drop2 *ditem;
+
+                    ditem = (struct delay_item_drop2 *)
+                        calloc (1, sizeof (struct delay_item_drop2));
+                    memcpy (&ditem->item_data, &md->lootitem[i],
+                            sizeof (md->lootitem[0]));
+                    ditem->m = md->bl.m;
+                    ditem->x = md->bl.x;
+                    ditem->y = md->bl.y;
+                    ditem->first_sd = mvp_sd;
+                    ditem->second_sd = second_sd;
+                    ditem->third_sd = third_sd;
+                    add_timer (tick + 540 + i, mob_delay_item_drop2,
+                               (int) ditem, 0);
+                }
+            }
+        }
+
+        // mvp処理
+        if (mvp_sd && mob_db[md->mob_class].mexp > 0)
+        {
+            int  j;
+            int  mexp = battle_get_mexp (&md->bl);
+            temp =
+                ((double) mexp * (double) battle_config.mvp_exp_rate *
+                 (9. + (double) count) / 1000.);
+            mexp = (temp > 2147483647.) ? 0x7fffffff : (int) temp;
+            if (mexp < 1)
+                mexp = 1;
+            clif_mvp_effect (mvp_sd);   // エフェクト
+            clif_mvp_exp (mvp_sd, mexp);
+            pc_gainexp (mvp_sd, mexp, 0);
+            for (j = 0; j < 3; j++)
+            {
+                i = MRAND (3);
+                if (mob_db[md->mob_class].mvpitem[i].nameid <= 0)
+                    continue;
+                drop_rate = mob_db[md->mob_class].mvpitem[i].p;
+                if (drop_rate <= 0 && battle_config.drop_rate0item == 1)
+                    drop_rate = 1;
+                if (drop_rate < battle_config.item_drop_mvp_min)
+                    drop_rate = battle_config.item_drop_mvp_min;
+                if (drop_rate > battle_config.item_drop_mvp_max)
+                    drop_rate = battle_config.item_drop_mvp_max;
+                if (drop_rate <= MRAND (10000))
+                    continue;
+                memset (&item, 0, sizeof (item));
+                item.nameid = mob_db[md->mob_class].mvpitem[i].nameid;
+                item.identify = !itemdb_isequip3 (item.nameid);
+                clif_mvp_item (mvp_sd, item.nameid);
+                if (mvp_sd->weight * 2 > mvp_sd->max_weight)
+                    map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
+                                      mvp_sd->bl.y, mvp_sd, second_sd,
+                                      third_sd, 1);
+                else if ((ret = pc_additem (mvp_sd, &item, 1)))
+                {
+                    clif_additem (sd, 0, 0, ret);
+                    map_addflooritem (&item, 1, mvp_sd->bl.m, mvp_sd->bl.x,
+                                      mvp_sd->bl.y, mvp_sd, second_sd,
+                                      third_sd, 1);
+                }
+                break;
+            }
+        }
+
+    }                           // [MouseJstr]
+
+    // <Agit> NPC Event [OnAgitBreak]
+    if (md->npc_event[0]
+        && strcmp (((md->npc_event) + strlen (md->npc_event) - 13),
+                   "::OnAgitBreak") == 0)
+    {
+        printf ("MOB.C: Run NPC_Event[OnAgitBreak].\n");
+        if (agit_flag == 1)     //Call to Run NPC_Event[OnAgitBreak]
+            guild_agit_break (md);
+    }
+
+    // SCRIPT実行
+    if (md->npc_event[0])
+    {
+        if (sd == NULL)
+        {
+            if (mvp_sd != NULL)
+                sd = mvp_sd;
+            else
+            {
+                struct map_session_data *tmpsd;
+                int  i;
+                for (i = 0; i < fd_max; i++)
+                {
+                    if (session[i] && (tmpsd = (struct map_session_data *)session[i]->session_data)
+                        && tmpsd->state.auth)
+                    {
+                        if (md->bl.m == tmpsd->bl.m)
+                        {
+                            sd = tmpsd;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        if (sd)
+            npc_event (sd, md->npc_event, 0);
+    }
+
+    clif_clearchar_area (&md->bl, 1);
+    map_delblock (&md->bl);
+    if (mob_get_viewclass (md->mob_class) <= 1000)
+        clif_clearchar_delay (tick + 3000, &md->bl, 0);
+    mob_deleteslave (md);
+    mob_setdelayspawn (md->bl.id);
+    map_freeblock_unlock ();
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int mob_class_change (struct mob_data *md, int *value)
+{
+    unsigned int tick = gettick ();
+    int  i, c, hp_rate, max_hp, mob_class, count = 0;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, value);
+
+    if (value[0] <= 1000 || value[0] > 2000)
+        return 0;
+    if (md->bl.prev == NULL)
+        return 0;
+
+    while (count < 5 && value[count] > 1000 && value[count] <= 2000)
+        count++;
+    if (count < 1)
+        return 0;
+
+    mob_class = value[MRAND (count)];
+    if (mob_class <= 1000 || mob_class > 2000)
+        return 0;
+
+    max_hp = battle_get_max_hp (&md->bl);
+    hp_rate = md->hp * 100 / max_hp;
+    clif_mob_class_change (md, mob_class);
+    md->mob_class = mob_class;
+    max_hp = battle_get_max_hp (&md->bl);
+    if (battle_config.monster_class_change_full_recover == 1)
+    {
+        md->hp = max_hp;
+        memset (md->dmglog, 0, sizeof (md->dmglog));
+    }
+    else
+        md->hp = max_hp * hp_rate / 100;
+    if (md->hp > max_hp)
+        md->hp = max_hp;
+    else if (md->hp < 1)
+        md->hp = 1;
+
+    memcpy (md->name, mob_db[mob_class].jname, 24);
+    memset (&md->state, 0, sizeof (md->state));
+    md->attacked_id = 0;
+    md->target_id = 0;
+    md->move_fail_count = 0;
+
+    md->stats[MOB_SPEED] = mob_db[md->mob_class].speed;
+    md->def_ele = mob_db[md->mob_class].element;
+
+    mob_changestate (md, MS_IDLE, 0);
+    skill_castcancel (&md->bl, 0);
+    md->state.skillstate = MSS_IDLE;
+    md->last_thinktime = tick;
+    md->next_walktime = tick + MPRAND (5000, 50);
+    md->attackabletime = tick;
+    md->canmove_tick = tick;
+    md->sg_count = 0;
+
+    for (i = 0, c = tick - 1000 * 3600 * 10; i < MAX_MOBSKILL; i++)
+        md->skilldelay[i] = c;
+    md->skillid = 0;
+    md->skilllv = 0;
+
+    if (md->lootitem == NULL && mob_db[mob_class].mode & 0x02)
+        md->lootitem = (struct item *)
+            calloc (LOOTITEM_SIZE, sizeof (struct item));
+
+    skill_clear_unitgroup (&md->bl);
+    skill_cleartimerskill (&md->bl);
+
+    clif_clearchar_area (&md->bl, 0);
+    clif_spawnmob (md);
+
+    return 0;
+}
+
+/*==========================================
+ * mob回復
+ *------------------------------------------
+ */
+int mob_heal (struct mob_data *md, int heal)
+{
+    int  max_hp = battle_get_max_hp (&md->bl);
+
+    nullpo_retr (0, md);
+
+    md->hp += heal;
+    if (max_hp < md->hp)
+        md->hp = max_hp;
+
+    if (md->mob_class >= 1285 && md->mob_class <= 1287)
+    {                           // guardian hp update [Valaris]
+        struct guild_castle *gc = guild_mapname2gc (map[md->bl.m].name);
+        if (gc)
+        {
+            if (md->bl.id == gc->GID0)
+                gc->Ghp0 = md->hp;
+            if (md->bl.id == gc->GID1)
+                gc->Ghp1 = md->hp;
+            if (md->bl.id == gc->GID2)
+                gc->Ghp2 = md->hp;
+            if (md->bl.id == gc->GID3)
+                gc->Ghp3 = md->hp;
+            if (md->bl.id == gc->GID4)
+                gc->Ghp4 = md->hp;
+            if (md->bl.id == gc->GID5)
+                gc->Ghp5 = md->hp;
+            if (md->bl.id == gc->GID6)
+                gc->Ghp6 = md->hp;
+            if (md->bl.id == gc->GID7)
+                gc->Ghp7 = md->hp;
+        }
+    }                           // end addition [Valaris]
+
+    return 0;
+}
+
+/*==========================================
+ * Added by RoVeRT
+ *------------------------------------------
+ */
+int mob_warpslave_sub (struct block_list *bl, va_list ap)
+{
+    struct mob_data *md = (struct mob_data *) bl;
+    int  id, x, y;
+    id = va_arg (ap, int);
+    x = va_arg (ap, int);
+    y = va_arg (ap, int);
+    if (md->master_id == id)
+    {
+        mob_warp (md, -1, x, y, 2);
+    }
+    return 0;
+}
+
+/*==========================================
+ * Added by RoVeRT
+ *------------------------------------------
+ */
+int mob_warpslave (struct mob_data *md, int x, int y)
+{
+//printf("warp slave\n");
+    map_foreachinarea (mob_warpslave_sub, md->bl.m,
+                       x - AREA_SIZE, y - AREA_SIZE,
+                       x + AREA_SIZE, y + AREA_SIZE, BL_MOB,
+                       md->bl.id, md->bl.x, md->bl.y);
+    return 0;
+}
+
+/*==========================================
+ * mobワープ
+ *------------------------------------------
+ */
+int mob_warp (struct mob_data *md, int m, int x, int y, int type)
+{
+    int  i = 0, c, xs = 0, ys = 0, bx = x, by = y;
+
+    nullpo_retr (0, md);
+
+    if (md->bl.prev == NULL)
+        return 0;
+
+    if (m < 0)
+        m = md->bl.m;
+
+    if (type >= 0)
+    {
+        if (map[md->bl.m].flag.monster_noteleport)
+            return 0;
+        clif_clearchar_area (&md->bl, type);
+    }
+    skill_unit_out_all (&md->bl, gettick (), 1);
+    map_delblock (&md->bl);
+
+    if (bx > 0 && by > 0)
+    {                           // 位置指定の場合周囲9セルを探索
+        xs = ys = 9;
+    }
+
+    while ((x < 0 || y < 0 || ((c = read_gat (m, x, y)) == 1 || c == 5))
+           && (i++) < 1000)
+    {
+        if (xs > 0 && ys > 0 && i < 250)
+        {                       // 指定位置付近の探索
+            x = MPRAND (bx, xs) - xs / 2;
+            y = MPRAND (by, ys) - ys / 2;
+        }
+        else
+        {                       // 完全ランダム探索
+            x = MPRAND (1, (map[m].xs - 2));
+            y = MPRAND (1, (map[m].ys - 2));
+        }
+    }
+    md->dir = 0;
+    if (i < 1000)
+    {
+        md->bl.x = md->to_x = x;
+        md->bl.y = md->to_y = y;
+        md->bl.m = m;
+    }
+    else
+    {
+        m = md->bl.m;
+        if (battle_config.error_log == 1)
+            printf ("MOB %d warp failed, mob_class = %d\n", md->bl.id, md->mob_class);
+    }
+
+    md->target_id = 0;          // タゲを解除する
+    md->state.targettype = NONE_ATTACKABLE;
+    md->attacked_id = 0;
+    md->state.skillstate = MSS_IDLE;
+    mob_changestate (md, MS_IDLE, 0);
+
+    if (type > 0 && i == 1000)
+    {
+        if (battle_config.battle_log == 1)
+            printf ("MOB %d warp to (%d,%d), mob_class = %d\n", md->bl.id, x, y,
+                    md->mob_class);
+    }
+
+    map_addblock (&md->bl);
+    if (type > 0)
+    {
+        clif_spawnmob (md);
+        mob_warpslave (md, md->bl.x, md->bl.y);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 画面内の取り巻きの数計算用(foreachinarea)
+ *------------------------------------------
+ */
+int mob_countslave_sub (struct block_list *bl, va_list ap)
+{
+    int  id, *c;
+    struct mob_data *md;
+
+    id = va_arg (ap, int);
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, c = va_arg (ap, int *));
+    nullpo_retr (0, md = (struct mob_data *) bl);
+
+    if (md->master_id == id)
+        (*c)++;
+    return 0;
+}
+
+/*==========================================
+ * 画面内の取り巻きの数計算
+ *------------------------------------------
+ */
+int mob_countslave (struct mob_data *md)
+{
+    int  c = 0;
+
+    nullpo_retr (0, md);
+
+    map_foreachinarea (mob_countslave_sub, md->bl.m,
+                       0, 0, map[md->bl.m].xs - 1, map[md->bl.m].ys - 1,
+                       BL_MOB, md->bl.id, &c);
+    return c;
+}
+
+/*==========================================
+ * 手下MOB召喚
+ *------------------------------------------
+ */
+int mob_summonslave (struct mob_data *md2, int *value, int amount, int flag)
+{
+    struct mob_data *md;
+    int  bx, by, m, count = 0, mob_class, k, a = amount;
+
+    nullpo_retr (0, md2);
+    nullpo_retr (0, value);
+
+    bx = md2->bl.x;
+    by = md2->bl.y;
+    m = md2->bl.m;
+
+    if (value[0] <= 1000 || value[0] > 2000)    // 値が異常なら召喚を止める
+        return 0;
+    while (count < 5 && value[count] > 1000 && value[count] <= 2000)
+        count++;
+    if (count < 1)
+        return 0;
+
+    for (k = 0; k < count; k++)
+    {
+        amount = a;
+        mob_class = value[k];
+        if (mob_class <= 1000 || mob_class > 2000)
+            continue;
+        for (; amount > 0; amount--)
+        {
+            int  x = 0, y = 0, c = 0, i = 0;
+            md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
+            if (mob_db[mob_class].mode & 0x02)
+                md->lootitem = (struct item *)
+                    calloc (LOOTITEM_SIZE, sizeof (struct item));
+            else
+                md->lootitem = NULL;
+
+            while ((x <= 0 || y <= 0 || (c = map_getcell (m, x, y)) == 1
+                    || c == 5) && (i++) < 100)
+            {
+                x = MPRAND (bx, 9) - 4;
+                y = MPRAND (by, 9) - 4;
+            }
+            if (i >= 100)
+            {
+                x = bx;
+                y = by;
+            }
+
+            mob_spawn_dataset (md, "--ja--", mob_class);
+            md->bl.prev = NULL;
+            md->bl.next = NULL;
+            md->bl.m = m;
+            md->bl.x = x;
+            md->bl.y = y;
+
+            md->m = m;
+            md->x0 = x;
+            md->y0 = y;
+            md->xs = 0;
+            md->ys = 0;
+            md->stats[MOB_SPEED] = md2->stats[MOB_SPEED];
+            md->spawndelay1 = -1;   // 一度のみフラグ
+            md->spawndelay2 = -1;   // 一度のみフラグ
+
+            memset (md->npc_event, 0, sizeof (md->npc_event));
+            md->bl.type = BL_MOB;
+            map_addiddb (&md->bl);
+            mob_spawn (md->bl.id);
+            clif_skill_nodamage (&md->bl, &md->bl,
+                                 (flag) ? NPC_SUMMONSLAVE : NPC_SUMMONMONSTER,
+                                 a, 1);
+
+            if (flag)
+                md->master_id = md2->bl.id;
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * 自分をロックしているPCの数を数える(foreachclient)
+ *------------------------------------------
+ */
+static int mob_counttargeted_sub (struct block_list *bl, va_list ap)
+{
+    int  id, *c, target_lv;
+    struct block_list *src;
+
+    id = va_arg (ap, int);
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, c = va_arg (ap, int *));
+
+    src = va_arg (ap, struct block_list *);
+    target_lv = va_arg (ap, int);
+    if (id == bl->id || (src && id == src->id))
+        return 0;
+    if (bl->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) bl;
+        if (sd && sd->attacktarget == id && sd->attacktimer != -1
+            && sd->attacktarget_lv >= target_lv)
+            (*c)++;
+    }
+    else if (bl->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) bl;
+        if (md && md->target_id == id && md->timer != -1
+            && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
+            (*c)++;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 自分をロックしているPCの数を数える
+ *------------------------------------------
+ */
+int mob_counttargeted (struct mob_data *md, struct block_list *src,
+                       int target_lv)
+{
+    int  c = 0;
+
+    nullpo_retr (0, md);
+
+    map_foreachinarea (mob_counttargeted_sub, md->bl.m,
+                       md->bl.x - AREA_SIZE, md->bl.y - AREA_SIZE,
+                       md->bl.x + AREA_SIZE, md->bl.y + AREA_SIZE, 0,
+                       md->bl.id, &c, src, target_lv);
+    return c;
+}
+
+/*==========================================
+ *MOBskillから該当skillidのskillidxを返す
+ *------------------------------------------
+ */
+int mob_skillid2skillidx (int mob_class, int skillid)
+{
+    int  i;
+    struct mob_skill *ms = mob_db[mob_class].skill;
+
+    if (ms == NULL)
+        return -1;
+
+    for (i = 0; i < mob_db[mob_class].maxskill; i++)
+    {
+        if (ms[i].skill_id == skillid)
+            return i;
+    }
+    return -1;
+
+}
+
+//
+// MOBスキル
+//
+
+/*==========================================
+ * スキル使用(詠唱完了、ID指定)
+ *------------------------------------------
+ */
+void mobskill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct mob_data *md = NULL;
+    struct block_list *bl;
+    struct block_list *mbl;
+    int  range;
+
+    if ((mbl = map_id2bl (id)) == NULL) //詠唱したMobがもういないというのは良くある正常処理
+        return;
+    if ((md = (struct mob_data *) mbl) == NULL)
+    {
+        printf ("mobskill_castend_id nullpo mbl->id:%d\n", mbl->id);
+        return;
+    }
+    if (md->bl.type != BL_MOB || md->bl.prev == NULL)
+        return;
+    if (md->skilltimer != tid)  // タイマIDの確認
+        return;
+
+    md->skilltimer = -1;
+    //沈黙や状態異常など
+    if (md->sc_data)
+    {
+        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
+            || md->sc_data[SC_ROKISWEIL].timer != -1
+            || md->sc_data[SC_STEELBODY].timer != -1)
+            return;
+        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
+            return;
+        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
+            return;
+        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
+            return;
+    }
+    if (md->skillid != NPC_EMOTION)
+        md->last_thinktime = tick + battle_get_adelay (&md->bl);
+
+    if ((bl = map_id2bl (md->skilltarget)) == NULL || bl->prev == NULL)
+    {                           //スキルターゲットが存在しない
+        //printf("mobskill_castend_id nullpo\n");//ターゲットがいないときはnullpoじゃなくて普通に終了
+        return;
+    }
+    if (md->bl.m != bl->m)
+        return;
+
+    if (md->skillid == PR_LEXAETERNA)
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        if (sc_data
+            && (sc_data[SC_FREEZE].timer != -1
+                || (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0)))
+            return;
+    }
+    else if (md->skillid == RG_BACKSTAP)
+    {
+        int  dir = map_calc_dir (&md->bl, bl->x, bl->y), t_dir =
+            battle_get_dir (bl);
+        int  dist = distance (md->bl.x, md->bl.y, bl->x, bl->y);
+        if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir)))
+            return;
+    }
+    if (((skill_get_inf (md->skillid) & 1) || (skill_get_inf2 (md->skillid) & 4)) &&    // 彼我敵対関係チェック
+        battle_check_target (&md->bl, bl, BCT_ENEMY) <= 0)
+        return;
+    range = skill_get_range (md->skillid, md->skilllv);
+    if (range < 0)
+        range = battle_get_range (&md->bl) - (range + 1);
+    if (range + battle_config.mob_skill_add_range <
+        distance (md->bl.x, md->bl.y, bl->x, bl->y))
+        return;
+
+    md->skilldelay[md->skillidx] = tick;
+
+    if (battle_config.mob_skill_log == 1)
+        printf ("MOB skill castend skill=%d, mob_class = %d\n", md->skillid,
+                md->mob_class);
+    mob_stop_walking (md, 0);
+
+    switch (skill_get_nk (md->skillid))
+    {
+            // 攻撃系/吹き飛ばし系
+        case 0:
+        case 2:
+            skill_castend_damage_id (&md->bl, bl, md->skillid, md->skilllv,
+                                     tick, 0);
+            break;
+        case 1:                // 支援系
+            if (!mob_db[md->mob_class].skill[md->skillidx].val[0] &&
+                (md->skillid == AL_HEAL
+                 || (md->skillid == ALL_RESURRECTION && bl->type != BL_PC))
+                && battle_check_undead (battle_get_race (bl),
+                                        battle_get_elem_type (bl)))
+                skill_castend_damage_id (&md->bl, bl, md->skillid,
+                                         md->skilllv, tick, 0);
+            else
+                skill_castend_nodamage_id (&md->bl, bl, md->skillid,
+                                           md->skilllv, tick, 0);
+            break;
+    }
+}
+
+/*==========================================
+ * スキル使用(詠唱完了、場所指定)
+ *------------------------------------------
+ */
+void mobskill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct mob_data *md = NULL;
+    struct block_list *bl;
+    int  range, maxcount;
+
+    //mobskill_castend_id同様詠唱したMobが詠唱完了時にもういないというのはありそうなのでnullpoから除外
+    if ((bl = map_id2bl (id)) == NULL)
+        return;
+
+    nullpo_retv (md = (struct mob_data *) bl);
+
+    if (md->bl.type != BL_MOB || md->bl.prev == NULL)
+        return;
+
+    if (md->skilltimer != tid)  // タイマIDの確認
+        return;
+
+    md->skilltimer = -1;
+    if (md->sc_data)
+    {
+        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
+            || md->sc_data[SC_ROKISWEIL].timer != -1
+            || md->sc_data[SC_STEELBODY].timer != -1)
+            return;
+        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
+            return;
+        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
+            return;
+        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
+            return;
+    }
+
+    if (battle_config.monster_skill_reiteration == 0)
+    {
+        range = -1;
+        switch (md->skillid)
+        {
+            case MG_SAFETYWALL:
+            case WZ_FIREPILLAR:
+            case HT_SKIDTRAP:
+            case HT_LANDMINE:
+            case HT_ANKLESNARE:
+            case HT_SHOCKWAVE:
+            case HT_SANDMAN:
+            case HT_FLASHER:
+            case HT_FREEZINGTRAP:
+            case HT_BLASTMINE:
+            case HT_CLAYMORETRAP:
+            case PF_SPIDERWEB: /* スパイダーウェッブ */
+                range = 0;
+                break;
+            case AL_PNEUMA:
+            case AL_WARP:
+                range = 1;
+                break;
+        }
+        if (range >= 0)
+        {
+            if (skill_check_unit_range
+                (md->bl.m, md->skillx, md->skilly, range, md->skillid) > 0)
+                return;
+        }
+    }
+    if (battle_config.monster_skill_nofootset == 1)
+    {
+        range = -1;
+        switch (md->skillid)
+        {
+            case WZ_FIREPILLAR:
+            case HT_SKIDTRAP:
+            case HT_LANDMINE:
+            case HT_ANKLESNARE:
+            case HT_SHOCKWAVE:
+            case HT_SANDMAN:
+            case HT_FLASHER:
+            case HT_FREEZINGTRAP:
+            case HT_BLASTMINE:
+            case HT_CLAYMORETRAP:
+            case AM_DEMONSTRATION:
+            case PF_SPIDERWEB: /* スパイダーウェッブ */
+                range = 1;
+                break;
+            case AL_WARP:
+                range = 0;
+                break;
+        }
+        if (range >= 0)
+        {
+            if (skill_check_unit_range2
+                (md->bl.m, md->skillx, md->skilly, range) > 0)
+                return;
+        }
+    }
+
+    if (battle_config.monster_land_skill_limit == 1)
+    {
+        maxcount = skill_get_maxcount (md->skillid);
+        if (maxcount > 0)
+        {
+            int  i, c;
+            for (i = c = 0; i < MAX_MOBSKILLUNITGROUP; i++)
+            {
+                if (md->skillunit[i].alive_count > 0
+                    && md->skillunit[i].skill_id == md->skillid)
+                    c++;
+            }
+            if (c >= maxcount)
+                return;
+        }
+    }
+
+    range = skill_get_range (md->skillid, md->skilllv);
+    if (range < 0)
+        range = battle_get_range (&md->bl) - (range + 1);
+    if (range + battle_config.mob_skill_add_range <
+        distance (md->bl.x, md->bl.y, md->skillx, md->skilly))
+        return;
+    md->skilldelay[md->skillidx] = tick;
+
+    if (battle_config.mob_skill_log == 1)
+        printf ("MOB skill castend skill=%d, mob_class = %d\n", md->skillid,
+                md->mob_class);
+    mob_stop_walking (md, 0);
+
+    skill_castend_pos2 (&md->bl, md->skillx, md->skilly, md->skillid,
+                        md->skilllv, tick, 0);
+
+    return;
+}
+
+/*==========================================
+ * Skill use (an aria start, ID specification)
+ *------------------------------------------
+ */
+int mobskill_use_id (struct mob_data *md, struct block_list *target,
+                     int skill_idx)
+{
+    int  casttime, range;
+    struct mob_skill *ms;
+    int  skill_id, skill_lv, forcecast = 0;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, ms = &mob_db[md->mob_class].skill[skill_idx]);
+
+    if (target == NULL && (target = map_id2bl (md->target_id)) == NULL)
+        return 0;
+
+    if (target->prev == NULL || md->bl.prev == NULL)
+        return 0;
+
+    skill_id = ms->skill_id;
+    skill_lv = ms->skill_lv;
+
+    // 沈黙や異常
+    if (md->sc_data)
+    {
+        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
+            || md->sc_data[SC_ROKISWEIL].timer != -1
+            || md->sc_data[SC_STEELBODY].timer != -1)
+            return 0;
+        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
+            return 0;
+        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
+            return 0;
+        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
+            return 0;
+    }
+
+    if (md->option & 4 && skill_id == TF_HIDING)
+        return 0;
+    if (md->option & 2 && skill_id != TF_HIDING && skill_id != AS_GRIMTOOTH
+        && skill_id != RG_BACKSTAP && skill_id != RG_RAID)
+        return 0;
+
+    if (map[md->bl.m].flag.gvg
+        && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
+            || skill_id == AL_WARP || skill_id == WZ_ICEWALL
+            || skill_id == TF_BACKSLIDING))
+        return 0;
+
+    if (skill_get_inf2 (skill_id) & 0x200 && md->bl.id == target->id)
+        return 0;
+
+    // 射程と障害物チェック
+    range = skill_get_range (skill_id, skill_lv);
+    if (range < 0)
+        range = battle_get_range (&md->bl) - (range + 1);
+
+    if (!battle_check_range (&md->bl, target, range))
+        return 0;
+
+//  delay=skill_delayfix(&md->bl, skill_get_delay( skill_id,skill_lv) );
+
+    casttime = skill_castfix (&md->bl, ms->casttime);
+    md->state.skillcastcancel = ms->cancel;
+    md->skilldelay[skill_idx] = gettick ();
+
+    switch (skill_id)
+    {                           /* 何か特殊な処理が必要 */
+        case ALL_RESURRECTION: /* リザレクション */
+            if (target->type != BL_PC
+                && battle_check_undead (battle_get_race (target),
+                                        battle_get_elem_type (target)))
+            {                   /* 敵がアンデッドなら */
+                forcecast = 1;  /* ターンアンデットと同じ詠唱時間 */
+                casttime =
+                    skill_castfix (&md->bl,
+                                   skill_get_cast (PR_TURNUNDEAD, skill_lv));
+            }
+            break;
+        case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */
+        case SA_MAGICROD:
+        case SA_SPELLBREAKER:
+            forcecast = 1;
+            break;
+    }
+
+    if (battle_config.mob_skill_log == 1)
+        printf
+            ("MOB skill use target_id=%d skill=%d lv=%d cast=%d, mob_class = %d\n",
+             target->id, skill_id, skill_lv, casttime, md->mob_class);
+
+    if (casttime > 0 || forcecast)
+    {                           // 詠唱が必要
+//      struct mob_data *md2;
+        clif_skillcasting (&md->bl,
+                           md->bl.id, target->id, 0, 0, skill_id, casttime);
+
+        // 詠唱反応モンスター
+/*		if( target->type==BL_MOB && mob_db[(md2=(struct mob_data *)target)->mob_class].mode&0x10 &&
+			md2->state.state!=MS_ATTACK){
+				md2->target_id=md->bl.id;
+				md->state.targettype = ATTACKABLE;
+				md2->min_chase=13;
+		}*/
+    }
+
+    if (casttime <= 0)          // 詠唱の無いものはキャンセルされない
+        md->state.skillcastcancel = 0;
+
+    md->skilltarget = target->id;
+    md->skillx = 0;
+    md->skilly = 0;
+    md->skillid = skill_id;
+    md->skilllv = skill_lv;
+    md->skillidx = skill_idx;
+
+    if (!(battle_config.monster_cloak_check_type & 2)
+        && md->sc_data[SC_CLOAKING].timer != -1 && md->skillid != AS_CLOAKING)
+        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
+
+    if (casttime > 0)
+    {
+        md->skilltimer =
+            add_timer (gettick () + casttime, mobskill_castend_id, md->bl.id,
+                       0);
+    }
+    else
+    {
+        md->skilltimer = -1;
+        mobskill_castend_id (md->skilltimer, gettick (), md->bl.id, 0);
+    }
+
+    return 1;
+}
+
+/*==========================================
+ * スキル使用(場所指定)
+ *------------------------------------------
+ */
+int mobskill_use_pos (struct mob_data *md,
+                      int skill_x, int skill_y, int skill_idx)
+{
+    int  casttime = 0, range;
+    struct mob_skill *ms;
+    struct block_list bl;
+    int  skill_id, skill_lv;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, ms = &mob_db[md->mob_class].skill[skill_idx]);
+
+    if (md->bl.prev == NULL)
+        return 0;
+
+    skill_id = ms->skill_id;
+    skill_lv = ms->skill_lv;
+
+    //沈黙や状態異常など
+    if (md->sc_data)
+    {
+        if (md->opt1 > 0 || md->sc_data[SC_DIVINA].timer != -1
+            || md->sc_data[SC_ROKISWEIL].timer != -1
+            || md->sc_data[SC_STEELBODY].timer != -1)
+            return 0;
+        if (md->sc_data[SC_AUTOCOUNTER].timer != -1 && md->skillid != KN_AUTOCOUNTER)   //オートカウンター
+            return 0;
+        if (md->sc_data[SC_BLADESTOP].timer != -1)  //白刃取り
+            return 0;
+        if (md->sc_data[SC_BERSERK].timer != -1)    //バーサーク
+            return 0;
+    }
+
+    if (md->option & 2)
+        return 0;
+
+    if (map[md->bl.m].flag.gvg
+        && (skill_id == SM_ENDURE || skill_id == AL_TELEPORT
+            || skill_id == AL_WARP || skill_id == WZ_ICEWALL
+            || skill_id == TF_BACKSLIDING))
+        return 0;
+
+    // 射程と障害物チェック
+    bl.type = BL_NUL;
+    bl.m = md->bl.m;
+    bl.x = skill_x;
+    bl.y = skill_y;
+    range = skill_get_range (skill_id, skill_lv);
+    if (range < 0)
+        range = battle_get_range (&md->bl) - (range + 1);
+    if (!battle_check_range (&md->bl, &bl, range))
+        return 0;
+
+//  delay=skill_delayfix(&sd->bl, skill_get_delay( skill_id,skill_lv) );
+    casttime = skill_castfix (&md->bl, ms->casttime);
+    md->skilldelay[skill_idx] = gettick ();
+    md->state.skillcastcancel = ms->cancel;
+
+    if (battle_config.mob_skill_log == 1)
+        printf
+            ("MOB skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d, mob_class = %d\n",
+             skill_x, skill_y, skill_id, skill_lv, casttime, md->mob_class);
+
+    if (casttime > 0)           // A cast time is required.
+        clif_skillcasting (&md->bl,
+                           md->bl.id, 0, skill_x, skill_y, skill_id,
+                           casttime);
+
+    if (casttime <= 0)          // A skill without a cast time wont be cancelled.
+        md->state.skillcastcancel = 0;
+
+    md->skillx = skill_x;
+    md->skilly = skill_y;
+    md->skilltarget = 0;
+    md->skillid = skill_id;
+    md->skilllv = skill_lv;
+    md->skillidx = skill_idx;
+    if (!(battle_config.monster_cloak_check_type & 2)
+        && md->sc_data[SC_CLOAKING].timer != -1)
+        skill_status_change_end (&md->bl, SC_CLOAKING, -1);
+    if (casttime > 0)
+    {
+        md->skilltimer =
+            add_timer (gettick () + casttime, mobskill_castend_pos, md->bl.id,
+                       0);
+    }
+    else
+    {
+        md->skilltimer = -1;
+        mobskill_castend_pos (md->skilltimer, gettick (), md->bl.id, 0);
+    }
+
+    return 1;
+}
+
+/*==========================================
+ * Friendly Mob whose HP is decreasing by a nearby MOB is looked for.
+ *------------------------------------------
+ */
+int mob_getfriendhpltmaxrate_sub (struct block_list *bl, va_list ap)
+{
+    int  rate;
+    struct mob_data **fr, *md, *mmd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
+
+    md = (struct mob_data *) bl;
+
+    if (mmd->bl.id == bl->id)
+        return 0;
+    rate = va_arg (ap, int);
+    fr = va_arg (ap, struct mob_data **);
+    if (md->hp < mob_db[md->mob_class].max_hp * rate / 100)
+        (*fr) = md;
+    return 0;
+}
+
+struct mob_data *mob_getfriendhpltmaxrate (struct mob_data *md, int rate)
+{
+    struct mob_data *fr = NULL;
+    const int r = 8;
+
+    nullpo_retr (NULL, md);
+
+    map_foreachinarea (mob_getfriendhpltmaxrate_sub, md->bl.m,
+                       md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
+                       BL_MOB, md, rate, &fr);
+    return fr;
+}
+
+/*==========================================
+ * What a status state suits by nearby MOB is looked for.
+ *------------------------------------------
+ */
+int mob_getfriendstatus_sub (struct block_list *bl, va_list ap)
+{
+    int  cond1, cond2;
+    struct mob_data **fr, *md, *mmd;
+    int  flag = 0;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = (struct mob_data *) bl);
+    nullpo_retr (0, mmd = va_arg (ap, struct mob_data *));
+
+    if (mmd->bl.id == bl->id)
+        return 0;
+    cond1 = va_arg (ap, int);
+    cond2 = va_arg (ap, int);
+    fr = va_arg (ap, struct mob_data **);
+    if (cond2 == -1)
+    {
+        int  j;
+        for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
+        {
+            flag = (md->sc_data[j].timer != -1);
+        }
+    }
+    else
+        flag = (md->sc_data[cond2].timer != -1);
+    if (flag ^ (cond1 == MSC_FRIENDSTATUSOFF))
+        (*fr) = md;
+
+    return 0;
+}
+
+struct mob_data *mob_getfriendstatus (struct mob_data *md, int cond1,
+                                      int cond2)
+{
+    struct mob_data *fr = NULL;
+    const int r = 8;
+
+    nullpo_retr (0, md);
+
+    map_foreachinarea (mob_getfriendstatus_sub, md->bl.m,
+                       md->bl.x - r, md->bl.y - r, md->bl.x + r, md->bl.y + r,
+                       BL_MOB, md, cond1, cond2, &fr);
+    return fr;
+}
+
+/*==========================================
+ * Skill use judging
+ *------------------------------------------
+ */
+int mobskill_use (struct mob_data *md, unsigned int tick, int event)
+{
+    struct mob_skill *ms;
+//  struct block_list *target=NULL;
+    int  i, max_hp;
+
+    nullpo_retr (0, md);
+    nullpo_retr (0, ms = mob_db[md->mob_class].skill);
+
+    max_hp = battle_get_max_hp (&md->bl);
+
+    if (battle_config.mob_skill_use == 0 || md->skilltimer != -1)
+        return 0;
+
+    if (md->state.special_mob_ai)
+        return 0;
+
+    if (md->sc_data[SC_SELFDESTRUCTION].timer != -1)    //自爆中はスキルを使わない
+        return 0;
+
+    for (i = 0; i < mob_db[md->mob_class].maxskill; i++)
+    {
+        int  c2 = ms[i].cond2, flag = 0;
+        struct mob_data *fmd = NULL;
+
+        // ディレイ中
+        if (DIFF_TICK (tick, md->skilldelay[i]) < ms[i].delay)
+            continue;
+
+        // 状態判定
+        if (ms[i].state >= 0 && ms[i].state != md->state.skillstate)
+            continue;
+
+        // 条件判定
+        flag = (event == ms[i].cond1);
+        if (!flag)
+        {
+            switch (ms[i].cond1)
+            {
+                case MSC_ALWAYS:
+                    flag = 1;
+                    break;
+                case MSC_MYHPLTMAXRATE:    // HP< maxhp%
+                    flag = (md->hp < max_hp * c2 / 100);
+                    break;
+                case MSC_MYSTATUSON:   // status[num] on
+                case MSC_MYSTATUSOFF:  // status[num] off
+                    if (ms[i].cond2 == -1)
+                    {
+                        int  j;
+                        for (j = SC_STONE; j <= SC_BLIND && !flag; j++)
+                        {
+                            flag = (md->sc_data[j].timer != -1);
+                        }
+                    }
+                    else
+                        flag = (md->sc_data[ms[i].cond2].timer != -1);
+                    flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF);
+                    break;
+                case MSC_FRIENDHPLTMAXRATE:    // friend HP < maxhp%
+                    flag =
+                        ((fmd =
+                          mob_getfriendhpltmaxrate (md,
+                                                    ms[i].cond2)) != NULL);
+                    break;
+                case MSC_FRIENDSTATUSON:   // friend status[num] on
+                case MSC_FRIENDSTATUSOFF:  // friend status[num] off
+                    flag =
+                        ((fmd =
+                          mob_getfriendstatus (md, ms[i].cond1,
+                                               ms[i].cond2)) != NULL);
+                    break;
+                case MSC_NOTINTOWN:     // Only outside of towns.
+                    flag = !map[md->bl.m].flag.town;
+                    break;
+                case MSC_SLAVELT:  // slave < num
+                    flag = (mob_countslave (md) < c2);
+                    break;
+                case MSC_ATTACKPCGT:   // attack pc > num
+                    flag = (mob_counttargeted (md, NULL, 0) > c2);
+                    break;
+                case MSC_SLAVELE:  // slave <= num
+                    flag = (mob_countslave (md) <= c2);
+                    break;
+                case MSC_ATTACKPCGE:   // attack pc >= num
+                    flag = (mob_counttargeted (md, NULL, 0) >= c2);
+                    break;
+                case MSC_SKILLUSED:    // specificated skill used
+                    flag = ((event & 0xffff) == MSC_SKILLUSED
+                            && ((event >> 16) == c2 || c2 == 0));
+                    break;
+            }
+        }
+
+        // 確率判定
+        if (flag && MRAND (10000) < ms[i].permillage)
+        {
+
+            if (skill_get_inf (ms[i].skill_id) & 2)
+            {
+                // 場所指定
+                struct block_list *bl = NULL;
+                int  x = 0, y = 0;
+                if (ms[i].target <= MST_AROUND)
+                {
+                    if (ms[i].target == MST_MASTER)
+                    {
+                        bl = &md->bl;
+                        if (md->master_id)
+                            bl = map_id2bl (md->master_id);
+                    }
+                    else
+                    {
+                        bl = ((ms[i].target == MST_TARGET
+                               || ms[i].target ==
+                               MST_AROUND5) ? map_id2bl (md->
+                                                         target_id)
+                              : (ms[i].target ==
+                                 MST_FRIEND) ? &fmd->bl : &md->bl);
+                    }
+
+                    if (bl)
+                    {
+                        x = bl->x;
+                        y = bl->y;
+                    }
+                }
+                if (x <= 0 || y <= 0)
+                    continue;
+                // 自分の周囲
+                if (ms[i].target >= MST_AROUND1)
+                {
+                    int  bx = x, by = y, i = 0, c, m = bl->m, r =
+                        ms[i].target - MST_AROUND1;
+                    do
+                    {
+                        bx = x + MRAND ((r * 2 + 3)) - r;
+                        by = y + MRAND ((r * 2 + 3)) - r;
+                    }
+                    while ((bx <= 0 || by <= 0 || bx >= map[m].xs
+                            || by >= map[m].ys
+                            || ((c = read_gat (m, bx, by)) == 1 || c == 5))
+                           && (i++) < 1000);
+                    if (i < 1000)
+                    {
+                        x = bx;
+                        y = by;
+                    }
+                }
+                // 相手の周囲
+                if (ms[i].target >= MST_AROUND5)
+                {
+                    int  bx = x, by = y, i = 0, c, m = bl->m, r =
+                        (ms[i].target - MST_AROUND5) + 1;
+                    do
+                    {
+                        bx = x + MRAND ((r * 2 + 1)) - r;
+                        by = y + MRAND ((r * 2 + 1)) - r;
+                    }
+                    while ((bx <= 0 || by <= 0 || bx >= map[m].xs
+                            || by >= map[m].ys
+                            || ((c = read_gat (m, bx, by)) == 1 || c == 5))
+                           && (i++) < 1000);
+                    if (i < 1000)
+                    {
+                        x = bx;
+                        y = by;
+                    }
+                }
+                if (!mobskill_use_pos (md, x, y, i))
+                    return 0;
+
+            }
+            else
+            {
+                if (ms[i].target == MST_MASTER)
+                {
+                    struct block_list *bl = &md->bl;
+                    if (md->master_id)
+                        bl = map_id2bl (md->master_id);
+
+                    if (bl && !mobskill_use_id (md, bl, i))
+                        return 0;
+                }
+                // ID指定
+                if (ms[i].target <= MST_FRIEND)
+                {
+                    struct block_list *bl = NULL;
+                    bl = ((ms[i].target ==
+                           MST_TARGET) ? map_id2bl (md->
+                                                    target_id) : (ms[i].target
+                                                                  ==
+                                                                  MST_FRIEND)
+                          ? &fmd->bl : &md->bl);
+                    if (bl && !mobskill_use_id (md, bl, i))
+                        return 0;
+                }
+            }
+            if (ms[i].emotion >= 0)
+                clif_emotion (&md->bl, ms[i].emotion);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Skill use event processing
+ *------------------------------------------
+ */
+int mobskill_event (struct mob_data *md, int flag)
+{
+    nullpo_retr (0, md);
+
+    if (flag == -1 && mobskill_use (md, gettick (), MSC_CASTTARGETED))
+        return 1;
+    if ((flag & BF_SHORT)
+        && mobskill_use (md, gettick (), MSC_CLOSEDATTACKED))
+        return 1;
+    if ((flag & BF_LONG)
+        && mobskill_use (md, gettick (), MSC_LONGRANGEATTACKED))
+        return 1;
+    return 0;
+}
+
+/*==========================================
+ * Mobがエンペリウムなどの場合の判定
+ *------------------------------------------
+ */
+int mob_gvmobcheck (struct map_session_data *sd, struct block_list *bl)
+{
+    struct mob_data *md = NULL;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_MOB && (md = (struct mob_data *) bl) &&
+        (md->mob_class == 1288 || md->mob_class == 1287 || md->mob_class == 1286
+         || md->mob_class == 1285))
+    {
+        struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
+        struct guild *g = guild_search (sd->status.guild_id);
+
+        if (g == NULL && md->mob_class == 1288)
+            return 0;           //ギルド未加入ならダメージ無し
+        else if (gc != NULL && !map[sd->bl.m].flag.gvg)
+            return 0;           //砦内でGvじゃないときはダメージなし
+        else if (g && gc != NULL && g->guild_id == gc->guild_id)
+            return 0;           //自占領ギルドのエンペならダメージ無し
+        else if (g && guild_checkskill (g, GD_APPROVAL) <= 0
+                 && md->mob_class == 1288)
+            return 0;           //正規ギルド承認がないとダメージ無し
+
+    }
+
+    return 1;
+}
+
+/*==========================================
+ * スキル用タイマー削除
+ *------------------------------------------
+ */
+int mobskill_deltimer (struct mob_data *md)
+{
+    nullpo_retr (0, md);
+
+    if (md->skilltimer != -1)
+    {
+        if (skill_get_inf (md->skillid) & 2)
+            delete_timer (md->skilltimer, mobskill_castend_pos);
+        else
+            delete_timer (md->skilltimer, mobskill_castend_id);
+        md->skilltimer = -1;
+    }
+    return 0;
+}
+
+//
+// 初期化
+//
+/*==========================================
+ * Since un-setting [ mob ] up was used, it is an initial provisional value setup.
+ *------------------------------------------
+ */
+static int mob_makedummymobdb (int mob_class)
+{
+    int  i;
+
+    sprintf (mob_db[mob_class].name, "mob%d", mob_class);
+    sprintf (mob_db[mob_class].jname, "mob%d", mob_class);
+    mob_db[mob_class].lv = 1;
+    mob_db[mob_class].max_hp = 1000;
+    mob_db[mob_class].max_sp = 1;
+    mob_db[mob_class].base_exp = 2;
+    mob_db[mob_class].job_exp = 1;
+    mob_db[mob_class].range = 1;
+    mob_db[mob_class].atk1 = 7;
+    mob_db[mob_class].atk2 = 10;
+    mob_db[mob_class].def = 0;
+    mob_db[mob_class].mdef = 0;
+    mob_db[mob_class].str = 1;
+    mob_db[mob_class].agi = 1;
+    mob_db[mob_class].vit = 1;
+    mob_db[mob_class].int_ = 1;
+    mob_db[mob_class].dex = 6;
+    mob_db[mob_class].luk = 2;
+    mob_db[mob_class].range2 = 10;
+    mob_db[mob_class].range3 = 10;
+    mob_db[mob_class].size = 0;
+    mob_db[mob_class].race = 0;
+    mob_db[mob_class].element = 0;
+    mob_db[mob_class].mode = 0;
+    mob_db[mob_class].speed = 300;
+    mob_db[mob_class].adelay = 1000;
+    mob_db[mob_class].amotion = 500;
+    mob_db[mob_class].dmotion = 500;
+    mob_db[mob_class].dropitem[0].nameid = 909; // Jellopy
+    mob_db[mob_class].dropitem[0].p = 1000;
+    for (i = 1; i < 8; i++)
+    {
+        mob_db[mob_class].dropitem[i].nameid = 0;
+        mob_db[mob_class].dropitem[i].p = 0;
+    }
+    // Item1,Item2
+    mob_db[mob_class].mexp = 0;
+    mob_db[mob_class].mexpper = 0;
+    for (i = 0; i < 3; i++)
+    {
+        mob_db[mob_class].mvpitem[i].nameid = 0;
+        mob_db[mob_class].mvpitem[i].p = 0;
+    }
+    for (i = 0; i < MAX_RANDOMMONSTER; i++)
+        mob_db[mob_class].summonper[i] = 0;
+    return 0;
+}
+
+/*==========================================
+ * db/mob_db.txt reading
+ *------------------------------------------
+ */
+static int mob_readdb (void)
+{
+    FILE *fp;
+    char line[1024];
+    char *filename[] = { "db/mob_db.txt", "db/mob_db2.txt" };
+    int  i;
+
+    memset (mob_db, 0, sizeof (mob_db));
+
+    for (i = 0; i < 2; i++)
+    {
+
+        fp = fopen_ (filename[i], "r");
+        if (fp == NULL)
+        {
+            if (i > 0)
+                continue;
+            return -1;
+        }
+        while (fgets (line, 1020, fp))
+        {
+            int  mob_class, i;
+            char *str[57], *p, *np;
+
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+
+            for (i = 0, p = line; i < 57; i++)
+            {
+                while (*p == '\t' || *p == ' ')
+                    p++;
+                if ((np = strchr (p, ',')) != NULL)
+                {
+                    str[i] = p;
+                    *np = 0;
+                    p = np + 1;
+                }
+                else
+                    str[i] = p;
+            }
+
+            mob_class = atoi (str[0]);
+            if (mob_class <= 1000 || mob_class > 2000)
+                continue;
+
+            mob_db[mob_class].view_class = mob_class;
+            memcpy (mob_db[mob_class].name, str[1], 24);
+            memcpy (mob_db[mob_class].jname, str[2], 24);
+            mob_db[mob_class].lv = atoi (str[3]);
+            mob_db[mob_class].max_hp = atoi (str[4]);
+            mob_db[mob_class].max_sp = atoi (str[5]);
+
+            mob_db[mob_class].base_exp = atoi (str[6]);
+            if (mob_db[mob_class].base_exp < 0)
+                mob_db[mob_class].base_exp = 0;
+            else if (mob_db[mob_class].base_exp > 0
+                     && (mob_db[mob_class].base_exp *
+                         battle_config.base_exp_rate / 100 > 1000000000
+                         || mob_db[mob_class].base_exp *
+                         battle_config.base_exp_rate / 100 < 0))
+                mob_db[mob_class].base_exp = 1000000000;
+            else
+                mob_db[mob_class].base_exp *= battle_config.base_exp_rate / 100;
+
+            mob_db[mob_class].job_exp = atoi (str[7]);
+            if (mob_db[mob_class].job_exp < 0)
+                mob_db[mob_class].job_exp = 0;
+            else if (mob_db[mob_class].job_exp > 0
+                     && (mob_db[mob_class].job_exp * battle_config.job_exp_rate /
+                         100 > 1000000000
+                         || mob_db[mob_class].job_exp *
+                         battle_config.job_exp_rate / 100 < 0))
+                mob_db[mob_class].job_exp = 1000000000;
+            else
+                mob_db[mob_class].job_exp *= battle_config.job_exp_rate / 100;
+
+            mob_db[mob_class].range = atoi (str[8]);
+            mob_db[mob_class].atk1 = atoi (str[9]);
+            mob_db[mob_class].atk2 = atoi (str[10]);
+            mob_db[mob_class].def = atoi (str[11]);
+            mob_db[mob_class].mdef = atoi (str[12]);
+            mob_db[mob_class].str = atoi (str[13]);
+            mob_db[mob_class].agi = atoi (str[14]);
+            mob_db[mob_class].vit = atoi (str[15]);
+            mob_db[mob_class].int_ = atoi (str[16]);
+            mob_db[mob_class].dex = atoi (str[17]);
+            mob_db[mob_class].luk = atoi (str[18]);
+            mob_db[mob_class].range2 = atoi (str[19]);
+            mob_db[mob_class].range3 = atoi (str[20]);
+            mob_db[mob_class].size = atoi (str[21]);
+            mob_db[mob_class].race = atoi (str[22]);
+            mob_db[mob_class].element = atoi (str[23]);
+            mob_db[mob_class].mode = atoi (str[24]);
+            mob_db[mob_class].speed = atoi (str[25]);
+            mob_db[mob_class].adelay = atoi (str[26]);
+            mob_db[mob_class].amotion = atoi (str[27]);
+            mob_db[mob_class].dmotion = atoi (str[28]);
+
+            for (i = 0; i < 8; i++)
+            {
+                int  rate = 0, type, ratemin, ratemax;
+                mob_db[mob_class].dropitem[i].nameid = atoi (str[29 + i * 2]);
+                type = itemdb_type (mob_db[mob_class].dropitem[i].nameid);
+                if (type == 0)
+                {               // Added [Valaris]
+                    rate = battle_config.item_rate_heal;
+                    ratemin = battle_config.item_drop_heal_min;
+                    ratemax = battle_config.item_drop_heal_max;
+                }
+                else if (type == 2)
+                {
+                    rate = battle_config.item_rate_use;
+                    ratemin = battle_config.item_drop_use_min;
+                    ratemax = battle_config.item_drop_use_max;  // End
+                }
+                else if (type == 4 || type == 5 || type == 8)
+                {
+                    rate = battle_config.item_rate_equip;
+                    ratemin = battle_config.item_drop_equip_min;
+                    ratemax = battle_config.item_drop_equip_max;
+                }
+                else if (type == 6)
+                {
+                    rate = battle_config.item_rate_card;
+                    ratemin = battle_config.item_drop_card_min;
+                    ratemax = battle_config.item_drop_card_max;
+                }
+                else
+                {
+                    rate = battle_config.item_rate_common;
+                    ratemin = battle_config.item_drop_common_min;
+                    ratemax = battle_config.item_drop_common_max;
+                }
+                rate = (rate / 100) * atoi (str[30 + i * 2]);
+                rate =
+                    (rate < ratemin) ? ratemin : (rate >
+                                                  ratemax) ? ratemax : rate;
+                mob_db[mob_class].dropitem[i].p = rate;
+            }
+            // Item1,Item2
+            mob_db[mob_class].mexp =
+                atoi (str[45]) * battle_config.mvp_exp_rate / 100;
+            mob_db[mob_class].mexpper = atoi (str[46]);
+            for (i = 0; i < 3; i++)
+            {
+                mob_db[mob_class].mvpitem[i].nameid = atoi (str[47 + i * 2]);
+                mob_db[mob_class].mvpitem[i].p =
+                    atoi (str[48 + i * 2]) * battle_config.mvp_item_rate /
+                    100;
+            }
+            mob_db[mob_class].mutations_nr = atoi (str[55]);
+            mob_db[mob_class].mutation_power = atoi (str[56]);
+
+            for (i = 0; i < MAX_RANDOMMONSTER; i++)
+                mob_db[mob_class].summonper[i] = 0;
+            mob_db[mob_class].maxskill = 0;
+
+            mob_db[mob_class].sex = 0;
+            mob_db[mob_class].hair = 0;
+            mob_db[mob_class].hair_color = 0;
+            mob_db[mob_class].weapon = 0;
+            mob_db[mob_class].shield = 0;
+            mob_db[mob_class].head_top = 0;
+            mob_db[mob_class].head_mid = 0;
+            mob_db[mob_class].head_buttom = 0;
+            mob_db[mob_class].clothes_color = 0;    //Add for player monster dye - Valaris
+
+            if (mob_db[mob_class].base_exp == 0)
+                mob_db[mob_class].base_exp = mob_gen_exp (&mob_db[mob_class]);
+        }
+        fclose_ (fp);
+        printf ("read %s done\n", filename[i]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * MOB display graphic change data reading
+ *------------------------------------------
+ */
+static int mob_readdb_mobavail (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  ln = 0;
+    int  mob_class, j, k;
+    char *str[20], *p, *np;
+
+    if ((fp = fopen_ ("db/mob_avail.txt", "r")) == NULL)
+    {
+        printf ("can't read db/mob_avail.txt\n");
+        return -1;
+    }
+
+    while (fgets (line, 1020, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        memset (str, 0, sizeof (str));
+
+        for (j = 0, p = line; j < 12; j++)
+        {
+            if ((np = strchr (p, ',')) != NULL)
+            {
+                str[j] = p;
+                *np = 0;
+                p = np + 1;
+            }
+            else
+                str[j] = p;
+        }
+
+        if (str[0] == NULL)
+            continue;
+
+        mob_class = atoi (str[0]);
+
+        if (mob_class <= 1000 || mob_class > 2000)  // 値が異常なら処理しない。
+            continue;
+        k = atoi (str[1]);
+        if (k >= 0)
+            mob_db[mob_class].view_class = k;
+
+        if ((mob_db[mob_class].view_class < 24)
+            || (mob_db[mob_class].view_class > 4000))
+        {
+            mob_db[mob_class].sex = atoi (str[2]);
+            mob_db[mob_class].hair = atoi (str[3]);
+            mob_db[mob_class].hair_color = atoi (str[4]);
+            mob_db[mob_class].weapon = atoi (str[5]);
+            mob_db[mob_class].shield = atoi (str[6]);
+            mob_db[mob_class].head_top = atoi (str[7]);
+            mob_db[mob_class].head_mid = atoi (str[8]);
+            mob_db[mob_class].head_buttom = atoi (str[9]);
+            mob_db[mob_class].option = atoi (str[10]) & ~0x46;
+            mob_db[mob_class].clothes_color = atoi (str[11]);   // Monster player dye option - Valaris
+        }
+
+        else if (atoi (str[2]) > 0)
+            mob_db[mob_class].equip = atoi (str[2]);    // mob equipment [Valaris]
+
+        ln++;
+    }
+    fclose_ (fp);
+    printf ("read db/mob_avail.txt done (count=%d)\n", ln);
+    return 0;
+}
+
+/*==========================================
+ * Reading of random monster data
+ *------------------------------------------
+ */
+static int mob_read_randommonster (void)
+{
+    FILE *fp;
+    char line[1024];
+    char *str[10], *p;
+    int  i, j;
+
+    const char *mobfile[] = {
+        "db/mob_branch.txt",
+        "db/mob_poring.txt",
+        "db/mob_boss.txt"
+    };
+
+    for (i = 0; i < MAX_RANDOMMONSTER; i++)
+    {
+        mob_db[0].summonper[i] = 1002;  // 設定し忘れた場合はポリンが出るようにしておく
+        fp = fopen_ (mobfile[i], "r");
+        if (fp == NULL)
+        {
+            printf ("can't read %s\n", mobfile[i]);
+            return -1;
+        }
+        while (fgets (line, 1020, fp))
+        {
+            int  mob_class, per;
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+            memset (str, 0, sizeof (str));
+            for (j = 0, p = line; j < 3 && p; j++)
+            {
+                str[j] = p;
+                p = strchr (p, ',');
+                if (p)
+                    *p++ = 0;
+            }
+
+            if (str[0] == NULL || str[2] == NULL)
+                continue;
+
+            mob_class = atoi (str[0]);
+            per = atoi (str[2]);
+            if ((mob_class > 1000 && mob_class <= 2000) || mob_class == 0)
+                mob_db[mob_class].summonper[i] = per;
+        }
+        fclose_ (fp);
+        printf ("read %s done\n", mobfile[i]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * db/mob_skill_db.txt reading
+ *------------------------------------------
+ */
+static int mob_readskilldb (void)
+{
+    FILE *fp;
+    char line[1024];
+    int  i;
+
+    const struct
+    {
+        char str[32];
+        int  id;
+    } cond1[] =
+    {
+        {
+        "always", MSC_ALWAYS},
+        {
+        "myhpltmaxrate", MSC_MYHPLTMAXRATE},
+        {
+        "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE},
+        {
+        "mystatuson", MSC_MYSTATUSON},
+        {
+        "mystatusoff", MSC_MYSTATUSOFF},
+        {
+        "friendstatuson", MSC_FRIENDSTATUSON},
+        {
+        "friendstatusoff", MSC_FRIENDSTATUSOFF},
+        {
+        "notintown", MSC_NOTINTOWN},
+        {
+        "attackpcgt", MSC_ATTACKPCGT},
+        {
+        "attackpcge", MSC_ATTACKPCGE},
+        {
+        "slavelt", MSC_SLAVELT},
+        {
+        "slavele", MSC_SLAVELE},
+        {
+        "closedattacked", MSC_CLOSEDATTACKED},
+        {
+        "longrangeattacked", MSC_LONGRANGEATTACKED},
+        {
+        "skillused", MSC_SKILLUSED},
+        {
+    "casttargeted", MSC_CASTTARGETED},}, cond2[] =
+    {
+        {
+        "anybad", -1},
+        {
+        "stone", SC_STONE},
+        {
+        "freeze", SC_FREEZE},
+        {
+        "stan", SC_STAN},
+        {
+        "sleep", SC_SLEEP},
+        {
+        "poison", SC_POISON},
+        {
+        "curse", SC_CURSE},
+        {
+        "silence", SC_SILENCE},
+        {
+        "confusion", SC_CONFUSION},
+        {
+        "blind", SC_BLIND},
+        {
+        "hiding", SC_HIDING},
+        {
+    "sight", SC_SIGHT},}, state[] =
+    {
+        {
+        "any", -1},
+        {
+        "idle", MSS_IDLE},
+        {
+        "walk", MSS_WALK},
+        {
+        "attack", MSS_ATTACK},
+        {
+        "dead", MSS_DEAD},
+        {
+        "loot", MSS_LOOT},
+        {
+    "chase", MSS_CHASE},}, target[] =
+    {
+        {
+        "target", MST_TARGET},
+        {
+        "self", MST_SELF},
+        {
+        "friend", MST_FRIEND},
+        {
+        "master", MST_MASTER},
+        {
+        "around5", MST_AROUND5},
+        {
+        "around6", MST_AROUND6},
+        {
+        "around7", MST_AROUND7},
+        {
+        "around8", MST_AROUND8},
+        {
+        "around1", MST_AROUND1},
+        {
+        "around2", MST_AROUND2},
+        {
+        "around3", MST_AROUND3},
+        {
+        "around4", MST_AROUND4},
+        {
+    "around", MST_AROUND},};
+
+    int  x;
+    char *filename[] = { "db/mob_skill_db.txt", "db/mob_skill_db2.txt" };
+
+    for (x = 0; x < 2; x++)
+    {
+
+        fp = fopen_ (filename[x], "r");
+        if (fp == NULL)
+        {
+            if (x == 0)
+                printf ("can't read %s\n", filename[x]);
+            continue;
+        }
+        while (fgets (line, 1020, fp))
+        {
+            char *sp[20], *p;
+            int  mob_id;
+            struct mob_skill *ms;
+            int  j = 0;
+
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+
+            memset (sp, 0, sizeof (sp));
+            for (i = 0, p = line; i < 18 && p; i++)
+            {
+                sp[i] = p;
+                if ((p = strchr (p, ',')) != NULL)
+                    *p++ = 0;
+            }
+            if ((mob_id = atoi (sp[0])) <= 0)
+                continue;
+
+            if (strcmp (sp[1], "clear") == 0)
+            {
+                memset (mob_db[mob_id].skill, 0,
+                        sizeof (mob_db[mob_id].skill));
+                mob_db[mob_id].maxskill = 0;
+                continue;
+            }
+
+            for (i = 0; i < MAX_MOBSKILL; i++)
+                if ((ms = &mob_db[mob_id].skill[i])->skill_id == 0)
+                    break;
+            if (i == MAX_MOBSKILL)
+            {
+                printf
+                    ("mob_skill: readdb: too many skill ! [%s] in %d[%s]\n",
+                     sp[1], mob_id, mob_db[mob_id].jname);
+                continue;
+            }
+
+            ms->state = atoi (sp[2]);
+            for (j = 0; j < sizeof (state) / sizeof (state[0]); j++)
+            {
+                if (strcmp (sp[2], state[j].str) == 0)
+                    ms->state = state[j].id;
+            }
+            ms->skill_id = atoi (sp[3]);
+            ms->skill_lv = atoi (sp[4]);
+
+            ms->permillage = atoi (sp[5]);
+            ms->casttime = atoi (sp[6]);
+            ms->delay = atoi (sp[7]);
+            ms->cancel = atoi (sp[8]);
+            if (strcmp (sp[8], "yes") == 0)
+                ms->cancel = 1;
+            ms->target = atoi (sp[9]);
+            for (j = 0; j < sizeof (target) / sizeof (target[0]); j++)
+            {
+                if (strcmp (sp[9], target[j].str) == 0)
+                    ms->target = target[j].id;
+            }
+            ms->cond1 = -1;
+            for (j = 0; j < sizeof (cond1) / sizeof (cond1[0]); j++)
+            {
+                if (strcmp (sp[10], cond1[j].str) == 0)
+                    ms->cond1 = cond1[j].id;
+            }
+            ms->cond2 = atoi (sp[11]);
+            for (j = 0; j < sizeof (cond2) / sizeof (cond2[0]); j++)
+            {
+                if (strcmp (sp[11], cond2[j].str) == 0)
+                    ms->cond2 = cond2[j].id;
+            }
+            ms->val[0] = atoi (sp[12]);
+            ms->val[1] = atoi (sp[13]);
+            ms->val[2] = atoi (sp[14]);
+            ms->val[3] = atoi (sp[15]);
+            ms->val[4] = atoi (sp[16]);
+            if (sp[17] != NULL && strlen (sp[17]) > 2)
+                ms->emotion = atoi (sp[17]);
+            else
+                ms->emotion = -1;
+            mob_db[mob_id].maxskill = i + 1;
+        }
+        fclose_ (fp);
+        printf ("read %s done\n", filename[x]);
+    }
+    return 0;
+}
+
+void mob_reload (void)
+{
+    /*
+     *
+     * <empty monster database>
+     * mob_read();
+     *
+     */
+
+    do_init_mob ();
+}
+
+/*==========================================
+ * Circumference initialization of mob
+ *------------------------------------------
+ */
+int do_init_mob (void)
+{
+    mob_readdb ();
+
+    mob_readdb_mobavail ();
+    mob_read_randommonster ();
+    mob_readskilldb ();
+
+    add_timer_interval (gettick () + MIN_MOBTHINKTIME, mob_ai_hard, 0, 0,
+                        MIN_MOBTHINKTIME);
+    add_timer_interval (gettick () + MIN_MOBTHINKTIME * 10, mob_ai_lazy, 0, 0,
+                        MIN_MOBTHINKTIME * 10);
+
+    return 0;
+}
diff --git a/src/map/mob.h b/src/map/mob.h
deleted file mode 100644
index b5d642a..0000000
--- a/src/map/mob.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// $Id: mob.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _MOB_H_
-#define _MOB_H_
-#include "../common/timer.h"
-#define MAX_RANDOMMONSTER 3
-
-struct mob_skill
-{
-    short state;
-    short skill_id, skill_lv;
-    short permillage;
-    int  casttime, delay;
-    short cancel;
-    short cond1, cond2;
-    short target;
-    int  val[5];
-    short emotion;
-};
-
-struct mob_db
-{
-    char name[24], jname[24];
-    int  lv;
-    int  max_hp, max_sp;
-    int  base_exp, job_exp;
-    int  atk1, atk2;
-    int  def, mdef;
-    int  str, agi, vit, int_, dex, luk;
-    int  range, range2, range3;
-    int  size, race, element, mode;
-    int  speed, adelay, amotion, dmotion;
-    int  mexp, mexpper;
-    int  mutations_nr, mutation_power;
-    struct
-    {
-        int  nameid, p;
-    } dropitem[8];
-    struct
-    {
-        int  nameid, p;
-    } mvpitem[3];
-    int  view_class, sex;
-    short hair, hair_color, weapon, shield, head_top, head_mid, head_buttom, option, clothes_color; // [Valaris]
-    int  equip;                 // [Valaris]
-    int  summonper[MAX_RANDOMMONSTER];
-    int  maxskill;
-    struct mob_skill skill[MAX_MOBSKILL];
-};
-extern struct mob_db mob_db[];
-
-enum
-{
-    MST_TARGET = 0,
-    MST_SELF,
-    MST_FRIEND,
-    MST_MASTER,
-    MST_AROUND5,
-    MST_AROUND6,
-    MST_AROUND7,
-    MST_AROUND8,
-    MST_AROUND1,
-    MST_AROUND2,
-    MST_AROUND3,
-    MST_AROUND4,
-    MST_AROUND = MST_AROUND4,
-
-    MSC_ALWAYS = 0x0000,
-    MSC_MYHPLTMAXRATE = 0x0001,
-    MSC_FRIENDHPLTMAXRATE = 0x0010,
-    MSC_MYSTATUSON = 0x0020,
-    MSC_MYSTATUSOFF = 0x0021,
-    MSC_FRIENDSTATUSON = 0x0030,
-    MSC_FRIENDSTATUSOFF = 0x0031,
-    MSC_NOTINTOWN = 0x0032,
-
-    MSC_ATTACKPCGT = 0x0100,
-    MSC_ATTACKPCGE = 0x0101,
-    MSC_SLAVELT = 0x0110,
-    MSC_SLAVELE = 0x0111,
-    MSC_CLOSEDATTACKED = 0x1000,
-    MSC_LONGRANGEATTACKED = 0x1001,
-    MSC_SKILLUSED = 0x1010,
-    MSC_CASTTARGETED = 0x1011,
-};
-
-enum
-{
-    MSS_IDLE,                   // 待機
-    MSS_WALK,                   // 移動
-    MSS_ATTACK,                 // 攻撃
-    MSS_DEAD,                   // 死亡
-    MSS_LOOT,                   // ルート
-    MSS_CHASE,                  // 突撃
-};
-
-int  mobdb_searchname (const char *str);
-int  mobdb_checkid (const int id);
-int  mob_once_spawn (struct map_session_data *sd, char *mapname,
-                     int x, int y, const char *mobname, int class_, int amount,
-                     const char *event);
-int  mob_once_spawn_area (struct map_session_data *sd, char *mapname, int x0,
-                          int y0, int x1, int y1, const char *mobname,
-                          int class_, int amount, const char *event);
-
-int  mob_spawn_guardian (struct map_session_data *sd, char *mapname,    // Spawning Guardians [Valaris]
-                         int x, int y, const char *mobname, int class_, int amount, const char *event, int guardian);    // Spawning Guardians [Valaris]
-
-int  mob_walktoxy (struct mob_data *md, int x, int y, int easy);
-
-int  mob_target (struct mob_data *md, struct block_list *bl, int dist);
-int  mob_stop_walking (struct mob_data *md, int type);
-int  mob_stopattack (struct mob_data *);
-int  mob_spawn (int);
-int  mob_damage (struct block_list *, struct mob_data *, int, int);
-int  mob_changestate (struct mob_data *md, int state, int type);
-int  mob_heal (struct mob_data *, int);
-int  mob_get_viewclass (int);
-int  mob_get_sex (int);
-short mob_get_hair (int);
-short mob_get_hair_color (int);
-short mob_get_weapon (int);
-short mob_get_shield (int);
-short mob_get_head_top (int);
-short mob_get_head_mid (int);
-short mob_get_head_buttom (int);
-short mob_get_clothes_color (int);  //player mob dye [Valaris]
-int  mob_get_equip (int);       // mob equip [Valaris]
-int  do_init_mob (void);
-
-int  mob_delete (struct mob_data *md);
-int  mob_catch_delete (struct mob_data *md, int type);
-void mob_timer_delete (timer_id, tick_t, custom_id_t, custom_data_t);
-
-int  mob_deleteslave (struct mob_data *md);
-
-int  mob_counttargeted (struct mob_data *md, struct block_list *src,
-                        int target_lv);
-
-int  mob_class_change (struct mob_data *md, int *value);
-int  mob_warp (struct mob_data *md, int m, int x, int y, int type);
-
-int  mobskill_use (struct mob_data *md, unsigned int tick, int event);
-int  mobskill_event (struct mob_data *md, int flag);
-void mobskill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
-void mobskill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
-int  mob_summonslave (struct mob_data *md2, int *value, int amount, int flag);
-
-int  mob_gvmobcheck (struct map_session_data *sd, struct block_list *bl);
-void mob_reload (void);
-
-#endif
diff --git a/src/map/mob.hpp b/src/map/mob.hpp
new file mode 100644
index 0000000..6161bab
--- /dev/null
+++ b/src/map/mob.hpp
@@ -0,0 +1,151 @@
+// $Id: mob.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef MOB_HPP
+#define MOB_HPP
+#include "../common/timer.hpp"
+#define MAX_RANDOMMONSTER 3
+
+struct mob_skill
+{
+    short state;
+    short skill_id, skill_lv;
+    short permillage;
+    int  casttime, delay;
+    short cancel;
+    short cond1, cond2;
+    short target;
+    int  val[5];
+    short emotion;
+};
+
+struct mob_db
+{
+    char name[24], jname[24];
+    int  lv;
+    int  max_hp, max_sp;
+    int  base_exp, job_exp;
+    int  atk1, atk2;
+    int  def, mdef;
+    int  str, agi, vit, int_, dex, luk;
+    int  range, range2, range3;
+    int  size, race, element, mode;
+    int  speed, adelay, amotion, dmotion;
+    int  mexp, mexpper;
+    int  mutations_nr, mutation_power;
+    struct
+    {
+        int  nameid, p;
+    } dropitem[8];
+    struct
+    {
+        int  nameid, p;
+    } mvpitem[3];
+    int  view_class, sex;
+    short hair, hair_color, weapon, shield, head_top, head_mid, head_buttom, option, clothes_color; // [Valaris]
+    int  equip;                 // [Valaris]
+    int  summonper[MAX_RANDOMMONSTER];
+    int  maxskill;
+    struct mob_skill skill[MAX_MOBSKILL];
+};
+extern struct mob_db mob_db[];
+
+enum
+{
+    MST_TARGET = 0,
+    MST_SELF,
+    MST_FRIEND,
+    MST_MASTER,
+    MST_AROUND5,
+    MST_AROUND6,
+    MST_AROUND7,
+    MST_AROUND8,
+    MST_AROUND1,
+    MST_AROUND2,
+    MST_AROUND3,
+    MST_AROUND4,
+    MST_AROUND = MST_AROUND4,
+
+    MSC_ALWAYS = 0x0000,
+    MSC_MYHPLTMAXRATE = 0x0001,
+    MSC_FRIENDHPLTMAXRATE = 0x0010,
+    MSC_MYSTATUSON = 0x0020,
+    MSC_MYSTATUSOFF = 0x0021,
+    MSC_FRIENDSTATUSON = 0x0030,
+    MSC_FRIENDSTATUSOFF = 0x0031,
+    MSC_NOTINTOWN = 0x0032,
+
+    MSC_ATTACKPCGT = 0x0100,
+    MSC_ATTACKPCGE = 0x0101,
+    MSC_SLAVELT = 0x0110,
+    MSC_SLAVELE = 0x0111,
+    MSC_CLOSEDATTACKED = 0x1000,
+    MSC_LONGRANGEATTACKED = 0x1001,
+    MSC_SKILLUSED = 0x1010,
+    MSC_CASTTARGETED = 0x1011,
+};
+
+enum
+{
+    MSS_IDLE,                   // 待機
+    MSS_WALK,                   // 移動
+    MSS_ATTACK,                 // 攻撃
+    MSS_DEAD,                   // 死亡
+    MSS_LOOT,                   // ルート
+    MSS_CHASE,                  // 突撃
+};
+
+int  mobdb_searchname (const char *str);
+int  mobdb_checkid (const int id);
+int  mob_once_spawn (struct map_session_data *sd, char *mapname,
+                     int x, int y, const char *mobname, int class_, int amount,
+                     const char *event);
+int  mob_once_spawn_area (struct map_session_data *sd, char *mapname, int x0,
+                          int y0, int x1, int y1, const char *mobname,
+                          int class_, int amount, const char *event);
+
+int  mob_spawn_guardian (struct map_session_data *sd, char *mapname,    // Spawning Guardians [Valaris]
+                         int x, int y, const char *mobname, int class_, int amount, const char *event, int guardian);    // Spawning Guardians [Valaris]
+
+int  mob_walktoxy (struct mob_data *md, int x, int y, int easy);
+
+int  mob_target (struct mob_data *md, struct block_list *bl, int dist);
+int  mob_stop_walking (struct mob_data *md, int type);
+int  mob_stopattack (struct mob_data *);
+int  mob_spawn (int);
+int  mob_damage (struct block_list *, struct mob_data *, int, int);
+int  mob_changestate (struct mob_data *md, int state, int type);
+int  mob_heal (struct mob_data *, int);
+int  mob_get_viewclass (int);
+int  mob_get_sex (int);
+short mob_get_hair (int);
+short mob_get_hair_color (int);
+short mob_get_weapon (int);
+short mob_get_shield (int);
+short mob_get_head_top (int);
+short mob_get_head_mid (int);
+short mob_get_head_buttom (int);
+short mob_get_clothes_color (int);  //player mob dye [Valaris]
+int  mob_get_equip (int);       // mob equip [Valaris]
+int  do_init_mob (void);
+
+int  mob_delete (struct mob_data *md);
+int  mob_catch_delete (struct mob_data *md, int type);
+void mob_timer_delete (timer_id, tick_t, custom_id_t, custom_data_t);
+
+int  mob_deleteslave (struct mob_data *md);
+
+int  mob_counttargeted (struct mob_data *md, struct block_list *src,
+                        int target_lv);
+
+int  mob_class_change (struct mob_data *md, int *value);
+int  mob_warp (struct mob_data *md, int m, int x, int y, int type);
+
+int  mobskill_use (struct mob_data *md, unsigned int tick, int event);
+int  mobskill_event (struct mob_data *md, int flag);
+void mobskill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
+void mobskill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
+int  mob_summonslave (struct mob_data *md2, int *value, int amount, int flag);
+
+int  mob_gvmobcheck (struct map_session_data *sd, struct block_list *bl);
+void mob_reload (void);
+
+#endif
diff --git a/src/map/npc.c b/src/map/npc.c
deleted file mode 100644
index a925430..0000000
--- a/src/map/npc.c
+++ /dev/null
@@ -1,2378 +0,0 @@
-// $Id: npc.c,v 1.5 2004/09/25 05:32:18 MouseJstr Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
-#include <math.h>
-#include <time.h>
-
-#include "../common/nullpo.h"
-#include "../common/timer.h"
-
-#include "battle.h"
-#include "clif.h"
-#include "../common/db.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "../common/socket.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-struct npc_src_list
-{
-    struct npc_src_list *next;
-    struct npc_src_list *prev;
-    char name[4];
-};
-
-static struct npc_src_list *npc_src_first, *npc_src_last;
-static int npc_id = START_NPC_NUM;
-static int npc_warp, npc_shop, npc_script, npc_mob;
-
-int npc_get_new_npc_id (void)
-{
-    return npc_id++;
-}
-
-static struct dbt *ev_db;
-static struct dbt *npcname_db;
-
-struct event_data
-{
-    struct npc_data *nd;
-    int  pos;
-};
-static struct tm ev_tm_b;       // 時計イベント用
-
-/*==========================================
- * NPCの無効化/有効化
- * npc_enable
- * npc_enable_sub 有効時にOnTouchイベントを実行
- *------------------------------------------
- */
-int npc_enable_sub (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-    struct npc_data *nd;
-    char *name = (char *) calloc (50, sizeof (char));
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, nd = va_arg (ap, struct npc_data *));
-    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
-    {
-
-        if (nd->flag & 1)       // 無効化されている
-            return 1;
-
-        memcpy (name, nd->name, sizeof(nd->name));
-        if (sd->areanpc_id == nd->bl.id)
-            return 1;
-        sd->areanpc_id = nd->bl.id;
-        npc_event (sd, strcat (name, "::OnTouch"), 0);
-    }
-    free (name);
-    return 0;
-}
-
-int npc_enable (const char *name, int flag)
-{
-    struct npc_data *nd = (struct npc_data *)strdb_search (npcname_db, name);
-    if (nd == NULL)
-        return 0;
-
-    if (flag & 1)
-    {                           // 有効化
-        nd->flag &= ~1;
-        clif_spawnnpc (nd);
-    }
-    else if (flag & 2)
-    {
-        nd->flag &= ~1;
-        nd->option = 0x0000;
-        clif_changeoption (&nd->bl);
-    }
-    else if (flag & 4)
-    {
-        nd->flag |= 1;
-        nd->option = 0x0002;
-        clif_changeoption (&nd->bl);
-    }
-    else
-    {                           // 無効化
-        nd->flag |= 1;
-        clif_clearchar (&nd->bl, 0);
-    }
-    if (flag & 3 && (nd->u.scr.xs > 0 || nd->u.scr.ys > 0))
-        map_foreachinarea (npc_enable_sub, nd->bl.m, nd->bl.x - nd->u.scr.xs,
-                           nd->bl.y - nd->u.scr.ys, nd->bl.x + nd->u.scr.xs,
-                           nd->bl.y + nd->u.scr.ys, BL_PC, nd);
-
-    return 0;
-}
-
-/*==========================================
- * NPCを名前で探す
- *------------------------------------------
- */
-struct npc_data *npc_name2id (const char *name)
-{
-    return (struct npc_data *)strdb_search (npcname_db, name);
-}
-
-/*==========================================
- * イベントキューのイベント処理
- *------------------------------------------
- */
-int npc_event_dequeue (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    sd->npc_id = 0;
-
-    if (sd->eventqueue[0][0]) // キューのイベント処理
-    {
-        if (!pc_addeventtimer(sd, 100, sd->eventqueue[0]))
-        {
-            printf ("npc_event_dequeue(): Event timer is full.\n");
-            return 0;
-        }
-
-        if (MAX_EVENTQUEUE > 1)
-            memmove (sd->eventqueue[0], sd->eventqueue[1],
-                     (MAX_EVENTQUEUE - 1) * sizeof (sd->eventqueue[0]));
-        sd->eventqueue[MAX_EVENTQUEUE - 1][0] = '\0';
-        return 1;
-    }
-
-    return 0;
-}
-
-int npc_delete (struct npc_data *nd)
-{
-    nullpo_retr (1, nd);
-
-    if (nd->bl.prev == NULL)
-        return 1;
-
-    clif_clearchar_area (&nd->bl, 1);
-    map_delblock (&nd->bl);
-    return 0;
-}
-
-/*==========================================
- * イベントの遅延実行
- *------------------------------------------
- */
-void npc_event_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = map_id2sd (id);
-    if (sd == NULL)
-        return;
-
-    npc_event (sd, (const char *) data, 0);
-    free ((void *) data);
-}
-
-int npc_timer_event (const char *eventname) // Added by RoVeRT
-{
-    struct event_data *ev = (struct event_data *)strdb_search (ev_db, eventname);
-    struct npc_data *nd;
-//  int xs,ys;
-
-    if ((ev == NULL || (nd = ev->nd) == NULL))
-    {
-        printf ("npc_event: event not found [%s]\n", eventname);
-        return 0;
-    }
-
-    run_script (nd->u.scr.script, ev->pos, nd->bl.id, nd->bl.id);
-
-    return 0;
-}
-
-/*
-int npc_timer_sub_sub(void *key,void *data,va_list ap)	// Added by RoVeRT
-{
-	char *p=(char *)key;
-	struct event_data *ev=(struct event_data *)data;
-	int *c=va_arg(ap,int *);
-	int tick=0,ctick=gettick();
-	char temp[10];
-	char event[100];
-
-	if(ev->nd->bl.id==(int)*c && (p=strchr(p,':')) && p && strncasecmp("::OnTimer",p,8)==0 ){
-		sscanf(&p[9],"%s",temp);
-		tick=atoi(temp);
-
-		strcpy( event, ev->nd->name);
-		strcat( event, p);
-
-		if (ctick >= ev->nd->lastaction && ctick - ev->nd->timer >= tick) {
-			npc_timer_event(event);
-			ev->nd->lastaction = ctick;
-		}
-	}
-	return 0;
-}
-
-int npc_timer_sub(void *key,void *data,va_list ap)	// Added by RoVeRT
-{
-	struct npc_data *nd=(struct npc_data*)data;
-
-	if(nd->timer == -1)
-		return 0;
-
-	strdb_foreach(ev_db,npc_timer_sub_sub,&nd->bl.id);
-
-	return 0;
-}
-
-int npc_timer(int tid,unsigned int tick,int id,int data)	// Added by RoVeRT
-{
-	strdb_foreach(npcname_db,npc_timer_sub);
-
-	free((void*)data);
-	return 0;
-}*/
-/*==========================================
- * イベント用ラベルのエクスポート
- * npc_parse_script->strdb_foreachから呼ばれる
- *------------------------------------------
- */
-int npc_event_export (void *key, void *data, va_list ap)
-{
-    char *lname = (char *) key;
-    int  pos = (int) data;
-    struct npc_data *nd = va_arg (ap, struct npc_data *);
-
-    if ((lname[0] == 'O' || lname[0] == 'o')
-        && (lname[1] == 'N' || lname[1] == 'n'))
-    {
-        struct event_data *ev;
-        char *buf;
-        char *p = strchr (lname, ':');
-        // エクスポートされる
-        CREATE (ev, struct event_data, 1);
-        CREATE (buf, char, 50);
-        if (p == NULL || (p - lname) > 24)
-        {
-            printf ("npc_event_export: label name error !\n");
-            exit (1);
-        }
-        else
-        {
-            ev->nd = nd;
-            ev->pos = pos;
-            *p = '\0';
-            sprintf (buf, "%s::%s", nd->exname, lname);
-            *p = ':';
-            strdb_insert (ev_db, buf, ev);
-//          if (battle_config.etc_log)
-//              printf("npc_event_export: export [%s]\n",buf);
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * 全てのNPCのOn*イベント実行
- *------------------------------------------
- */
-void npc_event_doall_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    const char *p = key.s;
-    int  rid, argc;
-    argrec_t *argv;
-    struct event_data *ev;
-    int *c;
-    const char *name;
-
-    nullpo_retv (ev = (struct event_data *) data);
-    nullpo_retv (ap);
-    nullpo_retv (c = va_arg (ap, int *));
-
-    name = va_arg (ap, const char *);
-    rid = va_arg (ap, int);
-    argc = va_arg (ap, int);
-    argv = va_arg (ap, argrec_t *);
-
-    if ((p = strchr (p, ':')) && p && strcasecmp (name, p) == 0)
-    {
-        run_script_l (ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id, argc,
-                      argv);
-        (*c)++;
-    }
-}
-
-int npc_event_doall_l (const char *name, int rid, int argc, argrec_t * args)
-{
-    int  c = 0;
-    char buf[64] = "::";
-
-    strncpy (buf + 2, name, sizeof(buf)-3);
-    buf[sizeof(buf)-1] = '\0';
-    strdb_foreach (ev_db, npc_event_doall_sub, &c, buf, rid, argc, args);
-    return c;
-}
-
-void npc_event_do_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    const char *p = key.s;
-    struct event_data *ev;
-    int *c;
-    const char *name;
-    int  rid, argc;
-    argrec_t *argv;
-
-    nullpo_retv (ev = (struct event_data *) data);
-    nullpo_retv (ap);
-    nullpo_retv (c = va_arg (ap, int *));
-
-    name = va_arg (ap, const char *);
-    rid = va_arg (ap, int);
-    argc = va_arg (ap, int);
-    argv = va_arg (ap, argrec_t *);
-
-    if (p && strcasecmp (name, p) == 0)
-    {
-        run_script_l (ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id, argc,
-                      argv);
-        (*c)++;
-    }
-}
-
-int npc_event_do_l (const char *name, int rid, int argc, argrec_t * args)
-{
-    int  c = 0;
-
-    if (*name == ':' && name[1] == ':')
-    {
-        return npc_event_doall_l (name + 2, rid, argc, args);
-    }
-
-    strdb_foreach (ev_db, npc_event_do_sub, &c, name, rid, argc, args);
-    return c;
-}
-
-/*==========================================
- * 時計イベント実行
- *------------------------------------------
- */
-void npc_event_do_clock (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    time_t timer;
-    struct tm *t;
-    char buf[64];
-    int  c = 0;
-
-    time (&timer);
-    t = gmtime (&timer);
-
-    if (t->tm_min != ev_tm_b.tm_min)
-    {
-        sprintf (buf, "OnMinute%02d", t->tm_min);
-        c += npc_event_doall (buf);
-        sprintf (buf, "OnClock%02d%02d", t->tm_hour, t->tm_min);
-        c += npc_event_doall (buf);
-    }
-    if (t->tm_hour != ev_tm_b.tm_hour)
-    {
-        sprintf (buf, "OnHour%02d", t->tm_hour);
-        c += npc_event_doall (buf);
-    }
-    if (t->tm_mday != ev_tm_b.tm_mday)
-    {
-        sprintf (buf, "OnDay%02d%02d", t->tm_mon + 1, t->tm_mday);
-        c += npc_event_doall (buf);
-    }
-    memcpy (&ev_tm_b, t, sizeof (ev_tm_b));
-}
-
-/*==========================================
- * OnInitイベント実行(&時計イベント開始)
- *------------------------------------------
- */
-int npc_event_do_oninit (void)
-{
-    int  c = npc_event_doall ("OnInit");
-    printf ("npc: OnInit Event done. (%d npc)\n", c);
-
-    add_timer_interval (gettick () + 100, npc_event_do_clock, 0, 0, 1000);
-
-    return 0;
-}
-
-/*==========================================
- * OnTimer NPC event - by RoVeRT
- *------------------------------------------
- */
-int npc_addeventtimer (struct npc_data *nd, int tick, const char *name)
-{
-    int  i;
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (nd->eventtimer[i] == -1)
-            break;
-    if (i < MAX_EVENTTIMER)
-    {
-        char *evname;
-        CREATE (evname, char, 24);
-        memcpy (evname, name, 24);
-        nd->eventtimer[i] = add_timer (gettick () + tick,
-                                       npc_event_timer, nd->bl.id,
-                                       (int) evname);
-    }
-    else
-        printf ("npc_addtimer: event timer is full !\n");
-
-    return 0;
-}
-
-int npc_deleventtimer (struct npc_data *nd, const char *name)
-{
-    int  i;
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (nd->eventtimer[i] != -1 && strcmp ((char
-                                                *) (get_timer (nd->eventtimer
-                                                               [i])->data),
-                                               name) == 0)
-        {
-            delete_timer (nd->eventtimer[i], npc_event_timer);
-            nd->eventtimer[i] = -1;
-            break;
-        }
-
-    return 0;
-}
-
-int npc_cleareventtimer (struct npc_data *nd)
-{
-    int  i;
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (nd->eventtimer[i] != -1)
-        {
-            delete_timer (nd->eventtimer[i], npc_event_timer);
-            nd->eventtimer[i] = -1;
-        }
-
-    return 0;
-}
-
-void npc_do_ontimer_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    const char *p = key.s;
-    struct event_data *ev = (struct event_data *) data;
-    int *c = va_arg (ap, int *);
-//  struct map_session_data *sd=va_arg(ap,struct map_session_data *);
-    int  option = va_arg (ap, int);
-    int  tick = 0;
-    char temp[10];
-    char event[50];
-
-    if (ev->nd->bl.id == (int) *c && (p = strchr (p, ':')) && p
-        && strncasecmp ("::OnTimer", p, 8) == 0)
-    {
-        sscanf (&p[9], "%s", temp);
-        tick = atoi (temp);
-
-        strcpy (event, ev->nd->name);
-        strcat (event, p);
-
-        if (option != 0)
-        {
-            npc_addeventtimer (ev->nd, tick, event);
-        }
-        else
-        {
-            npc_deleventtimer (ev->nd, event);
-        }
-    }
-}
-
-int npc_do_ontimer (int npc_id, struct map_session_data *sd, int option)
-{
-    strdb_foreach (ev_db, npc_do_ontimer_sub, &npc_id, sd, option);
-    return 0;
-}
-
-/*==========================================
- * タイマーイベント用ラベルの取り込み
- * npc_parse_script->strdb_foreachから呼ばれる
- *------------------------------------------
- */
-int npc_timerevent_import (void *key, void *data, va_list ap)
-{
-    char *lname = (char *) key;
-    int  pos = (int) data;
-    struct npc_data *nd = va_arg (ap, struct npc_data *);
-    int  t = 0, i = 0;
-
-    if (sscanf (lname, "OnTimer%d%n", &t, &i) == 1 && lname[i] == ':')
-    {
-        // タイマーイベント
-        struct npc_timerevent_list *te = nd->u.scr.timer_event;
-        int  j, i = nd->u.scr.timeramount;
-        RECREATE (te, struct npc_timerevent_list, i+1);
-        for (j = 0; j < i; j++)
-        {
-            if (te[j].timer > t)
-            {
-                memmove (te + j + 1, te + j,
-                         sizeof (struct npc_timerevent_list) * (i - j));
-                break;
-            }
-        }
-        te[j].timer = t;
-        te[j].pos = pos;
-        nd->u.scr.timer_event = te;
-        nd->u.scr.timeramount = i + 1;
-    }
-    return 0;
-}
-
-/*==========================================
- * タイマーイベント実行
- *------------------------------------------
- */
-void npc_timerevent (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  next, t;
-    struct npc_data *nd = (struct npc_data *) map_id2bl (id);
-    struct npc_timerevent_list *te;
-    if (nd == NULL || nd->u.scr.nexttimer < 0)
-    {
-        printf ("npc_timerevent: ??\n");
-        return;
-    }
-    nd->u.scr.timertick = tick;
-    te = nd->u.scr.timer_event + nd->u.scr.nexttimer;
-    nd->u.scr.timerid = -1;
-
-    t = nd->u.scr.timer += data;
-    nd->u.scr.nexttimer++;
-    if (nd->u.scr.timeramount > nd->u.scr.nexttimer)
-    {
-        next = nd->u.scr.timer_event[nd->u.scr.nexttimer].timer - t;
-        nd->u.scr.timerid = add_timer (tick + next, npc_timerevent, id, next);
-    }
-
-    run_script (nd->u.scr.script, te->pos, 0, nd->bl.id);
-}
-
-/*==========================================
- * タイマーイベント開始
- *------------------------------------------
- */
-int npc_timerevent_start (struct npc_data *nd)
-{
-    int  j, n, next;
-
-    nullpo_retr (0, nd);
-
-    n = nd->u.scr.timeramount;
-    if (nd->u.scr.nexttimer >= 0 || n == 0)
-        return 0;
-
-    for (j = 0; j < n; j++)
-    {
-        if (nd->u.scr.timer_event[j].timer > nd->u.scr.timer)
-            break;
-    }
-    nd->u.scr.nexttimer = j;
-    nd->u.scr.timertick = gettick ();
-
-    if (j >= n)
-        return 0;
-
-    next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer;
-    nd->u.scr.timerid =
-        add_timer (gettick () + next, npc_timerevent, nd->bl.id, next);
-    return 0;
-}
-
-/*==========================================
- * タイマーイベント終了
- *------------------------------------------
- */
-int npc_timerevent_stop (struct npc_data *nd)
-{
-    nullpo_retr (0, nd);
-
-    if (nd->u.scr.nexttimer >= 0)
-    {
-        nd->u.scr.nexttimer = -1;
-        nd->u.scr.timer += (int) (gettick () - nd->u.scr.timertick);
-        if (nd->u.scr.timerid != -1)
-            delete_timer (nd->u.scr.timerid, npc_timerevent);
-        nd->u.scr.timerid = -1;
-    }
-    return 0;
-}
-
-/*==========================================
- * タイマー値の所得
- *------------------------------------------
- */
-int npc_gettimerevent_tick (struct npc_data *nd)
-{
-    int  tick;
-
-    nullpo_retr (0, nd);
-
-    tick = nd->u.scr.timer;
-
-    if (nd->u.scr.nexttimer >= 0)
-        tick += (int) (gettick () - nd->u.scr.timertick);
-    return tick;
-}
-
-/*==========================================
- * タイマー値の設定
- *------------------------------------------
- */
-int npc_settimerevent_tick (struct npc_data *nd, int newtimer)
-{
-    int  flag;
-
-    nullpo_retr (0, nd);
-
-    flag = nd->u.scr.nexttimer;
-
-    npc_timerevent_stop (nd);
-    nd->u.scr.timer = newtimer;
-    if (flag >= 0)
-        npc_timerevent_start (nd);
-    return 0;
-}
-
-/*==========================================
- * イベント型のNPC処理
- *------------------------------------------
- */
-int npc_event (struct map_session_data *sd, const char *eventname,
-               int mob_kill)
-{
-    struct event_data *ev = (struct event_data *)strdb_search (ev_db, eventname);
-    struct npc_data *nd;
-    int  xs, ys;
-    char mobevent[100];
-
-    if (sd == NULL)
-    {
-        printf ("npc_event nullpo?\n");
-    }
-
-    if (ev == NULL && eventname
-        && strcmp (((eventname) + strlen (eventname) - 9), "::OnTouch") == 0)
-        return 1;
-
-    if (ev == NULL || (nd = ev->nd) == NULL)
-    {
-        if (mob_kill && (ev == NULL || (nd = ev->nd) == NULL))
-        {
-            strcpy (mobevent, eventname);
-            strcat (mobevent, "::OnMyMobDead");
-            ev = (struct event_data *)strdb_search (ev_db, mobevent);
-            if (ev == NULL || (nd = ev->nd) == NULL)
-            {
-                if (strncasecmp (eventname, "GM_MONSTER", 10) != 0)
-                    printf ("npc_event: event not found [%s]\n", mobevent);
-                return 0;
-            }
-        }
-        else
-        {
-            if (battle_config.error_log)
-                printf ("npc_event: event not found [%s]\n", eventname);
-            return 0;
-        }
-    }
-
-    xs = nd->u.scr.xs;
-    ys = nd->u.scr.ys;
-    if (xs >= 0 && ys >= 0)
-    {
-        if (nd->bl.m != sd->bl.m)
-            return 1;
-        if (xs > 0
-            && (sd->bl.x < nd->bl.x - xs / 2 || nd->bl.x + xs / 2 < sd->bl.x))
-            return 1;
-        if (ys > 0
-            && (sd->bl.y < nd->bl.y - ys / 2 || nd->bl.y + ys / 2 < sd->bl.y))
-            return 1;
-    }
-
-    if (sd->npc_id != 0)
-    {
-//      if (battle_config.error_log)
-//          printf("npc_event: npc_id != 0\n");
-        int  i;
-        for (i = 0; i < MAX_EVENTQUEUE; i++)
-            if (!sd->eventqueue[i][0])
-                break;
-        if (i == MAX_EVENTQUEUE)
-        {
-            if (battle_config.error_log)
-                printf ("npc_event: event queue is full !\n");
-        }
-        else
-        {
-//          if (battle_config.etc_log)
-//              printf("npc_event: enqueue\n");
-            strncpy (sd->eventqueue[i], eventname, 50);
-            sd->eventqueue[i][49] = '\0';
-        }
-        return 1;
-    }
-    if (nd->flag & 1)
-    {                           // 無効化されている
-        npc_event_dequeue (sd);
-        return 0;
-    }
-
-    sd->npc_id = nd->bl.id;
-    sd->npc_pos =
-        run_script (nd->u.scr.script, ev->pos, sd->bl.id, nd->bl.id);
-    return 0;
-}
-
-void npc_command_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    const char *p = key.s;
-    struct event_data *ev = (struct event_data *) data;
-    char *npcname = va_arg (ap, char *);
-    char *command = va_arg (ap, char *);
-    char temp[100];
-
-    if (strcmp (ev->nd->name, npcname) == 0 && (p = strchr (p, ':')) && p
-        && strncasecmp ("::OnCommand", p, 10) == 0)
-    {
-        sscanf (&p[11], "%s", temp);
-
-        if (strcmp (command, temp) == 0)
-            run_script (ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id);
-    }
-}
-
-int npc_command (struct map_session_data *sd, char *npcname, char *command)
-{
-    strdb_foreach (ev_db, npc_command_sub, npcname, command);
-
-    return 0;
-}
-
-/*==========================================
- * 接触型のNPC処理
- *------------------------------------------
- */
-int npc_touch_areanpc (struct map_session_data *sd, int m, int x, int y)
-{
-    int  i, f = 1;
-    int  xs, ys;
-
-    nullpo_retr (1, sd);
-
-    if (sd->npc_id)
-        return 1;
-
-    for (i = 0; i < map[m].npc_num; i++)
-    {
-        if (map[m].npc[i]->flag & 1)
-        {                       // 無効化されている
-            f = 0;
-            continue;
-        }
-
-        switch (map[m].npc[i]->bl.subtype)
-        {
-            case WARP:
-                xs = map[m].npc[i]->u.warp.xs;
-                ys = map[m].npc[i]->u.warp.ys;
-                break;
-            case MESSAGE:
-            case SCRIPT:
-                xs = map[m].npc[i]->u.scr.xs;
-                ys = map[m].npc[i]->u.scr.ys;
-                break;
-            default:
-                continue;
-        }
-        if (x >= map[m].npc[i]->bl.x - xs / 2
-            && x < map[m].npc[i]->bl.x - xs / 2 + xs
-            && y >= map[m].npc[i]->bl.y - ys / 2
-            && y < map[m].npc[i]->bl.y - ys / 2 + ys)
-            break;
-    }
-    if (i == map[m].npc_num)
-    {
-        if (f)
-        {
-            if (battle_config.error_log)
-                printf ("npc_touch_areanpc : some bug \n");
-        }
-        return 1;
-    }
-    switch (map[m].npc[i]->bl.subtype)
-    {
-        case WARP:
-            skill_stop_dancing (&sd->bl, 0);
-            pc_setpos (sd, map[m].npc[i]->u.warp.name,
-                       map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, 0);
-            break;
-        case MESSAGE:
-        case SCRIPT:
-        {
-            char *name = (char *)malloc (50);
-
-            memcpy (name, map[m].npc[i]->name, 50);
-            if (sd->areanpc_id == map[m].npc[i]->bl.id)
-                return 1;
-            sd->areanpc_id = map[m].npc[i]->bl.id;
-            if (npc_event (sd, strcat (name, "::OnTouch"), 0) > 0)
-                npc_click (sd, map[m].npc[i]->bl.id);
-            free (name);
-            break;
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * 近くかどうかの判定
- *------------------------------------------
- */
-int npc_checknear (struct map_session_data *sd, int id)
-{
-    struct npc_data *nd;
-
-    nullpo_retr (0, sd);
-
-    nd = (struct npc_data *) map_id2bl (id);
-    if (nd == NULL || nd->bl.type != BL_NPC)
-    {
-        if (battle_config.error_log)
-            printf ("no such npc : %d\n", id);
-        return 1;
-    }
-
-    if (nd->npc_class < 0)          // イベント系は常にOK
-        return 0;
-
-    // エリア判定
-    if (nd->bl.m != sd->bl.m ||
-        nd->bl.x < sd->bl.x - AREA_SIZE - 1
-        || nd->bl.x > sd->bl.x + AREA_SIZE + 1
-        || nd->bl.y < sd->bl.y - AREA_SIZE - 1
-        || nd->bl.y > sd->bl.y + AREA_SIZE + 1)
-        return 1;
-
-    return 0;
-}
-
-/*==========================================
- * クリック時のNPC処理
- *------------------------------------------
- */
-int npc_click (struct map_session_data *sd, int id)
-{
-    struct npc_data *nd;
-
-    nullpo_retr (1, sd);
-
-    if (sd->npc_id != 0)
-    {
-        if (battle_config.error_log)
-            printf ("npc_click: npc_id != 0\n");
-        return 1;
-    }
-
-    if (npc_checknear (sd, id)) {
-        clif_scriptclose (sd, id);
-        return 1;
-    }
-
-    nd = (struct npc_data *) map_id2bl (id);
-
-    if (nd->flag & 1)           // 無効化されている
-        return 1;
-
-    sd->npc_id = id;
-    switch (nd->bl.subtype)
-    {
-        case SHOP:
-            clif_npcbuysell (sd, id);
-            npc_event_dequeue (sd);
-            break;
-        case SCRIPT:
-            sd->npc_pos = run_script (nd->u.scr.script, 0, sd->bl.id, id);
-            break;
-        case MESSAGE:
-            if (nd->u.message)
-            {
-                clif_scriptmes (sd, id, nd->u.message);
-                clif_scriptclose (sd, id);
-            }
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int npc_scriptcont (struct map_session_data *sd, int id)
-{
-    struct npc_data *nd;
-
-    nullpo_retr (1, sd);
-
-    if (id != sd->npc_id)
-        return 1;
-    if (npc_checknear (sd, id)) {
-        clif_scriptclose (sd, id);
-        return 1;
-    }
-
-    nd = (struct npc_data *) map_id2bl (id);
-
-    if (!nd /* NPC was disposed? */  || nd->bl.subtype == MESSAGE)
-    {
-        clif_scriptclose (sd, id);
-        npc_event_dequeue (sd);
-        return 0;
-    }
-
-    sd->npc_pos = run_script (nd->u.scr.script, sd->npc_pos, sd->bl.id, id);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int npc_buysellsel (struct map_session_data *sd, int id, int type)
-{
-    struct npc_data *nd;
-
-    nullpo_retr (1, sd);
-
-    if (npc_checknear (sd, id))
-        return 1;
-
-    nd = (struct npc_data *) map_id2bl (id);
-    if (nd->bl.subtype != SHOP)
-    {
-        if (battle_config.error_log)
-            printf ("no such shop npc : %d\n", id);
-        sd->npc_id = 0;
-        return 1;
-    }
-    if (nd->flag & 1)           // 無効化されている
-        return 1;
-
-    sd->npc_shopid = id;
-    if (type == 0)
-    {
-        clif_buylist (sd, nd);
-    }
-    else
-    {
-        clif_selllist (sd);
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int npc_buylist (struct map_session_data *sd, int n,
-                 unsigned short *item_list)
-{
-    struct npc_data *nd;
-    double z;
-    int  i, j, w, skill, itemamount = 0, new_stacks = 0;
-
-    nullpo_retr (3, sd);
-    nullpo_retr (3, item_list);
-
-    if (npc_checknear (sd, sd->npc_shopid))
-        return 3;
-
-    nd = (struct npc_data *) map_id2bl (sd->npc_shopid);
-    if (nd->bl.subtype != SHOP)
-        return 3;
-
-    for (i = 0, w = 0, z = 0; i < n; i++)
-    {
-        for (j = 0; nd->u.shop_item[j].nameid; j++)
-        {
-            if (nd->u.shop_item[j].nameid == item_list[i * 2 + 1])
-                break;
-        }
-        if (nd->u.shop_item[j].nameid == 0)
-            return 3;
-
-        if (itemdb_value_notdc (nd->u.shop_item[j].nameid))
-            z += (double) nd->u.shop_item[j].value * item_list[i * 2];
-        else
-            z += (double) pc_modifybuyvalue (sd,
-                                             nd->u.shop_item[j].value) *
-                item_list[i * 2];
-        itemamount += item_list[i * 2];
-
-        switch (pc_checkadditem (sd, item_list[i * 2 + 1], item_list[i * 2]))
-        {
-            case ADDITEM_EXIST:
-                break;
-            case ADDITEM_NEW:
-                if (itemdb_isequip (item_list[i * 2 + 1]))
-                    new_stacks += item_list[i * 2];
-                else
-                    new_stacks++;
-                break;
-            case ADDITEM_OVERAMOUNT:
-                return 2;
-        }
-
-        w += itemdb_weight (item_list[i * 2 + 1]) * item_list[i * 2];
-    }
-
-    if (z > (double) sd->status.zeny)
-        return 1;               // zeny不足
-    if (w + sd->weight > sd->max_weight)
-        return 2;               // 重量超過
-    if (pc_inventoryblank (sd) < new_stacks)
-        return 3;               // 種類数超過
-    if (sd->trade_partner != 0)
-        return 4;               // cant buy while trading
-
-    pc_payzeny (sd, (int) z);
-
-    for (i = 0; i < n; i++)
-    {
-        struct item_data *item_data;
-        if ((item_data = itemdb_exists (item_list[i * 2 + 1])) != NULL)
-        {
-            int  amount = item_list[i * 2];
-            struct item item_tmp;
-            memset (&item_tmp, 0, sizeof (item_tmp));
-
-            item_tmp.nameid = item_data->nameid;
-            item_tmp.identify = 1;  // npc販売アイテムは鑑定済み
-
-            if (amount > 1
-                && (item_data->type == 4 || item_data->type == 5
-                    || item_data->type == 7 || item_data->type == 8))
-            {
-                for (j = 0; j < amount; j++)
-                {
-                    pc_additem (sd, &item_tmp, 1);
-                }
-            }
-            else
-            {
-                pc_additem (sd, &item_tmp, amount);
-            }
-        }
-    }
-
-    //商人経験値
-/*	if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
-		z = z * pc_checkskill(sd,MC_DISCOUNT) / ((1 + 300 / itemamount) * 4000) * battle_config.shop_exp;
-		pc_gainexp(sd,0,z);
-	}*/
-    if (battle_config.shop_exp > 0 && z > 0
-        && (skill = pc_checkskill (sd, MC_DISCOUNT)) > 0)
-    {
-        if (skill > 0)
-        {
-            z = (log (z * (double) skill) * (double) battle_config.shop_exp /
-                 100.);
-            if (z < 1)
-                z = 1;
-            pc_gainexp (sd, 0, (int) z);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int npc_selllist (struct map_session_data *sd, int n,
-                  unsigned short *item_list)
-{
-    double z;
-    int  i, skill, itemamount = 0;
-
-    nullpo_retr (1, sd);
-    nullpo_retr (1, item_list);
-
-    if (npc_checknear (sd, sd->npc_shopid))
-        return 1;
-    for (i = 0, z = 0; i < n; i++)
-    {
-        int  nameid;
-        if (item_list[i * 2] - 2 < 0 || item_list[i * 2] - 2 >= MAX_INVENTORY)
-            return 1;
-        nameid = sd->status.inventory[item_list[i * 2] - 2].nameid;
-        if (nameid == 0 ||
-            sd->status.inventory[item_list[i * 2] - 2].amount <
-            item_list[i * 2 + 1])
-            return 1;
-        if (sd->trade_partner != 0)
-            return 2;           // cant sell while trading
-        if (itemdb_value_notoc (nameid))
-            z += (double) itemdb_value_sell (nameid) * item_list[i * 2 + 1];
-        else
-            z += (double) pc_modifysellvalue (sd,
-                                              itemdb_value_sell (nameid)) *
-                item_list[i * 2 + 1];
-        itemamount += item_list[i * 2 + 1];
-    }
-
-    if (z > MAX_ZENY)
-        z = MAX_ZENY;
-    pc_getzeny (sd, (int) z);
-    for (i = 0; i < n; i++)
-    {
-        int  item_id = item_list[i * 2] - 2;
-        pc_delitem (sd, item_id, item_list[i * 2 + 1], 0);
-    }
-
-    //商人経験値
-/*	if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
-		z = z * pc_checkskill(sd,MC_OVERCHARGE) / ((1 + 500 / itemamount) * 4000) * battle_config.shop_exp ;
-		pc_gainexp(sd,0,z);
-	}*/
-    if (battle_config.shop_exp > 0 && z > 0
-        && (skill = pc_checkskill (sd, MC_OVERCHARGE)) > 0)
-    {
-        if (skill > 0)
-        {
-            z = (log (z * (double) skill) * (double) battle_config.shop_exp /
-                 100.);
-            if (z < 1)
-                z = 1;
-            pc_gainexp (sd, 0, (int) z);
-        }
-    }
-
-    return 0;
-
-}
-
-//
-// 初期化関係
-//
-
-/*==========================================
- * 読み込むnpcファイルのクリア
- *------------------------------------------
- */
-void npc_clearsrcfile (void)
-{
-    struct npc_src_list *p = npc_src_first;
-
-    while (p)
-    {
-        struct npc_src_list *p2 = p;
-        p = p->next;
-        free (p2);
-    }
-    npc_src_first = NULL;
-    npc_src_last = NULL;
-}
-
-/*==========================================
- * 読み込むnpcファイルの追加
- *------------------------------------------
- */
-void npc_addsrcfile (char *name)
-{
-    struct npc_src_list *new_src;
-    size_t len;
-
-    if (strcasecmp (name, "clear") == 0)
-    {
-        npc_clearsrcfile ();
-        return;
-    }
-
-    len = sizeof (*new_src) + strlen (name);
-    new_src = (struct npc_src_list *) calloc (1, len);
-    new_src->next = NULL;
-    strncpy (new_src->name, name, strlen (name) + 1);
-    if (npc_src_first == NULL)
-        npc_src_first = new_src;
-    if (npc_src_last)
-        npc_src_last->next = new_src;
-
-    npc_src_last = new_src;
-}
-
-/*==========================================
- * 読み込むnpcファイルの削除
- *------------------------------------------
- */
-void npc_delsrcfile (char *name)
-{
-    struct npc_src_list *p = npc_src_first, *pp = NULL, **lp = &npc_src_first;
-
-    if (strcasecmp (name, "all") == 0)
-    {
-        npc_clearsrcfile ();
-        return;
-    }
-
-    for (; p; lp = &p->next, pp = p, p = p->next)
-    {
-        if (strcmp (p->name, name) == 0)
-        {
-            *lp = p->next;
-            if (npc_src_last == p)
-                npc_src_last = pp;
-            free (p);
-            break;
-        }
-    }
-}
-
-/*==========================================
- * warp行解析
- *------------------------------------------
- */
-int npc_parse_warp (char *w1, char *w2, char *w3, char *w4)
-{
-    int  x, y, xs, ys, to_x, to_y, m;
-    int  i, j;
-    char mapname[24], to_mapname[24];
-    struct npc_data *nd;
-
-    // 引数の個数チェック
-    if (sscanf (w1, "%[^,],%d,%d", mapname, &x, &y) != 3 ||
-        sscanf (w4, "%d,%d,%[^,],%d,%d", &xs, &ys, to_mapname, &to_x,
-                &to_y) != 5)
-    {
-        printf ("bad warp line : %s\n", w3);
-        return 1;
-    }
-
-    m = map_mapname2mapid (mapname);
-
-    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data));
-    nd->bl.id = npc_get_new_npc_id ();
-    nd->n = map_addnpc (m, nd);
-
-    nd->bl.prev = nd->bl.next = NULL;
-    nd->bl.m = m;
-    nd->bl.x = x;
-    nd->bl.y = y;
-    nd->dir = 0;
-    nd->flag = 0;
-    memcpy (nd->name, w3, 24);
-    memcpy (nd->exname, w3, 24);
-
-    nd->chat_id = 0;
-    if (!battle_config.warp_point_debug)
-        nd->npc_class = WARP_CLASS;
-    else
-        nd->npc_class = WARP_DEBUG_CLASS;
-    nd->speed = 200;
-    nd->option = 0;
-    nd->opt1 = 0;
-    nd->opt2 = 0;
-    nd->opt3 = 0;
-    memcpy (nd->u.warp.name, to_mapname, 16);
-    xs += 2;
-    ys += 2;
-    nd->u.warp.x = to_x;
-    nd->u.warp.y = to_y;
-    nd->u.warp.xs = xs;
-    nd->u.warp.ys = ys;
-
-    for (i = 0; i < ys; i++)
-    {
-        for (j = 0; j < xs; j++)
-        {
-            int  t;
-            t = map_getcell (m, x - xs / 2 + j, y - ys / 2 + i);
-            if (t == 1 || t == 5)
-                continue;
-            map_setcell (m, x - xs / 2 + j, y - ys / 2 + i, t | 0x80);
-        }
-    }
-
-//  printf("warp npc %s %d read done\n",mapname,nd->bl.id);
-    npc_warp++;
-    nd->bl.type = BL_NPC;
-    nd->bl.subtype = WARP;
-    map_addblock (&nd->bl);
-    clif_spawnnpc (nd);
-    strdb_insert (npcname_db, nd->name, nd);
-
-    return 0;
-}
-
-/*==========================================
- * shop行解析
- *------------------------------------------
- */
-static int npc_parse_shop (char *w1, char *w2, char *w3, char *w4)
-{
-    char *p;
-    int  x, y, dir, m;
-    int  max = 100, pos = 0;
-    char mapname[24];
-    struct npc_data *nd;
-
-    // 引数の個数チェック
-    if (sscanf (w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ||
-        strchr (w4, ',') == NULL)
-    {
-        printf ("bad shop line : %s\n", w3);
-        return 1;
-    }
-    m = map_mapname2mapid (mapname);
-
-    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data) +
-                                      sizeof (nd->u.shop_item[0]) * (max +
-                                                                     1));
-    p = strchr (w4, ',');
-
-    while (p && pos < max)
-    {
-        int  nameid, value;
-        char name[24];
-        struct item_data *id = NULL;
-        p++;
-        if (sscanf (p, "%d:%d", &nameid, &value) == 2)
-        {
-        }
-        else if (sscanf (p, "%s :%d", name, &value) == 2)
-        {
-            id = itemdb_searchname (name);
-            if (id == NULL)
-                nameid = -1;
-            else
-                nameid = id->nameid;
-        }
-        else
-            break;
-
-        if (nameid > 0)
-        {
-            nd->u.shop_item[pos].nameid = nameid;
-            if (value < 0)
-            {
-                if (id == NULL)
-                    id = itemdb_search (nameid);
-                value = id->value_buy * abs (value);
-
-            }
-            nd->u.shop_item[pos].value = value;
-            pos++;
-        }
-        p = strchr (p, ',');
-    }
-    if (pos == 0)
-    {
-        free (nd);
-        return 1;
-    }
-    nd->u.shop_item[pos++].nameid = 0;
-
-    nd->bl.prev = nd->bl.next = NULL;
-    nd->bl.m = m;
-    nd->bl.x = x;
-    nd->bl.y = y;
-    nd->bl.id = npc_get_new_npc_id ();
-    nd->dir = dir;
-    nd->flag = 0;
-    memcpy (nd->name, w3, 24);
-    nd->npc_class = atoi (w4);
-    nd->speed = 200;
-    nd->chat_id = 0;
-    nd->option = 0;
-    nd->opt1 = 0;
-    nd->opt2 = 0;
-    nd->opt3 = 0;
-
-    nd = (struct npc_data *)
-        realloc (nd, sizeof (struct npc_data) + sizeof (nd->u.shop_item[0]) * pos);
-
-    //printf("shop npc %s %d read done\n",mapname,nd->bl.id);
-    npc_shop++;
-    nd->bl.type = BL_NPC;
-    nd->bl.subtype = SHOP;
-    nd->n = map_addnpc (m, nd);
-    map_addblock (&nd->bl);
-    clif_spawnnpc (nd);
-    strdb_insert (npcname_db, nd->name, nd);
-
-    return 0;
-}
-
-/*==========================================
- * NPCのラベルデータコンバート
- *------------------------------------------
- */
-void npc_convertlabel_db (db_key_t key, db_val_t data, va_list ap)
-{
-    const char *lname = key.s;
-    int  pos = (int) data;
-    struct npc_data *nd;
-    struct npc_label_list *lst;
-    int  num;
-    char *p = strchr (lname, ':');
-
-    nullpo_retv (ap);
-    nullpo_retv (nd = va_arg (ap, struct npc_data *));
-
-    lst = nd->u.scr.label_list;
-    num = nd->u.scr.label_list_num;
-    if (!lst)
-    {
-        lst = (struct npc_label_list *)
-                calloc (1, sizeof (struct npc_label_list));
-        num = 0;
-    }
-    else
-        lst = (struct npc_label_list *)
-                realloc (lst, sizeof (struct npc_label_list) * (num + 1));
-
-    *p = '\0';
-    strncpy (lst[num].name, lname, sizeof(lst[num].name)-1);
-    lst[num].name[sizeof(lst[num].name)-1] = '\0';
-    *p = ':';
-    lst[num].pos = pos;
-    nd->u.scr.label_list = lst;
-    nd->u.scr.label_list_num = num + 1;
-}
-
-/*==========================================
- * script行解析
- *------------------------------------------
- */
-static int npc_parse_script (char *w1, char *w2, char *w3, char *w4,
-                             char *first_line, FILE * fp, int *lines)
-{
-    int  x, y, dir = 0, m, xs = 0, ys = 0, npc_class = 0;   // [Valaris] thanks to fov
-    char mapname[24];
-    unsigned char *srcbuf = NULL, *script;
-    int  srcsize = 65536;
-    int  startline = 0;
-    unsigned char line[1024];
-    int  i;
-    struct npc_data *nd;
-    int  evflag = 0;
-    struct dbt *label_db;
-    char *p;
-    struct npc_label_list *label_dup = NULL;
-    int  label_dupnum = 0;
-    int  src_id = 0;
-
-    if (strcmp (w1, "-") == 0)
-    {
-        x = 0;
-        y = 0;
-        m = -1;
-    }
-    else
-    {
-        // 引数の個数チェック
-        if (sscanf (w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ||
-            (strcmp (w2, "script") == 0 && strchr (w4, ',') == NULL))
-        {
-            printf ("bad script line : %s\n", w3);
-            return 1;
-        }
-        m = map_mapname2mapid (mapname);
-    }
-
-    if (strcmp (w2, "script") == 0)
-    {
-        // スクリプトの解析
-        srcbuf = (char *) calloc (srcsize, sizeof (char));
-        if (strchr (first_line, '{'))
-        {
-            strcpy (srcbuf, strchr (first_line, '{'));
-            startline = *lines;
-        }
-        else
-            srcbuf[0] = 0;
-        while (1)
-        {
-            for (i = strlen (srcbuf) - 1; i >= 0 && isspace (srcbuf[i]); i--);
-            if (i >= 0 && srcbuf[i] == '}')
-                break;
-            if (!fgets (line, 1020, fp))
-                break;
-            (*lines)++;
-            if (feof (fp))
-                break;
-            if (strlen (srcbuf) + strlen (line) + 1 >= srcsize)
-            {
-                srcsize += 65536;
-                srcbuf = (char *) realloc (srcbuf, srcsize);
-                memset (srcbuf + srcsize - 65536, '\0', 65536);
-            }
-            if (srcbuf[0] != '{')
-            {
-                if (strchr (line, '{'))
-                {
-                    strcpy (srcbuf, strchr (line, '{'));
-                    startline = *lines;
-                }
-            }
-            else
-                strcat (srcbuf, line);
-        }
-        script = parse_script (srcbuf, startline);
-        if (script == NULL)
-        {
-            // script parse error?
-            free (srcbuf);
-            return 1;
-        }
-
-    }
-    else
-    {
-        // duplicateする
-
-        char srcname[128];
-        struct npc_data *nd2;
-        if (sscanf (w2, "duplicate(%[^)])", srcname) != 1)
-        {
-            printf ("bad duplicate name! : %s", w2);
-            return 0;
-        }
-        if ((nd2 = npc_name2id (srcname)) == NULL)
-        {
-            printf ("bad duplicate name! (not exist) : %s\n", srcname);
-            return 0;
-        }
-        script = nd2->u.scr.script;
-        label_dup = nd2->u.scr.label_list;
-        label_dupnum = nd2->u.scr.label_list_num;
-        src_id = nd2->bl.id;
-
-    }                           // end of スクリプト解析
-
-    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data));
-
-    if (m == -1)
-    {
-        // スクリプトコピー用のダミーNPC
-
-    }
-    else if (sscanf (w4, "%d,%d,%d", &npc_class, &xs, &ys) == 3)
-    {
-        // 接触型NPC
-        int  i, j;
-
-        if (xs >= 0)
-            xs = xs * 2 + 1;
-        if (ys >= 0)
-            ys = ys * 2 + 1;
-
-        if (npc_class >= 0)
-        {
-
-            for (i = 0; i < ys; i++)
-            {
-                for (j = 0; j < xs; j++)
-                {
-                    int  t;
-                    t = map_getcell (m, x - xs / 2 + j, y - ys / 2 + i);
-                    if (t == 1 || t == 5)
-                        continue;
-                    map_setcell (m, x - xs / 2 + j, y - ys / 2 + i, t | 0x80);
-                }
-            }
-        }
-
-        nd->u.scr.xs = xs;
-        nd->u.scr.ys = ys;
-    }
-    else
-    {                           // クリック型NPC
-        npc_class = atoi (w4);
-        nd->u.scr.xs = 0;
-        nd->u.scr.ys = 0;
-    }
-
-    if (npc_class < 0 && m >= 0)
-    {                           // イベント型NPC
-        evflag = 1;
-    }
-
-    while ((p = strchr (w3, ':')))
-    {
-        if (p[1] == ':')
-            break;
-    }
-    if (p)
-    {
-        *p = 0;
-        memcpy (nd->name, w3, 24);
-        memcpy (nd->exname, p + 2, 24);
-    }
-    else
-    {
-        memcpy (nd->name, w3, 24);
-        memcpy (nd->exname, w3, 24);
-    }
-
-    nd->bl.prev = nd->bl.next = NULL;
-    nd->bl.m = m;
-    nd->bl.x = x;
-    nd->bl.y = y;
-    nd->bl.id = npc_get_new_npc_id ();
-    nd->dir = dir;
-    nd->flag = 0;
-    nd->npc_class = npc_class;
-    nd->speed = 200;
-    nd->u.scr.script = script;
-    nd->u.scr.src_id = src_id;
-    nd->chat_id = 0;
-    nd->option = 0;
-    nd->opt1 = 0;
-    nd->opt2 = 0;
-    nd->opt3 = 0;
-
-    //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class);
-    npc_script++;
-    nd->bl.type = BL_NPC;
-    nd->bl.subtype = SCRIPT;
-    if (m >= 0)
-    {
-        nd->n = map_addnpc (m, nd);
-        map_addblock (&nd->bl);
-
-        if (evflag)
-        {                       // イベント型
-            struct event_data *ev =
-                (struct event_data *) calloc (1, sizeof (struct event_data));
-            ev->nd = nd;
-            ev->pos = 0;
-            strdb_insert (ev_db, nd->exname, ev);
-        }
-        else
-            clif_spawnnpc (nd);
-    }
-    strdb_insert (npcname_db, nd->exname, nd);
-
-    //-----------------------------------------
-    // ラベルデータの準備
-    if (srcbuf)
-    {
-        // script本体がある場合の処理
-
-        // ラベルデータのコンバート
-        label_db = script_get_label_db ();
-        strdb_foreach (label_db, npc_convertlabel_db, nd);
-
-        // もう使わないのでバッファ解放
-        free (srcbuf);
-
-    }
-    else
-    {
-        // duplicate
-
-//      nd->u.scr.label_list=malloc(sizeof(struct npc_label_list)*label_dupnum);
-//      memcpy(nd->u.scr.label_list,label_dup,sizeof(struct npc_label_list)*label_dupnum);
-
-        nd->u.scr.label_list = label_dup;   // ラベルデータ共有
-        nd->u.scr.label_list_num = label_dupnum;
-    }
-
-    //-----------------------------------------
-    // イベント用ラベルデータのエクスポート
-    for (i = 0; i < nd->u.scr.label_list_num; i++)
-    {
-        char *lname = nd->u.scr.label_list[i].name;
-        int  pos = nd->u.scr.label_list[i].pos;
-
-        if ((lname[0] == 'O' || lname[0] == 'o')
-            && (lname[1] == 'N' || lname[1] == 'n'))
-        {
-            struct event_data *ev;
-            char *buf;
-            // エクスポートされる
-            ev = (struct event_data *) calloc (1,
-                                                sizeof (struct event_data));
-            buf = (char *) calloc (50, sizeof (char));
-            if (strlen (lname) > 24)
-            {
-                printf ("npc_parse_script: label name error !\n");
-                exit (1);
-            }
-            else
-            {
-                ev->nd = nd;
-                ev->pos = pos;
-                sprintf (buf, "%s::%s", nd->exname, lname);
-                strdb_insert (ev_db, buf, ev);
-            }
-        }
-    }
-
-    //-----------------------------------------
-    // ラベルデータからタイマーイベント取り込み
-    for (i = 0; i < nd->u.scr.label_list_num; i++)
-    {
-        int  t = 0, k = 0;
-        char *lname = nd->u.scr.label_list[i].name;
-        int  pos = nd->u.scr.label_list[i].pos;
-        if (sscanf (lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0')
-        {
-            // タイマーイベント
-            struct npc_timerevent_list *te = nd->u.scr.timer_event;
-            int  j, k = nd->u.scr.timeramount;
-            if (te == NULL)
-                te = (struct npc_timerevent_list *) calloc (1,
-                                                             sizeof (struct
-                                                                     npc_timerevent_list));
-            else
-                te = (struct npc_timerevent_list *) realloc (te,
-                                                              sizeof (struct
-                                                                      npc_timerevent_list)
-                                                              * (k + 1));
-            for (j = 0; j < k; j++)
-            {
-                if (te[j].timer > t)
-                {
-                    memmove (te + j + 1, te + j,
-                             sizeof (struct npc_timerevent_list) * (k - j));
-                    break;
-                }
-            }
-            te[j].timer = t;
-            te[j].pos = pos;
-            nd->u.scr.timer_event = te;
-            nd->u.scr.timeramount = k + 1;
-        }
-    }
-    nd->u.scr.nexttimer = -1;
-    nd->u.scr.timerid = -1;
-
-    return 0;
-}
-
-/*==========================================
- * function行解析
- *------------------------------------------
- */
-static int npc_parse_function (char *w1, char *w2, char *w3, char *w4,
-                               char *first_line, FILE * fp, int *lines)
-{
-    char *srcbuf = NULL, *script;
-    int  srcsize = 65536;
-    int  startline = 0;
-    char line[1024];
-    int  i;
-//  struct dbt *label_db;
-    char *p;
-
-    // スクリプトの解析
-    srcbuf = (char *) calloc (srcsize, sizeof (char));
-    if (strchr (first_line, '{'))
-    {
-        strcpy (srcbuf, strchr (first_line, '{'));
-        startline = *lines;
-    }
-    else
-        srcbuf[0] = 0;
-    while (1)
-    {
-        for (i = strlen (srcbuf) - 1; i >= 0 && isspace (srcbuf[i]); i--);
-        if (i >= 0 && srcbuf[i] == '}')
-            break;
-        if (!fgets (line, 1020, fp))
-            break;
-        (*lines)++;
-        if (feof (fp))
-            break;
-        if (strlen (srcbuf) + strlen (line) + 1 >= srcsize)
-        {
-            srcsize += 65536;
-            srcbuf = (char *) realloc (srcbuf, srcsize);
-            memset (srcbuf + srcsize - 65536, '\0', 65536);
-        }
-        if (srcbuf[0] != '{')
-        {
-            if (strchr (line, '{'))
-            {
-                strcpy (srcbuf, strchr (line, '{'));
-                startline = *lines;
-            }
-        }
-        else
-            strcat (srcbuf, line);
-    }
-    script = parse_script (srcbuf, startline);
-    if (script == NULL)
-    {
-        // script parse error?
-        free (srcbuf);
-        return 1;
-    }
-
-    p = (char *) calloc (50, sizeof (char));
-
-    strncpy (p, w3, 49);
-    strdb_insert (script_get_userfunc_db (), p, script);
-
-//  label_db=script_get_label_db();
-
-    // もう使わないのでバッファ解放
-    free (srcbuf);
-
-//  printf("function %s => %p\n",p,script);
-
-    return 0;
-}
-
-/*==========================================
- * mob行解析
- *------------------------------------------
- */
-int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
-{
-    int  m, x, y, xs, ys, mob_class, num, delay1, delay2;
-    int  i;
-    char mapname[24];
-    char eventname[24] = "";
-    struct mob_data *md;
-
-    xs = ys = 0;
-    delay1 = delay2 = 0;
-    // 引数の個数チェック
-    if (sscanf (w1, "%[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 ||
-        sscanf (w4, "%d,%d,%d,%d,%s", &mob_class, &num, &delay1, &delay2,
-                eventname) < 2)
-    {
-        printf ("bad monster line : %s\n", w3);
-        return 1;
-    }
-
-    m = map_mapname2mapid (mapname);
-
-    if (num > 1 && battle_config.mob_count_rate != 100)
-    {
-        if ((num = num * battle_config.mob_count_rate / 100) < 1)
-            num = 1;
-    }
-
-    for (i = 0; i < num; i++)
-    {
-        md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
-
-        md->bl.prev = NULL;
-        md->bl.next = NULL;
-        md->bl.m = m;
-        md->bl.x = x;
-        md->bl.y = y;
-        if (strcmp (w3, "--en--") == 0)
-            memcpy (md->name, mob_db[mob_class].name, 24);
-        else if (strcmp (w3, "--ja--") == 0)
-            memcpy (md->name, mob_db[mob_class].jname, 24);
-        else
-            memcpy (md->name, w3, 24);
-
-        md->n = i;
-        md->base_class = md->mob_class = mob_class;
-        md->bl.id = npc_get_new_npc_id ();
-        md->m = m;
-        md->x0 = x;
-        md->y0 = y;
-        md->xs = xs;
-        md->ys = ys;
-        md->spawndelay1 = delay1;
-        md->spawndelay2 = delay2;
-
-        memset (&md->state, 0, sizeof (md->state));
-        md->timer = -1;
-        md->target_id = 0;
-        md->attacked_id = 0;
-
-        if (mob_db[mob_class].mode & 0x02)
-            md->lootitem =
-                (struct item *) calloc (LOOTITEM_SIZE, sizeof (struct item));
-        else
-            md->lootitem = NULL;
-
-        if (strlen (eventname) >= 4)
-        {
-            memcpy (md->npc_event, eventname, 24);
-        }
-        else
-            memset (md->npc_event, 0, 24);
-
-        md->bl.type = BL_MOB;
-        map_addiddb (&md->bl);
-        mob_spawn (md->bl.id);
-
-        npc_mob++;
-    }
-    //printf("warp npc %s %d read done\n",mapname,nd->bl.id);
-
-    return 0;
-}
-
-/*==========================================
- * マップフラグ行の解析
- *------------------------------------------
- */
-static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
-{
-    int  m;
-    char mapname[24], savemap[16];
-    int  savex, savey;
-    char drop_arg1[16], drop_arg2[16];
-    int  drop_id = 0, drop_type = 0, drop_per = 0;
-
-    // 引数の個数チェック
-//  if (    sscanf(w1,"%[^,],%d,%d,%d",mapname,&x,&y,&dir) != 4 )
-    if (sscanf (w1, "%[^,]", mapname) != 1)
-        return 1;
-
-    m = map_mapname2mapid (mapname);
-    if (m < 0)
-        return 1;
-
-//マップフラグ
-    if (strcasecmp (w3, "nosave") == 0)
-    {
-        if (strcmp (w4, "SavePoint") == 0)
-        {
-            memcpy (map[m].save.map, "SavePoint", 16);
-            map[m].save.x = -1;
-            map[m].save.y = -1;
-        }
-        else if (sscanf (w4, "%[^,],%d,%d", savemap, &savex, &savey) == 3)
-        {
-            memcpy (map[m].save.map, savemap, 16);
-            map[m].save.x = savex;
-            map[m].save.y = savey;
-        }
-        map[m].flag.nosave = 1;
-    }
-    else if (strcasecmp (w3, "nomemo") == 0)
-    {
-        map[m].flag.nomemo = 1;
-    }
-    else if (strcasecmp (w3, "noteleport") == 0)
-    {
-        map[m].flag.noteleport = 1;
-    }
-    else if (strcasecmp (w3, "nowarp") == 0)
-    {
-        map[m].flag.nowarp = 1;
-    }
-    else if (strcasecmp (w3, "nowarpto") == 0)
-    {
-        map[m].flag.nowarpto = 1;
-    }
-    else if (strcasecmp (w3, "noreturn") == 0)
-    {
-        map[m].flag.noreturn = 1;
-    }
-    else if (strcasecmp (w3, "monster_noteleport") == 0)
-    {
-        map[m].flag.monster_noteleport = 1;
-    }
-    else if (strcasecmp (w3, "nobranch") == 0)
-    {
-        map[m].flag.nobranch = 1;
-    }
-    else if (strcasecmp (w3, "nopenalty") == 0)
-    {
-        map[m].flag.nopenalty = 1;
-    }
-    else if (strcasecmp (w3, "pvp") == 0)
-    {
-        map[m].flag.pvp = 1;
-    }
-    else if (strcasecmp (w3, "pvp_noparty") == 0)
-    {
-        map[m].flag.pvp_noparty = 1;
-    }
-    else if (strcasecmp (w3, "pvp_noguild") == 0)
-    {
-        map[m].flag.pvp_noguild = 1;
-    }
-    else if (strcasecmp (w3, "pvp_nightmaredrop") == 0)
-    {
-        if (sscanf (w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) ==
-            3)
-        {
-            int  i;
-            if (strcmp (drop_arg1, "random") == 0)
-                drop_id = -1;
-            else if (itemdb_exists ((drop_id = atoi (drop_arg1))) == NULL)
-                drop_id = 0;
-            if (strcmp (drop_arg2, "inventory") == 0)
-                drop_type = 1;
-            else if (strcmp (drop_arg2, "equip") == 0)
-                drop_type = 2;
-            else if (strcmp (drop_arg2, "all") == 0)
-                drop_type = 3;
-
-            if (drop_id != 0)
-            {
-                for (i = 0; i < MAX_DROP_PER_MAP; i++)
-                {
-                    if (map[m].drop_list[i].drop_id == 0)
-                    {
-                        map[m].drop_list[i].drop_id = drop_id;
-                        map[m].drop_list[i].drop_type = drop_type;
-                        map[m].drop_list[i].drop_per = drop_per;
-                        break;
-                    }
-                }
-                map[m].flag.pvp_nightmaredrop = 1;
-            }
-        }
-    }
-    else if (strcasecmp (w3, "pvp_nocalcrank") == 0)
-    {
-        map[m].flag.pvp_nocalcrank = 1;
-    }
-    else if (strcasecmp (w3, "gvg") == 0)
-    {
-        map[m].flag.gvg = 1;
-    }
-    else if (strcasecmp (w3, "gvg_noparty") == 0)
-    {
-        map[m].flag.gvg_noparty = 1;
-    }
-    else if (strcasecmp (w3, "nozenypenalty") == 0)
-    {
-        map[m].flag.nozenypenalty = 1;
-    }
-    else if (strcasecmp (w3, "notrade") == 0)
-    {
-        map[m].flag.notrade = 1;
-    }
-    else if (strcasecmp (w3, "noskill") == 0)
-    {
-        map[m].flag.noskill = 1;
-    }
-    else if (battle_config.pk_mode && strcasecmp (w3, "nopvp") == 0)
-    {                           // nopvp for pk mode [Valaris]
-        map[m].flag.nopvp = 1;
-        map[m].flag.pvp = 0;
-    }
-    else if (strcasecmp (w3, "noicewall") == 0)
-    {                           // noicewall [Valaris]
-        map[m].flag.noicewall = 1;
-    }
-    else if (strcasecmp (w3, "snow") == 0)
-    {                           // snow [Valaris]
-        map[m].flag.snow = 1;
-    }
-    else if (strcasecmp (w3, "fog") == 0)
-    {                           // fog [Valaris]
-        map[m].flag.fog = 1;
-    }
-    else if (strcasecmp (w3, "sakura") == 0)
-    {                           // sakura [Valaris]
-        map[m].flag.sakura = 1;
-    }
-    else if (strcasecmp (w3, "leaves") == 0)
-    {                           // leaves [Valaris]
-        map[m].flag.leaves = 1;
-    }
-    else if (strcasecmp (w3, "rain") == 0)
-    {                           // rain [Valaris]
-        map[m].flag.rain = 1;
-    }
-    else if (strcasecmp (w3, "no_player_drops") == 0)
-    {                           // no player drops [Jaxad0127]
-        map[m].flag.no_player_drops = 1;
-    }
-    else if (strcasecmp (w3, "town") == 0)
-    {                           // town/safe zone [remoitnane]
-        map[m].flag.town = 1;
-    }
-
-    return 0;
-}
-
-static void ev_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-    if (strstr (key.s, "::") != NULL)
-        free ((char*)key.s);
-}
-
-struct npc_data *npc_spawn_text (int m, int x, int y,
-                                 int npc_class, char *name, char *message)
-{
-    struct npc_data *retval =
-        (struct npc_data *) calloc (1, sizeof (struct npc_data));
-    retval->bl.id = npc_get_new_npc_id ();
-    retval->bl.x = x;
-    retval->bl.y = y;
-    retval->bl.m = m;
-    retval->bl.type = BL_NPC;
-    retval->bl.subtype = MESSAGE;
-
-    strncpy (retval->name, name, 23);
-    strncpy (retval->exname, name, 23);
-    retval->name[15] = 0;
-    retval->exname[15] = 0;
-    retval->u.message = message ? strdup (message) : NULL;
-
-    retval->npc_class = npc_class;
-    retval->speed = 200;
-
-    clif_spawnnpc (retval);
-    map_addblock (&retval->bl);
-    map_addiddb (&retval->bl);
-    if (retval->name && retval->name[0])
-        strdb_insert (npcname_db, retval->name, retval);
-
-    return retval;
-}
-
-static void npc_free_internal (struct npc_data *nd)
-{
-    struct chat_data *cd;
-
-    if (nd->chat_id && (cd = (struct chat_data *) map_id2bl (nd->chat_id)))
-    {
-        free (cd);
-        cd = NULL;
-    }
-    if (nd->bl.subtype == SCRIPT)
-    {
-        if (nd->u.scr.timer_event)
-            free (nd->u.scr.timer_event);
-        if (nd->u.scr.src_id == 0)
-        {
-            if (nd->u.scr.script)
-            {
-                free (nd->u.scr.script);
-                nd->u.scr.script = NULL;
-            }
-            if (nd->u.scr.label_list)
-            {
-                free (nd->u.scr.label_list);
-                nd->u.scr.label_list = NULL;
-            }
-        }
-    }
-    else if (nd->bl.subtype == MESSAGE && nd->u.message)
-    {
-        free (nd->u.message);
-    }
-    free (nd);
-}
-
-void npc_propagate_update (struct npc_data *nd)
-{
-    map_foreachinarea (npc_enable_sub,
-                       nd->bl.m,
-                       nd->bl.x - nd->u.scr.xs, nd->bl.y - nd->u.scr.ys,
-                       nd->bl.x + nd->u.scr.xs, nd->bl.y + nd->u.scr.ys,
-                       BL_PC, nd);
-}
-
-void npc_free (struct npc_data *nd)
-{
-    clif_clearchar (&nd->bl, 0);
-    npc_propagate_update (nd);
-    map_deliddb (&nd->bl);
-    map_delblock (&nd->bl);
-    npc_free_internal (nd);
-}
-
-/*==========================================
- * 終了
- *------------------------------------------
- */
-int do_final_npc (void)
-{
-    int  i;
-    struct block_list *bl;
-    struct npc_data *nd;
-    struct mob_data *md;
-
-    if (ev_db)
-        strdb_final (ev_db, ev_db_final);
-    if (npcname_db)
-        strdb_final (npcname_db, NULL);
-
-    for (i = START_NPC_NUM; i < npc_id; i++)
-    {
-        if ((bl = map_id2bl (i)))
-        {
-            if (bl->type == BL_NPC && (nd = (struct npc_data *) bl))
-                npc_free_internal (nd);
-            else if (bl->type == BL_MOB && (md = (struct mob_data *) bl))
-            {
-                if (md->lootitem)
-                {
-                    free (md->lootitem);
-                    md->lootitem = NULL;
-                }
-                free (md);
-                md = NULL;
-            }
-        }
-    }
-
-    return 0;
-}
-
-void ev_release (db_key_t key, db_val_t val)
-{
-    free ((char*)key.s);
-    free (val);
-}
-
-/*==========================================
- * npc初期化
- *------------------------------------------
- */
-int do_init_npc (void)
-{
-    struct npc_src_list *nsl;
-    FILE *fp;
-    char line[1024];
-    int  m, lines;
-
-    ev_db = strdb_init (24);
-    npcname_db = strdb_init (24);
-
-    ev_db->release = ev_release;
-
-    memset (&ev_tm_b, -1, sizeof (ev_tm_b));
-
-    for (nsl = npc_src_first; nsl; nsl = nsl->next)
-    {
-        if (nsl->prev)
-        {
-            free (nsl->prev);
-            nsl->prev = NULL;
-        }
-        fp = fopen_ (nsl->name, "r");
-        if (fp == NULL)
-        {
-            printf ("file not found : %s\n", nsl->name);
-            exit (1);
-        }
-        lines = 0;
-        while (fgets (line, 1020, fp))
-        {
-            char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024];
-            int  i, j, w4pos, count;
-            lines++;
-
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-            // 不要なスペースやタブの連続は詰める
-            for (i = j = 0; line[i]; i++)
-            {
-                if (line[i] == ' ')
-                {
-                    if (!
-                        ((line[i + 1]
-                          && (isspace (line[i + 1]) || line[i + 1] == ','))
-                         || (j && line[j - 1] == ',')))
-                        line[j++] = ' ';
-                }
-                else if (line[i] == '\t' || line[i] == '|')
-                {
-                    if (!(j && (line[j - 1] == '\t' || line[j - 1] == '|')))
-                        line[j++] = '\t';
-                }
-                else
-                    line[j++] = line[i];
-            }
-            // 最初はタブ区切りでチェックしてみて、ダメならスペース区切りで確認
-            if ((count =
-                 sscanf (line, "%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]", w1,
-                         w2, w3, &w4pos, w4)) < 3
-                && (count =
-                    sscanf (line, "%s%s%s%n%s", w1, w2, w3, &w4pos, w4)) < 3)
-            {
-                continue;
-            }
-            // マップの存在確認
-            if (strcmp (w1, "-") != 0 && strcasecmp (w1, "function") != 0)
-            {
-                sscanf (w1, "%[^,]", mapname);
-                m = map_mapname2mapid (mapname);
-                if (strlen (mapname) > 16 || m < 0)
-                {
-                    // "mapname" is not assigned to this server
-                    continue;
-                }
-            }
-            if (strcasecmp (w2, "warp") == 0 && count > 3)
-            {
-                npc_parse_warp (w1, w2, w3, w4);
-            }
-            else if (strcasecmp (w2, "shop") == 0 && count > 3)
-            {
-                npc_parse_shop (w1, w2, w3, w4);
-            }
-            else if (strcasecmp (w2, "script") == 0 && count > 3)
-            {
-                if (strcasecmp (w1, "function") == 0)
-                {
-                    npc_parse_function (w1, w2, w3, w4, line + w4pos, fp,
-                                        &lines);
-                }
-                else
-                {
-                    npc_parse_script (w1, w2, w3, w4, line + w4pos, fp,
-                                      &lines);
-                }
-            }
-            else if ((i =
-                      0, sscanf (w2, "duplicate%n", &i), (i > 0
-                                                          && w2[i] == '('))
-                     && count > 3)
-            {
-                npc_parse_script (w1, w2, w3, w4, line + w4pos, fp, &lines);
-            }
-            else if (strcasecmp (w2, "monster") == 0 && count > 3)
-            {
-                npc_parse_mob (w1, w2, w3, w4);
-            }
-            else if (strcasecmp (w2, "mapflag") == 0 && count >= 3)
-            {
-                npc_parse_mapflag (w1, w2, w3, w4);
-            }
-        }
-        fclose_ (fp);
-        printf ("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM,
-                nsl->name);
-        fflush (stdout);
-    }
-    printf ("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d]\n",
-            npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob);
-
-    return 0;
-}
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
new file mode 100644
index 0000000..b2612f0
--- /dev/null
+++ b/src/map/npc.cpp
@@ -0,0 +1,2378 @@
+// $Id: npc.c,v 1.5 2004/09/25 05:32:18 MouseJstr Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "../common/nullpo.hpp"
+#include "../common/timer.hpp"
+
+#include "battle.hpp"
+#include "clif.hpp"
+#include "../common/db.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "../common/socket.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+struct npc_src_list
+{
+    struct npc_src_list *next;
+    struct npc_src_list *prev;
+    char name[4];
+};
+
+static struct npc_src_list *npc_src_first, *npc_src_last;
+static int npc_id = START_NPC_NUM;
+static int npc_warp, npc_shop, npc_script, npc_mob;
+
+int npc_get_new_npc_id (void)
+{
+    return npc_id++;
+}
+
+static struct dbt *ev_db;
+static struct dbt *npcname_db;
+
+struct event_data
+{
+    struct npc_data *nd;
+    int  pos;
+};
+static struct tm ev_tm_b;       // 時計イベント用
+
+/*==========================================
+ * NPCの無効化/有効化
+ * npc_enable
+ * npc_enable_sub 有効時にOnTouchイベントを実行
+ *------------------------------------------
+ */
+int npc_enable_sub (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+    struct npc_data *nd;
+    char *name = (char *) calloc (50, sizeof (char));
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, nd = va_arg (ap, struct npc_data *));
+    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
+    {
+
+        if (nd->flag & 1)       // 無効化されている
+            return 1;
+
+        memcpy (name, nd->name, sizeof(nd->name));
+        if (sd->areanpc_id == nd->bl.id)
+            return 1;
+        sd->areanpc_id = nd->bl.id;
+        npc_event (sd, strcat (name, "::OnTouch"), 0);
+    }
+    free (name);
+    return 0;
+}
+
+int npc_enable (const char *name, int flag)
+{
+    struct npc_data *nd = (struct npc_data *)strdb_search (npcname_db, name);
+    if (nd == NULL)
+        return 0;
+
+    if (flag & 1)
+    {                           // 有効化
+        nd->flag &= ~1;
+        clif_spawnnpc (nd);
+    }
+    else if (flag & 2)
+    {
+        nd->flag &= ~1;
+        nd->option = 0x0000;
+        clif_changeoption (&nd->bl);
+    }
+    else if (flag & 4)
+    {
+        nd->flag |= 1;
+        nd->option = 0x0002;
+        clif_changeoption (&nd->bl);
+    }
+    else
+    {                           // 無効化
+        nd->flag |= 1;
+        clif_clearchar (&nd->bl, 0);
+    }
+    if (flag & 3 && (nd->u.scr.xs > 0 || nd->u.scr.ys > 0))
+        map_foreachinarea (npc_enable_sub, nd->bl.m, nd->bl.x - nd->u.scr.xs,
+                           nd->bl.y - nd->u.scr.ys, nd->bl.x + nd->u.scr.xs,
+                           nd->bl.y + nd->u.scr.ys, BL_PC, nd);
+
+    return 0;
+}
+
+/*==========================================
+ * NPCを名前で探す
+ *------------------------------------------
+ */
+struct npc_data *npc_name2id (const char *name)
+{
+    return (struct npc_data *)strdb_search (npcname_db, name);
+}
+
+/*==========================================
+ * イベントキューのイベント処理
+ *------------------------------------------
+ */
+int npc_event_dequeue (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    sd->npc_id = 0;
+
+    if (sd->eventqueue[0][0]) // キューのイベント処理
+    {
+        if (!pc_addeventtimer(sd, 100, sd->eventqueue[0]))
+        {
+            printf ("npc_event_dequeue(): Event timer is full.\n");
+            return 0;
+        }
+
+        if (MAX_EVENTQUEUE > 1)
+            memmove (sd->eventqueue[0], sd->eventqueue[1],
+                     (MAX_EVENTQUEUE - 1) * sizeof (sd->eventqueue[0]));
+        sd->eventqueue[MAX_EVENTQUEUE - 1][0] = '\0';
+        return 1;
+    }
+
+    return 0;
+}
+
+int npc_delete (struct npc_data *nd)
+{
+    nullpo_retr (1, nd);
+
+    if (nd->bl.prev == NULL)
+        return 1;
+
+    clif_clearchar_area (&nd->bl, 1);
+    map_delblock (&nd->bl);
+    return 0;
+}
+
+/*==========================================
+ * イベントの遅延実行
+ *------------------------------------------
+ */
+void npc_event_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = map_id2sd (id);
+    if (sd == NULL)
+        return;
+
+    npc_event (sd, (const char *) data, 0);
+    free ((void *) data);
+}
+
+int npc_timer_event (const char *eventname) // Added by RoVeRT
+{
+    struct event_data *ev = (struct event_data *)strdb_search (ev_db, eventname);
+    struct npc_data *nd;
+//  int xs,ys;
+
+    if ((ev == NULL || (nd = ev->nd) == NULL))
+    {
+        printf ("npc_event: event not found [%s]\n", eventname);
+        return 0;
+    }
+
+    run_script (nd->u.scr.script, ev->pos, nd->bl.id, nd->bl.id);
+
+    return 0;
+}
+
+/*
+int npc_timer_sub_sub(void *key,void *data,va_list ap)	// Added by RoVeRT
+{
+	char *p=(char *)key;
+	struct event_data *ev=(struct event_data *)data;
+	int *c=va_arg(ap,int *);
+	int tick=0,ctick=gettick();
+	char temp[10];
+	char event[100];
+
+	if(ev->nd->bl.id==(int)*c && (p=strchr(p,':')) && p && strncasecmp("::OnTimer",p,8)==0 ){
+		sscanf(&p[9],"%s",temp);
+		tick=atoi(temp);
+
+		strcpy( event, ev->nd->name);
+		strcat( event, p);
+
+		if (ctick >= ev->nd->lastaction && ctick - ev->nd->timer >= tick) {
+			npc_timer_event(event);
+			ev->nd->lastaction = ctick;
+		}
+	}
+	return 0;
+}
+
+int npc_timer_sub(void *key,void *data,va_list ap)	// Added by RoVeRT
+{
+	struct npc_data *nd=(struct npc_data*)data;
+
+	if(nd->timer == -1)
+		return 0;
+
+	strdb_foreach(ev_db,npc_timer_sub_sub,&nd->bl.id);
+
+	return 0;
+}
+
+int npc_timer(int tid,unsigned int tick,int id,int data)	// Added by RoVeRT
+{
+	strdb_foreach(npcname_db,npc_timer_sub);
+
+	free((void*)data);
+	return 0;
+}*/
+/*==========================================
+ * イベント用ラベルのエクスポート
+ * npc_parse_script->strdb_foreachから呼ばれる
+ *------------------------------------------
+ */
+int npc_event_export (void *key, void *data, va_list ap)
+{
+    char *lname = (char *) key;
+    int  pos = (int) data;
+    struct npc_data *nd = va_arg (ap, struct npc_data *);
+
+    if ((lname[0] == 'O' || lname[0] == 'o')
+        && (lname[1] == 'N' || lname[1] == 'n'))
+    {
+        struct event_data *ev;
+        char *buf;
+        char *p = strchr (lname, ':');
+        // エクスポートされる
+        CREATE (ev, struct event_data, 1);
+        CREATE (buf, char, 50);
+        if (p == NULL || (p - lname) > 24)
+        {
+            printf ("npc_event_export: label name error !\n");
+            exit (1);
+        }
+        else
+        {
+            ev->nd = nd;
+            ev->pos = pos;
+            *p = '\0';
+            sprintf (buf, "%s::%s", nd->exname, lname);
+            *p = ':';
+            strdb_insert (ev_db, buf, ev);
+//          if (battle_config.etc_log)
+//              printf("npc_event_export: export [%s]\n",buf);
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * 全てのNPCのOn*イベント実行
+ *------------------------------------------
+ */
+void npc_event_doall_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    const char *p = key.s;
+    int  rid, argc;
+    argrec_t *argv;
+    struct event_data *ev;
+    int *c;
+    const char *name;
+
+    nullpo_retv (ev = (struct event_data *) data);
+    nullpo_retv (ap);
+    nullpo_retv (c = va_arg (ap, int *));
+
+    name = va_arg (ap, const char *);
+    rid = va_arg (ap, int);
+    argc = va_arg (ap, int);
+    argv = va_arg (ap, argrec_t *);
+
+    if ((p = strchr (p, ':')) && p && strcasecmp (name, p) == 0)
+    {
+        run_script_l (ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id, argc,
+                      argv);
+        (*c)++;
+    }
+}
+
+int npc_event_doall_l (const char *name, int rid, int argc, argrec_t * args)
+{
+    int  c = 0;
+    char buf[64] = "::";
+
+    strncpy (buf + 2, name, sizeof(buf)-3);
+    buf[sizeof(buf)-1] = '\0';
+    strdb_foreach (ev_db, npc_event_doall_sub, &c, buf, rid, argc, args);
+    return c;
+}
+
+void npc_event_do_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    const char *p = key.s;
+    struct event_data *ev;
+    int *c;
+    const char *name;
+    int  rid, argc;
+    argrec_t *argv;
+
+    nullpo_retv (ev = (struct event_data *) data);
+    nullpo_retv (ap);
+    nullpo_retv (c = va_arg (ap, int *));
+
+    name = va_arg (ap, const char *);
+    rid = va_arg (ap, int);
+    argc = va_arg (ap, int);
+    argv = va_arg (ap, argrec_t *);
+
+    if (p && strcasecmp (name, p) == 0)
+    {
+        run_script_l (ev->nd->u.scr.script, ev->pos, rid, ev->nd->bl.id, argc,
+                      argv);
+        (*c)++;
+    }
+}
+
+int npc_event_do_l (const char *name, int rid, int argc, argrec_t * args)
+{
+    int  c = 0;
+
+    if (*name == ':' && name[1] == ':')
+    {
+        return npc_event_doall_l (name + 2, rid, argc, args);
+    }
+
+    strdb_foreach (ev_db, npc_event_do_sub, &c, name, rid, argc, args);
+    return c;
+}
+
+/*==========================================
+ * 時計イベント実行
+ *------------------------------------------
+ */
+void npc_event_do_clock (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    time_t timer;
+    struct tm *t;
+    char buf[64];
+    int  c = 0;
+
+    time (&timer);
+    t = gmtime (&timer);
+
+    if (t->tm_min != ev_tm_b.tm_min)
+    {
+        sprintf (buf, "OnMinute%02d", t->tm_min);
+        c += npc_event_doall (buf);
+        sprintf (buf, "OnClock%02d%02d", t->tm_hour, t->tm_min);
+        c += npc_event_doall (buf);
+    }
+    if (t->tm_hour != ev_tm_b.tm_hour)
+    {
+        sprintf (buf, "OnHour%02d", t->tm_hour);
+        c += npc_event_doall (buf);
+    }
+    if (t->tm_mday != ev_tm_b.tm_mday)
+    {
+        sprintf (buf, "OnDay%02d%02d", t->tm_mon + 1, t->tm_mday);
+        c += npc_event_doall (buf);
+    }
+    memcpy (&ev_tm_b, t, sizeof (ev_tm_b));
+}
+
+/*==========================================
+ * OnInitイベント実行(&時計イベント開始)
+ *------------------------------------------
+ */
+int npc_event_do_oninit (void)
+{
+    int  c = npc_event_doall ("OnInit");
+    printf ("npc: OnInit Event done. (%d npc)\n", c);
+
+    add_timer_interval (gettick () + 100, npc_event_do_clock, 0, 0, 1000);
+
+    return 0;
+}
+
+/*==========================================
+ * OnTimer NPC event - by RoVeRT
+ *------------------------------------------
+ */
+int npc_addeventtimer (struct npc_data *nd, int tick, const char *name)
+{
+    int  i;
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (nd->eventtimer[i] == -1)
+            break;
+    if (i < MAX_EVENTTIMER)
+    {
+        char *evname;
+        CREATE (evname, char, 24);
+        memcpy (evname, name, 24);
+        nd->eventtimer[i] = add_timer (gettick () + tick,
+                                       npc_event_timer, nd->bl.id,
+                                       (int) evname);
+    }
+    else
+        printf ("npc_addtimer: event timer is full !\n");
+
+    return 0;
+}
+
+int npc_deleventtimer (struct npc_data *nd, const char *name)
+{
+    int  i;
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (nd->eventtimer[i] != -1 && strcmp ((char
+                                                *) (get_timer (nd->eventtimer
+                                                               [i])->data),
+                                               name) == 0)
+        {
+            delete_timer (nd->eventtimer[i], npc_event_timer);
+            nd->eventtimer[i] = -1;
+            break;
+        }
+
+    return 0;
+}
+
+int npc_cleareventtimer (struct npc_data *nd)
+{
+    int  i;
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (nd->eventtimer[i] != -1)
+        {
+            delete_timer (nd->eventtimer[i], npc_event_timer);
+            nd->eventtimer[i] = -1;
+        }
+
+    return 0;
+}
+
+void npc_do_ontimer_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    const char *p = key.s;
+    struct event_data *ev = (struct event_data *) data;
+    int *c = va_arg (ap, int *);
+//  struct map_session_data *sd=va_arg(ap,struct map_session_data *);
+    int  option = va_arg (ap, int);
+    int  tick = 0;
+    char temp[10];
+    char event[50];
+
+    if (ev->nd->bl.id == (int) *c && (p = strchr (p, ':')) && p
+        && strncasecmp ("::OnTimer", p, 8) == 0)
+    {
+        sscanf (&p[9], "%s", temp);
+        tick = atoi (temp);
+
+        strcpy (event, ev->nd->name);
+        strcat (event, p);
+
+        if (option != 0)
+        {
+            npc_addeventtimer (ev->nd, tick, event);
+        }
+        else
+        {
+            npc_deleventtimer (ev->nd, event);
+        }
+    }
+}
+
+int npc_do_ontimer (int npc_id, struct map_session_data *sd, int option)
+{
+    strdb_foreach (ev_db, npc_do_ontimer_sub, &npc_id, sd, option);
+    return 0;
+}
+
+/*==========================================
+ * タイマーイベント用ラベルの取り込み
+ * npc_parse_script->strdb_foreachから呼ばれる
+ *------------------------------------------
+ */
+int npc_timerevent_import (void *key, void *data, va_list ap)
+{
+    char *lname = (char *) key;
+    int  pos = (int) data;
+    struct npc_data *nd = va_arg (ap, struct npc_data *);
+    int  t = 0, i = 0;
+
+    if (sscanf (lname, "OnTimer%d%n", &t, &i) == 1 && lname[i] == ':')
+    {
+        // タイマーイベント
+        struct npc_timerevent_list *te = nd->u.scr.timer_event;
+        int  j, i = nd->u.scr.timeramount;
+        RECREATE (te, struct npc_timerevent_list, i+1);
+        for (j = 0; j < i; j++)
+        {
+            if (te[j].timer > t)
+            {
+                memmove (te + j + 1, te + j,
+                         sizeof (struct npc_timerevent_list) * (i - j));
+                break;
+            }
+        }
+        te[j].timer = t;
+        te[j].pos = pos;
+        nd->u.scr.timer_event = te;
+        nd->u.scr.timeramount = i + 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ * タイマーイベント実行
+ *------------------------------------------
+ */
+void npc_timerevent (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  next, t;
+    struct npc_data *nd = (struct npc_data *) map_id2bl (id);
+    struct npc_timerevent_list *te;
+    if (nd == NULL || nd->u.scr.nexttimer < 0)
+    {
+        printf ("npc_timerevent: ??\n");
+        return;
+    }
+    nd->u.scr.timertick = tick;
+    te = nd->u.scr.timer_event + nd->u.scr.nexttimer;
+    nd->u.scr.timerid = -1;
+
+    t = nd->u.scr.timer += data;
+    nd->u.scr.nexttimer++;
+    if (nd->u.scr.timeramount > nd->u.scr.nexttimer)
+    {
+        next = nd->u.scr.timer_event[nd->u.scr.nexttimer].timer - t;
+        nd->u.scr.timerid = add_timer (tick + next, npc_timerevent, id, next);
+    }
+
+    run_script (nd->u.scr.script, te->pos, 0, nd->bl.id);
+}
+
+/*==========================================
+ * タイマーイベント開始
+ *------------------------------------------
+ */
+int npc_timerevent_start (struct npc_data *nd)
+{
+    int  j, n, next;
+
+    nullpo_retr (0, nd);
+
+    n = nd->u.scr.timeramount;
+    if (nd->u.scr.nexttimer >= 0 || n == 0)
+        return 0;
+
+    for (j = 0; j < n; j++)
+    {
+        if (nd->u.scr.timer_event[j].timer > nd->u.scr.timer)
+            break;
+    }
+    nd->u.scr.nexttimer = j;
+    nd->u.scr.timertick = gettick ();
+
+    if (j >= n)
+        return 0;
+
+    next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer;
+    nd->u.scr.timerid =
+        add_timer (gettick () + next, npc_timerevent, nd->bl.id, next);
+    return 0;
+}
+
+/*==========================================
+ * タイマーイベント終了
+ *------------------------------------------
+ */
+int npc_timerevent_stop (struct npc_data *nd)
+{
+    nullpo_retr (0, nd);
+
+    if (nd->u.scr.nexttimer >= 0)
+    {
+        nd->u.scr.nexttimer = -1;
+        nd->u.scr.timer += (int) (gettick () - nd->u.scr.timertick);
+        if (nd->u.scr.timerid != -1)
+            delete_timer (nd->u.scr.timerid, npc_timerevent);
+        nd->u.scr.timerid = -1;
+    }
+    return 0;
+}
+
+/*==========================================
+ * タイマー値の所得
+ *------------------------------------------
+ */
+int npc_gettimerevent_tick (struct npc_data *nd)
+{
+    int  tick;
+
+    nullpo_retr (0, nd);
+
+    tick = nd->u.scr.timer;
+
+    if (nd->u.scr.nexttimer >= 0)
+        tick += (int) (gettick () - nd->u.scr.timertick);
+    return tick;
+}
+
+/*==========================================
+ * タイマー値の設定
+ *------------------------------------------
+ */
+int npc_settimerevent_tick (struct npc_data *nd, int newtimer)
+{
+    int  flag;
+
+    nullpo_retr (0, nd);
+
+    flag = nd->u.scr.nexttimer;
+
+    npc_timerevent_stop (nd);
+    nd->u.scr.timer = newtimer;
+    if (flag >= 0)
+        npc_timerevent_start (nd);
+    return 0;
+}
+
+/*==========================================
+ * イベント型のNPC処理
+ *------------------------------------------
+ */
+int npc_event (struct map_session_data *sd, const char *eventname,
+               int mob_kill)
+{
+    struct event_data *ev = (struct event_data *)strdb_search (ev_db, eventname);
+    struct npc_data *nd;
+    int  xs, ys;
+    char mobevent[100];
+
+    if (sd == NULL)
+    {
+        printf ("npc_event nullpo?\n");
+    }
+
+    if (ev == NULL && eventname
+        && strcmp (((eventname) + strlen (eventname) - 9), "::OnTouch") == 0)
+        return 1;
+
+    if (ev == NULL || (nd = ev->nd) == NULL)
+    {
+        if (mob_kill && (ev == NULL || (nd = ev->nd) == NULL))
+        {
+            strcpy (mobevent, eventname);
+            strcat (mobevent, "::OnMyMobDead");
+            ev = (struct event_data *)strdb_search (ev_db, mobevent);
+            if (ev == NULL || (nd = ev->nd) == NULL)
+            {
+                if (strncasecmp (eventname, "GM_MONSTER", 10) != 0)
+                    printf ("npc_event: event not found [%s]\n", mobevent);
+                return 0;
+            }
+        }
+        else
+        {
+            if (battle_config.error_log)
+                printf ("npc_event: event not found [%s]\n", eventname);
+            return 0;
+        }
+    }
+
+    xs = nd->u.scr.xs;
+    ys = nd->u.scr.ys;
+    if (xs >= 0 && ys >= 0)
+    {
+        if (nd->bl.m != sd->bl.m)
+            return 1;
+        if (xs > 0
+            && (sd->bl.x < nd->bl.x - xs / 2 || nd->bl.x + xs / 2 < sd->bl.x))
+            return 1;
+        if (ys > 0
+            && (sd->bl.y < nd->bl.y - ys / 2 || nd->bl.y + ys / 2 < sd->bl.y))
+            return 1;
+    }
+
+    if (sd->npc_id != 0)
+    {
+//      if (battle_config.error_log)
+//          printf("npc_event: npc_id != 0\n");
+        int  i;
+        for (i = 0; i < MAX_EVENTQUEUE; i++)
+            if (!sd->eventqueue[i][0])
+                break;
+        if (i == MAX_EVENTQUEUE)
+        {
+            if (battle_config.error_log)
+                printf ("npc_event: event queue is full !\n");
+        }
+        else
+        {
+//          if (battle_config.etc_log)
+//              printf("npc_event: enqueue\n");
+            strncpy (sd->eventqueue[i], eventname, 50);
+            sd->eventqueue[i][49] = '\0';
+        }
+        return 1;
+    }
+    if (nd->flag & 1)
+    {                           // 無効化されている
+        npc_event_dequeue (sd);
+        return 0;
+    }
+
+    sd->npc_id = nd->bl.id;
+    sd->npc_pos =
+        run_script (nd->u.scr.script, ev->pos, sd->bl.id, nd->bl.id);
+    return 0;
+}
+
+void npc_command_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    const char *p = key.s;
+    struct event_data *ev = (struct event_data *) data;
+    char *npcname = va_arg (ap, char *);
+    char *command = va_arg (ap, char *);
+    char temp[100];
+
+    if (strcmp (ev->nd->name, npcname) == 0 && (p = strchr (p, ':')) && p
+        && strncasecmp ("::OnCommand", p, 10) == 0)
+    {
+        sscanf (&p[11], "%s", temp);
+
+        if (strcmp (command, temp) == 0)
+            run_script (ev->nd->u.scr.script, ev->pos, 0, ev->nd->bl.id);
+    }
+}
+
+int npc_command (struct map_session_data *sd, char *npcname, char *command)
+{
+    strdb_foreach (ev_db, npc_command_sub, npcname, command);
+
+    return 0;
+}
+
+/*==========================================
+ * 接触型のNPC処理
+ *------------------------------------------
+ */
+int npc_touch_areanpc (struct map_session_data *sd, int m, int x, int y)
+{
+    int  i, f = 1;
+    int  xs, ys;
+
+    nullpo_retr (1, sd);
+
+    if (sd->npc_id)
+        return 1;
+
+    for (i = 0; i < map[m].npc_num; i++)
+    {
+        if (map[m].npc[i]->flag & 1)
+        {                       // 無効化されている
+            f = 0;
+            continue;
+        }
+
+        switch (map[m].npc[i]->bl.subtype)
+        {
+            case WARP:
+                xs = map[m].npc[i]->u.warp.xs;
+                ys = map[m].npc[i]->u.warp.ys;
+                break;
+            case MESSAGE:
+            case SCRIPT:
+                xs = map[m].npc[i]->u.scr.xs;
+                ys = map[m].npc[i]->u.scr.ys;
+                break;
+            default:
+                continue;
+        }
+        if (x >= map[m].npc[i]->bl.x - xs / 2
+            && x < map[m].npc[i]->bl.x - xs / 2 + xs
+            && y >= map[m].npc[i]->bl.y - ys / 2
+            && y < map[m].npc[i]->bl.y - ys / 2 + ys)
+            break;
+    }
+    if (i == map[m].npc_num)
+    {
+        if (f)
+        {
+            if (battle_config.error_log)
+                printf ("npc_touch_areanpc : some bug \n");
+        }
+        return 1;
+    }
+    switch (map[m].npc[i]->bl.subtype)
+    {
+        case WARP:
+            skill_stop_dancing (&sd->bl, 0);
+            pc_setpos (sd, map[m].npc[i]->u.warp.name,
+                       map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, 0);
+            break;
+        case MESSAGE:
+        case SCRIPT:
+        {
+            char *name = (char *)malloc (50);
+
+            memcpy (name, map[m].npc[i]->name, 50);
+            if (sd->areanpc_id == map[m].npc[i]->bl.id)
+                return 1;
+            sd->areanpc_id = map[m].npc[i]->bl.id;
+            if (npc_event (sd, strcat (name, "::OnTouch"), 0) > 0)
+                npc_click (sd, map[m].npc[i]->bl.id);
+            free (name);
+            break;
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * 近くかどうかの判定
+ *------------------------------------------
+ */
+int npc_checknear (struct map_session_data *sd, int id)
+{
+    struct npc_data *nd;
+
+    nullpo_retr (0, sd);
+
+    nd = (struct npc_data *) map_id2bl (id);
+    if (nd == NULL || nd->bl.type != BL_NPC)
+    {
+        if (battle_config.error_log)
+            printf ("no such npc : %d\n", id);
+        return 1;
+    }
+
+    if (nd->npc_class < 0)          // イベント系は常にOK
+        return 0;
+
+    // エリア判定
+    if (nd->bl.m != sd->bl.m ||
+        nd->bl.x < sd->bl.x - AREA_SIZE - 1
+        || nd->bl.x > sd->bl.x + AREA_SIZE + 1
+        || nd->bl.y < sd->bl.y - AREA_SIZE - 1
+        || nd->bl.y > sd->bl.y + AREA_SIZE + 1)
+        return 1;
+
+    return 0;
+}
+
+/*==========================================
+ * クリック時のNPC処理
+ *------------------------------------------
+ */
+int npc_click (struct map_session_data *sd, int id)
+{
+    struct npc_data *nd;
+
+    nullpo_retr (1, sd);
+
+    if (sd->npc_id != 0)
+    {
+        if (battle_config.error_log)
+            printf ("npc_click: npc_id != 0\n");
+        return 1;
+    }
+
+    if (npc_checknear (sd, id)) {
+        clif_scriptclose (sd, id);
+        return 1;
+    }
+
+    nd = (struct npc_data *) map_id2bl (id);
+
+    if (nd->flag & 1)           // 無効化されている
+        return 1;
+
+    sd->npc_id = id;
+    switch (nd->bl.subtype)
+    {
+        case SHOP:
+            clif_npcbuysell (sd, id);
+            npc_event_dequeue (sd);
+            break;
+        case SCRIPT:
+            sd->npc_pos = run_script (nd->u.scr.script, 0, sd->bl.id, id);
+            break;
+        case MESSAGE:
+            if (nd->u.message)
+            {
+                clif_scriptmes (sd, id, nd->u.message);
+                clif_scriptclose (sd, id);
+            }
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_scriptcont (struct map_session_data *sd, int id)
+{
+    struct npc_data *nd;
+
+    nullpo_retr (1, sd);
+
+    if (id != sd->npc_id)
+        return 1;
+    if (npc_checknear (sd, id)) {
+        clif_scriptclose (sd, id);
+        return 1;
+    }
+
+    nd = (struct npc_data *) map_id2bl (id);
+
+    if (!nd /* NPC was disposed? */  || nd->bl.subtype == MESSAGE)
+    {
+        clif_scriptclose (sd, id);
+        npc_event_dequeue (sd);
+        return 0;
+    }
+
+    sd->npc_pos = run_script (nd->u.scr.script, sd->npc_pos, sd->bl.id, id);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_buysellsel (struct map_session_data *sd, int id, int type)
+{
+    struct npc_data *nd;
+
+    nullpo_retr (1, sd);
+
+    if (npc_checknear (sd, id))
+        return 1;
+
+    nd = (struct npc_data *) map_id2bl (id);
+    if (nd->bl.subtype != SHOP)
+    {
+        if (battle_config.error_log)
+            printf ("no such shop npc : %d\n", id);
+        sd->npc_id = 0;
+        return 1;
+    }
+    if (nd->flag & 1)           // 無効化されている
+        return 1;
+
+    sd->npc_shopid = id;
+    if (type == 0)
+    {
+        clif_buylist (sd, nd);
+    }
+    else
+    {
+        clif_selllist (sd);
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_buylist (struct map_session_data *sd, int n,
+                 unsigned short *item_list)
+{
+    struct npc_data *nd;
+    double z;
+    int  i, j, w, skill, itemamount = 0, new_stacks = 0;
+
+    nullpo_retr (3, sd);
+    nullpo_retr (3, item_list);
+
+    if (npc_checknear (sd, sd->npc_shopid))
+        return 3;
+
+    nd = (struct npc_data *) map_id2bl (sd->npc_shopid);
+    if (nd->bl.subtype != SHOP)
+        return 3;
+
+    for (i = 0, w = 0, z = 0; i < n; i++)
+    {
+        for (j = 0; nd->u.shop_item[j].nameid; j++)
+        {
+            if (nd->u.shop_item[j].nameid == item_list[i * 2 + 1])
+                break;
+        }
+        if (nd->u.shop_item[j].nameid == 0)
+            return 3;
+
+        if (itemdb_value_notdc (nd->u.shop_item[j].nameid))
+            z += (double) nd->u.shop_item[j].value * item_list[i * 2];
+        else
+            z += (double) pc_modifybuyvalue (sd,
+                                             nd->u.shop_item[j].value) *
+                item_list[i * 2];
+        itemamount += item_list[i * 2];
+
+        switch (pc_checkadditem (sd, item_list[i * 2 + 1], item_list[i * 2]))
+        {
+            case ADDITEM_EXIST:
+                break;
+            case ADDITEM_NEW:
+                if (itemdb_isequip (item_list[i * 2 + 1]))
+                    new_stacks += item_list[i * 2];
+                else
+                    new_stacks++;
+                break;
+            case ADDITEM_OVERAMOUNT:
+                return 2;
+        }
+
+        w += itemdb_weight (item_list[i * 2 + 1]) * item_list[i * 2];
+    }
+
+    if (z > (double) sd->status.zeny)
+        return 1;               // zeny不足
+    if (w + sd->weight > sd->max_weight)
+        return 2;               // 重量超過
+    if (pc_inventoryblank (sd) < new_stacks)
+        return 3;               // 種類数超過
+    if (sd->trade_partner != 0)
+        return 4;               // cant buy while trading
+
+    pc_payzeny (sd, (int) z);
+
+    for (i = 0; i < n; i++)
+    {
+        struct item_data *item_data;
+        if ((item_data = itemdb_exists (item_list[i * 2 + 1])) != NULL)
+        {
+            int  amount = item_list[i * 2];
+            struct item item_tmp;
+            memset (&item_tmp, 0, sizeof (item_tmp));
+
+            item_tmp.nameid = item_data->nameid;
+            item_tmp.identify = 1;  // npc販売アイテムは鑑定済み
+
+            if (amount > 1
+                && (item_data->type == 4 || item_data->type == 5
+                    || item_data->type == 7 || item_data->type == 8))
+            {
+                for (j = 0; j < amount; j++)
+                {
+                    pc_additem (sd, &item_tmp, 1);
+                }
+            }
+            else
+            {
+                pc_additem (sd, &item_tmp, amount);
+            }
+        }
+    }
+
+    //商人経験値
+/*	if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
+		z = z * pc_checkskill(sd,MC_DISCOUNT) / ((1 + 300 / itemamount) * 4000) * battle_config.shop_exp;
+		pc_gainexp(sd,0,z);
+	}*/
+    if (battle_config.shop_exp > 0 && z > 0
+        && (skill = pc_checkskill (sd, MC_DISCOUNT)) > 0)
+    {
+        if (skill > 0)
+        {
+            z = (log (z * (double) skill) * (double) battle_config.shop_exp /
+                 100.);
+            if (z < 1)
+                z = 1;
+            pc_gainexp (sd, 0, (int) z);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int npc_selllist (struct map_session_data *sd, int n,
+                  unsigned short *item_list)
+{
+    double z;
+    int  i, skill, itemamount = 0;
+
+    nullpo_retr (1, sd);
+    nullpo_retr (1, item_list);
+
+    if (npc_checknear (sd, sd->npc_shopid))
+        return 1;
+    for (i = 0, z = 0; i < n; i++)
+    {
+        int  nameid;
+        if (item_list[i * 2] - 2 < 0 || item_list[i * 2] - 2 >= MAX_INVENTORY)
+            return 1;
+        nameid = sd->status.inventory[item_list[i * 2] - 2].nameid;
+        if (nameid == 0 ||
+            sd->status.inventory[item_list[i * 2] - 2].amount <
+            item_list[i * 2 + 1])
+            return 1;
+        if (sd->trade_partner != 0)
+            return 2;           // cant sell while trading
+        if (itemdb_value_notoc (nameid))
+            z += (double) itemdb_value_sell (nameid) * item_list[i * 2 + 1];
+        else
+            z += (double) pc_modifysellvalue (sd,
+                                              itemdb_value_sell (nameid)) *
+                item_list[i * 2 + 1];
+        itemamount += item_list[i * 2 + 1];
+    }
+
+    if (z > MAX_ZENY)
+        z = MAX_ZENY;
+    pc_getzeny (sd, (int) z);
+    for (i = 0; i < n; i++)
+    {
+        int  item_id = item_list[i * 2] - 2;
+        pc_delitem (sd, item_id, item_list[i * 2 + 1], 0);
+    }
+
+    //商人経験値
+/*	if ((sd->status.class == 5) || (sd->status.class == 10) || (sd->status.class == 18)) {
+		z = z * pc_checkskill(sd,MC_OVERCHARGE) / ((1 + 500 / itemamount) * 4000) * battle_config.shop_exp ;
+		pc_gainexp(sd,0,z);
+	}*/
+    if (battle_config.shop_exp > 0 && z > 0
+        && (skill = pc_checkskill (sd, MC_OVERCHARGE)) > 0)
+    {
+        if (skill > 0)
+        {
+            z = (log (z * (double) skill) * (double) battle_config.shop_exp /
+                 100.);
+            if (z < 1)
+                z = 1;
+            pc_gainexp (sd, 0, (int) z);
+        }
+    }
+
+    return 0;
+
+}
+
+//
+// 初期化関係
+//
+
+/*==========================================
+ * 読み込むnpcファイルのクリア
+ *------------------------------------------
+ */
+void npc_clearsrcfile (void)
+{
+    struct npc_src_list *p = npc_src_first;
+
+    while (p)
+    {
+        struct npc_src_list *p2 = p;
+        p = p->next;
+        free (p2);
+    }
+    npc_src_first = NULL;
+    npc_src_last = NULL;
+}
+
+/*==========================================
+ * 読み込むnpcファイルの追加
+ *------------------------------------------
+ */
+void npc_addsrcfile (char *name)
+{
+    struct npc_src_list *new_src;
+    size_t len;
+
+    if (strcasecmp (name, "clear") == 0)
+    {
+        npc_clearsrcfile ();
+        return;
+    }
+
+    len = sizeof (*new_src) + strlen (name);
+    new_src = (struct npc_src_list *) calloc (1, len);
+    new_src->next = NULL;
+    strncpy (new_src->name, name, strlen (name) + 1);
+    if (npc_src_first == NULL)
+        npc_src_first = new_src;
+    if (npc_src_last)
+        npc_src_last->next = new_src;
+
+    npc_src_last = new_src;
+}
+
+/*==========================================
+ * 読み込むnpcファイルの削除
+ *------------------------------------------
+ */
+void npc_delsrcfile (char *name)
+{
+    struct npc_src_list *p = npc_src_first, *pp = NULL, **lp = &npc_src_first;
+
+    if (strcasecmp (name, "all") == 0)
+    {
+        npc_clearsrcfile ();
+        return;
+    }
+
+    for (; p; lp = &p->next, pp = p, p = p->next)
+    {
+        if (strcmp (p->name, name) == 0)
+        {
+            *lp = p->next;
+            if (npc_src_last == p)
+                npc_src_last = pp;
+            free (p);
+            break;
+        }
+    }
+}
+
+/*==========================================
+ * warp行解析
+ *------------------------------------------
+ */
+int npc_parse_warp (char *w1, char *w2, char *w3, char *w4)
+{
+    int  x, y, xs, ys, to_x, to_y, m;
+    int  i, j;
+    char mapname[24], to_mapname[24];
+    struct npc_data *nd;
+
+    // 引数の個数チェック
+    if (sscanf (w1, "%[^,],%d,%d", mapname, &x, &y) != 3 ||
+        sscanf (w4, "%d,%d,%[^,],%d,%d", &xs, &ys, to_mapname, &to_x,
+                &to_y) != 5)
+    {
+        printf ("bad warp line : %s\n", w3);
+        return 1;
+    }
+
+    m = map_mapname2mapid (mapname);
+
+    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data));
+    nd->bl.id = npc_get_new_npc_id ();
+    nd->n = map_addnpc (m, nd);
+
+    nd->bl.prev = nd->bl.next = NULL;
+    nd->bl.m = m;
+    nd->bl.x = x;
+    nd->bl.y = y;
+    nd->dir = 0;
+    nd->flag = 0;
+    memcpy (nd->name, w3, 24);
+    memcpy (nd->exname, w3, 24);
+
+    nd->chat_id = 0;
+    if (!battle_config.warp_point_debug)
+        nd->npc_class = WARP_CLASS;
+    else
+        nd->npc_class = WARP_DEBUG_CLASS;
+    nd->speed = 200;
+    nd->option = 0;
+    nd->opt1 = 0;
+    nd->opt2 = 0;
+    nd->opt3 = 0;
+    memcpy (nd->u.warp.name, to_mapname, 16);
+    xs += 2;
+    ys += 2;
+    nd->u.warp.x = to_x;
+    nd->u.warp.y = to_y;
+    nd->u.warp.xs = xs;
+    nd->u.warp.ys = ys;
+
+    for (i = 0; i < ys; i++)
+    {
+        for (j = 0; j < xs; j++)
+        {
+            int  t;
+            t = map_getcell (m, x - xs / 2 + j, y - ys / 2 + i);
+            if (t == 1 || t == 5)
+                continue;
+            map_setcell (m, x - xs / 2 + j, y - ys / 2 + i, t | 0x80);
+        }
+    }
+
+//  printf("warp npc %s %d read done\n",mapname,nd->bl.id);
+    npc_warp++;
+    nd->bl.type = BL_NPC;
+    nd->bl.subtype = WARP;
+    map_addblock (&nd->bl);
+    clif_spawnnpc (nd);
+    strdb_insert (npcname_db, nd->name, nd);
+
+    return 0;
+}
+
+/*==========================================
+ * shop行解析
+ *------------------------------------------
+ */
+static int npc_parse_shop (char *w1, char *w2, char *w3, char *w4)
+{
+    char *p;
+    int  x, y, dir, m;
+    int  max = 100, pos = 0;
+    char mapname[24];
+    struct npc_data *nd;
+
+    // 引数の個数チェック
+    if (sscanf (w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ||
+        strchr (w4, ',') == NULL)
+    {
+        printf ("bad shop line : %s\n", w3);
+        return 1;
+    }
+    m = map_mapname2mapid (mapname);
+
+    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data) +
+                                      sizeof (nd->u.shop_item[0]) * (max +
+                                                                     1));
+    p = strchr (w4, ',');
+
+    while (p && pos < max)
+    {
+        int  nameid, value;
+        char name[24];
+        struct item_data *id = NULL;
+        p++;
+        if (sscanf (p, "%d:%d", &nameid, &value) == 2)
+        {
+        }
+        else if (sscanf (p, "%s :%d", name, &value) == 2)
+        {
+            id = itemdb_searchname (name);
+            if (id == NULL)
+                nameid = -1;
+            else
+                nameid = id->nameid;
+        }
+        else
+            break;
+
+        if (nameid > 0)
+        {
+            nd->u.shop_item[pos].nameid = nameid;
+            if (value < 0)
+            {
+                if (id == NULL)
+                    id = itemdb_search (nameid);
+                value = id->value_buy * abs (value);
+
+            }
+            nd->u.shop_item[pos].value = value;
+            pos++;
+        }
+        p = strchr (p, ',');
+    }
+    if (pos == 0)
+    {
+        free (nd);
+        return 1;
+    }
+    nd->u.shop_item[pos++].nameid = 0;
+
+    nd->bl.prev = nd->bl.next = NULL;
+    nd->bl.m = m;
+    nd->bl.x = x;
+    nd->bl.y = y;
+    nd->bl.id = npc_get_new_npc_id ();
+    nd->dir = dir;
+    nd->flag = 0;
+    memcpy (nd->name, w3, 24);
+    nd->npc_class = atoi (w4);
+    nd->speed = 200;
+    nd->chat_id = 0;
+    nd->option = 0;
+    nd->opt1 = 0;
+    nd->opt2 = 0;
+    nd->opt3 = 0;
+
+    nd = (struct npc_data *)
+        realloc (nd, sizeof (struct npc_data) + sizeof (nd->u.shop_item[0]) * pos);
+
+    //printf("shop npc %s %d read done\n",mapname,nd->bl.id);
+    npc_shop++;
+    nd->bl.type = BL_NPC;
+    nd->bl.subtype = SHOP;
+    nd->n = map_addnpc (m, nd);
+    map_addblock (&nd->bl);
+    clif_spawnnpc (nd);
+    strdb_insert (npcname_db, nd->name, nd);
+
+    return 0;
+}
+
+/*==========================================
+ * NPCのラベルデータコンバート
+ *------------------------------------------
+ */
+void npc_convertlabel_db (db_key_t key, db_val_t data, va_list ap)
+{
+    const char *lname = key.s;
+    int  pos = (int) data;
+    struct npc_data *nd;
+    struct npc_label_list *lst;
+    int  num;
+    char *p = strchr (lname, ':');
+
+    nullpo_retv (ap);
+    nullpo_retv (nd = va_arg (ap, struct npc_data *));
+
+    lst = nd->u.scr.label_list;
+    num = nd->u.scr.label_list_num;
+    if (!lst)
+    {
+        lst = (struct npc_label_list *)
+                calloc (1, sizeof (struct npc_label_list));
+        num = 0;
+    }
+    else
+        lst = (struct npc_label_list *)
+                realloc (lst, sizeof (struct npc_label_list) * (num + 1));
+
+    *p = '\0';
+    strncpy (lst[num].name, lname, sizeof(lst[num].name)-1);
+    lst[num].name[sizeof(lst[num].name)-1] = '\0';
+    *p = ':';
+    lst[num].pos = pos;
+    nd->u.scr.label_list = lst;
+    nd->u.scr.label_list_num = num + 1;
+}
+
+/*==========================================
+ * script行解析
+ *------------------------------------------
+ */
+static int npc_parse_script (char *w1, char *w2, char *w3, char *w4,
+                             char *first_line, FILE * fp, int *lines)
+{
+    int  x, y, dir = 0, m, xs = 0, ys = 0, npc_class = 0;   // [Valaris] thanks to fov
+    char mapname[24];
+    unsigned char *srcbuf = NULL, *script;
+    int  srcsize = 65536;
+    int  startline = 0;
+    unsigned char line[1024];
+    int  i;
+    struct npc_data *nd;
+    int  evflag = 0;
+    struct dbt *label_db;
+    char *p;
+    struct npc_label_list *label_dup = NULL;
+    int  label_dupnum = 0;
+    int  src_id = 0;
+
+    if (strcmp (w1, "-") == 0)
+    {
+        x = 0;
+        y = 0;
+        m = -1;
+    }
+    else
+    {
+        // 引数の個数チェック
+        if (sscanf (w1, "%[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ||
+            (strcmp (w2, "script") == 0 && strchr (w4, ',') == NULL))
+        {
+            printf ("bad script line : %s\n", w3);
+            return 1;
+        }
+        m = map_mapname2mapid (mapname);
+    }
+
+    if (strcmp (w2, "script") == 0)
+    {
+        // スクリプトの解析
+        srcbuf = (char *) calloc (srcsize, sizeof (char));
+        if (strchr (first_line, '{'))
+        {
+            strcpy (srcbuf, strchr (first_line, '{'));
+            startline = *lines;
+        }
+        else
+            srcbuf[0] = 0;
+        while (1)
+        {
+            for (i = strlen (srcbuf) - 1; i >= 0 && isspace (srcbuf[i]); i--);
+            if (i >= 0 && srcbuf[i] == '}')
+                break;
+            if (!fgets (line, 1020, fp))
+                break;
+            (*lines)++;
+            if (feof (fp))
+                break;
+            if (strlen (srcbuf) + strlen (line) + 1 >= srcsize)
+            {
+                srcsize += 65536;
+                srcbuf = (char *) realloc (srcbuf, srcsize);
+                memset (srcbuf + srcsize - 65536, '\0', 65536);
+            }
+            if (srcbuf[0] != '{')
+            {
+                if (strchr (line, '{'))
+                {
+                    strcpy (srcbuf, strchr (line, '{'));
+                    startline = *lines;
+                }
+            }
+            else
+                strcat (srcbuf, line);
+        }
+        script = parse_script (srcbuf, startline);
+        if (script == NULL)
+        {
+            // script parse error?
+            free (srcbuf);
+            return 1;
+        }
+
+    }
+    else
+    {
+        // duplicateする
+
+        char srcname[128];
+        struct npc_data *nd2;
+        if (sscanf (w2, "duplicate(%[^)])", srcname) != 1)
+        {
+            printf ("bad duplicate name! : %s", w2);
+            return 0;
+        }
+        if ((nd2 = npc_name2id (srcname)) == NULL)
+        {
+            printf ("bad duplicate name! (not exist) : %s\n", srcname);
+            return 0;
+        }
+        script = nd2->u.scr.script;
+        label_dup = nd2->u.scr.label_list;
+        label_dupnum = nd2->u.scr.label_list_num;
+        src_id = nd2->bl.id;
+
+    }                           // end of スクリプト解析
+
+    nd = (struct npc_data *) calloc (1, sizeof (struct npc_data));
+
+    if (m == -1)
+    {
+        // スクリプトコピー用のダミーNPC
+
+    }
+    else if (sscanf (w4, "%d,%d,%d", &npc_class, &xs, &ys) == 3)
+    {
+        // 接触型NPC
+        int  i, j;
+
+        if (xs >= 0)
+            xs = xs * 2 + 1;
+        if (ys >= 0)
+            ys = ys * 2 + 1;
+
+        if (npc_class >= 0)
+        {
+
+            for (i = 0; i < ys; i++)
+            {
+                for (j = 0; j < xs; j++)
+                {
+                    int  t;
+                    t = map_getcell (m, x - xs / 2 + j, y - ys / 2 + i);
+                    if (t == 1 || t == 5)
+                        continue;
+                    map_setcell (m, x - xs / 2 + j, y - ys / 2 + i, t | 0x80);
+                }
+            }
+        }
+
+        nd->u.scr.xs = xs;
+        nd->u.scr.ys = ys;
+    }
+    else
+    {                           // クリック型NPC
+        npc_class = atoi (w4);
+        nd->u.scr.xs = 0;
+        nd->u.scr.ys = 0;
+    }
+
+    if (npc_class < 0 && m >= 0)
+    {                           // イベント型NPC
+        evflag = 1;
+    }
+
+    while ((p = strchr (w3, ':')))
+    {
+        if (p[1] == ':')
+            break;
+    }
+    if (p)
+    {
+        *p = 0;
+        memcpy (nd->name, w3, 24);
+        memcpy (nd->exname, p + 2, 24);
+    }
+    else
+    {
+        memcpy (nd->name, w3, 24);
+        memcpy (nd->exname, w3, 24);
+    }
+
+    nd->bl.prev = nd->bl.next = NULL;
+    nd->bl.m = m;
+    nd->bl.x = x;
+    nd->bl.y = y;
+    nd->bl.id = npc_get_new_npc_id ();
+    nd->dir = dir;
+    nd->flag = 0;
+    nd->npc_class = npc_class;
+    nd->speed = 200;
+    nd->u.scr.script = script;
+    nd->u.scr.src_id = src_id;
+    nd->chat_id = 0;
+    nd->option = 0;
+    nd->opt1 = 0;
+    nd->opt2 = 0;
+    nd->opt3 = 0;
+
+    //printf("script npc %s %d %d read done\n",mapname,nd->bl.id,nd->class);
+    npc_script++;
+    nd->bl.type = BL_NPC;
+    nd->bl.subtype = SCRIPT;
+    if (m >= 0)
+    {
+        nd->n = map_addnpc (m, nd);
+        map_addblock (&nd->bl);
+
+        if (evflag)
+        {                       // イベント型
+            struct event_data *ev =
+                (struct event_data *) calloc (1, sizeof (struct event_data));
+            ev->nd = nd;
+            ev->pos = 0;
+            strdb_insert (ev_db, nd->exname, ev);
+        }
+        else
+            clif_spawnnpc (nd);
+    }
+    strdb_insert (npcname_db, nd->exname, nd);
+
+    //-----------------------------------------
+    // ラベルデータの準備
+    if (srcbuf)
+    {
+        // script本体がある場合の処理
+
+        // ラベルデータのコンバート
+        label_db = script_get_label_db ();
+        strdb_foreach (label_db, npc_convertlabel_db, nd);
+
+        // もう使わないのでバッファ解放
+        free (srcbuf);
+
+    }
+    else
+    {
+        // duplicate
+
+//      nd->u.scr.label_list=malloc(sizeof(struct npc_label_list)*label_dupnum);
+//      memcpy(nd->u.scr.label_list,label_dup,sizeof(struct npc_label_list)*label_dupnum);
+
+        nd->u.scr.label_list = label_dup;   // ラベルデータ共有
+        nd->u.scr.label_list_num = label_dupnum;
+    }
+
+    //-----------------------------------------
+    // イベント用ラベルデータのエクスポート
+    for (i = 0; i < nd->u.scr.label_list_num; i++)
+    {
+        char *lname = nd->u.scr.label_list[i].name;
+        int  pos = nd->u.scr.label_list[i].pos;
+
+        if ((lname[0] == 'O' || lname[0] == 'o')
+            && (lname[1] == 'N' || lname[1] == 'n'))
+        {
+            struct event_data *ev;
+            char *buf;
+            // エクスポートされる
+            ev = (struct event_data *) calloc (1,
+                                                sizeof (struct event_data));
+            buf = (char *) calloc (50, sizeof (char));
+            if (strlen (lname) > 24)
+            {
+                printf ("npc_parse_script: label name error !\n");
+                exit (1);
+            }
+            else
+            {
+                ev->nd = nd;
+                ev->pos = pos;
+                sprintf (buf, "%s::%s", nd->exname, lname);
+                strdb_insert (ev_db, buf, ev);
+            }
+        }
+    }
+
+    //-----------------------------------------
+    // ラベルデータからタイマーイベント取り込み
+    for (i = 0; i < nd->u.scr.label_list_num; i++)
+    {
+        int  t = 0, k = 0;
+        char *lname = nd->u.scr.label_list[i].name;
+        int  pos = nd->u.scr.label_list[i].pos;
+        if (sscanf (lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0')
+        {
+            // タイマーイベント
+            struct npc_timerevent_list *te = nd->u.scr.timer_event;
+            int  j, k = nd->u.scr.timeramount;
+            if (te == NULL)
+                te = (struct npc_timerevent_list *) calloc (1,
+                                                             sizeof (struct
+                                                                     npc_timerevent_list));
+            else
+                te = (struct npc_timerevent_list *) realloc (te,
+                                                              sizeof (struct
+                                                                      npc_timerevent_list)
+                                                              * (k + 1));
+            for (j = 0; j < k; j++)
+            {
+                if (te[j].timer > t)
+                {
+                    memmove (te + j + 1, te + j,
+                             sizeof (struct npc_timerevent_list) * (k - j));
+                    break;
+                }
+            }
+            te[j].timer = t;
+            te[j].pos = pos;
+            nd->u.scr.timer_event = te;
+            nd->u.scr.timeramount = k + 1;
+        }
+    }
+    nd->u.scr.nexttimer = -1;
+    nd->u.scr.timerid = -1;
+
+    return 0;
+}
+
+/*==========================================
+ * function行解析
+ *------------------------------------------
+ */
+static int npc_parse_function (char *w1, char *w2, char *w3, char *w4,
+                               char *first_line, FILE * fp, int *lines)
+{
+    char *srcbuf = NULL, *script;
+    int  srcsize = 65536;
+    int  startline = 0;
+    char line[1024];
+    int  i;
+//  struct dbt *label_db;
+    char *p;
+
+    // スクリプトの解析
+    srcbuf = (char *) calloc (srcsize, sizeof (char));
+    if (strchr (first_line, '{'))
+    {
+        strcpy (srcbuf, strchr (first_line, '{'));
+        startline = *lines;
+    }
+    else
+        srcbuf[0] = 0;
+    while (1)
+    {
+        for (i = strlen (srcbuf) - 1; i >= 0 && isspace (srcbuf[i]); i--);
+        if (i >= 0 && srcbuf[i] == '}')
+            break;
+        if (!fgets (line, 1020, fp))
+            break;
+        (*lines)++;
+        if (feof (fp))
+            break;
+        if (strlen (srcbuf) + strlen (line) + 1 >= srcsize)
+        {
+            srcsize += 65536;
+            srcbuf = (char *) realloc (srcbuf, srcsize);
+            memset (srcbuf + srcsize - 65536, '\0', 65536);
+        }
+        if (srcbuf[0] != '{')
+        {
+            if (strchr (line, '{'))
+            {
+                strcpy (srcbuf, strchr (line, '{'));
+                startline = *lines;
+            }
+        }
+        else
+            strcat (srcbuf, line);
+    }
+    script = parse_script (srcbuf, startline);
+    if (script == NULL)
+    {
+        // script parse error?
+        free (srcbuf);
+        return 1;
+    }
+
+    p = (char *) calloc (50, sizeof (char));
+
+    strncpy (p, w3, 49);
+    strdb_insert (script_get_userfunc_db (), p, script);
+
+//  label_db=script_get_label_db();
+
+    // もう使わないのでバッファ解放
+    free (srcbuf);
+
+//  printf("function %s => %p\n",p,script);
+
+    return 0;
+}
+
+/*==========================================
+ * mob行解析
+ *------------------------------------------
+ */
+int npc_parse_mob (char *w1, char *w2, char *w3, char *w4)
+{
+    int  m, x, y, xs, ys, mob_class, num, delay1, delay2;
+    int  i;
+    char mapname[24];
+    char eventname[24] = "";
+    struct mob_data *md;
+
+    xs = ys = 0;
+    delay1 = delay2 = 0;
+    // 引数の個数チェック
+    if (sscanf (w1, "%[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 ||
+        sscanf (w4, "%d,%d,%d,%d,%s", &mob_class, &num, &delay1, &delay2,
+                eventname) < 2)
+    {
+        printf ("bad monster line : %s\n", w3);
+        return 1;
+    }
+
+    m = map_mapname2mapid (mapname);
+
+    if (num > 1 && battle_config.mob_count_rate != 100)
+    {
+        if ((num = num * battle_config.mob_count_rate / 100) < 1)
+            num = 1;
+    }
+
+    for (i = 0; i < num; i++)
+    {
+        md = (struct mob_data *) calloc (1, sizeof (struct mob_data));
+
+        md->bl.prev = NULL;
+        md->bl.next = NULL;
+        md->bl.m = m;
+        md->bl.x = x;
+        md->bl.y = y;
+        if (strcmp (w3, "--en--") == 0)
+            memcpy (md->name, mob_db[mob_class].name, 24);
+        else if (strcmp (w3, "--ja--") == 0)
+            memcpy (md->name, mob_db[mob_class].jname, 24);
+        else
+            memcpy (md->name, w3, 24);
+
+        md->n = i;
+        md->base_class = md->mob_class = mob_class;
+        md->bl.id = npc_get_new_npc_id ();
+        md->m = m;
+        md->x0 = x;
+        md->y0 = y;
+        md->xs = xs;
+        md->ys = ys;
+        md->spawndelay1 = delay1;
+        md->spawndelay2 = delay2;
+
+        memset (&md->state, 0, sizeof (md->state));
+        md->timer = -1;
+        md->target_id = 0;
+        md->attacked_id = 0;
+
+        if (mob_db[mob_class].mode & 0x02)
+            md->lootitem =
+                (struct item *) calloc (LOOTITEM_SIZE, sizeof (struct item));
+        else
+            md->lootitem = NULL;
+
+        if (strlen (eventname) >= 4)
+        {
+            memcpy (md->npc_event, eventname, 24);
+        }
+        else
+            memset (md->npc_event, 0, 24);
+
+        md->bl.type = BL_MOB;
+        map_addiddb (&md->bl);
+        mob_spawn (md->bl.id);
+
+        npc_mob++;
+    }
+    //printf("warp npc %s %d read done\n",mapname,nd->bl.id);
+
+    return 0;
+}
+
+/*==========================================
+ * マップフラグ行の解析
+ *------------------------------------------
+ */
+static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
+{
+    int  m;
+    char mapname[24], savemap[16];
+    int  savex, savey;
+    char drop_arg1[16], drop_arg2[16];
+    int  drop_id = 0, drop_type = 0, drop_per = 0;
+
+    // 引数の個数チェック
+//  if (    sscanf(w1,"%[^,],%d,%d,%d",mapname,&x,&y,&dir) != 4 )
+    if (sscanf (w1, "%[^,]", mapname) != 1)
+        return 1;
+
+    m = map_mapname2mapid (mapname);
+    if (m < 0)
+        return 1;
+
+//マップフラグ
+    if (strcasecmp (w3, "nosave") == 0)
+    {
+        if (strcmp (w4, "SavePoint") == 0)
+        {
+            memcpy (map[m].save.map, "SavePoint", 16);
+            map[m].save.x = -1;
+            map[m].save.y = -1;
+        }
+        else if (sscanf (w4, "%[^,],%d,%d", savemap, &savex, &savey) == 3)
+        {
+            memcpy (map[m].save.map, savemap, 16);
+            map[m].save.x = savex;
+            map[m].save.y = savey;
+        }
+        map[m].flag.nosave = 1;
+    }
+    else if (strcasecmp (w3, "nomemo") == 0)
+    {
+        map[m].flag.nomemo = 1;
+    }
+    else if (strcasecmp (w3, "noteleport") == 0)
+    {
+        map[m].flag.noteleport = 1;
+    }
+    else if (strcasecmp (w3, "nowarp") == 0)
+    {
+        map[m].flag.nowarp = 1;
+    }
+    else if (strcasecmp (w3, "nowarpto") == 0)
+    {
+        map[m].flag.nowarpto = 1;
+    }
+    else if (strcasecmp (w3, "noreturn") == 0)
+    {
+        map[m].flag.noreturn = 1;
+    }
+    else if (strcasecmp (w3, "monster_noteleport") == 0)
+    {
+        map[m].flag.monster_noteleport = 1;
+    }
+    else if (strcasecmp (w3, "nobranch") == 0)
+    {
+        map[m].flag.nobranch = 1;
+    }
+    else if (strcasecmp (w3, "nopenalty") == 0)
+    {
+        map[m].flag.nopenalty = 1;
+    }
+    else if (strcasecmp (w3, "pvp") == 0)
+    {
+        map[m].flag.pvp = 1;
+    }
+    else if (strcasecmp (w3, "pvp_noparty") == 0)
+    {
+        map[m].flag.pvp_noparty = 1;
+    }
+    else if (strcasecmp (w3, "pvp_noguild") == 0)
+    {
+        map[m].flag.pvp_noguild = 1;
+    }
+    else if (strcasecmp (w3, "pvp_nightmaredrop") == 0)
+    {
+        if (sscanf (w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) ==
+            3)
+        {
+            int  i;
+            if (strcmp (drop_arg1, "random") == 0)
+                drop_id = -1;
+            else if (itemdb_exists ((drop_id = atoi (drop_arg1))) == NULL)
+                drop_id = 0;
+            if (strcmp (drop_arg2, "inventory") == 0)
+                drop_type = 1;
+            else if (strcmp (drop_arg2, "equip") == 0)
+                drop_type = 2;
+            else if (strcmp (drop_arg2, "all") == 0)
+                drop_type = 3;
+
+            if (drop_id != 0)
+            {
+                for (i = 0; i < MAX_DROP_PER_MAP; i++)
+                {
+                    if (map[m].drop_list[i].drop_id == 0)
+                    {
+                        map[m].drop_list[i].drop_id = drop_id;
+                        map[m].drop_list[i].drop_type = drop_type;
+                        map[m].drop_list[i].drop_per = drop_per;
+                        break;
+                    }
+                }
+                map[m].flag.pvp_nightmaredrop = 1;
+            }
+        }
+    }
+    else if (strcasecmp (w3, "pvp_nocalcrank") == 0)
+    {
+        map[m].flag.pvp_nocalcrank = 1;
+    }
+    else if (strcasecmp (w3, "gvg") == 0)
+    {
+        map[m].flag.gvg = 1;
+    }
+    else if (strcasecmp (w3, "gvg_noparty") == 0)
+    {
+        map[m].flag.gvg_noparty = 1;
+    }
+    else if (strcasecmp (w3, "nozenypenalty") == 0)
+    {
+        map[m].flag.nozenypenalty = 1;
+    }
+    else if (strcasecmp (w3, "notrade") == 0)
+    {
+        map[m].flag.notrade = 1;
+    }
+    else if (strcasecmp (w3, "noskill") == 0)
+    {
+        map[m].flag.noskill = 1;
+    }
+    else if (battle_config.pk_mode && strcasecmp (w3, "nopvp") == 0)
+    {                           // nopvp for pk mode [Valaris]
+        map[m].flag.nopvp = 1;
+        map[m].flag.pvp = 0;
+    }
+    else if (strcasecmp (w3, "noicewall") == 0)
+    {                           // noicewall [Valaris]
+        map[m].flag.noicewall = 1;
+    }
+    else if (strcasecmp (w3, "snow") == 0)
+    {                           // snow [Valaris]
+        map[m].flag.snow = 1;
+    }
+    else if (strcasecmp (w3, "fog") == 0)
+    {                           // fog [Valaris]
+        map[m].flag.fog = 1;
+    }
+    else if (strcasecmp (w3, "sakura") == 0)
+    {                           // sakura [Valaris]
+        map[m].flag.sakura = 1;
+    }
+    else if (strcasecmp (w3, "leaves") == 0)
+    {                           // leaves [Valaris]
+        map[m].flag.leaves = 1;
+    }
+    else if (strcasecmp (w3, "rain") == 0)
+    {                           // rain [Valaris]
+        map[m].flag.rain = 1;
+    }
+    else if (strcasecmp (w3, "no_player_drops") == 0)
+    {                           // no player drops [Jaxad0127]
+        map[m].flag.no_player_drops = 1;
+    }
+    else if (strcasecmp (w3, "town") == 0)
+    {                           // town/safe zone [remoitnane]
+        map[m].flag.town = 1;
+    }
+
+    return 0;
+}
+
+static void ev_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+    if (strstr (key.s, "::") != NULL)
+        free ((char*)key.s);
+}
+
+struct npc_data *npc_spawn_text (int m, int x, int y,
+                                 int npc_class, char *name, char *message)
+{
+    struct npc_data *retval =
+        (struct npc_data *) calloc (1, sizeof (struct npc_data));
+    retval->bl.id = npc_get_new_npc_id ();
+    retval->bl.x = x;
+    retval->bl.y = y;
+    retval->bl.m = m;
+    retval->bl.type = BL_NPC;
+    retval->bl.subtype = MESSAGE;
+
+    strncpy (retval->name, name, 23);
+    strncpy (retval->exname, name, 23);
+    retval->name[15] = 0;
+    retval->exname[15] = 0;
+    retval->u.message = message ? strdup (message) : NULL;
+
+    retval->npc_class = npc_class;
+    retval->speed = 200;
+
+    clif_spawnnpc (retval);
+    map_addblock (&retval->bl);
+    map_addiddb (&retval->bl);
+    if (retval->name && retval->name[0])
+        strdb_insert (npcname_db, retval->name, retval);
+
+    return retval;
+}
+
+static void npc_free_internal (struct npc_data *nd)
+{
+    struct chat_data *cd;
+
+    if (nd->chat_id && (cd = (struct chat_data *) map_id2bl (nd->chat_id)))
+    {
+        free (cd);
+        cd = NULL;
+    }
+    if (nd->bl.subtype == SCRIPT)
+    {
+        if (nd->u.scr.timer_event)
+            free (nd->u.scr.timer_event);
+        if (nd->u.scr.src_id == 0)
+        {
+            if (nd->u.scr.script)
+            {
+                free (nd->u.scr.script);
+                nd->u.scr.script = NULL;
+            }
+            if (nd->u.scr.label_list)
+            {
+                free (nd->u.scr.label_list);
+                nd->u.scr.label_list = NULL;
+            }
+        }
+    }
+    else if (nd->bl.subtype == MESSAGE && nd->u.message)
+    {
+        free (nd->u.message);
+    }
+    free (nd);
+}
+
+void npc_propagate_update (struct npc_data *nd)
+{
+    map_foreachinarea (npc_enable_sub,
+                       nd->bl.m,
+                       nd->bl.x - nd->u.scr.xs, nd->bl.y - nd->u.scr.ys,
+                       nd->bl.x + nd->u.scr.xs, nd->bl.y + nd->u.scr.ys,
+                       BL_PC, nd);
+}
+
+void npc_free (struct npc_data *nd)
+{
+    clif_clearchar (&nd->bl, 0);
+    npc_propagate_update (nd);
+    map_deliddb (&nd->bl);
+    map_delblock (&nd->bl);
+    npc_free_internal (nd);
+}
+
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+int do_final_npc (void)
+{
+    int  i;
+    struct block_list *bl;
+    struct npc_data *nd;
+    struct mob_data *md;
+
+    if (ev_db)
+        strdb_final (ev_db, ev_db_final);
+    if (npcname_db)
+        strdb_final (npcname_db, NULL);
+
+    for (i = START_NPC_NUM; i < npc_id; i++)
+    {
+        if ((bl = map_id2bl (i)))
+        {
+            if (bl->type == BL_NPC && (nd = (struct npc_data *) bl))
+                npc_free_internal (nd);
+            else if (bl->type == BL_MOB && (md = (struct mob_data *) bl))
+            {
+                if (md->lootitem)
+                {
+                    free (md->lootitem);
+                    md->lootitem = NULL;
+                }
+                free (md);
+                md = NULL;
+            }
+        }
+    }
+
+    return 0;
+}
+
+void ev_release (db_key_t key, db_val_t val)
+{
+    free ((char*)key.s);
+    free (val);
+}
+
+/*==========================================
+ * npc初期化
+ *------------------------------------------
+ */
+int do_init_npc (void)
+{
+    struct npc_src_list *nsl;
+    FILE *fp;
+    char line[1024];
+    int  m, lines;
+
+    ev_db = strdb_init (24);
+    npcname_db = strdb_init (24);
+
+    ev_db->release = ev_release;
+
+    memset (&ev_tm_b, -1, sizeof (ev_tm_b));
+
+    for (nsl = npc_src_first; nsl; nsl = nsl->next)
+    {
+        if (nsl->prev)
+        {
+            free (nsl->prev);
+            nsl->prev = NULL;
+        }
+        fp = fopen_ (nsl->name, "r");
+        if (fp == NULL)
+        {
+            printf ("file not found : %s\n", nsl->name);
+            exit (1);
+        }
+        lines = 0;
+        while (fgets (line, 1020, fp))
+        {
+            char w1[1024], w2[1024], w3[1024], w4[1024], mapname[1024];
+            int  i, j, w4pos, count;
+            lines++;
+
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+            // 不要なスペースやタブの連続は詰める
+            for (i = j = 0; line[i]; i++)
+            {
+                if (line[i] == ' ')
+                {
+                    if (!
+                        ((line[i + 1]
+                          && (isspace (line[i + 1]) || line[i + 1] == ','))
+                         || (j && line[j - 1] == ',')))
+                        line[j++] = ' ';
+                }
+                else if (line[i] == '\t' || line[i] == '|')
+                {
+                    if (!(j && (line[j - 1] == '\t' || line[j - 1] == '|')))
+                        line[j++] = '\t';
+                }
+                else
+                    line[j++] = line[i];
+            }
+            // 最初はタブ区切りでチェックしてみて、ダメならスペース区切りで確認
+            if ((count =
+                 sscanf (line, "%[^\t]\t%[^\t]\t%[^\t\r\n]\t%n%[^\t\r\n]", w1,
+                         w2, w3, &w4pos, w4)) < 3
+                && (count =
+                    sscanf (line, "%s%s%s%n%s", w1, w2, w3, &w4pos, w4)) < 3)
+            {
+                continue;
+            }
+            // マップの存在確認
+            if (strcmp (w1, "-") != 0 && strcasecmp (w1, "function") != 0)
+            {
+                sscanf (w1, "%[^,]", mapname);
+                m = map_mapname2mapid (mapname);
+                if (strlen (mapname) > 16 || m < 0)
+                {
+                    // "mapname" is not assigned to this server
+                    continue;
+                }
+            }
+            if (strcasecmp (w2, "warp") == 0 && count > 3)
+            {
+                npc_parse_warp (w1, w2, w3, w4);
+            }
+            else if (strcasecmp (w2, "shop") == 0 && count > 3)
+            {
+                npc_parse_shop (w1, w2, w3, w4);
+            }
+            else if (strcasecmp (w2, "script") == 0 && count > 3)
+            {
+                if (strcasecmp (w1, "function") == 0)
+                {
+                    npc_parse_function (w1, w2, w3, w4, line + w4pos, fp,
+                                        &lines);
+                }
+                else
+                {
+                    npc_parse_script (w1, w2, w3, w4, line + w4pos, fp,
+                                      &lines);
+                }
+            }
+            else if ((i =
+                      0, sscanf (w2, "duplicate%n", &i), (i > 0
+                                                          && w2[i] == '('))
+                     && count > 3)
+            {
+                npc_parse_script (w1, w2, w3, w4, line + w4pos, fp, &lines);
+            }
+            else if (strcasecmp (w2, "monster") == 0 && count > 3)
+            {
+                npc_parse_mob (w1, w2, w3, w4);
+            }
+            else if (strcasecmp (w2, "mapflag") == 0 && count >= 3)
+            {
+                npc_parse_mapflag (w1, w2, w3, w4);
+            }
+        }
+        fclose_ (fp);
+        printf ("\rLoading NPCs [%d]: %-54s", npc_id - START_NPC_NUM,
+                nsl->name);
+        fflush (stdout);
+    }
+    printf ("\rNPCs Loaded: %d [Warps:%d Shops:%d Scripts:%d Mobs:%d]\n",
+            npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob);
+
+    return 0;
+}
diff --git a/src/map/npc.h b/src/map/npc.h
deleted file mode 100644
index 757c7ab..0000000
--- a/src/map/npc.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// $Id: npc.h,v 1.5 2004/09/25 11:39:17 MouseJstr Exp $
-#ifndef _NPC_H_
-#define _NPC_H_
-
-#define START_NPC_NUM 110000000
-
-#define WARP_CLASS 45
-#define WARP_DEBUG_CLASS 722
-#define INVISIBLE_CLASS 32767
-
-int  npc_event_dequeue (struct map_session_data *sd);
-void npc_event_timer (timer_id, tick_t, custom_id_t, custom_data_t);
-int  npc_event (struct map_session_data *sd, const char *npcname, int);
-int  npc_timer_event (const char *eventname);   // Added by RoVeRT
-int  npc_command (struct map_session_data *sd, char *npcname, char *command);
-int  npc_touch_areanpc (struct map_session_data *, int, int, int);
-int  npc_click (struct map_session_data *, int);
-int  npc_scriptcont (struct map_session_data *, int);
-int  npc_checknear (struct map_session_data *, int);
-int  npc_buysellsel (struct map_session_data *, int, int);
-int  npc_buylist (struct map_session_data *, int, unsigned short *);
-int  npc_selllist (struct map_session_data *, int, unsigned short *);
-int  npc_parse_mob (char *w1, char *w2, char *w3, char *w4);
-int  npc_parse_warp (char *w1, char *w2, char *w3, char *w4);
-
-int  npc_enable (const char *name, int flag);
-struct npc_data *npc_name2id (const char *name);
-
-int  npc_get_new_npc_id (void);
-
-/**
- * Spawns and installs a talk-only NPC
- *
- * \param message The message to speak.  If message is NULL, the NPC will not do anything at all.
- */
-struct npc_data *npc_spawn_text (int m, int x, int y, int class_, char *name, char *message);    // message is strdup'd within
-
-/**
- * Uninstalls and frees an NPC
- */
-void npc_free (struct npc_data *npc);
-
-void npc_addsrcfile (char *);
-void npc_delsrcfile (char *);
-int  do_final_npc (void);
-int  do_init_npc (void);
-int  npc_event_do_oninit (void);
-int  npc_do_ontimer (int, struct map_session_data *, int);
-
-struct argrec;
-int  npc_event_doall_l (const char *name, int rid, int argc,
-                        struct argrec *argv);
-int  npc_event_do_l (const char *name, int rid, int argc,
-                     struct argrec *argv);
-#define npc_event_doall(name) npc_event_doall_l(name, 0, 0, NULL)
-#define npc_event_do(name) npc_event_do_l(name, 0, 0, NULL)
-
-int  npc_timerevent_start (struct npc_data *nd);
-int  npc_timerevent_stop (struct npc_data *nd);
-int  npc_gettimerevent_tick (struct npc_data *nd);
-int  npc_settimerevent_tick (struct npc_data *nd, int newtimer);
-int  npc_delete (struct npc_data *nd);
-
-#endif
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
new file mode 100644
index 0000000..6bb9370
--- /dev/null
+++ b/src/map/npc.hpp
@@ -0,0 +1,64 @@
+// $Id: npc.h,v 1.5 2004/09/25 11:39:17 MouseJstr Exp $
+#ifndef NPC_HPP
+#define NPC_HPP
+
+#define START_NPC_NUM 110000000
+
+#define WARP_CLASS 45
+#define WARP_DEBUG_CLASS 722
+#define INVISIBLE_CLASS 32767
+
+int  npc_event_dequeue (struct map_session_data *sd);
+void npc_event_timer (timer_id, tick_t, custom_id_t, custom_data_t);
+int  npc_event (struct map_session_data *sd, const char *npcname, int);
+int  npc_timer_event (const char *eventname);   // Added by RoVeRT
+int  npc_command (struct map_session_data *sd, char *npcname, char *command);
+int  npc_touch_areanpc (struct map_session_data *, int, int, int);
+int  npc_click (struct map_session_data *, int);
+int  npc_scriptcont (struct map_session_data *, int);
+int  npc_checknear (struct map_session_data *, int);
+int  npc_buysellsel (struct map_session_data *, int, int);
+int  npc_buylist (struct map_session_data *, int, unsigned short *);
+int  npc_selllist (struct map_session_data *, int, unsigned short *);
+int  npc_parse_mob (char *w1, char *w2, char *w3, char *w4);
+int  npc_parse_warp (char *w1, char *w2, char *w3, char *w4);
+
+int  npc_enable (const char *name, int flag);
+struct npc_data *npc_name2id (const char *name);
+
+int  npc_get_new_npc_id (void);
+
+/**
+ * Spawns and installs a talk-only NPC
+ *
+ * \param message The message to speak.  If message is NULL, the NPC will not do anything at all.
+ */
+struct npc_data *npc_spawn_text (int m, int x, int y, int class_, char *name, char *message);    // message is strdup'd within
+
+/**
+ * Uninstalls and frees an NPC
+ */
+void npc_free (struct npc_data *npc);
+
+void npc_addsrcfile (char *);
+void npc_delsrcfile (char *);
+int  do_final_npc (void);
+int  do_init_npc (void);
+int  npc_event_do_oninit (void);
+int  npc_do_ontimer (int, struct map_session_data *, int);
+
+struct argrec;
+int  npc_event_doall_l (const char *name, int rid, int argc,
+                        struct argrec *argv);
+int  npc_event_do_l (const char *name, int rid, int argc,
+                     struct argrec *argv);
+#define npc_event_doall(name) npc_event_doall_l(name, 0, 0, NULL)
+#define npc_event_do(name) npc_event_do_l(name, 0, 0, NULL)
+
+int  npc_timerevent_start (struct npc_data *nd);
+int  npc_timerevent_stop (struct npc_data *nd);
+int  npc_gettimerevent_tick (struct npc_data *nd);
+int  npc_settimerevent_tick (struct npc_data *nd, int newtimer);
+int  npc_delete (struct npc_data *nd);
+
+#endif
diff --git a/src/map/party.c b/src/map/party.c
deleted file mode 100644
index 6c2e627..0000000
--- a/src/map/party.c
+++ /dev/null
@@ -1,790 +0,0 @@
-// $Id: party.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "party.h"
-#include "../common/db.h"
-#include "../common/timer.h"
-#include "../common/socket.h"
-#include "../common/nullpo.h"
-#include "pc.h"
-#include "map.h"
-#include "battle.h"
-#include "intif.h"
-#include "clif.h"
-#include "skill.h"
-#include "tmw.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define PARTY_SEND_XYHP_INVERVAL	1000    // 座標やHP送信の間隔
-
-static struct dbt *party_db;
-
-void party_send_xyhp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
-/*==========================================
- * 終了
- *------------------------------------------
- */
-static void party_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-void do_final_party (void)
-{
-    if (party_db)
-        numdb_final (party_db, party_db_final);
-}
-
-// 初期化
-void do_init_party (void)
-{
-    party_db = numdb_init ();
-    add_timer_interval (gettick () + PARTY_SEND_XYHP_INVERVAL,
-                        party_send_xyhp_timer, 0, 0,
-                        PARTY_SEND_XYHP_INVERVAL);
-}
-
-// 検索
-struct party *party_search (int party_id)
-{
-    return (struct party *)numdb_search (party_db, party_id);
-}
-
-void party_searchname_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct party *p = (struct party *) data, **dst;
-    char *str;
-    str = va_arg (ap, char *);
-    dst = va_arg (ap, struct party **);
-    if (strcasecmp (p->name, str) == 0)
-        *dst = p;
-}
-
-// パーティ名検索
-struct party *party_searchname (char *str)
-{
-    struct party *p = NULL;
-    numdb_foreach (party_db, party_searchname_sub, str, &p);
-    return p;
-}
-
-/* Process a party creation request. */
-int party_create (struct map_session_data *sd, char *name)
-{
-    char pname[24];
-    nullpo_retr (0, sd);
-
-    strncpy (pname, name, 24);
-    pname[23] = '\0';
-    tmw_TrimStr (pname);
-
-    /* The party name is empty/invalid. */
-    if (!*pname)
-        clif_party_created (sd, 1);
-
-    /* Make sure the character isn't already in a party. */
-    if (sd->status.party_id == 0)
-        intif_create_party (sd, pname);
-    else
-        clif_party_created (sd, 2);
-
-    return 0;
-}
-
-/* Relay the result of a party creation request. */
-int party_created (int account_id, int fail, int party_id, char *name)
-{
-    struct map_session_data *sd;
-    sd = map_id2sd (account_id);
-
-    nullpo_retr (0, sd);
-
-    /* The party name is valid and not already taken. */
-    if (!fail)
-    {
-        struct party *p;
-        sd->status.party_id = party_id;
-
-        if ((p = (struct party *)numdb_search (party_db, party_id)) != NULL)
-        {
-            printf ("party_created(): ID already exists!\n");
-            exit (1);
-        }
-
-        CREATE (p, struct party, 1);
-        p->party_id = party_id;
-        memcpy (p->name, name, 24);
-        numdb_insert (party_db, party_id, p);
-
-        /* The party was created successfully. */
-        clif_party_created (sd, 0);
-    }
-
-    else
-        clif_party_created (sd, 1);
-
-    return 0;
-}
-
-// 情報要求
-int party_request_info (int party_id)
-{
-    return intif_request_partyinfo (party_id);
-}
-
-// 所属キャラの確認
-int party_check_member (struct party *p)
-{
-    int  i;
-    struct map_session_data *sd;
-
-    nullpo_retr (0, p);
-
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
-        {
-            if (sd->status.party_id == p->party_id)
-            {
-                int  j, f = 1;
-                for (j = 0; j < MAX_PARTY; j++)
-                {               // パーティにデータがあるか確認
-                    if (p->member[j].account_id == sd->status.account_id)
-                    {
-                        if (strcmp (p->member[j].name, sd->status.name) == 0)
-                            f = 0;  // データがある
-                        else
-                            p->member[j].sd = NULL; // 同垢別キャラだった
-                    }
-                }
-                if (f)
-                {
-                    sd->status.party_id = 0;
-                    if (battle_config.error_log)
-                        printf ("party: check_member %d[%s] is not member\n",
-                                sd->status.account_id, sd->status.name);
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-// 情報所得失敗(そのIDのキャラを全部未所属にする)
-int party_recv_noinfo (int party_id)
-{
-    int  i;
-    struct map_session_data *sd;
-    for (i = 0; i < fd_max; i++)
-    {
-        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
-        {
-            if (sd->status.party_id == party_id)
-                sd->status.party_id = 0;
-        }
-    }
-    return 0;
-}
-
-// 情報所得
-int party_recv_info (struct party *sp)
-{
-    struct party *p;
-    int  i;
-
-    nullpo_retr (0, sp);
-
-    if ((p = (struct party *)numdb_search (party_db, sp->party_id)) == NULL)
-    {
-        CREATE (p, struct party, 1);
-        numdb_insert (party_db, sp->party_id, p);
-
-        // 最初のロードなのでユーザーのチェックを行う
-        party_check_member (sp);
-    }
-    memcpy (p, sp, sizeof (struct party));
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // sdの設定
-        struct map_session_data *sd = map_id2sd (p->member[i].account_id);
-        p->member[i].sd = (sd != NULL
-                           && sd->status.party_id == p->party_id) ? sd : NULL;
-    }
-
-    clif_party_info (p, -1);
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // 設定情報の送信
-//      struct map_session_data *sd = map_id2sd(p->member[i].account_id);
-        struct map_session_data *sd = p->member[i].sd;
-        if (sd != NULL && sd->party_sended == 0)
-        {
-            clif_party_option (p, sd, 0x100);
-            sd->party_sended = 1;
-        }
-    }
-
-    return 0;
-}
-
-/* Process party invitation from sd to account_id. */
-int party_invite (struct map_session_data *sd, int account_id)
-{
-    struct map_session_data *tsd = map_id2sd (account_id);
-    struct party *p = party_search (sd->status.party_id);
-    int  i;
-    int  full = 1; /* Indicates whether or not there's room for one more. */
-
-    nullpo_retr (0, sd);
-
-    if (!tsd || !p || !tsd->fd)
-        return 0;
-
-    if (!battle_config.invite_request_check)
-    {
-        /* Disallow the invitation under these conditions. */
-        if (tsd->guild_invite > 0 || tsd->trade_partner || tsd->npc_id
-            || tsd->npc_shopid || pc_checkskill (tsd, NV_PARTY) < 1)
-        {
-            clif_party_inviteack (sd, tsd->status.name, 1);
-            return 0;
-        }
-    }
-
-    /* The target player is already in a party, or has a pending invitation. */
-    if (tsd->status.party_id > 0 || tsd->party_invite > 0)
-    {
-        clif_party_inviteack (sd, tsd->status.name, 0);
-        return 0;
-    }
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        /*
-         * A character from the target account is already in the same party.
-         * The response isn't strictly accurate, as they're separate
-         * characters, but we're making do with what was already in place and
-         * leaving this (mostly) alone for now.
-         */
-        if (p->member[i].account_id == account_id)
-        {
-            clif_party_inviteack (sd, tsd->status.name, 1);
-            return 0;
-        }
-
-        if (!p->member[i].account_id)
-            full = 0;
-    }
-
-    /* There isn't enough room for a new member. */
-    if (full)
-    {
-        clif_party_inviteack (sd, tsd->status.name, 3);
-        return 0;
-    }
-
-    /* Otherwise, relay the invitation to the target player. */
-    tsd->party_invite = sd->status.party_id;
-    tsd->party_invite_account = sd->status.account_id;
-
-    clif_party_invite (sd, tsd);
-    return 0;
-}
-
-/* Process response to party invitation. */
-int party_reply_invite (struct map_session_data *sd, int account_id, int flag)
-{
-    nullpo_retr (0, sd);
-
-    /* There is no pending invitation. */
-    if (!sd->party_invite || !sd->party_invite_account)
-        return 0;
-
-    /*
-     * Only one invitation can be pending, so these have to be the same. Since
-     * the client continues to send the wrong ID, and it's already managed on
-     * this side of things, the sent ID is being ignored.
-     */
-    account_id = sd->party_invite_account;
-
-    /* The invitation was accepted. */
-    if (flag == 1)
-        intif_party_addmember (sd->party_invite, sd->status.account_id);
-    /* The invitation was rejected. */
-    else
-    {
-        /* This is the player who sent the invitation. */
-        struct map_session_data *tsd = NULL;
-
-        sd->party_invite = 0;
-        sd->party_invite_account = 0;
-
-        if ((tsd = map_id2sd (account_id)))
-            clif_party_inviteack (tsd, sd->status.name, 1);
-    }
-    return 0;
-}
-
-// パーティが追加された
-int party_member_added (int party_id, int account_id, int flag)
-{
-    struct map_session_data *sd = map_id2sd (account_id), *sd2;
-    struct party *p = party_search (party_id);
-
-    if (sd == NULL)
-    {
-        if (flag == 0)
-        {
-            if (battle_config.error_log)
-                printf ("party: member added error %d is not online\n",
-                        account_id);
-            intif_party_leave (party_id, account_id);   // キャラ側に登録できなかったため脱退要求を出す
-        }
-        return 0;
-    }
-    sd2 = map_id2sd (sd->party_invite_account);
-    sd->party_invite = 0;
-    sd->party_invite_account = 0;
-
-    if (p == NULL)
-    {
-        printf ("party_member_added: party %d not found.\n", party_id);
-        intif_party_leave (party_id, account_id);
-        return 0;
-    }
-
-    if (flag == 1)
-    {                           // 失敗
-        if (sd2 != NULL)
-            clif_party_inviteack (sd2, sd->status.name, 0);
-        return 0;
-    }
-
-    // 成功
-    sd->party_sended = 0;
-    sd->status.party_id = party_id;
-
-    if (sd2 != NULL)
-        clif_party_inviteack (sd2, sd->status.name, 2);
-
-    // いちおう競合確認
-    party_check_conflict (sd);
-
-    party_send_xy_clear (p);
-
-    return 0;
-}
-
-// パーティ除名要求
-int party_removemember (struct map_session_data *sd, int account_id,
-                        char *name)
-{
-    struct party *p;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if ((p = party_search (sd->status.party_id)) == NULL)
-        return 0;
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // リーダーかどうかチェック
-        if (p->member[i].account_id == sd->status.account_id)
-            if (p->member[i].leader == 0)
-                return 0;
-    }
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // 所属しているか調べる
-        if (p->member[i].account_id == account_id)
-        {
-            intif_party_leave (p->party_id, account_id);
-            return 0;
-        }
-    }
-    return 0;
-}
-
-// パーティ脱退要求
-int party_leave (struct map_session_data *sd)
-{
-    struct party *p;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if ((p = party_search (sd->status.party_id)) == NULL)
-        return 0;
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // 所属しているか
-        if (p->member[i].account_id == sd->status.account_id)
-        {
-            intif_party_leave (p->party_id, sd->status.account_id);
-            return 0;
-        }
-    }
-    return 0;
-}
-
-// パーティメンバが脱退した
-int party_member_leaved (int party_id, int account_id, char *name)
-{
-    struct map_session_data *sd = map_id2sd (account_id);
-    struct party *p = party_search (party_id);
-    if (p != NULL)
-    {
-        int  i;
-        for (i = 0; i < MAX_PARTY; i++)
-            if (p->member[i].account_id == account_id)
-            {
-                clif_party_leaved (p, sd, account_id, name, 0x00);
-                p->member[i].account_id = 0;
-                p->member[i].sd = NULL;
-            }
-    }
-    if (sd != NULL && sd->status.party_id == party_id)
-    {
-        sd->status.party_id = 0;
-        sd->party_sended = 0;
-    }
-    return 0;
-}
-
-// パーティ解散通知
-int party_broken (int party_id)
-{
-    struct party *p;
-    int  i;
-    if ((p = party_search (party_id)) == NULL)
-        return 0;
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        if (p->member[i].sd != NULL)
-        {
-            clif_party_leaved (p, p->member[i].sd,
-                               p->member[i].account_id, p->member[i].name,
-                               0x10);
-            p->member[i].sd->status.party_id = 0;
-            p->member[i].sd->party_sended = 0;
-        }
-    }
-    numdb_erase (party_db, party_id);
-    return 0;
-}
-
-// パーティの設定変更要求
-int party_changeoption (struct map_session_data *sd, int exp, int item)
-{
-    struct party *p;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.party_id == 0
-        || (p = party_search (sd->status.party_id)) == NULL)
-        return 0;
-    intif_party_changeoption (sd->status.party_id, sd->status.account_id, exp,
-                              item);
-    return 0;
-}
-
-// パーティの設定変更通知
-int party_optionchanged (int party_id, int account_id, int exp, int item,
-                         int flag)
-{
-    struct party *p;
-    struct map_session_data *sd = map_id2sd (account_id);
-    if ((p = party_search (party_id)) == NULL)
-        return 0;
-
-    if (!(flag & 0x01))
-        p->exp = exp;
-    if (!(flag & 0x10))
-        p->item = item;
-    clif_party_option (p, sd, flag);
-    return 0;
-}
-
-// パーティメンバの移動通知
-int party_recv_movemap (int party_id, int account_id, char *map, int online,
-                        int lv)
-{
-    struct party *p;
-    int  i;
-    if ((p = party_search (party_id)) == NULL)
-        return 0;
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct party_member *m = &p->member[i];
-        if (m == NULL)
-        {
-            printf ("party_recv_movemap nullpo?\n");
-            return 0;
-        }
-        if (m->account_id == account_id)
-        {
-            memcpy (m->map, map, 16);
-            m->online = online;
-            m->lv = lv;
-            break;
-        }
-    }
-    if (i == MAX_PARTY)
-    {
-        if (battle_config.error_log)
-            printf ("party: not found member %d on %d[%s]", account_id,
-                    party_id, p->name);
-        return 0;
-    }
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {                           // sd再設定
-        struct map_session_data *sd = map_id2sd (p->member[i].account_id);
-        p->member[i].sd = (sd != NULL
-                           && sd->status.party_id == p->party_id) ? sd : NULL;
-    }
-
-    party_send_xy_clear (p);    // 座標再通知要請
-
-    clif_party_info (p, -1);
-    return 0;
-}
-
-// パーティメンバの移動
-int party_send_movemap (struct map_session_data *sd)
-{
-    struct party *p;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.party_id == 0)
-        return 0;
-    intif_party_changemap (sd, 1);
-
-    if (sd->party_sended != 0)  // もうパーティデータは送信済み
-        return 0;
-
-    // 競合確認
-    party_check_conflict (sd);
-
-    // あるならパーティ情報送信
-    if ((p = party_search (sd->status.party_id)) != NULL)
-    {
-        party_check_member (p); // 所属を確認する
-        if (sd->status.party_id == p->party_id)
-        {
-            clif_party_info (p, sd->fd);
-            clif_party_option (p, sd, 0x100);
-            sd->party_sended = 1;
-        }
-    }
-
-    return 0;
-}
-
-// パーティメンバのログアウト
-int party_send_logout (struct map_session_data *sd)
-{
-    struct party *p;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.party_id > 0)
-        intif_party_changemap (sd, 0);
-
-    // sdが無効になるのでパーティ情報から削除
-    if ((p = party_search (sd->status.party_id)) != NULL)
-    {
-        int  i;
-        for (i = 0; i < MAX_PARTY; i++)
-            if (p->member[i].sd == sd)
-                p->member[i].sd = NULL;
-    }
-
-    return 0;
-}
-
-// パーティメッセージ送信
-int party_send_message (struct map_session_data *sd, char *mes, int len)
-{
-    if (sd->status.party_id == 0)
-        return 0;
-    intif_party_message (sd->status.party_id, sd->status.account_id, mes,
-                         len);
-    return 0;
-}
-
-// パーティメッセージ受信
-int party_recv_message (int party_id, int account_id, char *mes, int len)
-{
-    struct party *p;
-    if ((p = party_search (party_id)) == NULL)
-        return 0;
-    clif_party_message (p, account_id, mes, len);
-    return 0;
-}
-
-// パーティ競合確認
-int party_check_conflict (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    intif_party_checkconflict (sd->status.party_id, sd->status.account_id,
-                               sd->status.name);
-    return 0;
-}
-
-// 位置やHP通知用
-void party_send_xyhp_timer_sub (db_key_t key, db_val_t data, va_list ap)
-{
-    struct party *p = (struct party *) data;
-    int  i;
-
-    nullpo_retv (p);
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct map_session_data *sd;
-        if ((sd = p->member[i].sd) != NULL)
-        {
-            // 座標通知
-            if (sd->party_x != sd->bl.x || sd->party_y != sd->bl.y)
-            {
-                clif_party_xy (p, sd);
-                sd->party_x = sd->bl.x;
-                sd->party_y = sd->bl.y;
-            }
-            // HP通知
-            if (sd->party_hp != sd->status.hp)
-            {
-                clif_party_hp (p, sd);
-                sd->party_hp = sd->status.hp;
-            }
-
-        }
-    }
-}
-
-// 位置やHP通知
-void party_send_xyhp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    numdb_foreach (party_db, party_send_xyhp_timer_sub, tick);
-}
-
-// 位置通知クリア
-int party_send_xy_clear (struct party *p)
-{
-    int  i;
-
-    nullpo_retr (0, p);
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct map_session_data *sd;
-        if ((sd = p->member[i].sd) != NULL)
-        {
-            sd->party_x = -1;
-            sd->party_y = -1;
-            sd->party_hp = -1;
-        }
-    }
-    return 0;
-}
-
-// HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる)
-int party_send_hp_check (struct block_list *bl, va_list ap)
-{
-    int  party_id;
-    int *flag;
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = (struct map_session_data *) bl);
-
-    party_id = va_arg (ap, int);
-    flag = va_arg (ap, int *);
-
-    if (sd->status.party_id == party_id)
-    {
-        *flag = 1;
-        sd->party_hp = -1;
-    }
-    return 0;
-}
-
-// 経験値公平分配
-int party_exp_share (struct party *p, int map, int base_exp, int job_exp)
-{
-    struct map_session_data *sd;
-    int  i, c;
-
-    nullpo_retr (0, p);
-
-    for (i = c = 0; i < MAX_PARTY; i++)
-        if ((sd = p->member[i].sd) != NULL && sd->bl.m == map)
-            c++;
-    if (c == 0)
-        return 0;
-    for (i = 0; i < MAX_PARTY; i++)
-        if ((sd = p->member[i].sd) != NULL && sd->bl.m == map)
-            pc_gainexp (sd, base_exp / c + 1, job_exp / c + 1);
-    return 0;
-}
-
-// 同じマップのパーティメンバー全体に処理をかける
-// type==0 同じマップ
-//     !=0 画面内
-void party_foreachsamemap (int (*func) (struct block_list *, va_list),
-                           struct map_session_data *sd, int type, ...)
-{
-    struct party *p;
-    va_list ap;
-    int  i;
-    int  x0, y0, x1, y1;
-    struct block_list *list[MAX_PARTY];
-    int  blockcount = 0;
-
-    nullpo_retv (sd);
-
-    if ((p = party_search (sd->status.party_id)) == NULL)
-        return;
-
-    x0 = sd->bl.x - AREA_SIZE;
-    y0 = sd->bl.y - AREA_SIZE;
-    x1 = sd->bl.x + AREA_SIZE;
-    y1 = sd->bl.y + AREA_SIZE;
-
-    va_start (ap, type);
-
-    for (i = 0; i < MAX_PARTY; i++)
-    {
-        struct party_member *m = &p->member[i];
-        if (m->sd != NULL)
-        {
-            if (sd->bl.m != m->sd->bl.m)
-                continue;
-            if (type != 0 &&
-                (m->sd->bl.x < x0 || m->sd->bl.y < y0 ||
-                 m->sd->bl.x > x1 || m->sd->bl.y > y1))
-                continue;
-            list[blockcount++] = &m->sd->bl;
-        }
-    }
-
-    map_freeblock_lock ();      // メモリからの解放を禁止する
-
-    for (i = 0; i < blockcount; i++)
-        if (list[i]->prev)      // 有効かどうかチェック
-            func (list[i], ap);
-
-    map_freeblock_unlock ();    // 解放を許可する
-
-    va_end (ap);
-}
diff --git a/src/map/party.cpp b/src/map/party.cpp
new file mode 100644
index 0000000..1c4088a
--- /dev/null
+++ b/src/map/party.cpp
@@ -0,0 +1,790 @@
+// $Id: party.c,v 1.2 2004/09/22 02:59:47 Akitasha Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "party.hpp"
+#include "../common/db.hpp"
+#include "../common/timer.hpp"
+#include "../common/socket.hpp"
+#include "../common/nullpo.hpp"
+#include "pc.hpp"
+#include "map.hpp"
+#include "battle.hpp"
+#include "intif.hpp"
+#include "clif.hpp"
+#include "skill.hpp"
+#include "tmw.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define PARTY_SEND_XYHP_INVERVAL	1000    // 座標やHP送信の間隔
+
+static struct dbt *party_db;
+
+void party_send_xyhp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data);
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+static void party_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+void do_final_party (void)
+{
+    if (party_db)
+        numdb_final (party_db, party_db_final);
+}
+
+// 初期化
+void do_init_party (void)
+{
+    party_db = numdb_init ();
+    add_timer_interval (gettick () + PARTY_SEND_XYHP_INVERVAL,
+                        party_send_xyhp_timer, 0, 0,
+                        PARTY_SEND_XYHP_INVERVAL);
+}
+
+// 検索
+struct party *party_search (int party_id)
+{
+    return (struct party *)numdb_search (party_db, party_id);
+}
+
+void party_searchname_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct party *p = (struct party *) data, **dst;
+    char *str;
+    str = va_arg (ap, char *);
+    dst = va_arg (ap, struct party **);
+    if (strcasecmp (p->name, str) == 0)
+        *dst = p;
+}
+
+// パーティ名検索
+struct party *party_searchname (char *str)
+{
+    struct party *p = NULL;
+    numdb_foreach (party_db, party_searchname_sub, str, &p);
+    return p;
+}
+
+/* Process a party creation request. */
+int party_create (struct map_session_data *sd, char *name)
+{
+    char pname[24];
+    nullpo_retr (0, sd);
+
+    strncpy (pname, name, 24);
+    pname[23] = '\0';
+    tmw_TrimStr (pname);
+
+    /* The party name is empty/invalid. */
+    if (!*pname)
+        clif_party_created (sd, 1);
+
+    /* Make sure the character isn't already in a party. */
+    if (sd->status.party_id == 0)
+        intif_create_party (sd, pname);
+    else
+        clif_party_created (sd, 2);
+
+    return 0;
+}
+
+/* Relay the result of a party creation request. */
+int party_created (int account_id, int fail, int party_id, char *name)
+{
+    struct map_session_data *sd;
+    sd = map_id2sd (account_id);
+
+    nullpo_retr (0, sd);
+
+    /* The party name is valid and not already taken. */
+    if (!fail)
+    {
+        struct party *p;
+        sd->status.party_id = party_id;
+
+        if ((p = (struct party *)numdb_search (party_db, party_id)) != NULL)
+        {
+            printf ("party_created(): ID already exists!\n");
+            exit (1);
+        }
+
+        CREATE (p, struct party, 1);
+        p->party_id = party_id;
+        memcpy (p->name, name, 24);
+        numdb_insert (party_db, party_id, p);
+
+        /* The party was created successfully. */
+        clif_party_created (sd, 0);
+    }
+
+    else
+        clif_party_created (sd, 1);
+
+    return 0;
+}
+
+// 情報要求
+int party_request_info (int party_id)
+{
+    return intif_request_partyinfo (party_id);
+}
+
+// 所属キャラの確認
+int party_check_member (struct party *p)
+{
+    int  i;
+    struct map_session_data *sd;
+
+    nullpo_retr (0, p);
+
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
+        {
+            if (sd->status.party_id == p->party_id)
+            {
+                int  j, f = 1;
+                for (j = 0; j < MAX_PARTY; j++)
+                {               // パーティにデータがあるか確認
+                    if (p->member[j].account_id == sd->status.account_id)
+                    {
+                        if (strcmp (p->member[j].name, sd->status.name) == 0)
+                            f = 0;  // データがある
+                        else
+                            p->member[j].sd = NULL; // 同垢別キャラだった
+                    }
+                }
+                if (f)
+                {
+                    sd->status.party_id = 0;
+                    if (battle_config.error_log)
+                        printf ("party: check_member %d[%s] is not member\n",
+                                sd->status.account_id, sd->status.name);
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+// 情報所得失敗(そのIDのキャラを全部未所属にする)
+int party_recv_noinfo (int party_id)
+{
+    int  i;
+    struct map_session_data *sd;
+    for (i = 0; i < fd_max; i++)
+    {
+        if (session[i] && (sd = (struct map_session_data *)session[i]->session_data) && sd->state.auth)
+        {
+            if (sd->status.party_id == party_id)
+                sd->status.party_id = 0;
+        }
+    }
+    return 0;
+}
+
+// 情報所得
+int party_recv_info (struct party *sp)
+{
+    struct party *p;
+    int  i;
+
+    nullpo_retr (0, sp);
+
+    if ((p = (struct party *)numdb_search (party_db, sp->party_id)) == NULL)
+    {
+        CREATE (p, struct party, 1);
+        numdb_insert (party_db, sp->party_id, p);
+
+        // 最初のロードなのでユーザーのチェックを行う
+        party_check_member (sp);
+    }
+    memcpy (p, sp, sizeof (struct party));
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // sdの設定
+        struct map_session_data *sd = map_id2sd (p->member[i].account_id);
+        p->member[i].sd = (sd != NULL
+                           && sd->status.party_id == p->party_id) ? sd : NULL;
+    }
+
+    clif_party_info (p, -1);
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // 設定情報の送信
+//      struct map_session_data *sd = map_id2sd(p->member[i].account_id);
+        struct map_session_data *sd = p->member[i].sd;
+        if (sd != NULL && sd->party_sended == 0)
+        {
+            clif_party_option (p, sd, 0x100);
+            sd->party_sended = 1;
+        }
+    }
+
+    return 0;
+}
+
+/* Process party invitation from sd to account_id. */
+int party_invite (struct map_session_data *sd, int account_id)
+{
+    struct map_session_data *tsd = map_id2sd (account_id);
+    struct party *p = party_search (sd->status.party_id);
+    int  i;
+    int  full = 1; /* Indicates whether or not there's room for one more. */
+
+    nullpo_retr (0, sd);
+
+    if (!tsd || !p || !tsd->fd)
+        return 0;
+
+    if (!battle_config.invite_request_check)
+    {
+        /* Disallow the invitation under these conditions. */
+        if (tsd->guild_invite > 0 || tsd->trade_partner || tsd->npc_id
+            || tsd->npc_shopid || pc_checkskill (tsd, NV_PARTY) < 1)
+        {
+            clif_party_inviteack (sd, tsd->status.name, 1);
+            return 0;
+        }
+    }
+
+    /* The target player is already in a party, or has a pending invitation. */
+    if (tsd->status.party_id > 0 || tsd->party_invite > 0)
+    {
+        clif_party_inviteack (sd, tsd->status.name, 0);
+        return 0;
+    }
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        /*
+         * A character from the target account is already in the same party.
+         * The response isn't strictly accurate, as they're separate
+         * characters, but we're making do with what was already in place and
+         * leaving this (mostly) alone for now.
+         */
+        if (p->member[i].account_id == account_id)
+        {
+            clif_party_inviteack (sd, tsd->status.name, 1);
+            return 0;
+        }
+
+        if (!p->member[i].account_id)
+            full = 0;
+    }
+
+    /* There isn't enough room for a new member. */
+    if (full)
+    {
+        clif_party_inviteack (sd, tsd->status.name, 3);
+        return 0;
+    }
+
+    /* Otherwise, relay the invitation to the target player. */
+    tsd->party_invite = sd->status.party_id;
+    tsd->party_invite_account = sd->status.account_id;
+
+    clif_party_invite (sd, tsd);
+    return 0;
+}
+
+/* Process response to party invitation. */
+int party_reply_invite (struct map_session_data *sd, int account_id, int flag)
+{
+    nullpo_retr (0, sd);
+
+    /* There is no pending invitation. */
+    if (!sd->party_invite || !sd->party_invite_account)
+        return 0;
+
+    /*
+     * Only one invitation can be pending, so these have to be the same. Since
+     * the client continues to send the wrong ID, and it's already managed on
+     * this side of things, the sent ID is being ignored.
+     */
+    account_id = sd->party_invite_account;
+
+    /* The invitation was accepted. */
+    if (flag == 1)
+        intif_party_addmember (sd->party_invite, sd->status.account_id);
+    /* The invitation was rejected. */
+    else
+    {
+        /* This is the player who sent the invitation. */
+        struct map_session_data *tsd = NULL;
+
+        sd->party_invite = 0;
+        sd->party_invite_account = 0;
+
+        if ((tsd = map_id2sd (account_id)))
+            clif_party_inviteack (tsd, sd->status.name, 1);
+    }
+    return 0;
+}
+
+// パーティが追加された
+int party_member_added (int party_id, int account_id, int flag)
+{
+    struct map_session_data *sd = map_id2sd (account_id), *sd2;
+    struct party *p = party_search (party_id);
+
+    if (sd == NULL)
+    {
+        if (flag == 0)
+        {
+            if (battle_config.error_log)
+                printf ("party: member added error %d is not online\n",
+                        account_id);
+            intif_party_leave (party_id, account_id);   // キャラ側に登録できなかったため脱退要求を出す
+        }
+        return 0;
+    }
+    sd2 = map_id2sd (sd->party_invite_account);
+    sd->party_invite = 0;
+    sd->party_invite_account = 0;
+
+    if (p == NULL)
+    {
+        printf ("party_member_added: party %d not found.\n", party_id);
+        intif_party_leave (party_id, account_id);
+        return 0;
+    }
+
+    if (flag == 1)
+    {                           // 失敗
+        if (sd2 != NULL)
+            clif_party_inviteack (sd2, sd->status.name, 0);
+        return 0;
+    }
+
+    // 成功
+    sd->party_sended = 0;
+    sd->status.party_id = party_id;
+
+    if (sd2 != NULL)
+        clif_party_inviteack (sd2, sd->status.name, 2);
+
+    // いちおう競合確認
+    party_check_conflict (sd);
+
+    party_send_xy_clear (p);
+
+    return 0;
+}
+
+// パーティ除名要求
+int party_removemember (struct map_session_data *sd, int account_id,
+                        char *name)
+{
+    struct party *p;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if ((p = party_search (sd->status.party_id)) == NULL)
+        return 0;
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // リーダーかどうかチェック
+        if (p->member[i].account_id == sd->status.account_id)
+            if (p->member[i].leader == 0)
+                return 0;
+    }
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // 所属しているか調べる
+        if (p->member[i].account_id == account_id)
+        {
+            intif_party_leave (p->party_id, account_id);
+            return 0;
+        }
+    }
+    return 0;
+}
+
+// パーティ脱退要求
+int party_leave (struct map_session_data *sd)
+{
+    struct party *p;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if ((p = party_search (sd->status.party_id)) == NULL)
+        return 0;
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // 所属しているか
+        if (p->member[i].account_id == sd->status.account_id)
+        {
+            intif_party_leave (p->party_id, sd->status.account_id);
+            return 0;
+        }
+    }
+    return 0;
+}
+
+// パーティメンバが脱退した
+int party_member_leaved (int party_id, int account_id, char *name)
+{
+    struct map_session_data *sd = map_id2sd (account_id);
+    struct party *p = party_search (party_id);
+    if (p != NULL)
+    {
+        int  i;
+        for (i = 0; i < MAX_PARTY; i++)
+            if (p->member[i].account_id == account_id)
+            {
+                clif_party_leaved (p, sd, account_id, name, 0x00);
+                p->member[i].account_id = 0;
+                p->member[i].sd = NULL;
+            }
+    }
+    if (sd != NULL && sd->status.party_id == party_id)
+    {
+        sd->status.party_id = 0;
+        sd->party_sended = 0;
+    }
+    return 0;
+}
+
+// パーティ解散通知
+int party_broken (int party_id)
+{
+    struct party *p;
+    int  i;
+    if ((p = party_search (party_id)) == NULL)
+        return 0;
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        if (p->member[i].sd != NULL)
+        {
+            clif_party_leaved (p, p->member[i].sd,
+                               p->member[i].account_id, p->member[i].name,
+                               0x10);
+            p->member[i].sd->status.party_id = 0;
+            p->member[i].sd->party_sended = 0;
+        }
+    }
+    numdb_erase (party_db, party_id);
+    return 0;
+}
+
+// パーティの設定変更要求
+int party_changeoption (struct map_session_data *sd, int exp, int item)
+{
+    struct party *p;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.party_id == 0
+        || (p = party_search (sd->status.party_id)) == NULL)
+        return 0;
+    intif_party_changeoption (sd->status.party_id, sd->status.account_id, exp,
+                              item);
+    return 0;
+}
+
+// パーティの設定変更通知
+int party_optionchanged (int party_id, int account_id, int exp, int item,
+                         int flag)
+{
+    struct party *p;
+    struct map_session_data *sd = map_id2sd (account_id);
+    if ((p = party_search (party_id)) == NULL)
+        return 0;
+
+    if (!(flag & 0x01))
+        p->exp = exp;
+    if (!(flag & 0x10))
+        p->item = item;
+    clif_party_option (p, sd, flag);
+    return 0;
+}
+
+// パーティメンバの移動通知
+int party_recv_movemap (int party_id, int account_id, char *map, int online,
+                        int lv)
+{
+    struct party *p;
+    int  i;
+    if ((p = party_search (party_id)) == NULL)
+        return 0;
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct party_member *m = &p->member[i];
+        if (m == NULL)
+        {
+            printf ("party_recv_movemap nullpo?\n");
+            return 0;
+        }
+        if (m->account_id == account_id)
+        {
+            memcpy (m->map, map, 16);
+            m->online = online;
+            m->lv = lv;
+            break;
+        }
+    }
+    if (i == MAX_PARTY)
+    {
+        if (battle_config.error_log)
+            printf ("party: not found member %d on %d[%s]", account_id,
+                    party_id, p->name);
+        return 0;
+    }
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {                           // sd再設定
+        struct map_session_data *sd = map_id2sd (p->member[i].account_id);
+        p->member[i].sd = (sd != NULL
+                           && sd->status.party_id == p->party_id) ? sd : NULL;
+    }
+
+    party_send_xy_clear (p);    // 座標再通知要請
+
+    clif_party_info (p, -1);
+    return 0;
+}
+
+// パーティメンバの移動
+int party_send_movemap (struct map_session_data *sd)
+{
+    struct party *p;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.party_id == 0)
+        return 0;
+    intif_party_changemap (sd, 1);
+
+    if (sd->party_sended != 0)  // もうパーティデータは送信済み
+        return 0;
+
+    // 競合確認
+    party_check_conflict (sd);
+
+    // あるならパーティ情報送信
+    if ((p = party_search (sd->status.party_id)) != NULL)
+    {
+        party_check_member (p); // 所属を確認する
+        if (sd->status.party_id == p->party_id)
+        {
+            clif_party_info (p, sd->fd);
+            clif_party_option (p, sd, 0x100);
+            sd->party_sended = 1;
+        }
+    }
+
+    return 0;
+}
+
+// パーティメンバのログアウト
+int party_send_logout (struct map_session_data *sd)
+{
+    struct party *p;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.party_id > 0)
+        intif_party_changemap (sd, 0);
+
+    // sdが無効になるのでパーティ情報から削除
+    if ((p = party_search (sd->status.party_id)) != NULL)
+    {
+        int  i;
+        for (i = 0; i < MAX_PARTY; i++)
+            if (p->member[i].sd == sd)
+                p->member[i].sd = NULL;
+    }
+
+    return 0;
+}
+
+// パーティメッセージ送信
+int party_send_message (struct map_session_data *sd, char *mes, int len)
+{
+    if (sd->status.party_id == 0)
+        return 0;
+    intif_party_message (sd->status.party_id, sd->status.account_id, mes,
+                         len);
+    return 0;
+}
+
+// パーティメッセージ受信
+int party_recv_message (int party_id, int account_id, char *mes, int len)
+{
+    struct party *p;
+    if ((p = party_search (party_id)) == NULL)
+        return 0;
+    clif_party_message (p, account_id, mes, len);
+    return 0;
+}
+
+// パーティ競合確認
+int party_check_conflict (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    intif_party_checkconflict (sd->status.party_id, sd->status.account_id,
+                               sd->status.name);
+    return 0;
+}
+
+// 位置やHP通知用
+void party_send_xyhp_timer_sub (db_key_t key, db_val_t data, va_list ap)
+{
+    struct party *p = (struct party *) data;
+    int  i;
+
+    nullpo_retv (p);
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct map_session_data *sd;
+        if ((sd = p->member[i].sd) != NULL)
+        {
+            // 座標通知
+            if (sd->party_x != sd->bl.x || sd->party_y != sd->bl.y)
+            {
+                clif_party_xy (p, sd);
+                sd->party_x = sd->bl.x;
+                sd->party_y = sd->bl.y;
+            }
+            // HP通知
+            if (sd->party_hp != sd->status.hp)
+            {
+                clif_party_hp (p, sd);
+                sd->party_hp = sd->status.hp;
+            }
+
+        }
+    }
+}
+
+// 位置やHP通知
+void party_send_xyhp_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    numdb_foreach (party_db, party_send_xyhp_timer_sub, tick);
+}
+
+// 位置通知クリア
+int party_send_xy_clear (struct party *p)
+{
+    int  i;
+
+    nullpo_retr (0, p);
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct map_session_data *sd;
+        if ((sd = p->member[i].sd) != NULL)
+        {
+            sd->party_x = -1;
+            sd->party_y = -1;
+            sd->party_hp = -1;
+        }
+    }
+    return 0;
+}
+
+// HP通知の必要性検査用(map_foreachinmoveareaから呼ばれる)
+int party_send_hp_check (struct block_list *bl, va_list ap)
+{
+    int  party_id;
+    int *flag;
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = (struct map_session_data *) bl);
+
+    party_id = va_arg (ap, int);
+    flag = va_arg (ap, int *);
+
+    if (sd->status.party_id == party_id)
+    {
+        *flag = 1;
+        sd->party_hp = -1;
+    }
+    return 0;
+}
+
+// 経験値公平分配
+int party_exp_share (struct party *p, int map, int base_exp, int job_exp)
+{
+    struct map_session_data *sd;
+    int  i, c;
+
+    nullpo_retr (0, p);
+
+    for (i = c = 0; i < MAX_PARTY; i++)
+        if ((sd = p->member[i].sd) != NULL && sd->bl.m == map)
+            c++;
+    if (c == 0)
+        return 0;
+    for (i = 0; i < MAX_PARTY; i++)
+        if ((sd = p->member[i].sd) != NULL && sd->bl.m == map)
+            pc_gainexp (sd, base_exp / c + 1, job_exp / c + 1);
+    return 0;
+}
+
+// 同じマップのパーティメンバー全体に処理をかける
+// type==0 同じマップ
+//     !=0 画面内
+void party_foreachsamemap (int (*func) (struct block_list *, va_list),
+                           struct map_session_data *sd, int type, ...)
+{
+    struct party *p;
+    va_list ap;
+    int  i;
+    int  x0, y0, x1, y1;
+    struct block_list *list[MAX_PARTY];
+    int  blockcount = 0;
+
+    nullpo_retv (sd);
+
+    if ((p = party_search (sd->status.party_id)) == NULL)
+        return;
+
+    x0 = sd->bl.x - AREA_SIZE;
+    y0 = sd->bl.y - AREA_SIZE;
+    x1 = sd->bl.x + AREA_SIZE;
+    y1 = sd->bl.y + AREA_SIZE;
+
+    va_start (ap, type);
+
+    for (i = 0; i < MAX_PARTY; i++)
+    {
+        struct party_member *m = &p->member[i];
+        if (m->sd != NULL)
+        {
+            if (sd->bl.m != m->sd->bl.m)
+                continue;
+            if (type != 0 &&
+                (m->sd->bl.x < x0 || m->sd->bl.y < y0 ||
+                 m->sd->bl.x > x1 || m->sd->bl.y > y1))
+                continue;
+            list[blockcount++] = &m->sd->bl;
+        }
+    }
+
+    map_freeblock_lock ();      // メモリからの解放を禁止する
+
+    for (i = 0; i < blockcount; i++)
+        if (list[i]->prev)      // 有効かどうかチェック
+            func (list[i], ap);
+
+    map_freeblock_unlock ();    // 解放を許可する
+
+    va_end (ap);
+}
diff --git a/src/map/party.h b/src/map/party.h
deleted file mode 100644
index 2e8bf78..0000000
--- a/src/map/party.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// $Id: party.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
-#ifndef _PARTY_H_
-#define _PARTY_H_
-
-#include <stdarg.h>
-
-struct party;
-struct map_session_data;
-struct block_list;
-
-void do_init_party (void);
-void do_final_party (void);
-struct party *party_search (int party_id);
-struct party *party_searchname (char *str);
-
-int  party_create (struct map_session_data *sd, char *name);
-int  party_created (int account_id, int fail, int party_id, char *name);
-int  party_request_info (int party_id);
-int  party_invite (struct map_session_data *sd, int account_id);
-int  party_member_added (int party_id, int account_id, int flag);
-int  party_leave (struct map_session_data *sd);
-int  party_removemember (struct map_session_data *sd, int account_id,
-                         char *name);
-int  party_member_leaved (int party_id, int account_id, char *name);
-int  party_reply_invite (struct map_session_data *sd, int account_id,
-                         int flag);
-int  party_recv_noinfo (int party_id);
-int  party_recv_info (struct party *sp);
-int  party_recv_movemap (int party_id, int account_id, char *map, int online,
-                         int lv);
-int  party_broken (int party_id);
-int  party_optionchanged (int party_id, int account_id, int exp, int item,
-                          int flag);
-int  party_changeoption (struct map_session_data *sd, int exp, int item);
-
-int  party_send_movemap (struct map_session_data *sd);
-int  party_send_logout (struct map_session_data *sd);
-
-int  party_send_message (struct map_session_data *sd, char *mes, int len);
-int  party_recv_message (int party_id, int account_id, char *mes, int len);
-
-int  party_check_conflict (struct map_session_data *sd);
-
-int  party_send_xy_clear (struct party *p);
-int  party_send_hp_check (struct block_list *bl, va_list ap);
-
-int  party_exp_share (struct party *p, int map, int base_exp, int job_exp);
-
-void party_foreachsamemap (int (*func) (struct block_list *, va_list),
-                           struct map_session_data *sd, int type, ...);
-
-#endif
diff --git a/src/map/party.hpp b/src/map/party.hpp
new file mode 100644
index 0000000..e40609a
--- /dev/null
+++ b/src/map/party.hpp
@@ -0,0 +1,52 @@
+// $Id: party.h,v 1.3 2004/09/25 05:32:18 MouseJstr Exp $
+#ifndef PARTY_HPP
+#define PARTY_HPP
+
+#include <stdarg.h>
+
+struct party;
+struct map_session_data;
+struct block_list;
+
+void do_init_party (void);
+void do_final_party (void);
+struct party *party_search (int party_id);
+struct party *party_searchname (char *str);
+
+int  party_create (struct map_session_data *sd, char *name);
+int  party_created (int account_id, int fail, int party_id, char *name);
+int  party_request_info (int party_id);
+int  party_invite (struct map_session_data *sd, int account_id);
+int  party_member_added (int party_id, int account_id, int flag);
+int  party_leave (struct map_session_data *sd);
+int  party_removemember (struct map_session_data *sd, int account_id,
+                         char *name);
+int  party_member_leaved (int party_id, int account_id, char *name);
+int  party_reply_invite (struct map_session_data *sd, int account_id,
+                         int flag);
+int  party_recv_noinfo (int party_id);
+int  party_recv_info (struct party *sp);
+int  party_recv_movemap (int party_id, int account_id, char *map, int online,
+                         int lv);
+int  party_broken (int party_id);
+int  party_optionchanged (int party_id, int account_id, int exp, int item,
+                          int flag);
+int  party_changeoption (struct map_session_data *sd, int exp, int item);
+
+int  party_send_movemap (struct map_session_data *sd);
+int  party_send_logout (struct map_session_data *sd);
+
+int  party_send_message (struct map_session_data *sd, char *mes, int len);
+int  party_recv_message (int party_id, int account_id, char *mes, int len);
+
+int  party_check_conflict (struct map_session_data *sd);
+
+int  party_send_xy_clear (struct party *p);
+int  party_send_hp_check (struct block_list *bl, va_list ap);
+
+int  party_exp_share (struct party *p, int map, int base_exp, int job_exp);
+
+void party_foreachsamemap (int (*func) (struct block_list *, va_list),
+                           struct map_session_data *sd, int type, ...);
+
+#endif
diff --git a/src/map/path.c b/src/map/path.c
deleted file mode 100644
index 7a864ed..0000000
--- a/src/map/path.c
+++ /dev/null
@@ -1,445 +0,0 @@
-// $Id: path.c,v 1.1.1.1 2004/09/10 17:27:00 MagicalTux Exp $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "map.h"
-#include "battle.h"
-#include "../common/nullpo.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-//#define PATH_STANDALONETEST
-
-#define MAX_HEAP 150
-struct tmp_path
-{
-    short x, y, dist, before, cost;
-    char dir, flag;
-};
-#define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1))
-
-/*==========================================
- * 経路探索補助heap push
- *------------------------------------------
- */
-static void push_heap_path (int *heap, struct tmp_path *tp, int index)
-{
-    int  i, h;
-
-    if (heap == NULL || tp == NULL)
-    {
-        printf ("push_heap_path nullpo\n");
-        return;
-    }
-
-    heap[0]++;
-
-    for (h = heap[0] - 1, i = (h - 1) / 2;
-         h > 0 && tp[index].cost < tp[heap[i + 1]].cost; i = (h - 1) / 2)
-        heap[h + 1] = heap[i + 1], h = i;
-    heap[h + 1] = index;
-}
-
-/*==========================================
- * 経路探索補助heap update
- * costが減ったので根の方へ移動
- *------------------------------------------
- */
-static void update_heap_path (int *heap, struct tmp_path *tp, int index)
-{
-    int  i, h;
-
-    nullpo_retv (heap);
-    nullpo_retv (tp);
-
-    for (h = 0; h < heap[0]; h++)
-        if (heap[h + 1] == index)
-            break;
-    if (h == heap[0])
-    {
-        fprintf (stderr, "update_heap_path bug\n");
-        exit (1);
-    }
-    for (i = (h - 1) / 2;
-         h > 0 && tp[index].cost < tp[heap[i + 1]].cost; i = (h - 1) / 2)
-        heap[h + 1] = heap[i + 1], h = i;
-    heap[h + 1] = index;
-}
-
-/*==========================================
- * 経路探索補助heap pop
- *------------------------------------------
- */
-static int pop_heap_path (int *heap, struct tmp_path *tp)
-{
-    int  i, h, k;
-    int  ret, last;
-
-    nullpo_retr (-1, heap);
-    nullpo_retr (-1, tp);
-
-    if (heap[0] <= 0)
-        return -1;
-    ret = heap[1];
-    last = heap[heap[0]];
-    heap[0]--;
-
-    for (h = 0, k = 2; k < heap[0]; k = k * 2 + 2)
-    {
-        if (tp[heap[k + 1]].cost > tp[heap[k]].cost)
-            k--;
-        heap[h + 1] = heap[k + 1], h = k;
-    }
-    if (k == heap[0])
-        heap[h + 1] = heap[k], h = k - 1;
-
-    for (i = (h - 1) / 2;
-         h > 0 && tp[heap[i + 1]].cost > tp[last].cost; i = (h - 1) / 2)
-        heap[h + 1] = heap[i + 1], h = i;
-    heap[h + 1] = last;
-
-    return ret;
-}
-
-/*==========================================
- * 現在の点のcost計算
- *------------------------------------------
- */
-static int calc_cost (struct tmp_path *p, int x1, int y1)
-{
-    int  xd, yd;
-
-    nullpo_retr (0, p);
-
-    xd = x1 - p->x;
-    if (xd < 0)
-        xd = -xd;
-    yd = y1 - p->y;
-    if (yd < 0)
-        yd = -yd;
-    return (xd + yd) * 10 + p->dist;
-}
-
-/*==========================================
- * 必要ならpathを追加/修正する
- *------------------------------------------
- */
-static int add_path (int *heap, struct tmp_path *tp, int x, int y, int dist,
-                     int dir, int before, int x1, int y1)
-{
-    int  i;
-
-    nullpo_retr (0, heap);
-    nullpo_retr (0, tp);
-
-    i = calc_index (x, y);
-
-    if (tp[i].x == x && tp[i].y == y)
-    {
-        if (tp[i].dist > dist)
-        {
-            tp[i].dist = dist;
-            tp[i].dir = dir;
-            tp[i].before = before;
-            tp[i].cost = calc_cost (&tp[i], x1, y1);
-            if (tp[i].flag)
-                push_heap_path (heap, tp, i);
-            else
-                update_heap_path (heap, tp, i);
-            tp[i].flag = 0;
-        }
-        return 0;
-    }
-
-    if (tp[i].x || tp[i].y)
-        return 1;
-
-    tp[i].x = x;
-    tp[i].y = y;
-    tp[i].dist = dist;
-    tp[i].dir = dir;
-    tp[i].before = before;
-    tp[i].cost = calc_cost (&tp[i], x1, y1);
-    tp[i].flag = 0;
-    push_heap_path (heap, tp, i);
-
-    return 0;
-}
-
-/*==========================================
- * (x,y)が移動不可能地帯かどうか
- * flag 0x10000 遠距離攻撃判定
- *------------------------------------------
- */
-static int can_place (struct map_data *m, int x, int y, int flag)
-{
-    int  c;
-
-    nullpo_retr (0, m);
-
-    c = read_gatp (m, x, y);
-
-    if (c == 1)
-        return 0;
-    if (!(flag & 0x10000) && c == 5)
-        return 0;
-    return 1;
-}
-
-/*==========================================
- * (x0,y0)から(x1,y1)へ1歩で移動可能か計算
- *------------------------------------------
- */
-static int can_move (struct map_data *m, int x0, int y0, int x1, int y1,
-                     int flag)
-{
-    nullpo_retr (0, m);
-
-    if (x0 - x1 < -1 || x0 - x1 > 1 || y0 - y1 < -1 || y0 - y1 > 1)
-        return 0;
-    if (x1 < 0 || y1 < 0 || x1 >= m->xs || y1 >= m->ys)
-        return 0;
-    if (!can_place (m, x0, y0, flag))
-        return 0;
-    if (!can_place (m, x1, y1, flag))
-        return 0;
-    if (x0 == x1 || y0 == y1)
-        return 1;
-    if (!can_place (m, x0, y1, flag) || !can_place (m, x1, y0, flag))
-        return 0;
-    return 1;
-}
-
-/*==========================================
- * (x0,y0)から(dx,dy)方向へcountセル分
- * 吹き飛ばしたあとの座標を所得
- *------------------------------------------
- */
-int path_blownpos (int m, int x0, int y0, int dx, int dy, int count)
-{
-    struct map_data *md;
-
-    if (!map[m].gat)
-        return -1;
-    md = &map[m];
-
-    if (count > 15)
-    {                           // 最大10マスに制限
-        if (battle_config.error_log)
-            printf ("path_blownpos: count too many %d !\n", count);
-        count = 15;
-    }
-    if (dx > 1 || dx < -1 || dy > 1 || dy < -1)
-    {
-        if (battle_config.error_log)
-            printf ("path_blownpos: illeagal dx=%d or dy=%d !\n", dx, dy);
-        dx = (dx >= 0) ? 1 : ((dx < 0) ? -1 : 0);
-        dy = (dy >= 0) ? 1 : ((dy < 0) ? -1 : 0);
-    }
-
-    while ((count--) > 0 && (dx != 0 || dy != 0))
-    {
-        if (!can_move (md, x0, y0, x0 + dx, y0 + dy, 0))
-        {
-            int  fx = (dx != 0 && can_move (md, x0, y0, x0 + dx, y0, 0));
-            int  fy = (dy != 0 && can_move (md, x0, y0, x0, y0 + dy, 0));
-            if (fx && fy)
-            {
-                if (rand () & 1)
-                    dx = 0;
-                else
-                    dy = 0;
-            }
-            if (!fx)
-                dx = 0;
-            if (!fy)
-                dy = 0;
-        }
-        x0 += dx;
-        y0 += dy;
-    }
-    return (x0 << 16) | y0;
-}
-
-/*==========================================
- * path探索 (x0,y0)->(x1,y1)
- *------------------------------------------
- */
-int path_search (struct walkpath_data *wpd, int m, int x0, int y0, int x1,
-                 int y1, int flag)
-{
-    int  heap[MAX_HEAP + 1];
-    struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH];
-    int  i, rp, x, y;
-    struct map_data *md;
-    int  dx, dy;
-
-    nullpo_retr (0, wpd);
-
-    if (!map[m].gat)
-        return -1;
-    md = &map[m];
-    if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys
-        || (i = read_gatp (md, x1, y1)) == 1 || i == 5)
-        return -1;
-
-    // easy
-    dx = (x1 - x0 < 0) ? -1 : 1;
-    dy = (y1 - y0 < 0) ? -1 : 1;
-    for (x = x0, y = y0, i = 0; x != x1 || y != y1;)
-    {
-        if (i >= sizeof (wpd->path))
-            return -1;
-        if (x != x1 && y != y1)
-        {
-            if (!can_move (md, x, y, x + dx, y + dy, flag))
-                break;
-            x += dx;
-            y += dy;
-            wpd->path[i++] =
-                (dx < 0) ? ((dy > 0) ? 1 : 3) : ((dy < 0) ? 5 : 7);
-        }
-        else if (x != x1)
-        {
-            if (!can_move (md, x, y, x + dx, y, flag))
-                break;
-            x += dx;
-            wpd->path[i++] = (dx < 0) ? 2 : 6;
-        }
-        else
-        {                       // y!=y1
-            if (!can_move (md, x, y, x, y + dy, flag))
-                break;
-            y += dy;
-            wpd->path[i++] = (dy > 0) ? 0 : 4;
-        }
-        if (x == x1 && y == y1)
-        {
-            wpd->path_len = i;
-            wpd->path_pos = 0;
-            wpd->path_half = 0;
-            return 0;
-        }
-    }
-    if (flag & 1)
-        return -1;
-
-    memset (tp, 0, sizeof (tp));
-
-    i = calc_index (x0, y0);
-    tp[i].x = x0;
-    tp[i].y = y0;
-    tp[i].dist = 0;
-    tp[i].dir = 0;
-    tp[i].before = 0;
-    tp[i].cost = calc_cost (&tp[i], x1, y1);
-    tp[i].flag = 0;
-    heap[0] = 0;
-    push_heap_path (heap, tp, calc_index (x0, y0));
-    while (1)
-    {
-        int  e = 0, fromdir;
-
-        if (heap[0] == 0)
-            return -1;
-        rp = pop_heap_path (heap, tp);
-        x = tp[rp].x;
-        y = tp[rp].y;
-        if (x == x1 && y == y1)
-        {
-            int  len, j;
-
-            for (len = 0, i = rp; len < 100 && i != calc_index (x0, y0);
-                 i = tp[i].before, len++);
-            if (len == 100 || len >= sizeof (wpd->path))
-                return -1;
-            wpd->path_len = len;
-            wpd->path_pos = 0;
-            wpd->path_half = 0;
-            for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--)
-                wpd->path[j] = tp[i].dir;
-
-            return 0;
-        }
-        fromdir = tp[rp].dir;
-        if (can_move (md, x, y, x + 1, y - 1, flag))
-            e += add_path (heap, tp, x + 1, y - 1, tp[rp].dist + 14, 5, rp,
-                           x1, y1);
-        if (can_move (md, x, y, x + 1, y, flag))
-            e += add_path (heap, tp, x + 1, y, tp[rp].dist + 10, 6, rp, x1,
-                           y1);
-        if (can_move (md, x, y, x + 1, y + 1, flag))
-            e += add_path (heap, tp, x + 1, y + 1, tp[rp].dist + 14, 7, rp,
-                           x1, y1);
-        if (can_move (md, x, y, x, y + 1, flag))
-            e += add_path (heap, tp, x, y + 1, tp[rp].dist + 10, 0, rp, x1,
-                           y1);
-        if (can_move (md, x, y, x - 1, y + 1, flag))
-            e += add_path (heap, tp, x - 1, y + 1, tp[rp].dist + 14, 1, rp,
-                           x1, y1);
-        if (can_move (md, x, y, x - 1, y, flag))
-            e += add_path (heap, tp, x - 1, y, tp[rp].dist + 10, 2, rp, x1,
-                           y1);
-        if (can_move (md, x, y, x - 1, y - 1, flag))
-            e += add_path (heap, tp, x - 1, y - 1, tp[rp].dist + 14, 3, rp,
-                           x1, y1);
-        if (can_move (md, x, y, x, y - 1, flag))
-            e += add_path (heap, tp, x, y - 1, tp[rp].dist + 10, 4, rp, x1,
-                           y1);
-        tp[rp].flag = 1;
-        if (e || heap[0] >= MAX_HEAP - 5)
-            return -1;
-    }
-    return -1;
-}
-
-#ifdef PATH_STANDALONETEST
-char gat[64][64] = {
-    {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, 1, 0, 0, 0, 0, 0},
-};
-
-struct map_data map[1];
-
-/*==========================================
- * 経路探索ルーチン単体テスト用main関数
- *------------------------------------------
- */
-void main (int argc, char *argv[])
-{
-    struct walkpath_data wpd;
-
-    map[0].gat = gat;
-    map[0].xs = 64;
-    map[0].ys = 64;
-
-    path_search (&wpd, 0, 3, 4, 5, 4);
-    path_search (&wpd, 0, 5, 4, 3, 4);
-    path_search (&wpd, 0, 6, 4, 3, 4);
-    path_search (&wpd, 0, 7, 4, 3, 4);
-    path_search (&wpd, 0, 4, 3, 4, 5);
-    path_search (&wpd, 0, 4, 2, 4, 5);
-    path_search (&wpd, 0, 4, 1, 4, 5);
-    path_search (&wpd, 0, 4, 5, 4, 3);
-    path_search (&wpd, 0, 4, 6, 4, 3);
-    path_search (&wpd, 0, 4, 7, 4, 3);
-    path_search (&wpd, 0, 7, 4, 3, 4);
-    path_search (&wpd, 0, 8, 4, 3, 4);
-    path_search (&wpd, 0, 9, 4, 3, 4);
-    path_search (&wpd, 0, 10, 4, 3, 4);
-    path_search (&wpd, 0, 11, 4, 3, 4);
-    path_search (&wpd, 0, 12, 4, 3, 4);
-    path_search (&wpd, 0, 13, 4, 3, 4);
-    path_search (&wpd, 0, 14, 4, 3, 4);
-    path_search (&wpd, 0, 15, 4, 3, 4);
-    path_search (&wpd, 0, 16, 4, 3, 4);
-    path_search (&wpd, 0, 17, 4, 3, 4);
-    path_search (&wpd, 0, 18, 4, 3, 4);
-}
-#endif
diff --git a/src/map/path.cpp b/src/map/path.cpp
new file mode 100644
index 0000000..b68dae6
--- /dev/null
+++ b/src/map/path.cpp
@@ -0,0 +1,445 @@
+// $Id: path.c,v 1.1.1.1 2004/09/10 17:27:00 MagicalTux Exp $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "map.hpp"
+#include "battle.hpp"
+#include "../common/nullpo.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+//#define PATH_STANDALONETEST
+
+#define MAX_HEAP 150
+struct tmp_path
+{
+    short x, y, dist, before, cost;
+    char dir, flag;
+};
+#define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1))
+
+/*==========================================
+ * 経路探索補助heap push
+ *------------------------------------------
+ */
+static void push_heap_path (int *heap, struct tmp_path *tp, int index)
+{
+    int  i, h;
+
+    if (heap == NULL || tp == NULL)
+    {
+        printf ("push_heap_path nullpo\n");
+        return;
+    }
+
+    heap[0]++;
+
+    for (h = heap[0] - 1, i = (h - 1) / 2;
+         h > 0 && tp[index].cost < tp[heap[i + 1]].cost; i = (h - 1) / 2)
+        heap[h + 1] = heap[i + 1], h = i;
+    heap[h + 1] = index;
+}
+
+/*==========================================
+ * 経路探索補助heap update
+ * costが減ったので根の方へ移動
+ *------------------------------------------
+ */
+static void update_heap_path (int *heap, struct tmp_path *tp, int index)
+{
+    int  i, h;
+
+    nullpo_retv (heap);
+    nullpo_retv (tp);
+
+    for (h = 0; h < heap[0]; h++)
+        if (heap[h + 1] == index)
+            break;
+    if (h == heap[0])
+    {
+        fprintf (stderr, "update_heap_path bug\n");
+        exit (1);
+    }
+    for (i = (h - 1) / 2;
+         h > 0 && tp[index].cost < tp[heap[i + 1]].cost; i = (h - 1) / 2)
+        heap[h + 1] = heap[i + 1], h = i;
+    heap[h + 1] = index;
+}
+
+/*==========================================
+ * 経路探索補助heap pop
+ *------------------------------------------
+ */
+static int pop_heap_path (int *heap, struct tmp_path *tp)
+{
+    int  i, h, k;
+    int  ret, last;
+
+    nullpo_retr (-1, heap);
+    nullpo_retr (-1, tp);
+
+    if (heap[0] <= 0)
+        return -1;
+    ret = heap[1];
+    last = heap[heap[0]];
+    heap[0]--;
+
+    for (h = 0, k = 2; k < heap[0]; k = k * 2 + 2)
+    {
+        if (tp[heap[k + 1]].cost > tp[heap[k]].cost)
+            k--;
+        heap[h + 1] = heap[k + 1], h = k;
+    }
+    if (k == heap[0])
+        heap[h + 1] = heap[k], h = k - 1;
+
+    for (i = (h - 1) / 2;
+         h > 0 && tp[heap[i + 1]].cost > tp[last].cost; i = (h - 1) / 2)
+        heap[h + 1] = heap[i + 1], h = i;
+    heap[h + 1] = last;
+
+    return ret;
+}
+
+/*==========================================
+ * 現在の点のcost計算
+ *------------------------------------------
+ */
+static int calc_cost (struct tmp_path *p, int x1, int y1)
+{
+    int  xd, yd;
+
+    nullpo_retr (0, p);
+
+    xd = x1 - p->x;
+    if (xd < 0)
+        xd = -xd;
+    yd = y1 - p->y;
+    if (yd < 0)
+        yd = -yd;
+    return (xd + yd) * 10 + p->dist;
+}
+
+/*==========================================
+ * 必要ならpathを追加/修正する
+ *------------------------------------------
+ */
+static int add_path (int *heap, struct tmp_path *tp, int x, int y, int dist,
+                     int dir, int before, int x1, int y1)
+{
+    int  i;
+
+    nullpo_retr (0, heap);
+    nullpo_retr (0, tp);
+
+    i = calc_index (x, y);
+
+    if (tp[i].x == x && tp[i].y == y)
+    {
+        if (tp[i].dist > dist)
+        {
+            tp[i].dist = dist;
+            tp[i].dir = dir;
+            tp[i].before = before;
+            tp[i].cost = calc_cost (&tp[i], x1, y1);
+            if (tp[i].flag)
+                push_heap_path (heap, tp, i);
+            else
+                update_heap_path (heap, tp, i);
+            tp[i].flag = 0;
+        }
+        return 0;
+    }
+
+    if (tp[i].x || tp[i].y)
+        return 1;
+
+    tp[i].x = x;
+    tp[i].y = y;
+    tp[i].dist = dist;
+    tp[i].dir = dir;
+    tp[i].before = before;
+    tp[i].cost = calc_cost (&tp[i], x1, y1);
+    tp[i].flag = 0;
+    push_heap_path (heap, tp, i);
+
+    return 0;
+}
+
+/*==========================================
+ * (x,y)が移動不可能地帯かどうか
+ * flag 0x10000 遠距離攻撃判定
+ *------------------------------------------
+ */
+static int can_place (struct map_data *m, int x, int y, int flag)
+{
+    int  c;
+
+    nullpo_retr (0, m);
+
+    c = read_gatp (m, x, y);
+
+    if (c == 1)
+        return 0;
+    if (!(flag & 0x10000) && c == 5)
+        return 0;
+    return 1;
+}
+
+/*==========================================
+ * (x0,y0)から(x1,y1)へ1歩で移動可能か計算
+ *------------------------------------------
+ */
+static int can_move (struct map_data *m, int x0, int y0, int x1, int y1,
+                     int flag)
+{
+    nullpo_retr (0, m);
+
+    if (x0 - x1 < -1 || x0 - x1 > 1 || y0 - y1 < -1 || y0 - y1 > 1)
+        return 0;
+    if (x1 < 0 || y1 < 0 || x1 >= m->xs || y1 >= m->ys)
+        return 0;
+    if (!can_place (m, x0, y0, flag))
+        return 0;
+    if (!can_place (m, x1, y1, flag))
+        return 0;
+    if (x0 == x1 || y0 == y1)
+        return 1;
+    if (!can_place (m, x0, y1, flag) || !can_place (m, x1, y0, flag))
+        return 0;
+    return 1;
+}
+
+/*==========================================
+ * (x0,y0)から(dx,dy)方向へcountセル分
+ * 吹き飛ばしたあとの座標を所得
+ *------------------------------------------
+ */
+int path_blownpos (int m, int x0, int y0, int dx, int dy, int count)
+{
+    struct map_data *md;
+
+    if (!map[m].gat)
+        return -1;
+    md = &map[m];
+
+    if (count > 15)
+    {                           // 最大10マスに制限
+        if (battle_config.error_log)
+            printf ("path_blownpos: count too many %d !\n", count);
+        count = 15;
+    }
+    if (dx > 1 || dx < -1 || dy > 1 || dy < -1)
+    {
+        if (battle_config.error_log)
+            printf ("path_blownpos: illeagal dx=%d or dy=%d !\n", dx, dy);
+        dx = (dx >= 0) ? 1 : ((dx < 0) ? -1 : 0);
+        dy = (dy >= 0) ? 1 : ((dy < 0) ? -1 : 0);
+    }
+
+    while ((count--) > 0 && (dx != 0 || dy != 0))
+    {
+        if (!can_move (md, x0, y0, x0 + dx, y0 + dy, 0))
+        {
+            int  fx = (dx != 0 && can_move (md, x0, y0, x0 + dx, y0, 0));
+            int  fy = (dy != 0 && can_move (md, x0, y0, x0, y0 + dy, 0));
+            if (fx && fy)
+            {
+                if (rand () & 1)
+                    dx = 0;
+                else
+                    dy = 0;
+            }
+            if (!fx)
+                dx = 0;
+            if (!fy)
+                dy = 0;
+        }
+        x0 += dx;
+        y0 += dy;
+    }
+    return (x0 << 16) | y0;
+}
+
+/*==========================================
+ * path探索 (x0,y0)->(x1,y1)
+ *------------------------------------------
+ */
+int path_search (struct walkpath_data *wpd, int m, int x0, int y0, int x1,
+                 int y1, int flag)
+{
+    int  heap[MAX_HEAP + 1];
+    struct tmp_path tp[MAX_WALKPATH * MAX_WALKPATH];
+    int  i, rp, x, y;
+    struct map_data *md;
+    int  dx, dy;
+
+    nullpo_retr (0, wpd);
+
+    if (!map[m].gat)
+        return -1;
+    md = &map[m];
+    if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys
+        || (i = read_gatp (md, x1, y1)) == 1 || i == 5)
+        return -1;
+
+    // easy
+    dx = (x1 - x0 < 0) ? -1 : 1;
+    dy = (y1 - y0 < 0) ? -1 : 1;
+    for (x = x0, y = y0, i = 0; x != x1 || y != y1;)
+    {
+        if (i >= sizeof (wpd->path))
+            return -1;
+        if (x != x1 && y != y1)
+        {
+            if (!can_move (md, x, y, x + dx, y + dy, flag))
+                break;
+            x += dx;
+            y += dy;
+            wpd->path[i++] =
+                (dx < 0) ? ((dy > 0) ? 1 : 3) : ((dy < 0) ? 5 : 7);
+        }
+        else if (x != x1)
+        {
+            if (!can_move (md, x, y, x + dx, y, flag))
+                break;
+            x += dx;
+            wpd->path[i++] = (dx < 0) ? 2 : 6;
+        }
+        else
+        {                       // y!=y1
+            if (!can_move (md, x, y, x, y + dy, flag))
+                break;
+            y += dy;
+            wpd->path[i++] = (dy > 0) ? 0 : 4;
+        }
+        if (x == x1 && y == y1)
+        {
+            wpd->path_len = i;
+            wpd->path_pos = 0;
+            wpd->path_half = 0;
+            return 0;
+        }
+    }
+    if (flag & 1)
+        return -1;
+
+    memset (tp, 0, sizeof (tp));
+
+    i = calc_index (x0, y0);
+    tp[i].x = x0;
+    tp[i].y = y0;
+    tp[i].dist = 0;
+    tp[i].dir = 0;
+    tp[i].before = 0;
+    tp[i].cost = calc_cost (&tp[i], x1, y1);
+    tp[i].flag = 0;
+    heap[0] = 0;
+    push_heap_path (heap, tp, calc_index (x0, y0));
+    while (1)
+    {
+        int  e = 0, fromdir;
+
+        if (heap[0] == 0)
+            return -1;
+        rp = pop_heap_path (heap, tp);
+        x = tp[rp].x;
+        y = tp[rp].y;
+        if (x == x1 && y == y1)
+        {
+            int  len, j;
+
+            for (len = 0, i = rp; len < 100 && i != calc_index (x0, y0);
+                 i = tp[i].before, len++);
+            if (len == 100 || len >= sizeof (wpd->path))
+                return -1;
+            wpd->path_len = len;
+            wpd->path_pos = 0;
+            wpd->path_half = 0;
+            for (i = rp, j = len - 1; j >= 0; i = tp[i].before, j--)
+                wpd->path[j] = tp[i].dir;
+
+            return 0;
+        }
+        fromdir = tp[rp].dir;
+        if (can_move (md, x, y, x + 1, y - 1, flag))
+            e += add_path (heap, tp, x + 1, y - 1, tp[rp].dist + 14, 5, rp,
+                           x1, y1);
+        if (can_move (md, x, y, x + 1, y, flag))
+            e += add_path (heap, tp, x + 1, y, tp[rp].dist + 10, 6, rp, x1,
+                           y1);
+        if (can_move (md, x, y, x + 1, y + 1, flag))
+            e += add_path (heap, tp, x + 1, y + 1, tp[rp].dist + 14, 7, rp,
+                           x1, y1);
+        if (can_move (md, x, y, x, y + 1, flag))
+            e += add_path (heap, tp, x, y + 1, tp[rp].dist + 10, 0, rp, x1,
+                           y1);
+        if (can_move (md, x, y, x - 1, y + 1, flag))
+            e += add_path (heap, tp, x - 1, y + 1, tp[rp].dist + 14, 1, rp,
+                           x1, y1);
+        if (can_move (md, x, y, x - 1, y, flag))
+            e += add_path (heap, tp, x - 1, y, tp[rp].dist + 10, 2, rp, x1,
+                           y1);
+        if (can_move (md, x, y, x - 1, y - 1, flag))
+            e += add_path (heap, tp, x - 1, y - 1, tp[rp].dist + 14, 3, rp,
+                           x1, y1);
+        if (can_move (md, x, y, x, y - 1, flag))
+            e += add_path (heap, tp, x, y - 1, tp[rp].dist + 10, 4, rp, x1,
+                           y1);
+        tp[rp].flag = 1;
+        if (e || heap[0] >= MAX_HEAP - 5)
+            return -1;
+    }
+    return -1;
+}
+
+#ifdef PATH_STANDALONETEST
+char gat[64][64] = {
+    {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, 1, 0, 0, 0, 0, 0},
+};
+
+struct map_data map[1];
+
+/*==========================================
+ * 経路探索ルーチン単体テスト用main関数
+ *------------------------------------------
+ */
+void main (int argc, char *argv[])
+{
+    struct walkpath_data wpd;
+
+    map[0].gat = gat;
+    map[0].xs = 64;
+    map[0].ys = 64;
+
+    path_search (&wpd, 0, 3, 4, 5, 4);
+    path_search (&wpd, 0, 5, 4, 3, 4);
+    path_search (&wpd, 0, 6, 4, 3, 4);
+    path_search (&wpd, 0, 7, 4, 3, 4);
+    path_search (&wpd, 0, 4, 3, 4, 5);
+    path_search (&wpd, 0, 4, 2, 4, 5);
+    path_search (&wpd, 0, 4, 1, 4, 5);
+    path_search (&wpd, 0, 4, 5, 4, 3);
+    path_search (&wpd, 0, 4, 6, 4, 3);
+    path_search (&wpd, 0, 4, 7, 4, 3);
+    path_search (&wpd, 0, 7, 4, 3, 4);
+    path_search (&wpd, 0, 8, 4, 3, 4);
+    path_search (&wpd, 0, 9, 4, 3, 4);
+    path_search (&wpd, 0, 10, 4, 3, 4);
+    path_search (&wpd, 0, 11, 4, 3, 4);
+    path_search (&wpd, 0, 12, 4, 3, 4);
+    path_search (&wpd, 0, 13, 4, 3, 4);
+    path_search (&wpd, 0, 14, 4, 3, 4);
+    path_search (&wpd, 0, 15, 4, 3, 4);
+    path_search (&wpd, 0, 16, 4, 3, 4);
+    path_search (&wpd, 0, 17, 4, 3, 4);
+    path_search (&wpd, 0, 18, 4, 3, 4);
+}
+#endif
diff --git a/src/map/pc.c b/src/map/pc.c
deleted file mode 100644
index 8096679..0000000
--- a/src/map/pc.c
+++ /dev/null
@@ -1,9032 +0,0 @@
-// $Id: pc.c 101 2004-09-25 17:57:22Z Valaris $
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "../common/socket.h"             // [Valaris]
-#include "../common/timer.h"
-#include "../common/db.h"
-
-#include "../common/nullpo.h"
-#include "../common/mt_rand.h"
-
-#include "atcommand.h"
-#include "battle.h"
-#include "chat.h"
-#include "chrif.h"
-#include "clif.h"
-#include "guild.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "storage.h"
-#include "trade.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define PVP_CALCRANK_INTERVAL 1000  // PVP順位計算の間隔
-
-//define it here, since the ifdef only occurs in this file
-#define USE_ASTRAL_SOUL_SKILL
-
-#define STATE_BLIND 0x10
-
-#ifdef USE_ASTRAL_SOUL_SKILL
-#define MAGIC_SKILL_THRESHOLD 200   // [fate] At this threshold, the Astral Soul skill kicks in
-#endif
-
-#define MAP_LOG_STATS(sd, suffix)	\
-        MAP_LOG_PC(sd, "STAT %d %d %d %d %d %d " suffix,            \
-                   sd->status.str, sd->status.agi, sd->status.vit, sd->status.int_, sd->status.dex, sd->status.luk)
-
-#define MAP_LOG_XP(sd, suffix)	\
-        MAP_LOG_PC(sd, "XP %d %d JOB %d %d %d ZENY %d + %d " suffix,		\
-                   sd->status.base_level, sd->status.base_exp, sd->status.job_level, sd->status.job_exp, sd->status.skill_point,  sd->status.zeny, pc_readaccountreg(sd, "BankAccount"))
-
-#define MAP_LOG_MAGIC(sd, suffix)	\
-        MAP_LOG_PC(sd, "MAGIC %d %d %d %d %d %d EXP %d %d " suffix,	\
-                   sd->status.skill[TMW_MAGIC].lv,                      \
-                   sd->status.skill[TMW_MAGIC_LIFE].lv,			\
-                   sd->status.skill[TMW_MAGIC_WAR].lv,			\
-                   sd->status.skill[TMW_MAGIC_TRANSMUTE].lv,		\
-                   sd->status.skill[TMW_MAGIC_NATURE].lv,               \
-                   sd->status.skill[TMW_MAGIC_ETHER].lv,                \
-                   pc_readglobalreg(sd, "MAGIC_EXPERIENCE") & 0xffff,	\
-                   (pc_readglobalreg(sd, "MAGIC_EXPERIENCE") >> 24) & 0xff)
-
-static int max_weight_base[MAX_PC_CLASS];
-static int hp_coefficient[MAX_PC_CLASS];
-static int hp_coefficient2[MAX_PC_CLASS];
-static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
-static int sp_coefficient[MAX_PC_CLASS];
-static int aspd_base[MAX_PC_CLASS][20];
-static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL];
-static int exp_table[14][MAX_LEVEL];
-static char statp[255][7];
-static struct
-{
-    int  id;
-    int  max;
-    struct
-    {
-        short id, lv;
-    } need[6];
-} skill_tree[3][MAX_PC_CLASS][100];
-
-static int atkmods[3][20];      // 武器ATKサイズ修正(size_fix.txt)
-static int refinebonus[5][3];   // 精錬ボーナステーブル(refine_db.txt)
-static int percentrefinery[5][10];  // 精錬成功率(refine_db.txt)
-
-static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-
-static unsigned int equip_pos[11] =
-    { 0x0080, 0x0008, 0x0040, 0x0004, 0x0001, 0x0200, 0x0100, 0x0010, 0x0020,
-    0x0002, 0x8000
-};
-
-//static struct dbt *gm_account_db;
-static struct gm_account *gm_account = NULL;
-static int GM_num = 0;
-
-int pc_isGM (struct map_session_data *sd)
-{
-//  struct gm_account *p;
-    int  i;
-
-    nullpo_retr (0, sd);
-
-/*	p = numdb_search(gm_account_db, sd->status.account_id);
-	if (p == NULL)
-		return 0;
-	return p->level;*/
-
-    for (i = 0; i < GM_num; i++)
-        if (gm_account[i].account_id == sd->status.account_id)
-            return gm_account[i].level;
-    return 0;
-
-}
-
-int pc_iskiller (struct map_session_data *src,
-                 struct map_session_data *target)
-{
-    nullpo_retr (0, src);
-
-    if (src->bl.type != BL_PC)
-        return 0;
-    if (src->special_state.killer)
-        return 1;
-
-    if (target->bl.type != BL_PC)
-        return 0;
-    if (target->special_state.killable)
-        return 1;
-
-    return 0;
-}
-
-int pc_set_gm_level (int account_id, int level)
-{
-    int  i;
-    for (i = 0; i < GM_num; i++)
-    {
-        if (account_id == gm_account[i].account_id)
-        {
-            gm_account[i].level = level;
-            return 0;
-        }
-    }
-
-    GM_num++;
-    RECREATE (gm_account, struct gm_account, GM_num);
-    gm_account[GM_num - 1].account_id = account_id;
-    gm_account[GM_num - 1].level = level;
-    return 0;
-}
-
-int pc_getrefinebonus (int lv, int type)
-{
-    if (lv >= 0 && lv < 5 && type >= 0 && type < 3)
-        return refinebonus[lv][type];
-    return 0;
-}
-
-static int distance (int x0, int y0, int x1, int y1)
-{
-    int  dx, dy;
-
-    dx = abs (x0 - x1);
-    dy = abs (y0 - y1);
-    return dx > dy ? dx : dy;
-}
-
-static void pc_invincible_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd;
-
-    if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
-        || sd->bl.type != BL_PC)
-        return;
-
-    if (sd->invincible_timer != tid)
-    {
-        if (battle_config.error_log)
-            printf ("invincible_timer %d != %d\n", sd->invincible_timer, tid);
-        return;
-    }
-    sd->invincible_timer = -1;
-}
-
-int pc_setinvincibletimer (struct map_session_data *sd, int val)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->invincible_timer != -1)
-        delete_timer (sd->invincible_timer, pc_invincible_timer);
-    sd->invincible_timer =
-        add_timer (gettick () + val, pc_invincible_timer, sd->bl.id, 0);
-    return 0;
-}
-
-int pc_delinvincibletimer (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->invincible_timer != -1)
-    {
-        delete_timer (sd->invincible_timer, pc_invincible_timer);
-        sd->invincible_timer = -1;
-    }
-    return 0;
-}
-
-static void pc_spiritball_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd;
-    int  i;
-
-    if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
-        || sd->bl.type != BL_PC)
-        return;
-
-    if (sd->spirit_timer[0] != tid)
-    {
-        if (battle_config.error_log)
-            printf ("spirit_timer %d != %d\n", sd->spirit_timer[0], tid);
-        return;
-    }
-    sd->spirit_timer[0] = -1;
-    for (i = 1; i < sd->spiritball; i++)
-    {
-        sd->spirit_timer[i - 1] = sd->spirit_timer[i];
-        sd->spirit_timer[i] = -1;
-    }
-    sd->spiritball--;
-    if (sd->spiritball < 0)
-        sd->spiritball = 0;
-    clif_spiritball (sd);
-}
-
-int pc_addspiritball (struct map_session_data *sd, int interval, int max)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (max > MAX_SKILL_LEVEL)
-        max = MAX_SKILL_LEVEL;
-    if (sd->spiritball < 0)
-        sd->spiritball = 0;
-
-    if (sd->spiritball >= max)
-    {
-        if (sd->spirit_timer[0] != -1)
-        {
-            delete_timer (sd->spirit_timer[0], pc_spiritball_timer);
-            sd->spirit_timer[0] = -1;
-        }
-        for (i = 1; i < max; i++)
-        {
-            sd->spirit_timer[i - 1] = sd->spirit_timer[i];
-            sd->spirit_timer[i] = -1;
-        }
-    }
-    else
-        sd->spiritball++;
-
-    sd->spirit_timer[sd->spiritball - 1] =
-        add_timer (gettick () + interval, pc_spiritball_timer, sd->bl.id, 0);
-    clif_spiritball (sd);
-
-    return 0;
-}
-
-int pc_delspiritball (struct map_session_data *sd, int count, int type)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (sd->spiritball <= 0)
-    {
-        sd->spiritball = 0;
-        return 0;
-    }
-
-    if (count > sd->spiritball)
-        count = sd->spiritball;
-    sd->spiritball -= count;
-    if (count > MAX_SKILL_LEVEL)
-        count = MAX_SKILL_LEVEL;
-
-    for (i = 0; i < count; i++)
-    {
-        if (sd->spirit_timer[i] != -1)
-        {
-            delete_timer (sd->spirit_timer[i], pc_spiritball_timer);
-            sd->spirit_timer[i] = -1;
-        }
-    }
-    for (i = count; i < MAX_SKILL_LEVEL; i++)
-    {
-        sd->spirit_timer[i - count] = sd->spirit_timer[i];
-        sd->spirit_timer[i] = -1;
-    }
-
-    if (!type)
-        clif_spiritball (sd);
-
-    return 0;
-}
-
-int pc_setrestartvalue (struct map_session_data *sd, int type)
-{
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    //-----------------------
-    // 死亡した
-    if (sd->special_state.restart_full_recover)
-    {                           // オシリスカード
-        sd->status.hp = sd->status.max_hp;
-        sd->status.sp = sd->status.max_sp;
-    }
-    else
-    {
-        if (s_class.job == 0 && battle_config.restart_hp_rate < 50)
-        {                       //ノビは半分回復
-            sd->status.hp = (sd->status.max_hp) / 2;
-        }
-        else
-        {
-            if (battle_config.restart_hp_rate <= 0)
-                sd->status.hp = 1;
-            else
-            {
-                sd->status.hp =
-                    sd->status.max_hp * battle_config.restart_hp_rate / 100;
-                if (sd->status.hp <= 0)
-                    sd->status.hp = 1;
-            }
-        }
-        if (battle_config.restart_sp_rate > 0)
-        {
-            int  sp = sd->status.max_sp * battle_config.restart_sp_rate / 100;
-            if (sd->status.sp < sp)
-                sd->status.sp = sp;
-        }
-    }
-    if (type & 1)
-        clif_updatestatus (sd, SP_HP);
-    if (type & 1)
-        clif_updatestatus (sd, SP_SP);
-
-    /* removed exp penalty on spawn [Valaris] */
-
-    if (type & 2 && sd->status.pc_class != 0 && battle_config.zeny_penalty > 0
-        && !map[sd->bl.m].flag.nozenypenalty)
-    {
-        int  zeny =
-            (int) ((double) sd->status.zeny *
-                   (double) battle_config.zeny_penalty / 10000.);
-        if (zeny < 1)
-            zeny = 1;
-        sd->status.zeny -= zeny;
-        if (sd->status.zeny < 0)
-            sd->status.zeny = 0;
-        clif_updatestatus (sd, SP_ZENY);
-    }
-    sd->heal_xp = 0;            // [Fate] Set gainable xp for healing this player to 0
-
-    return 0;
-}
-
-/*==========================================
- * 自分をロックしているMOBの数を数える(foreachclient)
- *------------------------------------------
- */
-static int pc_counttargeted_sub (struct block_list *bl, va_list ap)
-{
-    int  id, *c, target_lv;
-    struct block_list *src;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    id = va_arg (ap, int);
-
-    nullpo_retr (0, c = va_arg (ap, int *));
-
-    src = va_arg (ap, struct block_list *);
-    target_lv = va_arg (ap, int);
-    if (id == bl->id || (src && id == src->id))
-        return 0;
-    if (bl->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) bl;
-        if (sd && sd->attacktarget == id && sd->attacktimer != -1
-            && sd->attacktarget_lv >= target_lv)
-            (*c)++;
-    }
-    else if (bl->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) bl;
-        if (md && md->target_id == id && md->timer != -1
-            && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
-
-            (*c)++;
-        //printf("md->target_lv:%d, target_lv:%d\n",((struct mob_data *)bl)->target_lv,target_lv);
-    }
-    return 0;
-}
-
-int pc_counttargeted (struct map_session_data *sd, struct block_list *src,
-                      int target_lv)
-{
-    int  c = 0;
-    map_foreachinarea (pc_counttargeted_sub, sd->bl.m,
-                       sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
-                       sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE, 0,
-                       sd->bl.id, &c, src, target_lv);
-    return c;
-}
-
-/*==========================================
- * ローカルプロトタイプ宣言 (必要な物のみ)
- *------------------------------------------
- */
-static int pc_walktoxy_sub (struct map_session_data *);
-
-/*==========================================
- * saveに必要なステータス修正を行なう
- *------------------------------------------
- */
-int pc_makesavestatus (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    // 服の色は色々弊害が多いので保存対象にはしない
-    if (!battle_config.save_clothcolor)
-        sd->status.clothes_color = 0;
-
-    // 死亡状態だったのでhpを1、位置をセーブ場所に変更
-    if (pc_isdead (sd))
-    {
-        pc_setrestartvalue (sd, 0);
-        memcpy (&sd->status.last_point, &sd->status.save_point,
-                sizeof (sd->status.last_point));
-    }
-    else
-    {
-        memcpy (sd->status.last_point.map, sd->mapname, 24);
-        sd->status.last_point.x = sd->bl.x;
-        sd->status.last_point.y = sd->bl.y;
-    }
-
-    // セーブ禁止マップだったので指定位置に移動
-    if (map[sd->bl.m].flag.nosave)
-    {
-        struct map_data *m = &map[sd->bl.m];
-        if (strcmp (m->save.map, "SavePoint") == 0)
-            memcpy (&sd->status.last_point, &sd->status.save_point,
-                    sizeof (sd->status.last_point));
-        else
-            memcpy (&sd->status.last_point, &m->save,
-                    sizeof (sd->status.last_point));
-    }
-
-    //マナーポイントがプラスだった場合0に
-    if (battle_config.muting_players && sd->status.manner > 0)
-        sd->status.manner = 0;
-    return 0;
-}
-
-/*==========================================
- * 接続時の初期化
- *------------------------------------------
- */
-int pc_setnewpc (struct map_session_data *sd, int account_id, int char_id,
-                 int login_id1, int client_tick, int sex, int fd)
-{
-    nullpo_retr (0, sd);
-
-    sd->bl.id = account_id;
-    sd->char_id = char_id;
-    sd->login_id1 = login_id1;
-    sd->login_id2 = 0;          // at this point, we can not know the value :(
-    sd->client_tick = client_tick;
-    sd->sex = sex;
-    sd->state.auth = 0;
-    sd->bl.type = BL_PC;
-    sd->canact_tick = sd->canmove_tick = gettick ();
-    sd->canlog_tick = gettick ();
-    sd->state.waitingdisconnect = 0;
-
-    return 0;
-}
-
-int pc_equippoint (struct map_session_data *sd, int n)
-{
-    int  ep = 0;
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    if (!sd->inventory_data[n])
-        return 0;
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    ep = sd->inventory_data[n]->equip;
-    if ((sd->inventory_data[n]->look == 1 || sd->inventory_data[n]->look == 2
-         || sd->inventory_data[n]->look == 6) && (ep == 2
-                                                  &&
-                                                  (pc_checkskill (sd, AS_LEFT)
-                                                   > 0 || s_class.job == 12)))
-    {
-        return 34;
-    }
-
-    return ep;
-}
-
-int pc_setinventorydata (struct map_session_data *sd)
-{
-    int  i, id;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        id = sd->status.inventory[i].nameid;
-        sd->inventory_data[i] = itemdb_search (id);
-    }
-    return 0;
-}
-
-int pc_calcweapontype (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->weapontype1 != 0 && sd->weapontype2 == 0)
-        sd->status.weapon = sd->weapontype1;
-    if (sd->weapontype1 == 0 && sd->weapontype2 != 0)   // 左手武器 Only
-        sd->status.weapon = sd->weapontype2;
-    else if (sd->weapontype1 == 1 && sd->weapontype2 == 1)  // 双短剣
-        sd->status.weapon = 0x11;
-    else if (sd->weapontype1 == 2 && sd->weapontype2 == 2)  // 双単手剣
-        sd->status.weapon = 0x12;
-    else if (sd->weapontype1 == 6 && sd->weapontype2 == 6)  // 双単手斧
-        sd->status.weapon = 0x13;
-    else if ((sd->weapontype1 == 1 && sd->weapontype2 == 2) || (sd->weapontype1 == 2 && sd->weapontype2 == 1))  // 短剣 - 単手剣
-        sd->status.weapon = 0x14;
-    else if ((sd->weapontype1 == 1 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 1))  // 短剣 - 斧
-        sd->status.weapon = 0x15;
-    else if ((sd->weapontype1 == 2 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 2))  // 単手剣 - 斧
-        sd->status.weapon = 0x16;
-    else
-        sd->status.weapon = sd->weapontype1;
-
-    return 0;
-}
-
-int pc_setequipindex (struct map_session_data *sd)
-{
-    int  i, j;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < 11; i++)
-        sd->equip_index[i] = -1;
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid <= 0)
-            continue;
-        if (sd->status.inventory[i].equip)
-        {
-            for (j = 0; j < 11; j++)
-                if (sd->status.inventory[i].equip & equip_pos[j])
-                    sd->equip_index[j] = i;
-            if (sd->status.inventory[i].equip & 0x0002)
-            {
-                if (sd->inventory_data[i])
-                    sd->weapontype1 = sd->inventory_data[i]->look;
-                else
-                    sd->weapontype1 = 0;
-            }
-            if (sd->status.inventory[i].equip & 0x0020)
-            {
-                if (sd->inventory_data[i])
-                {
-                    if (sd->inventory_data[i]->type == 4)
-                    {
-                        if (sd->status.inventory[i].equip == 0x0020)
-                            sd->weapontype2 = sd->inventory_data[i]->look;
-                        else
-                            sd->weapontype2 = 0;
-                    }
-                    else
-                        sd->weapontype2 = 0;
-                }
-                else
-                    sd->weapontype2 = 0;
-            }
-        }
-    }
-    pc_calcweapontype (sd);
-
-    return 0;
-}
-
-int pc_isequip (struct map_session_data *sd, int n)
-{
-    struct item_data *item;
-    struct status_change *sc_data;
-    //転生や養子の場合の元の職業を算出する
-
-    nullpo_retr (0, sd);
-
-    item = sd->inventory_data[n];
-    sc_data = battle_get_sc_data (&sd->bl);
-    //s_class = pc_calc_base_job(sd->status.class);
-
-    if (battle_config.gm_allequip > 0
-        && pc_isGM (sd) >= battle_config.gm_allequip)
-        return 1;
-
-    if (item == NULL)
-        return 0;
-    if (item->sex != 2 && sd->status.sex != item->sex)
-        return 0;
-    if (item->elv > 0 && sd->status.base_level < item->elv)
-        return 0;
-
-    if (map[sd->bl.m].flag.pvp
-        && (item->flag.no_equip == 1 || item->flag.no_equip == 3))
-        return 0;
-    if (map[sd->bl.m].flag.gvg
-        && (item->flag.no_equip == 2 || item->flag.no_equip == 3))
-        return 0;
-    if (item->equip & 0x0002 && sc_data
-        && sc_data[SC_STRIPWEAPON].timer != -1)
-        return 0;
-    if (item->equip & 0x0020 && sc_data
-        && sc_data[SC_STRIPSHIELD].timer != -1)
-        return 0;
-    if (item->equip & 0x0010 && sc_data && sc_data[SC_STRIPARMOR].timer != -1)
-        return 0;
-    if (item->equip & 0x0100 && sc_data && sc_data[SC_STRIPHELM].timer != -1)
-        return 0;
-    return 1;
-}
-
-/*==========================================
- * Weapon Breaking [Valaris]
- *------------------------------------------
- */
-int pc_breakweapon (struct map_session_data *sd)
-{
-    struct item_data *item;
-    char output[255];
-    int  i;
-
-    if (sd == NULL)
-        return -1;
-    if (sd->unbreakable >= MRAND (100))
-        return 0;
-    if (sd->sc_data && sd->sc_data[SC_CP_WEAPON].timer != -1)
-        return 0;
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].equip
-            && sd->status.inventory[i].equip & 0x0002
-            && !sd->status.inventory[i].broken)
-        {
-            item = sd->inventory_data[i];
-            sd->status.inventory[i].broken = 1;
-            //pc_unequipitem(sd,i,0);
-            if (sd->status.inventory[i].equip
-                && sd->status.inventory[i].equip & 0x0002
-                && sd->status.inventory[i].broken == 1)
-            {
-                sprintf (output, "%s has broken.", item->jname);
-                clif_emotion (&sd->bl, 23);
-                clif_displaymessage (sd->fd, output);
-                clif_equiplist (sd);
-                skill_status_change_start (&sd->bl, SC_BROKNWEAPON, 0, 0, 0,
-                                           0, 0, 0);
-            }
-        }
-        if (sd->status.inventory[i].broken == 1)
-            return 0;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * Armor Breaking [Valaris]
- *------------------------------------------
- */
-int pc_breakarmor (struct map_session_data *sd)
-{
-    struct item_data *item;
-    char output[255];
-    int  i;
-
-    if (sd == NULL)
-        return -1;
-    if (sd->unbreakable >= MRAND (100))
-        return 0;
-    if (sd->sc_data && sd->sc_data[SC_CP_ARMOR].timer != -1)
-        return 0;
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].equip
-            && sd->status.inventory[i].equip & 0x0010
-            && !sd->status.inventory[i].broken)
-        {
-            item = sd->inventory_data[i];
-            sd->status.inventory[i].broken = 1;
-            //pc_unequipitem(sd,i,0);
-            if (sd->status.inventory[i].equip
-                && sd->status.inventory[i].equip & 0x0010
-                && sd->status.inventory[i].broken == 1)
-            {
-                sprintf (output, "%s has broken.", item->jname);
-                clif_emotion (&sd->bl, 23);
-                clif_displaymessage (sd->fd, output);
-                clif_equiplist (sd);
-                skill_status_change_start (&sd->bl, SC_BROKNARMOR, 0, 0, 0, 0,
-                                           0, 0);
-            }
-        }
-        if (sd->status.inventory[i].broken == 1)
-            return 0;
-    }
-    return 0;
-}
-
-/*==========================================
- * session idに問題無し
- * char鯖から送られてきたステータスを設定
- *------------------------------------------
- */
-int pc_authok (int id, int login_id2, time_t connect_until_time,
-               short tmw_version, struct mmo_charstatus *st)
-{
-    struct map_session_data *sd = NULL;
-
-    struct party *p;
-    struct guild *g;
-    int  i;
-    unsigned long tick = gettick ();
-    struct sockaddr_in sai;
-    socklen_t sa_len = sizeof(struct sockaddr);
-
-    sd = map_id2sd (id);
-    if (sd == NULL)
-        return 1;
-
-    sd->login_id2 = login_id2;
-    sd->tmw_version = tmw_version;
-
-    memcpy (&sd->status, st, sizeof (*st));
-
-    if (sd->status.sex != sd->sex)
-    {
-        clif_authfail_fd (sd->fd, 0);
-        return 1;
-    }
-
-    MAP_LOG_STATS (sd, "LOGIN");
-    MAP_LOG_XP (sd, "LOGIN");
-    MAP_LOG_MAGIC (sd, "LOGIN");
-
-    memset (&sd->state, 0, sizeof (sd->state));
-    // 基本的な初期化
-    sd->state.connect_new = 1;
-    sd->bl.prev = sd->bl.next = NULL;
-
-    sd->weapontype1 = sd->weapontype2 = 0;
-    sd->view_class = sd->status.pc_class;
-    sd->speed = DEFAULT_WALK_SPEED;
-    sd->state.dead_sit = 0;
-    sd->dir = 0;
-    sd->head_dir = 0;
-    sd->state.auth = 1;
-    sd->walktimer = -1;
-    sd->attacktimer = -1;
-    sd->followtimer = -1;       // [MouseJstr]
-    sd->skilltimer = -1;
-    sd->skillitem = -1;
-    sd->skillitemlv = -1;
-    sd->invincible_timer = -1;
-    sd->sg_count = 0;
-
-    sd->deal_locked = 0;
-    sd->trade_partner = 0;
-
-    sd->inchealhptick = 0;
-    sd->inchealsptick = 0;
-    sd->hp_sub = 0;
-    sd->sp_sub = 0;
-    sd->quick_regeneration_hp.amount = 0;
-    sd->quick_regeneration_sp.amount = 0;
-    sd->heal_xp = 0;
-    sd->inchealspirithptick = 0;
-    sd->inchealspiritsptick = 0;
-    sd->canact_tick = tick;
-    sd->canmove_tick = tick;
-    sd->attackabletime = tick;
-    /* We don't want players bypassing spell restrictions. [remoitnane] */
-    // Removed because it was buggy with the ~50 day wraparound,
-    // and there's already a limit on how fast you can log in and log out.
-    // -o11c
-    sd->cast_tick = tick; // + pc_readglobalreg (sd, "MAGIC_CAST_TICK");
-
-    sd->doridori_counter = 0;
-
-    sd->spiritball = 0;
-    for (i = 0; i < MAX_SKILL_LEVEL; i++)
-        sd->spirit_timer[i] = -1;
-    for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
-        sd->skilltimerskill[i].timer = -1;
-
-    memset (&sd->dev, 0, sizeof (struct square));
-    for (i = 0; i < 5; i++)
-    {
-        sd->dev.val1[i] = 0;
-        sd->dev.val2[i] = 0;
-    }
-
-    // アカウント変数の送信要求
-    intif_request_accountreg (sd);
-
-    // アイテムチェック
-    pc_setinventorydata (sd);
-    pc_checkitem (sd);
-
-    // ステータス異常の初期化
-    for (i = 0; i < MAX_STATUSCHANGE; i++)
-    {
-        sd->sc_data[i].timer = -1;
-        sd->sc_data[i].val1 = sd->sc_data[i].val2 = sd->sc_data[i].val3 =
-            sd->sc_data[i].val4 = 0;
-    }
-    sd->sc_count = 0;
-    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
-        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Hide)))
-        sd->status.option &= (OPTION_MASK | OPTION_HIDE);
-    else
-        sd->status.option &= OPTION_MASK;
-
-    // スキルユニット関係の初期化
-    memset (sd->skillunit, 0, sizeof (sd->skillunit));
-    memset (sd->skillunittick, 0, sizeof (sd->skillunittick));
-
-    // init ignore list
-    memset (sd->ignore, 0, sizeof (sd->ignore));
-
-    // パーティー関係の初期化
-    sd->party_sended = 0;
-    sd->party_invite = 0;
-    sd->party_x = -1;
-    sd->party_y = -1;
-    sd->party_hp = -1;
-
-    // ギルド関係の初期化
-    sd->guild_sended = 0;
-    sd->guild_invite = 0;
-    sd->guild_alliance = 0;
-
-    // イベント関係の初期化
-    memset (sd->eventqueue, 0, sizeof (sd->eventqueue));
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        sd->eventtimer[i] = -1;
-
-    // 位置の設定
-    pc_setpos (sd, sd->status.last_point.map, sd->status.last_point.x,
-               sd->status.last_point.y, 0);
-
-    // パーティ、ギルドデータの要求
-    if (sd->status.party_id > 0
-        && (p = party_search (sd->status.party_id)) == NULL)
-        party_request_info (sd->status.party_id);
-    if (sd->status.guild_id > 0
-        && (g = guild_search (sd->status.guild_id)) == NULL)
-        guild_request_info (sd->status.guild_id);
-
-    // pvpの設定
-    sd->pvp_rank = 0;
-    sd->pvp_point = 0;
-    sd->pvp_timer = -1;
-
-    // 通知
-
-    clif_authok (sd);
-    map_addnickdb (sd);
-    if (map_charid2nick (sd->status.char_id) == NULL)
-        map_addchariddb (sd->status.char_id, sd->status.name);
-
-    //スパノビ用死にカウンターのスクリプト変数からの読み出しとsdへのセット
-    sd->die_counter = pc_readglobalreg (sd, "PC_DIE_COUNTER");
-
-    if (night_flag == 1)
-    {
-        char tmpstr[1024];
-        strcpy (tmpstr, msg_txt (500)); // Actually, it's the night...
-        clif_wis_message (sd->fd, wisp_server_name, tmpstr,
-                          strlen (tmpstr) + 1);
-        sd->opt2 |= STATE_BLIND;
-    }
-
-    // ステータス初期計算など
-    pc_calcstatus (sd, 1);
-
-    if (pc_isGM (sd))
-    {
-        printf
-            ("Connection accepted: character '%s' (account: %d; GM level %d).\n",
-             sd->status.name, sd->status.account_id, pc_isGM (sd));
-        clif_updatestatus (sd, SP_GM);
-    }
-    else
-        printf ("Connection accepted: Character '%s' (account: %d).\n",
-                sd->status.name, sd->status.account_id);
-
-    // Message of the Dayの送信
-    {
-        char buf[256];
-        FILE *fp;
-        if ((fp = fopen_ (motd_txt, "r")) != NULL)
-        {
-            while (fgets (buf, sizeof (buf) - 1, fp) != NULL)
-            {
-                int  i;
-                for (i = 0; buf[i]; i++)
-                {
-                    if (buf[i] == '\r' || buf[i] == '\n')
-                    {
-                        buf[i] = 0;
-                        break;
-                    }
-                }
-                clif_displaymessage (sd->fd, buf);
-            }
-            fclose_ (fp);
-        }
-    }
-
-    sd->auto_ban_info.in_progress = 0;
-
-    // Initialize antispam vars
-    sd->chat_reset_due = sd->chat_lines_in = sd->chat_total_repeats =
-        sd->chat_repeat_reset_due = 0;
-    sd->chat_lastmsg[0] = '\0';
-
-    memset(sd->flood_rates, 0, sizeof(sd->flood_rates));
-    sd->packet_flood_reset_due = sd->packet_flood_in = 0;
-
-    // Obtain IP address (if they are still connected)
-    if (!getpeername(sd->fd, (struct sockaddr *)&sai, &sa_len))
-        sd->ip = sai.sin_addr.s_addr;
-
-    // message of the limited time of the account
-    if (connect_until_time != 0)
-    {                           // don't display if it's unlimited or unknow value
-        char tmpstr[1024];
-        strftime (tmpstr, sizeof (tmpstr) - 1, msg_txt (501), gmtime (&connect_until_time));    // "Your account time limit is: %d-%m-%Y %H:%M:%S."
-        clif_wis_message (sd->fd, wisp_server_name, tmpstr,
-                          strlen (tmpstr) + 1);
-    }
-    pc_calcstatus (sd, 1);
-
-    return 0;
-}
-
-/*==========================================
- * session idに問題ありなので後始末
- *------------------------------------------
- */
-int pc_authfail (int id)
-{
-    struct map_session_data *sd;
-
-    sd = map_id2sd (id);
-    if (sd == NULL)
-        return 1;
-
-    clif_authfail_fd (sd->fd, 0);
-
-    return 0;
-}
-
-static int pc_calc_skillpoint (struct map_session_data *sd)
-{
-    int  i, skill_points = 0;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < skill_pool_skills_size; i++) {
-        int lv = sd->status.skill[skill_pool_skills[i]].lv;
-        if (lv)
-            skill_points += ((lv * (lv - 1)) >> 1) - 1;
-    }
-
-    return skill_points;
-}
-
-/*==========================================
- * 覚えられるスキルの計算
- *------------------------------------------
- */
-int pc_calc_skilltree (struct map_session_data *sd)
-{
-    int  i, id = 0, flag;
-    int  c = 0, s = 0;
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-    c = s_class.job;
-    s = (s_class.upper == 1) ? 1 : 0;   //ソ転生以外は通常のスキル?
-
-    if ((battle_config.skillup_limit)
-        && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023)
-            || (c >= 4023 && c < 4045)))
-    {
-        int  skill_point = pc_calc_skillpoint (sd);
-        if (skill_point < 9)
-            c = 0;
-        else if ((sd->status.skill_point >= sd->status.job_level
-                  && skill_point < 58) && ((c > 6 && c < 23) || (c > 4007
-                                                                 && c < 4023)
-                                           || (c > 4029 && c < 4045)))
-        {
-            switch (c)
-            {
-                case 7:
-                case 14:
-                    c = 1;
-                    break;
-                case 8:
-                case 15:
-                    c = 4;
-                    break;
-                case 9:
-                case 16:
-                    c = 2;
-                    break;
-                case 10:
-                case 18:
-                    c = 5;
-                    break;
-                case 11:
-                case 19:
-                case 20:
-                    c = 3;
-                    break;
-                case 12:
-                case 17:
-                    c = 6;
-                    break;
-                case 4008:
-                case 4015:
-                    c = 4002;
-                    break;
-                case 4009:
-                case 4016:
-                    c = 4005;
-                    break;
-                case 4010:
-                case 4017:
-                    c = 4003;
-                    break;
-                case 4011:
-                case 4019:
-                    c = 4006;
-                    break;
-                case 4012:
-                case 4020:
-                case 4021:
-                    c = 4004;
-                    break;
-                case 4013:
-                case 4018:
-                    c = 4007;
-                    break;
-                case 4030:
-                case 4037:
-                    c = 4024;
-                    break;
-                case 4031:
-                case 4038:
-                    c = 4027;
-                    break;
-                case 4032:
-                case 4039:
-                    c = 4025;
-                    break;
-                case 4033:
-                case 4040:
-                    c = 4028;
-                    break;
-                case 4034:
-                case 4041:
-                case 4042:
-                    c = 4026;
-                    break;
-                case 4035:
-                case 4043:
-                    c = 4029;
-                    break;
-
-            }
-        }
-    }
-
-    /*Comment this out for now, as we manage skills differently
-     * for(i=0;i<MAX_SKILL;i++)
-     * if (i < TMW_MAGIC || i > TMW_MAGIC_END){ // [Fate] This hack gets TMW magic working and persisted without bothering about the skill tree.
-     * if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
-     * if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
-     * sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2;   // 本当のlvに
-     * sd->status.skill[i].flag=0;  // flagは0にしておく
-     * }
-     * }
-     */
-
-    if (battle_config.gm_allskill > 0
-        && pc_isGM (sd) >= battle_config.gm_allskill)
-    {
-        // 全てのスキル
-        for (i = 1; i < 158; i++)
-            sd->status.skill[i].id = i;
-        for (i = 210; i < 291; i++)
-            sd->status.skill[i].id = i;
-        for (i = 304; i < 337; i++)
-            sd->status.skill[i].id = i;
-        if (battle_config.enable_upper_class)
-        {                       //confで無効でなければ読み込む
-            for (i = 355; i < MAX_SKILL; i++)
-                sd->status.skill[i].id = i;
-        }
-
-    }
-    else
-    {
-        // 通常の計算
-        do
-        {
-            flag = 0;
-            for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
-            {
-                int  j, f = 1;
-                if (!battle_config.skillfree)
-                {
-                    for (j = 0; j < 5; j++)
-                    {
-                        if (skill_tree[s][c][i].need[j].id &&
-                            pc_checkskill (sd,
-                                           skill_tree[s][c][i].need[j].id) <
-                            skill_tree[s][c][i].need[j].lv)
-                            f = 0;
-                    }
-                }
-                if (f && sd->status.skill[id].id == 0)
-                {
-                    sd->status.skill[id].id = id;
-                    flag = 1;
-                }
-            }
-        }
-        while (flag);
-    }
-//  if(battle_config.etc_log)
-//      printf("calc skill_tree\n");
-    return 0;
-}
-
-/*==========================================
- * 重量アイコンの確認
- *------------------------------------------
- */
-int pc_checkweighticon (struct map_session_data *sd)
-{
-    int  flag = 0;
-
-    nullpo_retr (0, sd);
-
-    if (sd->weight * 2 >= sd->max_weight
-        && sd->sc_data[SC_FLYING_BACKPACK].timer == -1)
-        flag = 1;
-    if (sd->weight * 10 >= sd->max_weight * 9)
-        flag = 2;
-
-    if (flag == 1)
-    {
-        if (sd->sc_data[SC_WEIGHT50].timer == -1)
-            skill_status_change_start (&sd->bl, SC_WEIGHT50, 0, 0, 0, 0, 0,
-                                       0);
-    }
-    else
-    {
-        skill_status_change_end (&sd->bl, SC_WEIGHT50, -1);
-    }
-    if (flag == 2)
-    {
-        if (sd->sc_data[SC_WEIGHT90].timer == -1)
-            skill_status_change_start (&sd->bl, SC_WEIGHT90, 0, 0, 0, 0, 0,
-                                       0);
-    }
-    else
-    {
-        skill_status_change_end (&sd->bl, SC_WEIGHT90, -1);
-    }
-    return 0;
-}
-
-void pc_set_weapon_look (struct map_session_data *sd)
-{
-    if (sd->attack_spell_override)
-        clif_changelook (&sd->bl, LOOK_WEAPON,
-                         sd->attack_spell_look_override);
-    else
-        clif_changelook (&sd->bl, LOOK_WEAPON, sd->status.weapon);
-}
-
-/*==========================================
- * パラメータ計算
- * first==0の時、計算対象のパラメータが呼び出し前から
- * 変 化した場合自動でsendするが、
- * 能動的に変化させたパラメータは自前でsendするように
- *------------------------------------------
- */
-int pc_calcstatus (struct map_session_data *sd, int first)
-{
-    int  b_speed, b_max_hp, b_max_sp, b_hp, b_sp, b_weight, b_max_weight,
-        b_paramb[6], b_parame[6], b_hit, b_flee;
-    int  b_aspd, b_watk, b_def, b_watk2, b_def2, b_flee2, b_critical,
-        b_attackrange, b_matk1, b_matk2, b_mdef, b_mdef2, b_class;
-    int  b_base_atk;
-    struct skill b_skill[MAX_SKILL];
-    int  i, bl, index;
-    int  skill, aspd_rate, wele, wele_, def_ele, refinedef = 0;
-    int  str, dstr, dex;
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    //転生や養子の場合の元の職業を算出する
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    b_speed = sd->speed;
-    b_max_hp = sd->status.max_hp;
-    b_max_sp = sd->status.max_sp;
-    b_hp = sd->status.hp;
-    b_sp = sd->status.sp;
-    b_weight = sd->weight;
-    b_max_weight = sd->max_weight;
-    memcpy (b_paramb, &sd->paramb, sizeof (b_paramb));
-    memcpy (b_parame, &sd->paramc, sizeof (b_parame));
-    memcpy (b_skill, &sd->status.skill, sizeof (b_skill));
-    b_hit = sd->hit;
-    b_flee = sd->flee;
-    b_aspd = sd->aspd;
-    b_watk = sd->watk;
-    b_def = sd->def;
-    b_watk2 = sd->watk2;
-    b_def2 = sd->def2;
-    b_flee2 = sd->flee2;
-    b_critical = sd->critical;
-    b_attackrange = sd->attackrange;
-    b_matk1 = sd->matk1;
-    b_matk2 = sd->matk2;
-    b_mdef = sd->mdef;
-    b_mdef2 = sd->mdef2;
-    b_class = sd->view_class;
-    sd->view_class = sd->status.pc_class;
-    b_base_atk = sd->base_atk;
-
-    pc_calc_skilltree (sd);     // スキルツリーの計算
-
-    sd->max_weight = max_weight_base[s_class.job] + sd->status.str * 300;
-
-    if (first & 1)
-    {
-        sd->weight = 0;
-        for (i = 0; i < MAX_INVENTORY; i++)
-        {
-            if (sd->status.inventory[i].nameid == 0
-                || sd->inventory_data[i] == NULL)
-                continue;
-            sd->weight +=
-                sd->inventory_data[i]->weight *
-                sd->status.inventory[i].amount;
-        }
-        sd->cart_max_weight = battle_config.max_cart_weight;
-        sd->cart_weight = 0;
-        sd->cart_max_num = MAX_CART;
-        sd->cart_num = 0;
-        for (i = 0; i < MAX_CART; i++)
-        {
-            if (sd->status.cart[i].nameid == 0)
-                continue;
-            sd->cart_weight +=
-                itemdb_weight (sd->status.cart[i].nameid) *
-                sd->status.cart[i].amount;
-            sd->cart_num++;
-        }
-    }
-
-    memset (sd->paramb, 0, sizeof (sd->paramb));
-    memset (sd->parame, 0, sizeof (sd->parame));
-    sd->hit = 0;
-    sd->flee = 0;
-    sd->flee2 = 0;
-    sd->critical = 0;
-    sd->aspd = 0;
-    sd->watk = 0;
-    sd->def = 0;
-    sd->mdef = 0;
-    sd->watk2 = 0;
-    sd->def2 = 0;
-    sd->mdef2 = 0;
-    sd->status.max_hp = 0;
-    sd->status.max_sp = 0;
-    sd->attackrange = 0;
-    sd->attackrange_ = 0;
-    sd->atk_ele = 0;
-    sd->def_ele = 0;
-    sd->star = 0;
-    sd->overrefine = 0;
-    sd->matk1 = 0;
-    sd->matk2 = 0;
-    sd->speed = DEFAULT_WALK_SPEED;
-    sd->hprate = 100;
-    sd->sprate = 100;
-    sd->castrate = 100;
-    sd->dsprate = 100;
-    sd->base_atk = 0;
-    sd->arrow_atk = 0;
-    sd->arrow_ele = 0;
-    sd->arrow_hit = 0;
-    sd->arrow_range = 0;
-    sd->nhealhp = sd->nhealsp = sd->nshealhp = sd->nshealsp = sd->nsshealhp =
-        sd->nsshealsp = 0;
-    memset (sd->addele, 0, sizeof (sd->addele));
-    memset (sd->addrace, 0, sizeof (sd->addrace));
-    memset (sd->addsize, 0, sizeof (sd->addsize));
-    memset (sd->addele_, 0, sizeof (sd->addele_));
-    memset (sd->addrace_, 0, sizeof (sd->addrace_));
-    memset (sd->addsize_, 0, sizeof (sd->addsize_));
-    memset (sd->subele, 0, sizeof (sd->subele));
-    memset (sd->subrace, 0, sizeof (sd->subrace));
-    memset (sd->addeff, 0, sizeof (sd->addeff));
-    memset (sd->addeff2, 0, sizeof (sd->addeff2));
-    memset (sd->reseff, 0, sizeof (sd->reseff));
-    memset (&sd->special_state, 0, sizeof (sd->special_state));
-    memset (sd->weapon_coma_ele, 0, sizeof (sd->weapon_coma_ele));
-    memset (sd->weapon_coma_race, 0, sizeof (sd->weapon_coma_race));
-
-    sd->watk_ = 0;              //二刀流用(仮)
-    sd->watk_2 = 0;
-    sd->atk_ele_ = 0;
-    sd->star_ = 0;
-    sd->overrefine_ = 0;
-
-    sd->aspd_rate = 100;
-    sd->speed_rate = 100;
-    sd->hprecov_rate = 100;
-    sd->sprecov_rate = 100;
-    sd->critical_def = 0;
-    sd->double_rate = 0;
-    sd->near_attack_def_rate = sd->long_attack_def_rate = 0;
-    sd->atk_rate = sd->matk_rate = 100;
-    sd->ignore_def_ele = sd->ignore_def_race = 0;
-    sd->ignore_def_ele_ = sd->ignore_def_race_ = 0;
-    sd->ignore_mdef_ele = sd->ignore_mdef_race = 0;
-    sd->arrow_cri = 0;
-    sd->magic_def_rate = sd->misc_def_rate = 0;
-    memset (sd->arrow_addele, 0, sizeof (sd->arrow_addele));
-    memset (sd->arrow_addrace, 0, sizeof (sd->arrow_addrace));
-    memset (sd->arrow_addsize, 0, sizeof (sd->arrow_addsize));
-    memset (sd->arrow_addeff, 0, sizeof (sd->arrow_addeff));
-    memset (sd->arrow_addeff2, 0, sizeof (sd->arrow_addeff2));
-    memset (sd->magic_addele, 0, sizeof (sd->magic_addele));
-    memset (sd->magic_addrace, 0, sizeof (sd->magic_addrace));
-    memset (sd->magic_subrace, 0, sizeof (sd->magic_subrace));
-    sd->perfect_hit = 0;
-    sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
-    sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
-    sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0;
-    sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0;
-    sd->get_zeny_num = 0;
-    sd->add_damage_class_count = sd->add_damage_class_count_ =
-        sd->add_magic_damage_class_count = 0;
-    sd->add_def_class_count = sd->add_mdef_class_count = 0;
-    sd->monster_drop_item_count = 0;
-    memset (sd->add_damage_classrate, 0, sizeof (sd->add_damage_classrate));
-    memset (sd->add_damage_classrate_, 0, sizeof (sd->add_damage_classrate_));
-    memset (sd->add_magic_damage_classrate, 0,
-            sizeof (sd->add_magic_damage_classrate));
-    memset (sd->add_def_classrate, 0, sizeof (sd->add_def_classrate));
-    memset (sd->add_mdef_classrate, 0, sizeof (sd->add_mdef_classrate));
-    memset (sd->monster_drop_race, 0, sizeof (sd->monster_drop_race));
-    memset (sd->monster_drop_itemrate, 0, sizeof (sd->monster_drop_itemrate));
-    sd->speed_add_rate = sd->aspd_add_rate = 100;
-    sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0;
-    sd->splash_range = sd->splash_add_range = 0;
-    sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0;
-    sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate =
-        sd->sp_drain_per = 0;
-    sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ =
-        sd->sp_drain_per_ = 0;
-    sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
-    sd->magic_damage_return = 0;    //AppleGirl Was Here
-    sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
-
-    if (!sd->disguiseflag && sd->disguise)
-    {
-        sd->disguise = 0;
-        pc_set_weapon_look (sd);
-        clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
-        clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
-        clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
-        clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
-        clif_clearchar (&sd->bl, 9);
-        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
-    }
-
-    sd->spellpower_bonus_target = 0;
-
-    for (i = 0; i < 10; i++)
-    {
-        index = sd->equip_index[i];
-        if (index < 0)
-            continue;
-        if (i == 9 && sd->equip_index[8] == index)
-            continue;
-        if (i == 5 && sd->equip_index[4] == index)
-            continue;
-        if (i == 6
-            && (sd->equip_index[5] == index || sd->equip_index[4] == index))
-            continue;
-
-        if (sd->inventory_data[index])
-        {
-            sd->spellpower_bonus_target +=
-                sd->inventory_data[index]->magic_bonus;
-
-            if (sd->inventory_data[index]->type == 4)
-            {
-                if (sd->status.inventory[index].card[0] != 0x00ff
-                    && sd->status.inventory[index].card[0] != 0x00fe
-                    && sd->status.inventory[index].card[0] != (short) 0xff00)
-                {
-                    int  j;
-                    for (j = 0; j < sd->inventory_data[index]->slot; j++)
-                    {           // カード
-                        int  c = sd->status.inventory[index].card[j];
-                        if (c > 0)
-                        {
-                            argrec_t arg[2];
-                            arg[0].name = "@slotId";
-                            arg[0].v.i = i;
-                            arg[1].name = "@itemId";
-                            arg[1].v.i = sd->inventory_data[index]->nameid;
-                            if (i == 8
-                                && sd->status.inventory[index].equip == 0x20)
-                                sd->state.lr_flag = 1;
-                            run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
-                                        0, 2, arg);
-                            sd->state.lr_flag = 0;
-                        }
-                    }
-                }
-            }
-            else if (sd->inventory_data[index]->type == 5)
-            {                   // 防具
-                if (sd->status.inventory[index].card[0] != 0x00ff
-                    && sd->status.inventory[index].card[0] != 0x00fe
-                    && sd->status.inventory[index].card[0] != (short) 0xff00)
-                {
-                    int  j;
-                    for (j = 0; j < sd->inventory_data[index]->slot; j++)
-                    {           // カード
-                        int  c = sd->status.inventory[index].card[j];
-                        if (c > 0) {
-                            argrec_t arg[2];
-                            arg[0].name = "@slotId";
-                            arg[0].v.i = i;
-                            arg[1].name = "@itemId";
-                            arg[1].v.i = sd->inventory_data[index]->nameid;
-                            run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
-                                        0, 2, arg);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-#ifdef USE_ASTRAL_SOUL_SKILL
-    if (sd->spellpower_bonus_target < 0)
-        sd->spellpower_bonus_target =
-            (sd->spellpower_bonus_target * 256) /
-            (MIN (128 + skill_power (sd, TMW_ASTRAL_SOUL), 256));
-#endif
-
-    if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
-        sd->spellpower_bonus_current = sd->spellpower_bonus_target;
-
-    wele = sd->atk_ele;
-    wele_ = sd->atk_ele_;
-    def_ele = sd->def_ele;
-    memcpy (sd->paramcard, sd->parame, sizeof (sd->paramcard));
-
-    // 装備品によるステータス変化はここで実行
-    for (i = 0; i < 10; i++)
-    {
-        index = sd->equip_index[i];
-        if (index < 0)
-            continue;
-        if (i == 9 && sd->equip_index[8] == index)
-            continue;
-        if (i == 5 && sd->equip_index[4] == index)
-            continue;
-        if (i == 6
-            && (sd->equip_index[5] == index || sd->equip_index[4] == index))
-            continue;
-        if (sd->inventory_data[index])
-        {
-            sd->def += sd->inventory_data[index]->def;
-            if (sd->inventory_data[index]->type == 4)
-            {
-                int  r, wlv = sd->inventory_data[index]->wlv;
-                if (i == 8 && sd->status.inventory[index].equip == 0x20)
-                {
-                    //二刀流用データ入力
-                    sd->watk_ += sd->inventory_data[index]->atk;
-                    sd->watk_2 = (r = sd->status.inventory[index].refine) * // 精錬攻撃力
-                        refinebonus[wlv][0];
-                    if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
-                        sd->overrefine_ = r * refinebonus[wlv][1];
-
-                    if (sd->status.inventory[index].card[0] == 0x00ff)
-                    {           // 製造武器
-                        sd->star_ = (sd->status.inventory[index].card[1] >> 8); // 星のかけら
-                        wele_ = (sd->status.inventory[index].card[1] & 0x0f);   // 属 性
-                    }
-                    sd->attackrange_ += sd->inventory_data[index]->range;
-                    sd->state.lr_flag = 1;
-                    {
-                        argrec_t arg[2];
-                        arg[0].name = "@slotId";
-                        arg[0].v.i = i;
-                        arg[1].name = "@itemId";
-                        arg[1].v.i = sd->inventory_data[index]->nameid;
-                        run_script_l (sd->inventory_data[index]->equip_script, 0,
-                                      sd->bl.id, 0, 2, arg);
-                    }
-                    sd->state.lr_flag = 0;
-                }
-                else
-                {               //二刀流武器以外
-                    argrec_t arg[2];
-                    arg[0].name = "@slotId";
-                    arg[0].v.i = i;
-                    arg[1].name = "@itemId";
-                    arg[1].v.i = sd->inventory_data[index]->nameid;
-                    sd->watk += sd->inventory_data[index]->atk;
-                    sd->watk2 += (r = sd->status.inventory[index].refine) * // 精錬攻撃力
-                        refinebonus[wlv][0];
-                    if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
-                        sd->overrefine += r * refinebonus[wlv][1];
-
-                    if (sd->status.inventory[index].card[0] == 0x00ff)
-                    {           // 製造武器
-                        sd->star += (sd->status.inventory[index].card[1] >> 8); // 星のかけら
-                        wele = (sd->status.inventory[index].card[1] & 0x0f);    // 属 性
-                    }
-                    sd->attackrange += sd->inventory_data[index]->range;
-                    run_script_l (sd->inventory_data[index]->equip_script, 0,
-                                  sd->bl.id, 0, 2, arg);
-                }
-            }
-            else if (sd->inventory_data[index]->type == 5)
-            {
-                argrec_t arg[2];
-                arg[0].name = "@slotId";
-                arg[0].v.i = i;
-                arg[1].name = "@itemId";
-                arg[1].v.i = sd->inventory_data[index]->nameid;
-                sd->watk += sd->inventory_data[index]->atk;
-                refinedef +=
-                    sd->status.inventory[index].refine * refinebonus[0][0];
-                run_script_l (sd->inventory_data[index]->equip_script, 0,
-                              sd->bl.id, 0, 2, arg);
-            }
-        }
-    }
-
-    if (battle_is_unarmed (&sd->bl))
-    {
-        sd->watk += skill_power (sd, TMW_BRAWLING) / 3; // +66 for 200
-        sd->watk2 += skill_power (sd, TMW_BRAWLING) >> 3;   // +25 for 200
-        sd->watk_ += skill_power (sd, TMW_BRAWLING) / 3;    // +66 for 200
-        sd->watk_2 += skill_power (sd, TMW_BRAWLING) >> 3;  // +25 for 200
-    }
-
-    if (sd->equip_index[10] >= 0)
-    {                           // 矢
-        index = sd->equip_index[10];
-        if (sd->inventory_data[index])
-        {                       //まだ属性が入っていない
-            argrec_t arg[2];
-            arg[0].name = "@slotId";
-            arg[0].v.i = i;
-            arg[1].name = "@itemId";
-            arg[1].v.i = sd->inventory_data[index]->nameid;
-            sd->state.lr_flag = 2;
-            run_script_l (sd->inventory_data[index]->equip_script, 0, sd->bl.id,
-                        0, 2, arg);
-            sd->state.lr_flag = 0;
-            sd->arrow_atk += sd->inventory_data[index]->atk;
-        }
-    }
-    sd->def += (refinedef + 50) / 100;
-
-    if (sd->attackrange < 1)
-        sd->attackrange = 1;
-    if (sd->attackrange_ < 1)
-        sd->attackrange_ = 1;
-    if (sd->attackrange < sd->attackrange_)
-        sd->attackrange = sd->attackrange_;
-    if (sd->status.weapon == 11)
-        sd->attackrange += sd->arrow_range;
-    if (wele > 0)
-        sd->atk_ele = wele;
-    if (wele_ > 0)
-        sd->atk_ele_ = wele_;
-    if (def_ele > 0)
-        sd->def_ele = def_ele;
-    sd->double_rate += sd->double_add_rate;
-    sd->perfect_hit += sd->perfect_hit_add;
-    sd->get_zeny_num += sd->get_zeny_add_num;
-    sd->splash_range += sd->splash_add_range;
-    if (sd->speed_add_rate != 100)
-        sd->speed_rate += sd->speed_add_rate - 100;
-    if (sd->aspd_add_rate != 100)
-        sd->aspd_rate += sd->aspd_add_rate - 100;
-
-    // 武器ATKサイズ補正 (右手)
-    sd->atkmods[0] = atkmods[0][sd->weapontype1];
-    sd->atkmods[1] = atkmods[1][sd->weapontype1];
-    sd->atkmods[2] = atkmods[2][sd->weapontype1];
-    //武器ATKサイズ補正 (左手)
-    sd->atkmods_[0] = atkmods[0][sd->weapontype2];
-    sd->atkmods_[1] = atkmods[1][sd->weapontype2];
-    sd->atkmods_[2] = atkmods[2][sd->weapontype2];
-
-/*
-	// jobボーナス分
-	for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){
-		if(job_bonus[s_class.upper][s_class.job][i])
-			sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++;
-	}
-*/
-
-    if ((skill = pc_checkskill (sd, MC_INCCARRY)) > 0)  // skill can be used with an item now, thanks to orn [Valaris]
-        sd->max_weight += skill * 1000;
-
-    // ステータス変化による基本パラメータ補正
-    if (sd->sc_count)
-    {
-        if (sd->sc_data[SC_CONCENTRATE].timer != -1
-            && sd->sc_data[SC_QUAGMIRE].timer == -1)
-        {                       // 集中力向上
-            sd->paramb[1] +=
-                (sd->status.agi + sd->paramb[1] + sd->parame[1] -
-                 sd->paramcard[1]) * (2 +
-                                      sd->sc_data[SC_CONCENTRATE].val1) / 100;
-            sd->paramb[4] +=
-                (sd->status.dex + sd->paramb[4] + sd->parame[4] -
-                 sd->paramcard[4]) * (2 +
-                                      sd->sc_data[SC_CONCENTRATE].val1) / 100;
-        }
-        if (sd->sc_data[SC_INCREASEAGI].timer != -1
-            && sd->sc_data[SC_QUAGMIRE].timer == -1
-            && sd->sc_data[SC_DONTFORGETME].timer == -1)
-        {                       // 速度増加
-            sd->paramb[1] += 2 + sd->sc_data[SC_INCREASEAGI].val1;
-            sd->speed -= sd->speed * 25 / 100;
-        }
-        if (sd->sc_data[SC_DECREASEAGI].timer != -1)    // 速度減少(agiはbattle.cで)
-            sd->speed = sd->speed * 125 / 100;
-        if (sd->sc_data[SC_CLOAKING].timer != -1)
-            sd->speed =
-                (sd->speed * (76 + (sd->sc_data[SC_INCREASEAGI].val1 * 3))) /
-                100;
-        if (sd->sc_data[SC_BLESSING].timer != -1)
-        {                       // ブレッシング
-            sd->paramb[0] += sd->sc_data[SC_BLESSING].val1;
-            sd->paramb[3] += sd->sc_data[SC_BLESSING].val1;
-            sd->paramb[4] += sd->sc_data[SC_BLESSING].val1;
-        }
-        if (sd->sc_data[SC_GLORIA].timer != -1) // グロリア
-            sd->paramb[5] += 30;
-        if (sd->sc_data[SC_LOUD].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1)   // ラウドボイス
-            sd->paramb[0] += 4;
-        if (sd->sc_data[SC_QUAGMIRE].timer != -1)
-        {                       // クァグマイア
-            sd->speed = sd->speed * 3 / 2;
-            sd->paramb[1] -=
-                (sd->status.agi + sd->paramb[1] + sd->parame[1]) / 2;
-            sd->paramb[4] -=
-                (sd->status.dex + sd->paramb[4] + sd->parame[4]) / 2;
-        }
-        if (sd->sc_data[SC_TRUESIGHT].timer != -1)
-        {                       // トゥルーサイト
-            sd->paramb[0] += 5;
-            sd->paramb[1] += 5;
-            sd->paramb[2] += 5;
-            sd->paramb[3] += 5;
-            sd->paramb[4] += 5;
-            sd->paramb[5] += 5;
-        }
-    }
-    sd->speed -= skill_power (sd, TMW_SPEED) >> 3;
-    sd->aspd_rate -= skill_power (sd, TMW_SPEED) / 10;
-    if (sd->aspd_rate < 20)
-        sd->aspd_rate = 20;
-
-/*
-	//1度も死んでないJob70スパノビに+10
-	if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
-		sd->paramb[0]+= 15;
-		sd->paramb[1]+= 15;
-		sd->paramb[2]+= 15;
-		sd->paramb[3]+= 15;
-		sd->paramb[4]+= 15;
-		sd->paramb[5]+= 15;
-	}
-*/
-    sd->paramc[0] = sd->status.str + sd->paramb[0] + sd->parame[0];
-    sd->paramc[1] = sd->status.agi + sd->paramb[1] + sd->parame[1];
-    sd->paramc[2] = sd->status.vit + sd->paramb[2] + sd->parame[2];
-    sd->paramc[3] = sd->status.int_ + sd->paramb[3] + sd->parame[3];
-    sd->paramc[4] = sd->status.dex + sd->paramb[4] + sd->parame[4];
-    sd->paramc[5] = sd->status.luk + sd->paramb[5] + sd->parame[5];
-    for (i = 0; i < 6; i++)
-        if (sd->paramc[i] < 0)
-            sd->paramc[i] = 0;
-
-    if (sd->status.weapon == 11 || sd->status.weapon == 13
-        || sd->status.weapon == 14)
-    {
-        str = sd->paramc[4];
-        dex = sd->paramc[0];
-    }
-    else
-    {
-        str = sd->paramc[0];
-        dex = sd->paramc[4];
-        sd->critical += ((dex * 3) >> 1);
-    }
-    dstr = str / 10;
-    sd->base_atk += str + dstr * dstr + dex / 5 + sd->paramc[5] / 5;
-//fprintf(stderr, "baseatk = %d = x + %d + %d + %d + %d\n", sd->base_atk, str, dstr*dstr, dex/5, sd->paramc[5]/5);
-    sd->matk1 += sd->paramc[3] + (sd->paramc[3] / 5) * (sd->paramc[3] / 5);
-    sd->matk2 += sd->paramc[3] + (sd->paramc[3] / 7) * (sd->paramc[3] / 7);
-    if (sd->matk1 < sd->matk2)
-    {
-        int  temp = sd->matk2;
-        sd->matk2 = sd->matk1;
-        sd->matk1 = temp;
-    }
-    // [Fate] New tmw magic system
-    sd->matk1 += sd->status.base_level + sd->spellpower_bonus_current;
-#ifdef USE_ASTRAL_SOUL_SKILL
-    if (sd->matk1 > MAGIC_SKILL_THRESHOLD)
-    {
-        int  bonus = sd->matk1 - MAGIC_SKILL_THRESHOLD;
-        // Ok if you are above a certain threshold, you get only (1/8) of that matk1
-        // if you have Astral soul skill you can get the whole power again (and additionally the 1/8 added)
-        sd->matk1 = MAGIC_SKILL_THRESHOLD + (bonus>>3) + ((3*bonus*skill_power(sd, TMW_ASTRAL_SOUL))>>9);
-    }
-#endif
-    sd->matk2 = 0;
-    if (sd->matk1 < 0)
-        sd->matk1 = 0;
-
-    sd->hit += sd->paramc[4] + sd->status.base_level;
-    sd->flee += sd->paramc[1] + sd->status.base_level;
-    sd->def2 += sd->paramc[2];
-    sd->mdef2 += sd->paramc[3];
-    sd->flee2 += sd->paramc[5] + 10;
-    sd->critical += (sd->paramc[5] * 3) + 10;
-
-    // 200 is the maximum of the skill
-    // def2 is the defence gained by vit, whereas "def", which is gained by armor, stays as is
-    int spbsk = skill_power (sd, TMW_RAGING);
-    if (spbsk != 0 && sd->attackrange <= 2)
-    {
-        sd->critical += sd->critical * spbsk / 100;
-        sd->def2 = (sd->def2 * 256) / (256 + spbsk);
-    }
-
-    if (sd->base_atk < 1)
-        sd->base_atk = 1;
-    if (sd->critical_rate != 100)
-        sd->critical = (sd->critical * sd->critical_rate) / 100;
-    if (sd->critical < 10)
-        sd->critical = 10;
-    if (sd->hit_rate != 100)
-        sd->hit = (sd->hit * sd->hit_rate) / 100;
-    if (sd->hit < 1)
-        sd->hit = 1;
-    if (sd->flee_rate != 100)
-        sd->flee = (sd->flee * sd->flee_rate) / 100;
-    if (sd->flee < 1)
-        sd->flee = 1;
-    if (sd->flee2_rate != 100)
-        sd->flee2 = (sd->flee2 * sd->flee2_rate) / 100;
-    if (sd->flee2 < 10)
-        sd->flee2 = 10;
-    if (sd->def_rate != 100)
-        sd->def = (sd->def * sd->def_rate) / 100;
-    if (sd->def < 0)
-        sd->def = 0;
-    if (sd->def2_rate != 100)
-        sd->def2 = (sd->def2 * sd->def2_rate) / 100;
-    if (sd->def2 < 1)
-        sd->def2 = 1;
-    if (sd->mdef_rate != 100)
-        sd->mdef = (sd->mdef * sd->mdef_rate) / 100;
-    if (sd->mdef < 0)
-        sd->mdef = 0;
-    if (sd->mdef2_rate != 100)
-        sd->mdef2 = (sd->mdef2 * sd->mdef2_rate) / 100;
-    if (sd->mdef2 < 1)
-        sd->mdef2 = 1;
-
-    // 二刀流 ASPD 修正
-    if (sd->status.weapon <= 16)
-        sd->aspd +=
-            aspd_base[s_class.job][sd->status.weapon] - (sd->paramc[1] * 4 +
-                                                         sd->paramc[4]) *
-            aspd_base[s_class.job][sd->status.weapon] / 1000;
-    else
-        sd->aspd += ((aspd_base[s_class.job][sd->weapontype1] -
-                      (sd->paramc[1] * 4 +
-                       sd->paramc[4]) *
-                      aspd_base[s_class.job][sd->weapontype1] / 1000) +
-                     (aspd_base[s_class.job][sd->weapontype2] -
-                      (sd->paramc[1] * 4 +
-                       sd->paramc[4]) *
-                      aspd_base[s_class.job][sd->weapontype2] / 1000)) * 140 /
-            200;
-
-    aspd_rate = sd->aspd_rate;
-
-    //攻撃速度増加
-
-    if ((skill = pc_checkskill (sd, AC_VULTURE)) > 0)
-    {                           // ワシの目
-        sd->hit += skill;
-        if (sd->status.weapon == 11)
-            sd->attackrange += skill;
-    }
-
-    if (sd->attackrange > 2)
-    {                           // [fate] ranged weapon?
-        sd->attackrange += MIN (skill_power (sd, AC_OWL) / 60, 3);
-        sd->hit += skill_power (sd, AC_OWL) / 10;   // 20 for 200
-    }
-
-    if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0)    // 武器研究の命中率増加
-        sd->hit += skill * 2;
-    if (sd->status.option & 2 && (skill = pc_checkskill (sd, RG_TUNNELDRIVE)) > 0)  // トンネルドライブ
-        sd->speed += (1.2 * DEFAULT_WALK_SPEED - skill * 9);
-    if (pc_iscarton (sd) && (skill = pc_checkskill (sd, MC_PUSHCART)) > 0)  // カートによる速度低下
-        sd->speed += (10 - skill) * (DEFAULT_WALK_SPEED * 0.1);
-    else if (pc_isriding (sd))  // ペコペコ乗りによる速度増加
-        sd->speed -= (0.25 * DEFAULT_WALK_SPEED);
-    sd->max_weight += 1000;
-    if (sd->sc_count)
-    {
-        if (sd->sc_data[SC_WINDWALK].timer != -1)   //ウィンドウォーク時はLv*2%減算
-            sd->speed -=
-                sd->speed * (sd->sc_data[SC_WINDWALK].val1 * 2) / 100;
-        if (sd->sc_data[SC_CARTBOOST].timer != -1)  // カートブースト
-            sd->speed -= (DEFAULT_WALK_SPEED * 20) / 100;
-        if (sd->sc_data[SC_BERSERK].timer != -1)    //バーサーク中はIAと同じぐらい速い?
-            sd->speed -= sd->speed * 25 / 100;
-        if (sd->sc_data[SC_WEDDING].timer != -1)    //結婚中は歩くのが遅い
-            sd->speed = 2 * DEFAULT_WALK_SPEED;
-    }
-
-    if ((skill = pc_checkskill (sd, CR_TRUST)) > 0)
-    {                           // フェイス
-        sd->status.max_hp += skill * 200;
-        sd->subele[6] += skill * 5;
-    }
-    if ((skill = pc_checkskill (sd, BS_SKINTEMPER)) > 0)
-        sd->subele[3] += skill * 4;
-
-    bl = sd->status.base_level;
-
-    sd->status.max_hp +=
-        (3500 + bl * hp_coefficient2[s_class.job] +
-         hp_sigma_val[s_class.job][(bl > 0) ? bl - 1 : 0]) / 100 * (100 +
-                                                                    sd->paramc
-                                                                    [2]) /
-        100 + (sd->parame[2] - sd->paramcard[2]);
-    if (s_class.upper == 1)     // [MouseJstr]
-        sd->status.max_hp = sd->status.max_hp * 130 / 100;
-    if (sd->hprate != 100)
-        sd->status.max_hp = sd->status.max_hp * sd->hprate / 100;
-
-    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1)
-    {                           // バーサーク
-        sd->status.max_hp = sd->status.max_hp * 3;
-        sd->status.hp = sd->status.hp * 3;
-        if (sd->status.max_hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
-            sd->status.max_hp = battle_config.max_hp;
-        if (sd->status.hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
-            sd->status.hp = battle_config.max_hp;
-    }
-    if (s_class.job == 23 && sd->status.base_level >= 99)
-    {
-        sd->status.max_hp = sd->status.max_hp + 2000;
-    }
-
-    if (sd->status.max_hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
-        sd->status.max_hp = battle_config.max_hp;
-    if (sd->status.max_hp <= 0)
-        sd->status.max_hp = 1;  // end
-
-    // 最大SP計算
-    sd->status.max_sp +=
-        ((sp_coefficient[s_class.job] * bl) + 1000) / 100 * (100 +
-                                                             sd->paramc[3]) /
-        100 + (sd->parame[3] - sd->paramcard[3]);
-    if (s_class.upper == 1)     // [MouseJstr]
-        sd->status.max_sp = sd->status.max_sp * 130 / 100;
-    if (sd->sprate != 100)
-        sd->status.max_sp = sd->status.max_sp * sd->sprate / 100;
-
-    if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ
-        sd->status.max_sp += sd->status.max_sp * skill / 100;
-    if ((skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0) // ソウルドレイン
-        sd->status.max_sp += sd->status.max_sp * 2 * skill / 100;
-
-    if (sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
-        sd->status.max_sp = battle_config.max_sp;
-
-    //自然回復HP
-    sd->nhealhp = 1 + (sd->paramc[2] / 5) + (sd->status.max_hp / 200);
-    if ((skill = pc_checkskill (sd, SM_RECOVERY)) > 0)
-    {                           // HP回復力向上
-        sd->nshealhp = skill * 5 + (sd->status.max_hp * skill / 500);
-        if (sd->nshealhp > 0x7fff)
-            sd->nshealhp = 0x7fff;
-    }
-    //自然回復SP
-    sd->nhealsp = 1 + (sd->paramc[3] / 6) + (sd->status.max_sp / 100);
-    if (sd->paramc[3] >= 120)
-        sd->nhealsp += ((sd->paramc[3] - 120) >> 1) + 4;
-    if ((skill = pc_checkskill (sd, MG_SRECOVERY)) > 0)
-    {                           // SP回復力向上
-        sd->nshealsp = skill * 3 + (sd->status.max_sp * skill / 500);
-        if (sd->nshealsp > 0x7fff)
-            sd->nshealsp = 0x7fff;
-    }
-
-    if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0)
-    {
-        sd->nsshealhp = skill * 4 + (sd->status.max_hp * skill / 500);
-        sd->nsshealsp = skill * 2 + (sd->status.max_sp * skill / 500);
-        if (sd->nsshealhp > 0x7fff)
-            sd->nsshealhp = 0x7fff;
-        if (sd->nsshealsp > 0x7fff)
-            sd->nsshealsp = 0x7fff;
-    }
-    if (sd->hprecov_rate != 100)
-    {
-        sd->nhealhp = sd->nhealhp * sd->hprecov_rate / 100;
-        if (sd->nhealhp < 1)
-            sd->nhealhp = 1;
-    }
-    if (sd->sprecov_rate != 100)
-    {
-        sd->nhealsp = sd->nhealsp * sd->sprecov_rate / 100;
-        if (sd->nhealsp < 1)
-            sd->nhealsp = 1;
-    }
-    if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0)
-    {                           // メディテイティオはSPRではなく自然回復にかかる
-        sd->nhealsp += 3 * skill * (sd->status.max_sp) / 100;
-        if (sd->nhealsp > 0x7fff)
-            sd->nhealsp = 0x7fff;
-    }
-
-    // 種族耐性(これでいいの? ディバインプロテクションと同じ処理がいるかも)
-    if ((skill = pc_checkskill (sd, SA_DRAGONOLOGY)) > 0)
-    {                           // ドラゴノロジー
-        skill = skill * 4;
-        sd->addrace[9] += skill;
-        sd->addrace_[9] += skill;
-        sd->subrace[9] += skill;
-        sd->magic_addrace[9] += skill;
-        sd->magic_subrace[9] -= skill;
-    }
-
-    //Flee上昇
-    if ((skill = pc_checkskill (sd, TF_MISS)) > 0)
-    {                           // 回避率増加
-        if (sd->status.pc_class == 6 || sd->status.pc_class == 4007
-            || sd->status.pc_class == 23)
-        {
-            sd->flee += skill * 3;
-        }
-        if (sd->status.pc_class == 12 || sd->status.pc_class == 17
-            || sd->status.pc_class == 4013 || sd->status.pc_class == 4018)
-            sd->flee += skill * 4;
-        if (sd->status.pc_class == 12 || sd->status.pc_class == 4013)
-            sd->speed -= sd->speed * (skill * .5) / 100;
-    }
-    if ((skill = pc_checkskill (sd, MO_DODGE)) > 0) // 見切り
-        sd->flee += (skill * 3) >> 1;
-
-    // スキルやステータス異常による残りのパラメータ補正
-    if (sd->sc_count)
-    {
-        // ATK/DEF変化形
-        if (sd->sc_data[SC_ANGELUS].timer != -1)    // エンジェラス
-            sd->def2 =
-                sd->def2 * (110 + 5 * sd->sc_data[SC_ANGELUS].val1) / 100;
-        if (sd->sc_data[SC_IMPOSITIO].timer != -1)
-        {                       // インポシティオマヌス
-            sd->watk += sd->sc_data[SC_IMPOSITIO].val1 * 5;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 4)
-                sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1 * 5;
-        }
-        if (sd->sc_data[SC_PROVOKE].timer != -1)
-        {                       // プロボック
-            sd->def2 =
-                sd->def2 * (100 - 6 * sd->sc_data[SC_PROVOKE].val1) / 100;
-            sd->base_atk =
-                sd->base_atk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
-            sd->watk =
-                sd->watk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 4)
-                sd->watk_ =
-                    sd->watk_ * (100 +
-                                 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
-        }
-        if (sd->sc_data[SC_ENDURE].timer != -1)
-            sd->mdef2 += sd->sc_data[SC_ENDURE].val1;
-        if (sd->sc_data[SC_MINDBREAKER].timer != -1)
-        {                       // プロボック
-            sd->mdef2 =
-                sd->mdef2 * (100 -
-                             6 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
-            sd->matk1 =
-                sd->matk1 * (100 +
-                             2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
-            sd->matk2 =
-                sd->matk2 * (100 +
-                             2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
-        }
-        if (sd->sc_data[SC_POISON].timer != -1) // 毒状態
-            sd->def2 = sd->def2 * 75 / 100;
-        if (sd->sc_data[SC_DRUMBATTLE].timer != -1)
-        {                       // 戦太鼓の響き
-            sd->watk += sd->sc_data[SC_DRUMBATTLE].val2;
-            sd->def += sd->sc_data[SC_DRUMBATTLE].val3;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 4)
-                sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2;
-        }
-        if (sd->sc_data[SC_NIBELUNGEN].timer != -1)
-        {                       // ニーベルングの指輪
-            index = sd->equip_index[9];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->wlv == 3)
-                sd->watk += sd->sc_data[SC_NIBELUNGEN].val3;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->wlv == 3)
-                sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3;
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->wlv == 4)
-                sd->watk += sd->sc_data[SC_NIBELUNGEN].val2;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->wlv == 4)
-                sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val2;
-        }
-
-        if (sd->sc_data[SC_VOLCANO].timer != -1 && sd->def_ele == 3)
-        {                       // ボルケーノ
-            sd->watk += sd->sc_data[SC_VIOLENTGALE].val3;
-        }
-
-        if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1)
-            sd->def =
-                sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2) / 100;
-        if (sd->sc_data[SC_ETERNALCHAOS].timer != -1)   // エターナルカオス
-            sd->def = 0;
-
-        if (sd->sc_data[SC_CONCENTRATION].timer != -1)
-        {                       //コンセントレーション
-            sd->watk =
-                sd->watk * (100 +
-                            5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
-            index = sd->equip_index[8];
-            if (index >= 0 && sd->inventory_data[index]
-                && sd->inventory_data[index]->type == 4)
-                sd->watk_ =
-                    sd->watk * (100 +
-                                5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
-            sd->def =
-                sd->def * (100 -
-                           5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
-        }
-
-        if (sd->sc_data[SC_MAGICPOWER].timer != -1)
-        {                       //魔法力増幅
-            sd->matk1 =
-                sd->matk1 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
-            sd->matk2 =
-                sd->matk2 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
-        }
-        if (sd->sc_data[SC_ATKPOT].timer != -1)
-            sd->watk += sd->sc_data[SC_ATKPOT].val1;
-        if (sd->sc_data[SC_MATKPOT].timer != -1)
-        {
-            sd->matk1 += sd->sc_data[SC_MATKPOT].val1;
-            sd->matk2 += sd->sc_data[SC_MATKPOT].val1;
-        }
-
-        // ASPD/移動速度変化系
-        if (sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
-            aspd_rate -= 30;
-        if (sd->sc_data[SC_ADRENALINE].timer != -1
-            && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
-            && sd->sc_data[SC_QUAGMIRE].timer == -1
-            && sd->sc_data[SC_DONTFORGETME].timer == -1)
-        {                       // アドレナリンラッシュ
-            if (sd->sc_data[SC_ADRENALINE].val2
-                || !battle_config.party_skill_penaly)
-                aspd_rate -= 30;
-            else
-                aspd_rate -= 25;
-        }
-        if (sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
-            aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2;
-        if (sd->sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
-            sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
-            && sd->sc_data[SC_ADRENALINE].timer == -1
-            && sd->sc_data[SC_SPEARSQUICKEN].timer == -1
-            && sd->sc_data[SC_DONTFORGETME].timer == -1)
-            aspd_rate -=
-                5 + sd->sc_data[SC_ASSNCROS].val1 +
-                sd->sc_data[SC_ASSNCROS].val2 + sd->sc_data[SC_ASSNCROS].val3;
-        if (sd->sc_data[SC_DONTFORGETME].timer != -1)
-        {                       // 私を忘れないで
-            aspd_rate +=
-                sd->sc_data[SC_DONTFORGETME].val1 * 3 +
-                sd->sc_data[SC_DONTFORGETME].val2 +
-                (sd->sc_data[SC_DONTFORGETME].val3 >> 16);
-            sd->speed =
-                sd->speed * (100 + sd->sc_data[SC_DONTFORGETME].val1 * 2 +
-                             sd->sc_data[SC_DONTFORGETME].val2 +
-                             (sd->sc_data[SC_DONTFORGETME].val3 & 0xffff)) /
-                100;
-        }
-        if (sd->sc_data[i = SC_SPEEDPOTION2].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION1].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION0].timer != -1)   // 増 速ポーション
-            aspd_rate -= sd->sc_data[i].val1;
-
-        if (sd->sc_data[SC_HASTE].timer != -1)
-            aspd_rate -= sd->sc_data[SC_HASTE].val1;
-
-        /* Slow down if protected */
-
-        if (sd->sc_data[SC_PHYS_SHIELD].timer != -1)
-            aspd_rate += sd->sc_data[SC_PHYS_SHIELD].val1;
-
-        // HIT/FLEE変化系
-        if (sd->sc_data[SC_WHISTLE].timer != -1)
-        {                       // 口笛
-            sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1
-                                    + sd->sc_data[SC_WHISTLE].val2 +
-                                    (sd->sc_data[SC_WHISTLE].val3 >> 16)) /
-                100;
-            sd->flee2 +=
-                (sd->sc_data[SC_WHISTLE].val1 + sd->sc_data[SC_WHISTLE].val2 +
-                 (sd->sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;
-        }
-        if (sd->sc_data[SC_HUMMING].timer != -1)    // ハミング
-            sd->hit +=
-                (sd->sc_data[SC_HUMMING].val1 * 2 +
-                 sd->sc_data[SC_HUMMING].val2 +
-                 sd->sc_data[SC_HUMMING].val3) * sd->hit / 100;
-        if (sd->sc_data[SC_VIOLENTGALE].timer != -1 && sd->def_ele == 4)
-        {                       // バイオレントゲイル
-            sd->flee += sd->flee * sd->sc_data[SC_VIOLENTGALE].val3 / 100;
-        }
-        if (sd->sc_data[SC_BLIND].timer != -1)
-        {                       // 暗黒
-            sd->hit -= sd->hit * 25 / 100;
-            sd->flee -= sd->flee * 25 / 100;
-        }
-        if (sd->sc_data[SC_WINDWALK].timer != -1)   // ウィンドウォーク
-            sd->flee += sd->flee * (sd->sc_data[SC_WINDWALK].val2) / 100;
-        if (sd->sc_data[SC_SPIDERWEB].timer != -1)  //スパイダーウェブ
-            sd->flee -= sd->flee * 50 / 100;
-        if (sd->sc_data[SC_TRUESIGHT].timer != -1)  //トゥルーサイト
-            sd->hit += 3 * (sd->sc_data[SC_TRUESIGHT].val1);
-        if (sd->sc_data[SC_CONCENTRATION].timer != -1)  //コンセントレーション
-            sd->hit += (10 * (sd->sc_data[SC_CONCENTRATION].val1));
-
-        // 耐性
-        if (sd->sc_data[SC_SIEGFRIED].timer != -1)
-        {                       // 不死身のジークフリード
-            sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-            sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
-        }
-        if (sd->sc_data[SC_PROVIDENCE].timer != -1)
-        {                       // プロヴィデンス
-            sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2;   // 対 聖属性
-            sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2;  // 対 悪魔
-        }
-
-        // その他
-        if (sd->sc_data[SC_APPLEIDUN].timer != -1)
-        {                       // イドゥンの林檎
-            sd->status.max_hp +=
-                ((5 + sd->sc_data[SC_APPLEIDUN].val1 * 2 +
-                  ((sd->sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
-                  sd->sc_data[SC_APPLEIDUN].val3 / 10) * sd->status.max_hp) /
-                100;
-            if (sd->status.max_hp < 0
-                || sd->status.max_hp > battle_config.max_hp)
-                sd->status.max_hp = battle_config.max_hp;
-        }
-        if (sd->sc_data[SC_DELUGE].timer != -1 && sd->def_ele == 1)
-        {                       // デリュージ
-            sd->status.max_hp +=
-                sd->status.max_hp * sd->sc_data[SC_DELUGE].val3 / 100;
-            if (sd->status.max_hp < 0
-                || sd->status.max_hp > battle_config.max_hp)
-                sd->status.max_hp = battle_config.max_hp;
-        }
-        if (sd->sc_data[SC_SERVICE4U].timer != -1)
-        {                       // サービスフォーユー
-            sd->status.max_sp +=
-                sd->status.max_sp * (10 + sd->sc_data[SC_SERVICE4U].val1 +
-                                     sd->sc_data[SC_SERVICE4U].val2 +
-                                     sd->sc_data[SC_SERVICE4U].val3) / 100;
-            if (sd->status.max_sp < 0
-                || sd->status.max_sp > battle_config.max_sp)
-                sd->status.max_sp = battle_config.max_sp;
-            sd->dsprate -=
-                (10 + sd->sc_data[SC_SERVICE4U].val1 * 3 +
-                 sd->sc_data[SC_SERVICE4U].val2 +
-                 sd->sc_data[SC_SERVICE4U].val3);
-            if (sd->dsprate < 0)
-                sd->dsprate = 0;
-        }
-
-        if (sd->sc_data[SC_FORTUNE].timer != -1)    // 幸運のキス
-            sd->critical +=
-                (10 + sd->sc_data[SC_FORTUNE].val1 +
-                 sd->sc_data[SC_FORTUNE].val2 +
-                 sd->sc_data[SC_FORTUNE].val3) * 10;
-
-        if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
-        {                       // 爆裂波動
-            if (s_class.job == 23)
-                sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1 * 100;
-            else
-                sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2;
-        }
-
-        if (sd->sc_data[SC_STEELBODY].timer != -1)
-        {                       // 金剛
-            sd->def = 90;
-            sd->mdef = 90;
-            aspd_rate += 25;
-            sd->speed = (sd->speed * 125) / 100;
-        }
-        if (sd->sc_data[SC_DEFENDER].timer != -1)
-        {
-            sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1 * 50);
-            sd->speed =
-                (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1 * 5)) / 100;
-        }
-        if (sd->sc_data[SC_ENCPOISON].timer != -1)
-            sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2;
-
-        if (sd->sc_data[SC_DANCING].timer != -1)
-        {                       // 演奏/ダンス使用中
-            sd->speed *= 4;
-            sd->nhealsp = 0;
-            sd->nshealsp = 0;
-            sd->nsshealsp = 0;
-        }
-        if (sd->sc_data[SC_CURSE].timer != -1)
-            sd->speed += 450;
-
-        if (sd->sc_data[SC_TRUESIGHT].timer != -1)  //トゥルーサイト
-            sd->critical +=
-                sd->critical * (sd->sc_data[SC_TRUESIGHT].val1) / 100;
-
-/*		if(sd->sc_data[SC_VOLCANO].timer!=-1)	// エンチャントポイズン(属性はbattle.cで)
-			sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting
-		if(sd->sc_data[SC_DELUGE].timer!=-1)	// エンチャントポイズン(属性はbattle.cで)
-			sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting
-		*/
-    }
-
-    if (sd->speed_rate != 100)
-        sd->speed = sd->speed * sd->speed_rate / 100;
-    if (sd->speed < 1)
-        sd->speed = 1;
-    if (aspd_rate != 100)
-        sd->aspd = sd->aspd * aspd_rate / 100;
-    if (pc_isriding (sd))       // 騎兵修練
-        sd->aspd =
-            sd->aspd * (100 +
-                        10 * (5 -
-                              pc_checkskill (sd, KN_CAVALIERMASTERY))) / 100;
-
-    if (sd->attack_spell_override)
-        sd->aspd = sd->attack_spell_delay;
-
-    if (sd->aspd < battle_config.max_aspd)
-        sd->aspd = battle_config.max_aspd;
-    sd->amotion = sd->aspd;
-    sd->dmotion = 800 - sd->paramc[1] * 4;
-    if (sd->dmotion < 400)
-        sd->dmotion = 400;
-    if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)
-    {
-        sd->prev_speed = sd->speed;
-        sd->speed = sd->speed * (175 - skill * 5) / 100;
-    }
-
-    if (sd->status.hp > sd->status.max_hp)
-        sd->status.hp = sd->status.max_hp;
-    if (sd->status.sp > sd->status.max_sp)
-        sd->status.sp = sd->status.max_sp;
-
-    if (first & 4)
-        return 0;
-    if (first & 3)
-    {
-        clif_updatestatus (sd, SP_SPEED);
-        clif_updatestatus (sd, SP_MAXHP);
-        clif_updatestatus (sd, SP_MAXSP);
-        if (first & 1)
-        {
-            clif_updatestatus (sd, SP_HP);
-            clif_updatestatus (sd, SP_SP);
-        }
-        return 0;
-    }
-
-    if (b_class != sd->view_class)
-    {
-        clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);
-        clif_changelook (&sd->bl, LOOK_WEAPON, 0);
-    }
-
-    if (memcmp (b_skill, sd->status.skill, sizeof (sd->status.skill))
-        || b_attackrange != sd->attackrange)
-        clif_skillinfoblock (sd);   // スキル送信
-
-    if (b_speed != sd->speed)
-        clif_updatestatus (sd, SP_SPEED);
-    if (b_weight != sd->weight)
-        clif_updatestatus (sd, SP_WEIGHT);
-    if (b_max_weight != sd->max_weight)
-    {
-        clif_updatestatus (sd, SP_MAXWEIGHT);
-        pc_checkweighticon (sd);
-    }
-    for (i = 0; i < 6; i++)
-        if (b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i])
-            clif_updatestatus (sd, SP_STR + i);
-    if (b_hit != sd->hit)
-        clif_updatestatus (sd, SP_HIT);
-    if (b_flee != sd->flee)
-        clif_updatestatus (sd, SP_FLEE1);
-    if (b_aspd != sd->aspd)
-        clif_updatestatus (sd, SP_ASPD);
-    if (b_watk != sd->watk || b_base_atk != sd->base_atk)
-        clif_updatestatus (sd, SP_ATK1);
-    if (b_def != sd->def)
-        clif_updatestatus (sd, SP_DEF1);
-    if (b_watk2 != sd->watk2)
-        clif_updatestatus (sd, SP_ATK2);
-    if (b_def2 != sd->def2)
-        clif_updatestatus (sd, SP_DEF2);
-    if (b_flee2 != sd->flee2)
-        clif_updatestatus (sd, SP_FLEE2);
-    if (b_critical != sd->critical)
-        clif_updatestatus (sd, SP_CRITICAL);
-    if (b_matk1 != sd->matk1)
-        clif_updatestatus (sd, SP_MATK1);
-    if (b_matk2 != sd->matk2)
-        clif_updatestatus (sd, SP_MATK2);
-    if (b_mdef != sd->mdef)
-        clif_updatestatus (sd, SP_MDEF1);
-    if (b_mdef2 != sd->mdef2)
-        clif_updatestatus (sd, SP_MDEF2);
-    if (b_attackrange != sd->attackrange)
-        clif_updatestatus (sd, SP_ATTACKRANGE);
-    if (b_max_hp != sd->status.max_hp)
-        clif_updatestatus (sd, SP_MAXHP);
-    if (b_max_sp != sd->status.max_sp)
-        clif_updatestatus (sd, SP_MAXSP);
-    if (b_hp != sd->status.hp)
-        clif_updatestatus (sd, SP_HP);
-    if (b_sp != sd->status.sp)
-        clif_updatestatus (sd, SP_SP);
-
-/*	if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num ||
-		before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight )
-		clif_updatestatus(sd,SP_CARTINFO);*/
-
-    if (sd->status.hp < sd->status.max_hp >> 2
-        && pc_checkskill (sd, SM_AUTOBERSERK) > 0
-        && (sd->sc_data[SC_PROVOKE].timer == -1
-            || sd->sc_data[SC_PROVOKE].val2 == 0) && !pc_isdead (sd))
-        // オートバーサーク発動
-        skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 装 備品による能力等のボーナス設定
- *------------------------------------------
- */
-int pc_bonus (struct map_session_data *sd, int type, int val)
-{
-    nullpo_retr (0, sd);
-
-    switch (type)
-    {
-        case SP_STR:
-        case SP_AGI:
-        case SP_VIT:
-        case SP_INT:
-        case SP_DEX:
-        case SP_LUK:
-            if (sd->state.lr_flag != 2)
-                sd->parame[type - SP_STR] += val;
-            break;
-        case SP_ATK1:
-            if (!sd->state.lr_flag)
-                sd->watk += val;
-            else if (sd->state.lr_flag == 1)
-                sd->watk_ += val;
-            break;
-        case SP_ATK2:
-            if (!sd->state.lr_flag)
-                sd->watk2 += val;
-            else if (sd->state.lr_flag == 1)
-                sd->watk_2 += val;
-            break;
-        case SP_BASE_ATK:
-            if (sd->state.lr_flag != 2)
-                sd->base_atk += val;
-            break;
-        case SP_MATK1:
-            if (sd->state.lr_flag != 2)
-                sd->matk1 += val;
-            break;
-        case SP_MATK2:
-            if (sd->state.lr_flag != 2)
-                sd->matk2 += val;
-            break;
-        case SP_MATK:
-            if (sd->state.lr_flag != 2)
-            {
-                sd->matk1 += val;
-                sd->matk2 += val;
-            }
-            break;
-        case SP_DEF1:
-            if (sd->state.lr_flag != 2)
-                sd->def += val;
-            break;
-        case SP_MDEF1:
-            if (sd->state.lr_flag != 2)
-                sd->mdef += val;
-            break;
-        case SP_MDEF2:
-            if (sd->state.lr_flag != 2)
-                sd->mdef += val;
-            break;
-        case SP_HIT:
-            if (sd->state.lr_flag != 2)
-                sd->hit += val;
-            else
-                sd->arrow_hit += val;
-            break;
-        case SP_FLEE1:
-            if (sd->state.lr_flag != 2)
-                sd->flee += val;
-            break;
-        case SP_FLEE2:
-            if (sd->state.lr_flag != 2)
-                sd->flee2 += val * 10;
-            break;
-        case SP_CRITICAL:
-            if (sd->state.lr_flag != 2)
-                sd->critical += val * 10;
-            else
-                sd->arrow_cri += val * 10;
-            break;
-        case SP_ATKELE:
-            if (!sd->state.lr_flag)
-                sd->atk_ele = val;
-            else if (sd->state.lr_flag == 1)
-                sd->atk_ele_ = val;
-            else if (sd->state.lr_flag == 2)
-                sd->arrow_ele = val;
-            break;
-        case SP_DEFELE:
-            if (sd->state.lr_flag != 2)
-                sd->def_ele = val;
-            break;
-        case SP_MAXHP:
-            if (sd->state.lr_flag != 2)
-                sd->status.max_hp += val;
-            break;
-        case SP_MAXSP:
-            if (sd->state.lr_flag != 2)
-                sd->status.max_sp += val;
-            break;
-        case SP_CASTRATE:
-            if (sd->state.lr_flag != 2)
-                sd->castrate += val;
-            break;
-        case SP_MAXHPRATE:
-            if (sd->state.lr_flag != 2)
-                sd->hprate += val;
-            break;
-        case SP_MAXSPRATE:
-            if (sd->state.lr_flag != 2)
-                sd->sprate += val;
-            break;
-        case SP_SPRATE:
-            if (sd->state.lr_flag != 2)
-                sd->dsprate += val;
-            break;
-        case SP_ATTACKRANGE:
-            if (!sd->state.lr_flag)
-                sd->attackrange += val;
-            else if (sd->state.lr_flag == 1)
-                sd->attackrange_ += val;
-            else if (sd->state.lr_flag == 2)
-                sd->arrow_range += val;
-            break;
-        case SP_ADD_SPEED:
-            if (sd->state.lr_flag != 2)
-                sd->speed -= val;
-            break;
-        case SP_SPEED_RATE:
-            if (sd->state.lr_flag != 2)
-            {
-                if (sd->speed_rate > 100 - val)
-                    sd->speed_rate = 100 - val;
-            }
-            break;
-        case SP_SPEED_ADDRATE:
-            if (sd->state.lr_flag != 2)
-                sd->speed_add_rate = sd->speed_add_rate * (100 - val) / 100;
-            break;
-        case SP_ASPD:
-            if (sd->state.lr_flag != 2)
-                sd->aspd -= val * 10;
-            break;
-        case SP_ASPD_RATE:
-            if (sd->state.lr_flag != 2)
-            {
-                if (sd->aspd_rate > 100 - val)
-                    sd->aspd_rate = 100 - val;
-            }
-            break;
-        case SP_ASPD_ADDRATE:
-            if (sd->state.lr_flag != 2)
-                sd->aspd_add_rate = sd->aspd_add_rate * (100 - val) / 100;
-            break;
-        case SP_HP_RECOV_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->hprecov_rate += val;
-            break;
-        case SP_SP_RECOV_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->sprecov_rate += val;
-            break;
-        case SP_CRITICAL_DEF:
-            if (sd->state.lr_flag != 2)
-                sd->critical_def += val;
-            break;
-        case SP_NEAR_ATK_DEF:
-            if (sd->state.lr_flag != 2)
-                sd->near_attack_def_rate += val;
-            break;
-        case SP_LONG_ATK_DEF:
-            if (sd->state.lr_flag != 2)
-                sd->long_attack_def_rate += val;
-            break;
-        case SP_DOUBLE_RATE:
-            if (sd->state.lr_flag == 0 && sd->double_rate < val)
-                sd->double_rate = val;
-            break;
-        case SP_DOUBLE_ADD_RATE:
-            if (sd->state.lr_flag == 0)
-                sd->double_add_rate += val;
-            break;
-        case SP_MATK_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->matk_rate += val;
-            break;
-        case SP_IGNORE_DEF_ELE:
-            if (!sd->state.lr_flag)
-                sd->ignore_def_ele |= 1 << val;
-            else if (sd->state.lr_flag == 1)
-                sd->ignore_def_ele_ |= 1 << val;
-            break;
-        case SP_IGNORE_DEF_RACE:
-            if (!sd->state.lr_flag)
-                sd->ignore_def_race |= 1 << val;
-            else if (sd->state.lr_flag == 1)
-                sd->ignore_def_race_ |= 1 << val;
-            break;
-        case SP_ATK_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->atk_rate += val;
-            break;
-        case SP_MAGIC_ATK_DEF:
-            if (sd->state.lr_flag != 2)
-                sd->magic_def_rate += val;
-            break;
-        case SP_MISC_ATK_DEF:
-            if (sd->state.lr_flag != 2)
-                sd->misc_def_rate += val;
-            break;
-        case SP_IGNORE_MDEF_ELE:
-            if (sd->state.lr_flag != 2)
-                sd->ignore_mdef_ele |= 1 << val;
-            break;
-        case SP_IGNORE_MDEF_RACE:
-            if (sd->state.lr_flag != 2)
-                sd->ignore_mdef_race |= 1 << val;
-            break;
-        case SP_PERFECT_HIT_RATE:
-            if (sd->state.lr_flag != 2 && sd->perfect_hit < val)
-                sd->perfect_hit = val;
-            break;
-        case SP_PERFECT_HIT_ADD_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->perfect_hit_add += val;
-            break;
-        case SP_CRITICAL_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->critical_rate += val;
-            break;
-        case SP_GET_ZENY_NUM:
-            if (sd->state.lr_flag != 2 && sd->get_zeny_num < val)
-                sd->get_zeny_num = val;
-            break;
-        case SP_ADD_GET_ZENY_NUM:
-            if (sd->state.lr_flag != 2)
-                sd->get_zeny_add_num += val;
-            break;
-        case SP_DEF_RATIO_ATK_ELE:
-            if (!sd->state.lr_flag)
-                sd->def_ratio_atk_ele |= 1 << val;
-            else if (sd->state.lr_flag == 1)
-                sd->def_ratio_atk_ele_ |= 1 << val;
-            break;
-        case SP_DEF_RATIO_ATK_RACE:
-            if (!sd->state.lr_flag)
-                sd->def_ratio_atk_race |= 1 << val;
-            else if (sd->state.lr_flag == 1)
-                sd->def_ratio_atk_race_ |= 1 << val;
-            break;
-        case SP_HIT_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->hit_rate += val;
-            break;
-        case SP_FLEE_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->flee_rate += val;
-            break;
-        case SP_FLEE2_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->flee2_rate += val;
-            break;
-        case SP_DEF_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->def_rate += val;
-            break;
-        case SP_DEF2_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->def2_rate += val;
-            break;
-        case SP_MDEF_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->mdef_rate += val;
-            break;
-        case SP_MDEF2_RATE:
-            if (sd->state.lr_flag != 2)
-                sd->mdef2_rate += val;
-            break;
-        case SP_RESTART_FULL_RECORVER:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.restart_full_recover = 1;
-            break;
-        case SP_NO_CASTCANCEL:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_castcancel = 1;
-            break;
-        case SP_NO_CASTCANCEL2:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_castcancel2 = 1;
-            break;
-        case SP_NO_SIZEFIX:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_sizefix = 1;
-            break;
-        case SP_NO_MAGIC_DAMAGE:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_magic_damage = 1;
-            break;
-        case SP_NO_WEAPON_DAMAGE:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_weapon_damage = 1;
-            break;
-        case SP_NO_GEMSTONE:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.no_gemstone = 1;
-            break;
-        case SP_INFINITE_ENDURE:
-            if (sd->state.lr_flag != 2)
-                sd->special_state.infinite_endure = 1;
-            break;
-        case SP_SPLASH_RANGE:
-            if (sd->state.lr_flag != 2 && sd->splash_range < val)
-                sd->splash_range = val;
-            break;
-        case SP_SPLASH_ADD_RANGE:
-            if (sd->state.lr_flag != 2)
-                sd->splash_add_range += val;
-            break;
-        case SP_SHORT_WEAPON_DAMAGE_RETURN:
-            if (sd->state.lr_flag != 2)
-                sd->short_weapon_damage_return += val;
-            break;
-        case SP_LONG_WEAPON_DAMAGE_RETURN:
-            if (sd->state.lr_flag != 2)
-                sd->long_weapon_damage_return += val;
-            break;
-        case SP_MAGIC_DAMAGE_RETURN:   //AppleGirl Was Here
-            if (sd->state.lr_flag != 2)
-                sd->magic_damage_return += val;
-            break;
-        case SP_ALL_STATS:     // [Valaris]
-            if (sd->state.lr_flag != 2)
-            {
-                sd->parame[SP_STR - SP_STR] += val;
-                sd->parame[SP_AGI - SP_STR] += val;
-                sd->parame[SP_VIT - SP_STR] += val;
-                sd->parame[SP_INT - SP_STR] += val;
-                sd->parame[SP_DEX - SP_STR] += val;
-                sd->parame[SP_LUK - SP_STR] += val;
-                clif_updatestatus (sd, 13);
-                clif_updatestatus (sd, 14);
-                clif_updatestatus (sd, 15);
-                clif_updatestatus (sd, 16);
-                clif_updatestatus (sd, 17);
-                clif_updatestatus (sd, 18);
-            }
-            break;
-        case SP_AGI_VIT:       // [Valaris]
-            if (sd->state.lr_flag != 2)
-            {
-                sd->parame[SP_AGI - SP_STR] += val;
-                sd->parame[SP_VIT - SP_STR] += val;
-                clif_updatestatus (sd, 14);
-                clif_updatestatus (sd, 15);
-            }
-            break;
-        case SP_AGI_DEX_STR:   // [Valaris]
-            if (sd->state.lr_flag != 2)
-            {
-                sd->parame[SP_AGI - SP_STR] += val;
-                sd->parame[SP_DEX - SP_STR] += val;
-                sd->parame[SP_STR - SP_STR] += val;
-                clif_updatestatus (sd, 14);
-                clif_updatestatus (sd, 17);
-                clif_updatestatus (sd, 13);
-            }
-            break;
-        case SP_PERFECT_HIDE:  // [Valaris]
-            if (sd->state.lr_flag != 2)
-            {
-                sd->perfect_hiding = 1;
-            }
-            break;
-        case SP_DISGUISE:      // Disguise script for items [Valaris]
-            if (sd->state.lr_flag != 2 && sd->disguiseflag == 0)
-            {
-                if (pc_isriding (sd))
-                {               // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-                    clif_displaymessage (sd->fd,
-                                         "Cannot wear disguise when riding a Peco.");
-                    break;
-                }
-                sd->disguise = val;
-                clif_clearchar (&sd->bl, 9);
-                pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
-            }
-            break;
-        case SP_UNBREAKABLE:
-            if (sd->state.lr_flag != 2)
-            {
-                sd->unbreakable += val;
-            }
-            break;
-        case SP_DEAF:
-            sd->special_state.deaf = 1;
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("pc_bonus: unknown type %d %d !\n", type, val);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * ソスソス ソスソスソスiソスノゑソスソスソスソス\ソスヘ難ソスソスフボソス[ソスiソスXソスン抵ソス
- *------------------------------------------
- */
-int pc_bonus2 (struct map_session_data *sd, int type, int type2, int val)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    switch (type)
-    {
-        case SP_ADDELE:
-            if (!sd->state.lr_flag)
-                sd->addele[type2] += val;
-            else if (sd->state.lr_flag == 1)
-                sd->addele_[type2] += val;
-            else if (sd->state.lr_flag == 2)
-                sd->arrow_addele[type2] += val;
-            break;
-        case SP_ADDRACE:
-            if (!sd->state.lr_flag)
-                sd->addrace[type2] += val;
-            else if (sd->state.lr_flag == 1)
-                sd->addrace_[type2] += val;
-            else if (sd->state.lr_flag == 2)
-                sd->arrow_addrace[type2] += val;
-            break;
-        case SP_ADDSIZE:
-            if (!sd->state.lr_flag)
-                sd->addsize[type2] += val;
-            else if (sd->state.lr_flag == 1)
-                sd->addsize_[type2] += val;
-            else if (sd->state.lr_flag == 2)
-                sd->arrow_addsize[type2] += val;
-            break;
-        case SP_SUBELE:
-            if (sd->state.lr_flag != 2)
-                sd->subele[type2] += val;
-            break;
-        case SP_SUBRACE:
-            if (sd->state.lr_flag != 2)
-                sd->subrace[type2] += val;
-            break;
-        case SP_ADDEFF:
-            if (sd->state.lr_flag != 2)
-                sd->addeff[type2] += val;
-            else
-                sd->arrow_addeff[type2] += val;
-            break;
-        case SP_ADDEFF2:
-            if (sd->state.lr_flag != 2)
-                sd->addeff2[type2] += val;
-            else
-                sd->arrow_addeff2[type2] += val;
-            break;
-        case SP_RESEFF:
-            if (sd->state.lr_flag != 2)
-                sd->reseff[type2] += val;
-            break;
-        case SP_MAGIC_ADDELE:
-            if (sd->state.lr_flag != 2)
-                sd->magic_addele[type2] += val;
-            break;
-        case SP_MAGIC_ADDRACE:
-            if (sd->state.lr_flag != 2)
-                sd->magic_addrace[type2] += val;
-            break;
-        case SP_MAGIC_SUBRACE:
-            if (sd->state.lr_flag != 2)
-                sd->magic_subrace[type2] += val;
-            break;
-        case SP_ADD_DAMAGE_CLASS:
-            if (!sd->state.lr_flag)
-            {
-                for (i = 0; i < sd->add_damage_class_count; i++)
-                {
-                    if (sd->add_damage_classid[i] == type2)
-                    {
-                        sd->add_damage_classrate[i] += val;
-                        break;
-                    }
-                }
-                if (i >= sd->add_damage_class_count
-                    && sd->add_damage_class_count < 10)
-                {
-                    sd->add_damage_classid[sd->add_damage_class_count] =
-                        type2;
-                    sd->add_damage_classrate[sd->add_damage_class_count] +=
-                        val;
-                    sd->add_damage_class_count++;
-                }
-            }
-            else if (sd->state.lr_flag == 1)
-            {
-                for (i = 0; i < sd->add_damage_class_count_; i++)
-                {
-                    if (sd->add_damage_classid_[i] == type2)
-                    {
-                        sd->add_damage_classrate_[i] += val;
-                        break;
-                    }
-                }
-                if (i >= sd->add_damage_class_count_
-                    && sd->add_damage_class_count_ < 10)
-                {
-                    sd->add_damage_classid_[sd->add_damage_class_count_] =
-                        type2;
-                    sd->add_damage_classrate_[sd->add_damage_class_count_] +=
-                        val;
-                    sd->add_damage_class_count_++;
-                }
-            }
-            break;
-        case SP_ADD_MAGIC_DAMAGE_CLASS:
-            if (sd->state.lr_flag != 2)
-            {
-                for (i = 0; i < sd->add_magic_damage_class_count; i++)
-                {
-                    if (sd->add_magic_damage_classid[i] == type2)
-                    {
-                        sd->add_magic_damage_classrate[i] += val;
-                        break;
-                    }
-                }
-                if (i >= sd->add_magic_damage_class_count
-                    && sd->add_magic_damage_class_count < 10)
-                {
-                    sd->add_magic_damage_classid
-                        [sd->add_magic_damage_class_count] = type2;
-                    sd->add_magic_damage_classrate
-                        [sd->add_magic_damage_class_count] += val;
-                    sd->add_magic_damage_class_count++;
-                }
-            }
-            break;
-        case SP_ADD_DEF_CLASS:
-            if (sd->state.lr_flag != 2)
-            {
-                for (i = 0; i < sd->add_def_class_count; i++)
-                {
-                    if (sd->add_def_classid[i] == type2)
-                    {
-                        sd->add_def_classrate[i] += val;
-                        break;
-                    }
-                }
-                if (i >= sd->add_def_class_count
-                    && sd->add_def_class_count < 10)
-                {
-                    sd->add_def_classid[sd->add_def_class_count] = type2;
-                    sd->add_def_classrate[sd->add_def_class_count] += val;
-                    sd->add_def_class_count++;
-                }
-            }
-            break;
-        case SP_ADD_MDEF_CLASS:
-            if (sd->state.lr_flag != 2)
-            {
-                for (i = 0; i < sd->add_mdef_class_count; i++)
-                {
-                    if (sd->add_mdef_classid[i] == type2)
-                    {
-                        sd->add_mdef_classrate[i] += val;
-                        break;
-                    }
-                }
-                if (i >= sd->add_mdef_class_count
-                    && sd->add_mdef_class_count < 10)
-                {
-                    sd->add_mdef_classid[sd->add_mdef_class_count] = type2;
-                    sd->add_mdef_classrate[sd->add_mdef_class_count] += val;
-                    sd->add_mdef_class_count++;
-                }
-            }
-            break;
-        case SP_HP_DRAIN_RATE:
-            if (!sd->state.lr_flag)
-            {
-                sd->hp_drain_rate += type2;
-                sd->hp_drain_per += val;
-            }
-            else if (sd->state.lr_flag == 1)
-            {
-                sd->hp_drain_rate_ += type2;
-                sd->hp_drain_per_ += val;
-            }
-            break;
-        case SP_SP_DRAIN_RATE:
-            if (!sd->state.lr_flag)
-            {
-                sd->sp_drain_rate += type2;
-                sd->sp_drain_per += val;
-            }
-            else if (sd->state.lr_flag == 1)
-            {
-                sd->sp_drain_rate_ += type2;
-                sd->sp_drain_per_ += val;
-            }
-            break;
-        case SP_WEAPON_COMA_ELE:
-            if (sd->state.lr_flag != 2)
-                sd->weapon_coma_ele[type2] += val;
-            break;
-        case SP_WEAPON_COMA_RACE:
-            if (sd->state.lr_flag != 2)
-                sd->weapon_coma_race[type2] += val;
-            break;
-        case SP_RANDOM_ATTACK_INCREASE:    // [Valaris]
-            if (sd->state.lr_flag != 2)
-            {
-                sd->random_attack_increase_add = type2;
-                sd->random_attack_increase_per += val;
-                break;
-            }                   // end addition
-        default:
-            if (battle_config.error_log)
-                printf ("pc_bonus2: unknown type %d %d %d!\n", type, type2,
-                        val);
-            break;
-    }
-    return 0;
-}
-
-int pc_bonus3 (struct map_session_data *sd, int type, int type2, int type3,
-               int val)
-{
-    int  i;
-    switch (type)
-    {
-        case SP_ADD_MONSTER_DROP_ITEM:
-            if (sd->state.lr_flag != 2)
-            {
-                for (i = 0; i < sd->monster_drop_item_count; i++)
-                {
-                    if (sd->monster_drop_itemid[i] == type2)
-                    {
-                        sd->monster_drop_race[i] |= 1 << type3;
-                        if (sd->monster_drop_itemrate[i] < val)
-                            sd->monster_drop_itemrate[i] = val;
-                        break;
-                    }
-                }
-                if (i >= sd->monster_drop_item_count
-                    && sd->monster_drop_item_count < 10)
-                {
-                    sd->monster_drop_itemid[sd->monster_drop_item_count] =
-                        type2;
-                    sd->monster_drop_race[sd->monster_drop_item_count] |=
-                        1 << type3;
-                    sd->monster_drop_itemrate[sd->monster_drop_item_count] =
-                        val;
-                    sd->monster_drop_item_count++;
-                }
-            }
-            break;
-        case SP_AUTOSPELL:
-            if (sd->state.lr_flag != 2)
-            {
-                sd->autospell_id = type2;
-                sd->autospell_lv = type3;
-                sd->autospell_rate = val;
-            }
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("pc_bonus3: unknown type %d %d %d %d!\n", type, type2,
-                        type3, val);
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スクリプトによるスキル所得
- *------------------------------------------
- */
-int pc_skill (struct map_session_data *sd, int id, int level, int flag)
-{
-    nullpo_retr (0, sd);
-
-    if (level > MAX_SKILL_LEVEL)
-    {
-        if (battle_config.error_log)
-            printf ("support card skill only!\n");
-        return 0;
-    }
-    if (!flag && (sd->status.skill[id].id == id || level == 0))
-    {                           // クエスト所得ならここで条件を確認して送信する
-        sd->status.skill[id].lv = level;
-        pc_calcstatus (sd, 0);
-        clif_skillinfoblock (sd);
-    }
-    else if (sd->status.skill[id].lv < level)
-    {                           // 覚えられるがlvが小さいなら
-        sd->status.skill[id].id = id;
-        sd->status.skill[id].lv = level;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * カード挿入
- *------------------------------------------
- */
-int pc_insert_card (struct map_session_data *sd, int idx_card, int idx_equip)
-{
-    nullpo_retr (0, sd);
-
-    if (idx_card >= 0 && idx_card < MAX_INVENTORY && idx_equip >= 0
-        && idx_equip < MAX_INVENTORY && sd->inventory_data[idx_card])
-    {
-        int  i;
-        int  nameid = sd->status.inventory[idx_equip].nameid;
-        int  cardid = sd->status.inventory[idx_card].nameid;
-        int  ep = sd->inventory_data[idx_card]->equip;
-
-        if (nameid <= 0 || sd->inventory_data[idx_equip] == NULL ||
-            (sd->inventory_data[idx_equip]->type != 4 && sd->inventory_data[idx_equip]->type != 5) ||   // 装 備じゃない
-            (sd->status.inventory[idx_equip].identify == 0) ||  // 未鑑定
-            (sd->status.inventory[idx_equip].card[0] == 0x00ff) ||  // 製造武器
-            (sd->status.inventory[idx_equip].card[0] == 0x00fe) ||
-            ((sd->inventory_data[idx_equip]->equip & ep) == 0) ||    // 装 備個所違い
-            (sd->inventory_data[idx_equip]->type == 4 && ep == 32) ||   // 両 手武器と盾カード
-            (sd->status.inventory[idx_equip].card[0] == (short) 0xff00)
-            || sd->status.inventory[idx_equip].equip)
-        {
-
-            clif_insert_card (sd, idx_equip, idx_card, 1);
-            return 0;
-        }
-        for (i = 0; i < sd->inventory_data[idx_equip]->slot; i++)
-        {
-            if (sd->status.inventory[idx_equip].card[i] == 0)
-            {
-                // 空きスロットがあったので差し込む
-                sd->status.inventory[idx_equip].card[i] = cardid;
-
-                // カードは減らす
-                clif_insert_card (sd, idx_equip, idx_card, 0);
-                pc_delitem (sd, idx_card, 1, 1);
-                return 0;
-            }
-        }
-    }
-    else
-        clif_insert_card (sd, idx_equip, idx_card, 1);
-
-    return 0;
-}
-
-//
-// アイテム物
-//
-
-/*==========================================
- * スキルによる買い値修正
- *------------------------------------------
- */
-int pc_modifybuyvalue (struct map_session_data *sd, int orig_value)
-{
-    int  skill, val = orig_value, rate1 = 0, rate2 = 0;
-    if ((skill = pc_checkskill (sd, MC_DISCOUNT)) > 0)  // ディスカウント
-        rate1 = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
-    if ((skill = pc_checkskill (sd, RG_COMPULSION)) > 0)    // コムパルションディスカウント
-        rate2 = 5 + skill * 4;
-    if (rate1 < rate2)
-        rate1 = rate2;
-    if (rate1)
-        val = (int) ((double) orig_value * (double) (100 - rate1) / 100.);
-    if (val < 0)
-        val = 0;
-    if (orig_value > 0 && val < 1)
-        val = 1;
-
-    return val;
-}
-
-/*==========================================
- * スキルによる売り値修正
- *------------------------------------------
- */
-int pc_modifysellvalue (struct map_session_data *sd, int orig_value)
-{
-    int  skill, val = orig_value, rate = 0;
-    if ((skill = pc_checkskill (sd, MC_OVERCHARGE)) > 0)    // オーバーチャージ
-        rate = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
-    if (rate)
-        val = (int) ((double) orig_value * (double) (100 + rate) / 100.);
-    if (val < 0)
-        val = 0;
-    if (orig_value > 0 && val < 1)
-        val = 1;
-
-    return val;
-}
-
-/*==========================================
- * アイテムを買った時に、新しいアイテム欄を使うか、
- * 3万個制限にかかるか確認
- *------------------------------------------
- */
-int pc_checkadditem (struct map_session_data *sd, int nameid, int amount)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (itemdb_isequip (nameid))
-        return ADDITEM_NEW;
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid == nameid)
-        {
-            if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
-                return ADDITEM_OVERAMOUNT;
-            return ADDITEM_EXIST;
-        }
-    }
-
-    if (amount > MAX_AMOUNT)
-        return ADDITEM_OVERAMOUNT;
-    return ADDITEM_NEW;
-}
-
-/*==========================================
- * 空きアイテム欄の個数
- *------------------------------------------
- */
-int pc_inventoryblank (struct map_session_data *sd)
-{
-    int  i, b;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0, b = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid == 0)
-            b++;
-    }
-
-    return b;
-}
-
-/*==========================================
- * お金を払う
- *------------------------------------------
- */
-int pc_payzeny (struct map_session_data *sd, int zeny)
-{
-    double z;
-
-    nullpo_retr (0, sd);
-
-    z = (double) sd->status.zeny;
-    if (sd->status.zeny < zeny || z - (double) zeny > MAX_ZENY)
-        return 1;
-    sd->status.zeny -= zeny;
-    clif_updatestatus (sd, SP_ZENY);
-
-    return 0;
-}
-
-/*==========================================
- * お金を得る
- *------------------------------------------
- */
-int pc_getzeny (struct map_session_data *sd, int zeny)
-{
-    double z;
-
-    nullpo_retr (0, sd);
-
-    z = (double) sd->status.zeny;
-    if (z + (double) zeny > MAX_ZENY)
-    {
-        zeny = 0;
-        sd->status.zeny = MAX_ZENY;
-    }
-    sd->status.zeny += zeny;
-    clif_updatestatus (sd, SP_ZENY);
-
-    return 0;
-}
-
-/*==========================================
- * アイテムを探して、インデックスを返す
- *------------------------------------------
- */
-int pc_search_inventory (struct map_session_data *sd, int item_id)
-{
-    int  i;
-
-    nullpo_retr (-1, sd);
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid == item_id &&
-            (sd->status.inventory[i].amount > 0 || item_id == 0))
-            return i;
-    }
-
-    return -1;
-}
-
-int pc_count_all_items (struct map_session_data *player, int item_id)
-{
-    int  i;
-    int  count = 0;
-
-    nullpo_retr (0, player);
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (player->status.inventory[i].nameid == item_id)
-            count += player->status.inventory[i].amount;
-    }
-
-    return count;
-}
-
-int pc_remove_items (struct map_session_data *player, int item_id, int count)
-{
-    int  i;
-
-    nullpo_retr (0, player);
-
-    for (i = 0; i < MAX_INVENTORY && count; i++)
-    {
-        if (player->status.inventory[i].nameid == item_id)
-        {
-            int  to_delete = count;
-            /* only delete as much as we have */
-            if (to_delete > player->status.inventory[i].amount)
-                to_delete = player->status.inventory[i].amount;
-
-            count -= to_delete;
-
-            pc_delitem (player, i, to_delete,
-                        0 /* means `really delete and update status' */ );
-
-            if (!count)
-                return 0;
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * アイテム追加。個数のみitem構造体の数字を無視
- *------------------------------------------
- */
-int pc_additem (struct map_session_data *sd, struct item *item_data,
-                int amount)
-{
-    struct item_data *data;
-    int  i, w;
-
-    MAP_LOG_PC (sd, "PICKUP %d %d", item_data->nameid, amount);
-
-    nullpo_retr (1, sd);
-    nullpo_retr (1, item_data);
-
-    if (item_data->nameid <= 0 || amount <= 0)
-        return 1;
-    data = itemdb_search (item_data->nameid);
-    if ((w = data->weight * amount) + sd->weight > sd->max_weight)
-        return 2;
-
-    i = MAX_INVENTORY;
-
-    if (!itemdb_isequip2 (data))
-    {
-        // 装 備品ではないので、既所有品なら個数のみ変化させる
-        for (i = 0; i < MAX_INVENTORY; i++)
-            if (sd->status.inventory[i].nameid == item_data->nameid &&
-                sd->status.inventory[i].card[0] == item_data->card[0]
-                && sd->status.inventory[i].card[1] == item_data->card[1]
-                && sd->status.inventory[i].card[2] == item_data->card[2]
-                && sd->status.inventory[i].card[3] == item_data->card[3])
-            {
-                if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
-                    return 5;
-                sd->status.inventory[i].amount += amount;
-                clif_additem (sd, i, amount, 0);
-                break;
-            }
-    }
-    if (i >= MAX_INVENTORY)
-    {
-        // 装 備品か未所有品だったので空き欄へ追加
-        i = pc_search_inventory (sd, 0);
-        if (i >= 0)
-        {
-            memcpy (&sd->status.inventory[i], item_data,
-                    sizeof (sd->status.inventory[0]));
-
-            if (item_data->equip)
-                sd->status.inventory[i].equip = 0;
-
-            sd->status.inventory[i].amount = amount;
-            sd->inventory_data[i] = data;
-            clif_additem (sd, i, amount, 0);
-        }
-        else
-            return 4;
-    }
-    sd->weight += w;
-    clif_updatestatus (sd, SP_WEIGHT);
-
-    return 0;
-}
-
-/*==========================================
- * アイテムを減らす
- *------------------------------------------
- */
-int pc_delitem (struct map_session_data *sd, int n, int amount, int type)
-{
-    nullpo_retr (1, sd);
-
-    if (sd->trade_partner != 0)
-        trade_tradecancel (sd);
-
-    if (sd->status.inventory[n].nameid == 0 || amount <= 0
-        || sd->status.inventory[n].amount < amount
-        || sd->inventory_data[n] == NULL)
-        return 1;
-
-    sd->status.inventory[n].amount -= amount;
-    sd->weight -= sd->inventory_data[n]->weight * amount;
-    if (sd->status.inventory[n].amount <= 0)
-    {
-        if (sd->status.inventory[n].equip)
-            pc_unequipitem (sd, n, 0);
-        memset (&sd->status.inventory[n], 0,
-                sizeof (sd->status.inventory[0]));
-        sd->inventory_data[n] = NULL;
-    }
-    if (!(type & 1))
-        clif_delitem (sd, n, amount);
-    if (!(type & 2))
-        clif_updatestatus (sd, SP_WEIGHT);
-
-    return 0;
-}
-
-/*==========================================
- * アイテムを落す
- *------------------------------------------
- */
-int pc_dropitem (struct map_session_data *sd, int n, int amount)
-{
-    nullpo_retr (1, sd);
-
-    if (sd->trade_partner != 0 || sd->npc_id != 0 || sd->state.storage_flag)
-        return 0;               // no dropping while trading/npc/storage
-
-    if (n < 0 || n >= MAX_INVENTORY)
-        return 0;
-
-    if (amount <= 0)
-        return 0;
-
-    pc_unequipinvyitem (sd, n, 0);
-
-    if (sd->status.inventory[n].nameid <= 0 ||
-        sd->status.inventory[n].amount < amount ||
-        sd->trade_partner != 0 || sd->status.inventory[n].amount <= 0)
-        return 1;
-    map_addflooritem (&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x,
-                      sd->bl.y, NULL, NULL, NULL, 0);
-    pc_delitem (sd, n, amount, 0);
-
-    return 0;
-}
-
-/*==========================================
- * アイテムを拾う
- *------------------------------------------
- */
-
-static int can_pick_item_up_from (struct map_session_data *self, int other_id)
-{
-    struct party *p = party_search (self->status.party_id);
-
-    /* From ourselves or from no-one? */
-    if (!self || self->bl.id == other_id || !other_id)
-        return 1;
-
-    struct map_session_data *other = map_id2sd (other_id);
-
-    /* Other no longer exists? */
-    if (!other)
-        return 1;
-
-    /* From our partner? */
-    if (self->status.partner_id == other->status.char_id)
-        return 1;
-
-    /* From a party member? */
-    if (self->status.party_id
-        && self->status.party_id == other->status.party_id
-        && p && p->item != 0)
-        return 1;
-
-    /* From someone who is far away? */
-    /* On another map? */
-    if (other->bl.m != self->bl.m)
-        return 1;
-    else
-    {
-        int  distance_x = abs (other->bl.x - self->bl.x);
-        int  distance_y = abs (other->bl.y - self->bl.y);
-        int  distance = (distance_x > distance_y) ? distance_x : distance_y;
-
-        return distance > battle_config.drop_pickup_safety_zone;
-    }
-}
-
-int pc_takeitem (struct map_session_data *sd, struct flooritem_data *fitem)
-{
-    int  flag;
-    unsigned int tick = gettick ();
-    int  can_take;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, fitem);
-
-    /* Sometimes the owners reported to us are buggy: */
-
-    if (fitem->first_get_id == fitem->third_get_id
-        || fitem->second_get_id == fitem->third_get_id)
-        fitem->third_get_id = 0;
-
-    if (fitem->first_get_id == fitem->second_get_id)
-    {
-        fitem->second_get_id = fitem->third_get_id;
-        fitem->third_get_id = 0;
-    }
-
-    can_take = can_pick_item_up_from (sd, fitem->first_get_id);
-    if (!can_take)
-        can_take = fitem->first_get_tick <= tick
-            && can_pick_item_up_from (sd, fitem->second_get_id);
-
-    if (!can_take)
-        can_take = fitem->second_get_tick <= tick
-            && can_pick_item_up_from (sd, fitem->third_get_id);
-
-    if (!can_take)
-        can_take = fitem->third_get_tick <= tick;
-
-    if (can_take)
-    {
-        /* Can pick up */
-
-        if ((flag =
-             pc_additem (sd, &fitem->item_data, fitem->item_data.amount)))
-            // 重量overで取得失敗
-            clif_additem (sd, 0, 0, flag);
-        else
-        {
-            // 取得成功
-            if (sd->attacktimer != -1)
-                pc_stopattack (sd);
-            clif_takeitem (&sd->bl, &fitem->bl);
-            map_clearflooritem (fitem->bl.id);
-        }
-        return 0;
-    }
-
-    /* Otherwise, we can't pick up */
-    clif_additem (sd, 0, 0, 6);
-    return 0;
-}
-
-int pc_isUseitem (struct map_session_data *sd, int n)
-{
-    struct item_data *item;
-    int  nameid;
-
-    nullpo_retr (0, sd);
-
-    item = sd->inventory_data[n];
-    nameid = sd->status.inventory[n].nameid;
-
-    if (item == NULL)
-        return 0;
-    if (itemdb_type (nameid) != 0)
-        return 0;
-    if ((nameid == 605) && map[sd->bl.m].flag.gvg)
-        return 0;
-    if (nameid == 601
-        && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg))
-    {
-        clif_skill_teleportmessage (sd, 0);
-        return 0;
-    }
-
-    if (nameid == 602 && map[sd->bl.m].flag.noreturn)
-        return 0;
-    if (nameid == 604
-        && (map[sd->bl.m].flag.nobranch || map[sd->bl.m].flag.gvg))
-        return 0;
-    if (item->sex != 2 && sd->status.sex != item->sex)
-        return 0;
-    if (item->elv > 0 && sd->status.base_level < item->elv)
-        return 0;
-
-    return 1;
-}
-
-/*==========================================
- * アイテムを使う
- *------------------------------------------
- */
-int pc_useitem (struct map_session_data *sd, int n)
-{
-    int  nameid, amount;
-
-    nullpo_retr (1, sd);
-
-    if (n >= 0 && n < MAX_INVENTORY && sd->inventory_data[n])
-    {
-        nameid = sd->status.inventory[n].nameid;
-        amount = sd->status.inventory[n].amount;
-        if (sd->status.inventory[n].nameid <= 0
-            || sd->status.inventory[n].amount <= 0
-            || sd->sc_data[SC_BERSERK].timer != -1 || !pc_isUseitem (sd, n))
-        {
-            clif_useitemack (sd, n, 0, 0);
-            return 1;
-        }
-
-        run_script (sd->inventory_data[n]->use_script, 0, sd->bl.id, 0);
-
-        clif_useitemack (sd, n, amount - 1, 1);
-        pc_delitem (sd, n, 1, 1);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * カートアイテム追加。個数のみitem構造体の数字を無視
- *------------------------------------------
- */
-int pc_cart_additem (struct map_session_data *sd, struct item *item_data,
-                     int amount)
-{
-    struct item_data *data;
-    int  i, w;
-
-    nullpo_retr (1, sd);
-    nullpo_retr (1, item_data);
-
-    if (item_data->nameid <= 0 || amount <= 0)
-        return 1;
-    data = itemdb_search (item_data->nameid);
-
-    if ((w = data->weight * amount) + sd->cart_weight > sd->cart_max_weight)
-        return 1;
-
-    i = MAX_CART;
-    if (!itemdb_isequip2 (data))
-    {
-        // 装 備品ではないので、既所有品なら個数のみ変化させる
-        for (i = 0; i < MAX_CART; i++)
-        {
-            if (sd->status.cart[i].nameid == item_data->nameid &&
-                sd->status.cart[i].card[0] == item_data->card[0]
-                && sd->status.cart[i].card[1] == item_data->card[1]
-                && sd->status.cart[i].card[2] == item_data->card[2]
-                && sd->status.cart[i].card[3] == item_data->card[3])
-            {
-                if (sd->status.cart[i].amount + amount > MAX_AMOUNT)
-                    return 1;
-                sd->status.cart[i].amount += amount;
-                clif_cart_additem (sd, i, amount, 0);
-                break;
-            }
-        }
-    }
-    if (i >= MAX_CART)
-    {
-        // 装 備品か未所有品だったので空き欄へ追加
-        for (i = 0; i < MAX_CART; i++)
-        {
-            if (sd->status.cart[i].nameid == 0)
-            {
-                memcpy (&sd->status.cart[i], item_data,
-                        sizeof (sd->status.cart[0]));
-                sd->status.cart[i].amount = amount;
-                sd->cart_num++;
-                clif_cart_additem (sd, i, amount, 0);
-                break;
-            }
-        }
-        if (i >= MAX_CART)
-            return 1;
-    }
-    sd->cart_weight += w;
-    clif_updatestatus (sd, SP_CARTINFO);
-
-    return 0;
-}
-
-/*==========================================
- * カートアイテムを減らす
- *------------------------------------------
- */
-int pc_cart_delitem (struct map_session_data *sd, int n, int amount, int type)
-{
-    nullpo_retr (1, sd);
-
-    if (sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount)
-        return 1;
-
-    sd->status.cart[n].amount -= amount;
-    sd->cart_weight -= itemdb_weight (sd->status.cart[n].nameid) * amount;
-    if (sd->status.cart[n].amount <= 0)
-    {
-        memset (&sd->status.cart[n], 0, sizeof (sd->status.cart[0]));
-        sd->cart_num--;
-    }
-    if (!type)
-    {
-        clif_cart_delitem (sd, n, amount);
-        clif_updatestatus (sd, SP_CARTINFO);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * カートへアイテム移動
- *------------------------------------------
- */
-int pc_putitemtocart (struct map_session_data *sd, int idx, int amount)
-{
-    struct item *item_data;
-
-    nullpo_retr (0, sd);
-
-    if (idx < 0 || idx >= MAX_INVENTORY)
-        return 1;
-
-    nullpo_retr (0, item_data = &sd->status.inventory[idx]);
-
-    if (!pc_iscarton (sd))
-        return 1;
-    if (item_data->nameid == 0 || item_data->amount < amount)
-        return 1;
-    if (pc_cart_additem (sd, item_data, amount) == 0)
-        return pc_delitem (sd, idx, amount, 0);
-
-    return 1;
-}
-
-/*==========================================
- * カート内のアイテム数確認(個数の差分を返す)
- *------------------------------------------
- */
-int pc_cartitem_amount (struct map_session_data *sd, int idx, int amount)
-{
-    struct item *item_data;
-
-    nullpo_retr (-1, sd);
-
-    if (idx < 0 || idx >= MAX_CART)
-        return -1;
-
-    nullpo_retr (-1, item_data = &sd->status.cart[idx]);
-
-    if (!pc_iscarton (sd))
-        return -1;
-    if (item_data->nameid == 0 || !item_data->amount)
-        return -1;
-    return item_data->amount - amount;
-}
-
-/*==========================================
- * カートからアイテム移動
- *------------------------------------------
- */
-
-int pc_getitemfromcart (struct map_session_data *sd, int idx, int amount)
-{
-    struct item *item_data;
-    int  flag;
-
-    nullpo_retr (0, sd);
-
-    if (idx < 0 || idx >= MAX_CART)
-        return 1;
-
-    nullpo_retr (0, item_data = &sd->status.cart[idx]);
-
-    if (!pc_iscarton (sd))
-        return 1;
-    if (item_data->nameid == 0 || item_data->amount < amount)
-        return 1;
-    if ((flag = pc_additem (sd, item_data, amount)) == 0)
-        return pc_cart_delitem (sd, idx, amount, 0);
-
-    clif_additem (sd, 0, 0, flag);
-    return 1;
-}
-
-/*==========================================
- * アイテム鑑定
- *------------------------------------------
- */
-int pc_item_identify (struct map_session_data *sd, int idx)
-{
-    int  flag = 1;
-
-    nullpo_retr (0, sd);
-
-    if (idx >= 0 && idx < MAX_INVENTORY)
-    {
-        if (sd->status.inventory[idx].nameid > 0
-            && sd->status.inventory[idx].identify == 0)
-        {
-            flag = 0;
-            sd->status.inventory[idx].identify = 1;
-        }
-        clif_item_identified (sd, idx, flag);
-    }
-    else
-        clif_item_identified (sd, idx, flag);
-
-    return !flag;
-}
-
-/*==========================================
- * スティル品公開
- *------------------------------------------
- */
-int pc_show_steal (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-    int  itemid;
-    int  type;
-
-    struct item_data *item = NULL;
-    char output[100];
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
-
-    itemid = va_arg (ap, int);
-    type = va_arg (ap, int);
-
-    if (!type)
-    {
-        if ((item = itemdb_exists (itemid)) == NULL)
-            sprintf (output, "%s stole an Unknown_Item.", sd->status.name);
-        else
-            sprintf (output, "%s stole %s.", sd->status.name, item->jname);
-        clif_displaymessage (((struct map_session_data *) bl)->fd, output);
-    }
-    else
-    {
-        sprintf (output,
-                 "%s has not stolen the item because of being  overweight.",
-                 sd->status.name);
-        clif_displaymessage (((struct map_session_data *) bl)->fd, output);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-//** pc.c: Small Steal Item fix by fritz
-int pc_steal_item (struct map_session_data *sd, struct block_list *bl)
-{
-    if (sd != NULL && bl != NULL && bl->type == BL_MOB)
-    {
-        int  i, skill, rate, itemid, flag, count;
-        struct mob_data *md;
-        md = (struct mob_data *) bl;
-        if (!md->state.steal_flag && mob_db[md->mob_class].mexp <= 0 &&
-            !(mob_db[md->mob_class].mode & 0x20) &&
-            md->sc_data[SC_STONE].timer == -1 &&
-            md->sc_data[SC_FREEZE].timer == -1 &&
-            (!(md->mob_class > 1324 && md->mob_class < 1364)))   // prevent stealing from treasure boxes [Valaris]
-        {
-            skill = sd->paramc[4] - mob_db[md->mob_class].dex
-                + pc_checkskill (sd, TF_STEAL) + 10;
-
-            if (0 < skill)
-            {
-                for (count = 8; count <= 8 && count != 0; count--)
-                {
-                    i = rand () % 8;
-                    itemid = mob_db[md->mob_class].dropitem[i].nameid;
-
-                    if (itemid > 0 && itemdb_type (itemid) != 6)
-                    {
-                        rate =
-                            (mob_db[md->mob_class].dropitem[i].p /
-                             battle_config.item_rate_common * 100 * skill) /
-                            100;
-
-                        if (rand () % 10000 < rate)
-                        {
-                            struct item tmp_item;
-                            memset (&tmp_item, 0, sizeof (tmp_item));
-                            tmp_item.nameid = itemid;
-                            tmp_item.amount = 1;
-                            tmp_item.identify = 1;
-                            flag = pc_additem (sd, &tmp_item, 1);
-                            if (battle_config.show_steal_in_same_party)
-                            {
-                                party_foreachsamemap (pc_show_steal, sd, 1,
-                                                      sd, tmp_item.nameid, 0);
-                            }
-
-                            if (flag)
-                            {
-                                if (battle_config.show_steal_in_same_party)
-                                {
-                                    party_foreachsamemap (pc_show_steal, sd,
-                                                          1, sd,
-                                                          tmp_item.nameid, 1);
-                                }
-
-                                clif_additem (sd, 0, 0, flag);
-                            }
-                            md->state.steal_flag = 1;
-                            return 1;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int pc_steal_coin (struct map_session_data *sd, struct block_list *bl)
-{
-    if (sd != NULL && bl != NULL && bl->type == BL_MOB)
-    {
-        int  rate, skill;
-        struct mob_data *md = (struct mob_data *) bl;
-        if (md && !md->state.steal_coin_flag && md->sc_data
-            && md->sc_data[SC_STONE].timer == -1
-            && md->sc_data[SC_FREEZE].timer == -1)
-        {
-            skill = pc_checkskill (sd, RG_STEALCOIN) * 10;
-            rate =
-                skill + (sd->status.base_level - mob_db[md->mob_class].lv) * 3 +
-                sd->paramc[4] * 2 + sd->paramc[5] * 2;
-            if (MRAND (1000) < rate)
-            {
-                pc_getzeny (sd, mob_db[md->mob_class].lv * 10 + MRAND (100));
-                md->state.steal_coin_flag = 1;
-                return 1;
-            }
-        }
-    }
-
-    return 0;
-}
-
-//
-//
-//
-/*==========================================
- * PCの位置設定
- *------------------------------------------
- */
-int pc_setpos (struct map_session_data *sd, char *mapname_org, int x, int y,
-               int clrtype)
-{
-    char mapname[24];
-    int  m = 0, c = 0, disguise = 0;
-
-    nullpo_retr (0, sd);
-
-    if (sd->chatID)             // チャットから出る
-        chat_leavechat (sd);
-    if (sd->trade_partner)      // 取引を中断する
-        trade_tradecancel (sd);
-    if (sd->state.storage_flag == 1)
-        storage_storage_quit (sd);  // 倉庫を開いてるなら保存する
-    else if (sd->state.storage_flag == 2)
-        storage_guild_storage_quit (sd, 0);
-
-    if (sd->party_invite > 0)   // パーティ勧誘を拒否する
-        party_reply_invite (sd, sd->party_invite_account, 0);
-    if (sd->guild_invite > 0)   // ギルド勧誘を拒否する
-        guild_reply_invite (sd, sd->guild_invite, 0);
-    if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する
-        guild_reply_reqalliance (sd, sd->guild_alliance_account, 0);
-
-    skill_castcancel (&sd->bl, 0);  // 詠唱中断
-    pc_stop_walking (sd, 0);    // 歩行中断
-    pc_stopattack (sd);         // 攻撃中断
-
-    if (pc_issit (sd))
-    {
-//        pc_setstand (sd); // [fate] Nothing wrong with warping while sitting
-        skill_gangsterparadise (sd, 0);
-    }
-
-    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
-        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
-    if (sd->status.option & 2)
-        skill_status_change_end (&sd->bl, SC_HIDING, -1);
-    if (sd->status.option & 4)
-        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
-    if (sd->status.option & 16386)
-        skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
-    if (sd->sc_data[SC_BLADESTOP].timer != -1)
-        skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
-    if (sd->sc_data[SC_DANCING].timer != -1)    // clear dance effect when warping [Valaris]
-        skill_stop_dancing (&sd->bl, 0);
-
-    if (sd->disguise)
-    {                           // clear disguises when warping [Valaris]
-        clif_clearchar (&sd->bl, 9);
-        disguise = sd->disguise;
-        sd->disguise = 0;
-    }
-
-    memcpy (mapname, mapname_org, 24);
-    mapname[16] = 0;
-    if (strstr (mapname, ".gat") == NULL && strlen (mapname) < 16)
-    {
-        strcat (mapname, ".gat");
-    }
-
-    m = map_mapname2mapid (mapname);
-    if (m < 0)
-    {
-        if (sd->mapname[0])
-        {
-            int  ip, port;
-            if (map_mapname2ipport (mapname, &ip, &port) == 0)
-            {
-                skill_stop_dancing (&sd->bl, 1);
-                skill_unit_out_all (&sd->bl, gettick (), 1);
-                clif_clearchar_area (&sd->bl, clrtype & 0xffff);
-                skill_gangsterparadise (sd, 0);
-                map_delblock (&sd->bl);
-                memcpy (sd->mapname, mapname, 24);
-                sd->bl.x = x;
-                sd->bl.y = y;
-                sd->state.waitingdisconnect = 1;
-                pc_makesavestatus (sd);
-                //The storage close routines save the char data. [Skotlex]
-                if (!sd->state.storage_flag)
-                    chrif_save (sd);
-                else if (sd->state.storage_flag == 1)
-                    storage_storage_quit (sd);
-                else if (sd->state.storage_flag == 2)
-                    storage_guild_storage_quit (sd, 1);
-
-                chrif_changemapserver (sd, mapname, x, y, ip, port);
-                return 0;
-            }
-        }
-#if 0
-        clif_authfail_fd (sd->fd, 0);   // cancel
-        clif_setwaitclose (sd->fd);
-#endif
-        return 1;
-    }
-
-    if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
-        x = y = 0;
-    if ((x == 0 && y == 0) || (c = read_gat (m, x, y)) == 1 || c == 5)
-    {
-        if (x || y)
-        {
-            if (battle_config.error_log)
-                printf ("stacked (%d,%d)\n", x, y);
-        }
-        do
-        {
-            x = MRAND (map[m].xs - 2) + 1;
-            y = MRAND (map[m].ys - 2) + 1;
-        }
-        while ((c = read_gat (m, x, y)) == 1 || c == 5);
-    }
-
-    if (sd->mapname[0] && sd->bl.prev != NULL)
-    {
-        skill_unit_out_all (&sd->bl, gettick (), 1);
-        clif_clearchar_area (&sd->bl, clrtype & 0xffff);
-        skill_gangsterparadise (sd, 0);
-        map_delblock (&sd->bl);
-        clif_changemap (sd, map[m].name, x, y); // [MouseJstr]
-    }
-
-    if (disguise)               // disguise teleport fix [Valaris]
-        sd->disguise = disguise;
-
-    memcpy (sd->mapname, mapname, 24);
-    sd->bl.m = m;
-    sd->to_x = x;
-    sd->to_y = y;
-
-    // moved and changed dance effect stopping
-
-    sd->bl.x = x;
-    sd->bl.y = y;
-
-//  map_addblock(&sd->bl);  // ブロック登録とspawnは
-//  clif_spawnpc(sd);
-
-    return 0;
-}
-
-/*==========================================
- * PCのランダムワープ
- *------------------------------------------
- */
-int pc_randomwarp (struct map_session_data *sd, int type)
-{
-    int  x, y, c, i = 0;
-    int  m;
-
-    nullpo_retr (0, sd);
-
-    m = sd->bl.m;
-
-    if (map[sd->bl.m].flag.noteleport)  // テレポート禁止
-        return 0;
-
-    do
-    {
-        x = MRAND (map[m].xs - 2) + 1;
-        y = MRAND (map[m].ys - 2) + 1;
-    }
-    while (((c = read_gat (m, x, y)) == 1 || c == 5) && (i++) < 1000);
-
-    if (i < 1000)
-        pc_setpos (sd, map[m].name, x, y, type);
-
-    return 0;
-}
-
-/*==========================================
- * 現在位置のメモ
- *------------------------------------------
- */
-int pc_memo (struct map_session_data *sd, int i)
-{
-    int  skill;
-    int  j;
-
-    nullpo_retr (0, sd);
-
-    skill = pc_checkskill (sd, AL_WARP);
-
-    if (i >= MIN_PORTAL_MEMO)
-        i -= MIN_PORTAL_MEMO;
-    else if (map[sd->bl.m].flag.nomemo
-             || (map[sd->bl.m].flag.nowarpto
-                 && battle_config.any_warp_GM_min_level > pc_isGM (sd)))
-    {
-        clif_skill_teleportmessage (sd, 1);
-        return 0;
-    }
-
-    if (skill < 1)
-    {
-        clif_skill_memo (sd, 2);
-    }
-
-    if (skill < 2 || i < -1 || i > 2)
-    {
-        clif_skill_memo (sd, 1);
-        return 0;
-    }
-
-    for (j = 0; j < 3; j++)
-    {
-        if (strcmp (sd->status.memo_point[j].map, map[sd->bl.m].name) == 0)
-        {
-            i = j;
-            break;
-        }
-    }
-
-    if (i == -1)
-    {
-        for (i = skill - 3; i >= 0; i--)
-        {
-            memcpy (&sd->status.memo_point[i + 1], &sd->status.memo_point[i],
-                    sizeof (struct point));
-        }
-        i = 0;
-    }
-    memcpy (sd->status.memo_point[i].map, map[sd->bl.m].name, 24);
-    sd->status.memo_point[i].x = sd->bl.x;
-    sd->status.memo_point[i].y = sd->bl.y;
-
-    clif_skill_memo (sd, 0);
-
-    return 1;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int pc_can_reach (struct map_session_data *sd, int x, int y)
-{
-    struct walkpath_data wpd;
-
-    nullpo_retr (0, sd);
-
-    if (sd->bl.x == x && sd->bl.y == y) // 同じマス
-        return 1;
-
-    // 障害物判定
-    wpd.path_len = 0;
-    wpd.path_pos = 0;
-    wpd.path_half = 0;
-    return (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, x, y, 0) !=
-            -1) ? 1 : 0;
-}
-
-//
-// 歩 行物
-//
-/*==========================================
- * 次の1歩にかかる時間を計算
- *------------------------------------------
- */
-static int calc_next_walk_step (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->walkpath.path_pos >= sd->walkpath.path_len)
-        return -1;
-    if (sd->walkpath.path[sd->walkpath.path_pos] & 1)
-        return sd->speed * 14 / 10;
-
-    return sd->speed;
-}
-
-/*==========================================
- * 半歩進む(timer関数)
- *------------------------------------------
- */
-static void pc_walk (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd;
-    int  i, ctype;
-    int  moveblock;
-    int  x, y, dx, dy;
-
-    sd = map_id2sd (id);
-    if (sd == NULL)
-        return;
-
-    if (sd->walktimer != tid)
-    {
-        if (battle_config.error_log)
-            printf ("pc_walk %d != %d\n", sd->walktimer, tid);
-        return;
-    }
-    sd->walktimer = -1;
-    if (sd->walkpath.path_pos >= sd->walkpath.path_len
-        || sd->walkpath.path_pos != data)
-        return;
-
-    //歩いたので息吹のタイマーを初期化
-    sd->inchealspirithptick = 0;
-    sd->inchealspiritsptick = 0;
-
-    sd->walkpath.path_half ^= 1;
-    if (sd->walkpath.path_half == 0)
-    {                           // マス目中心へ到着
-        sd->walkpath.path_pos++;
-        if (sd->state.change_walk_target)
-        {
-            pc_walktoxy_sub (sd);
-            return;
-        }
-    }
-    else
-    {                           // マス目境界へ到着
-        if (sd->walkpath.path[sd->walkpath.path_pos] >= 8)
-            return;
-
-        x = sd->bl.x;
-        y = sd->bl.y;
-        ctype = map_getcell (sd->bl.m, x, y);
-        if (ctype == 1 || ctype == 5)
-        {
-            pc_stop_walking (sd, 1);
-            return;
-        }
-        sd->dir = sd->head_dir = sd->walkpath.path[sd->walkpath.path_pos];
-        dx = dirx[(int) sd->dir];
-        dy = diry[(int) sd->dir];
-        ctype = map_getcell (sd->bl.m, x + dx, y + dy);
-        if (ctype == 1 || ctype == 5)
-        {
-            pc_walktoxy_sub (sd);
-            return;
-        }
-
-        moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
-                     || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
-
-        sd->walktimer = 1;
-        map_foreachinmovearea (clif_pcoutsight, sd->bl.m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               dx, dy, 0, sd);
-
-        x += dx;
-        y += dy;
-
-        if (moveblock)
-            map_delblock (&sd->bl);
-        sd->bl.x = x;
-        sd->bl.y = y;
-        if (moveblock)
-            map_addblock (&sd->bl);
-
-        if (sd->sc_data[SC_DANCING].timer != -1)
-            skill_unit_move_unit_group ((struct skill_unit_group *)
-                                        sd->sc_data[SC_DANCING].val2,
-                                        sd->bl.m, dx, dy);
-
-        map_foreachinmovearea (clif_pcinsight, sd->bl.m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               -dx, -dy, 0, sd);
-        sd->walktimer = -1;
-
-        if (sd->status.party_id > 0)
-        {                       // パーティのHP情報通知検査
-            struct party *p = party_search (sd->status.party_id);
-            if (p != NULL)
-            {
-                int  p_flag = 0;
-                map_foreachinmovearea (party_send_hp_check, sd->bl.m,
-                                       x - AREA_SIZE, y - AREA_SIZE,
-                                       x + AREA_SIZE, y + AREA_SIZE, -dx, -dy,
-                                       BL_PC, sd->status.party_id, &p_flag);
-                if (p_flag)
-                    sd->party_hp = -1;
-            }
-        }
-        if (sd->status.option & 4)  // クローキングの消滅検査
-            skill_check_cloaking (&sd->bl);
-        // ディボーション検査
-        for (i = 0; i < 5; i++)
-            if (sd->dev.val1[i])
-            {
-                skill_devotion3 (&sd->bl, sd->dev.val1[i]);
-                break;
-            }
-        // 被ディボーション検査
-        if (sd->sc_data && sd->sc_data[SC_DEVOTION].val1)
-        {
-            skill_devotion2 (&sd->bl, sd->sc_data[SC_DEVOTION].val1);
-        }
-
-        skill_unit_move (&sd->bl, tick, 1); // スキルユニットの検査
-
-        if (map_getcell (sd->bl.m, x, y) & 0x80)
-            npc_touch_areanpc (sd, sd->bl.m, x, y);
-        else
-            sd->areanpc_id = 0;
-    }
-    if ((i = calc_next_walk_step (sd)) > 0)
-    {
-        i = i >> 1;
-        if (i < 1 && sd->walkpath.path_half == 0)
-            i = 1;
-        sd->walktimer =
-            add_timer (tick + i, pc_walk, id, sd->walkpath.path_pos);
-    }
-}
-
-/*==========================================
- * 移動可能か確認して、可能なら歩行開始
- *------------------------------------------
- */
-static int pc_walktoxy_sub (struct map_session_data *sd)
-{
-    struct walkpath_data wpd;
-    int  i;
-
-    nullpo_retr (1, sd);
-
-    if (path_search
-        (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y, 0))
-        return 1;
-    memcpy (&sd->walkpath, &wpd, sizeof (wpd));
-
-    clif_walkok (sd);
-    sd->state.change_walk_target = 0;
-
-    if ((i = calc_next_walk_step (sd)) > 0)
-    {
-        i = i >> 2;
-        sd->walktimer = add_timer (gettick () + i, pc_walk, sd->bl.id, 0);
-    }
-    clif_movechar (sd);
-
-    return 0;
-}
-
-/*==========================================
- * pc歩 行要求
- *------------------------------------------
- */
-int pc_walktoxy (struct map_session_data *sd, int x, int y)
-{
-
-    nullpo_retr (0, sd);
-
-    sd->to_x = x;
-    sd->to_y = y;
-
-    if (pc_issit (sd))
-        pc_setstand (sd);
-
-    if (sd->walktimer != -1 && sd->state.change_walk_target == 0)
-    {
-        // 現在歩いている最中の目的地変更なのでマス目の中心に来た時に
-        // timer関数からpc_walktoxy_subを呼ぶようにする
-        sd->state.change_walk_target = 1;
-    }
-    else
-    {
-        pc_walktoxy_sub (sd);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 歩 行停止
- *------------------------------------------
- */
-int pc_stop_walking (struct map_session_data *sd, int type)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->walktimer != -1)
-    {
-        delete_timer (sd->walktimer, pc_walk);
-        sd->walktimer = -1;
-    }
-    sd->walkpath.path_len = 0;
-    sd->to_x = sd->bl.x;
-    sd->to_y = sd->bl.y;
-    if (type & 0x01)
-        clif_fixpos (&sd->bl);
-    if (type & 0x02 && battle_config.pc_damage_delay)
-    {
-        unsigned int tick = gettick ();
-        int  delay = battle_get_dmotion (&sd->bl);
-        if (sd->canmove_tick < tick)
-            sd->canmove_tick = tick + delay;
-    }
-
-    return 0;
-}
-
-void pc_touch_all_relevant_npcs (struct map_session_data *sd)
-{
-    if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) & 0x80)
-        npc_touch_areanpc (sd, sd->bl.m, sd->bl.x, sd->bl.y);
-    else
-        sd->areanpc_id = 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int pc_movepos (struct map_session_data *sd, int dst_x, int dst_y)
-{
-    int  moveblock;
-    int  dx, dy, dist;
-
-    struct walkpath_data wpd;
-
-    nullpo_retr (0, sd);
-
-    if (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, dst_x, dst_y, 0))
-        return 1;
-
-    sd->dir = sd->head_dir = map_calc_dir (&sd->bl, dst_x, dst_y);
-
-    dx = dst_x - sd->bl.x;
-    dy = dst_y - sd->bl.y;
-    dist = distance (sd->bl.x, sd->bl.y, dst_x, dst_y);
-
-    moveblock = (sd->bl.x / BLOCK_SIZE != dst_x / BLOCK_SIZE
-                 || sd->bl.y / BLOCK_SIZE != dst_y / BLOCK_SIZE);
-
-    map_foreachinmovearea (clif_pcoutsight, sd->bl.m, sd->bl.x - AREA_SIZE,
-                           sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
-                           sd->bl.y + AREA_SIZE, dx, dy, 0, sd);
-
-    if (moveblock)
-        map_delblock (&sd->bl);
-    sd->bl.x = dst_x;
-    sd->bl.y = dst_y;
-    if (moveblock)
-        map_addblock (&sd->bl);
-
-    map_foreachinmovearea (clif_pcinsight, sd->bl.m, sd->bl.x - AREA_SIZE,
-                           sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
-                           sd->bl.y + AREA_SIZE, -dx, -dy, 0, sd);
-
-    if (sd->status.party_id > 0)
-    {                           // パーティのHP情報通知検査
-        struct party *p = party_search (sd->status.party_id);
-        if (p != NULL)
-        {
-            int  flag = 0;
-            map_foreachinmovearea (party_send_hp_check, sd->bl.m,
-                                   sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
-                                   sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE,
-                                   -dx, -dy, BL_PC, sd->status.party_id,
-                                   &flag);
-            if (flag)
-                sd->party_hp = -1;
-        }
-    }
-
-    if (sd->status.option & 4)  // クローキングの消滅検査
-        skill_check_cloaking (&sd->bl);
-
-    skill_unit_move (&sd->bl, gettick (), dist + 7);    // スキルユニットの検査
-
-    pc_touch_all_relevant_npcs (sd);
-    return 0;
-}
-
-//
-// 武器戦闘
-//
-/*==========================================
- * スキルの検索 所有していた場合Lvが返る
- *------------------------------------------
- */
-int pc_checkskill (struct map_session_data *sd, int skill_id)
-{
-    if (sd == NULL)
-        return 0;
-    if (skill_id >= 10000)
-    {
-        struct guild *g;
-        if (sd->status.guild_id > 0
-            && (g = guild_search (sd->status.guild_id)) != NULL)
-            return guild_checkskill (g, skill_id);
-        return 0;
-    }
-
-    if (sd->status.skill[skill_id].id == skill_id)
-        return (sd->status.skill[skill_id].lv);
-
-    return 0;
-}
-
-/*==========================================
- * 武器変更によるスキルの継続チェック
- * 引数:
- *   struct map_session_data *sd	セッションデータ
- *   int nameid						装備品ID
- * 返り値:
- *   0		変更なし
- *   -1		スキルを解除
- *------------------------------------------
- */
-int pc_checkallowskill (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->sc_data == NULL)
-        return 0;
-
-    if (!(skill_get_weapontype (KN_TWOHANDQUICKEN) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_TWOHANDQUICKEN].timer != -1)
-    {                           // 2HQ
-        skill_status_change_end (&sd->bl, SC_TWOHANDQUICKEN, -1);   // 2HQを解除
-        return -1;
-    }
-    if (!(skill_get_weapontype (LK_AURABLADE) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_AURABLADE].timer != -1)
-    {                           // オーラブレード
-        skill_status_change_end (&sd->bl, SC_AURABLADE, -1);    // オーラブレードを解除
-        return -1;
-    }
-    if (!(skill_get_weapontype (LK_PARRYING) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_PARRYING].timer != -1)
-    {                           // パリイング
-        skill_status_change_end (&sd->bl, SC_PARRYING, -1); // パリイングを解除
-        return -1;
-    }
-    if (!(skill_get_weapontype (LK_CONCENTRATION) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_CONCENTRATION].timer != -1)
-    {                           // コンセントレーション
-        skill_status_change_end (&sd->bl, SC_CONCENTRATION, -1);    // コンセントレーションを解除
-        return -1;
-    }
-    if (!(skill_get_weapontype (CR_SPEARQUICKEN) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_SPEARSQUICKEN].timer != -1)
-    {                           // スピアクィッケン
-        skill_status_change_end (&sd->bl, SC_SPEARSQUICKEN, -1);    // スピアクイッケンを解除
-        return -1;
-    }
-    if (!(skill_get_weapontype (BS_ADRENALINE) & (1 << sd->status.weapon))
-        && sd->sc_data[SC_ADRENALINE].timer != -1)
-    {                           // アドレナリンラッシュ
-        skill_status_change_end (&sd->bl, SC_ADRENALINE, -1);   // アドレナリンラッシュを解除
-        return -1;
-    }
-
-    if (sd->status.shield <= 0)
-    {
-        if (sd->sc_data[SC_AUTOGUARD].timer != -1)
-        {                       // オートガード
-            skill_status_change_end (&sd->bl, SC_AUTOGUARD, -1);
-            return -1;
-        }
-        if (sd->sc_data[SC_DEFENDER].timer != -1)
-        {                       // ディフェンダー
-            skill_status_change_end (&sd->bl, SC_DEFENDER, -1);
-            return -1;
-        }
-        if (sd->sc_data[SC_REFLECTSHIELD].timer != -1)
-        {                       //リフレクトシールド
-            skill_status_change_end (&sd->bl, SC_REFLECTSHIELD, -1);
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 装 備品のチェック
- *------------------------------------------
- */
-int pc_checkequip (struct map_session_data *sd, int pos)
-{
-    int  i;
-
-    nullpo_retr (-1, sd);
-
-    for (i = 0; i < 11; i++)
-    {
-        if (pos & equip_pos[i])
-            return sd->equip_index[i];
-    }
-
-    return -1;
-}
-
-/*==========================================
- * 転生職や養子職の元の職業を返す
- *------------------------------------------
- */
-struct pc_base_job pc_calc_base_job (int b_class)
-{
-    struct pc_base_job bj;
-    //転生や養子の場合の元の職業を算出する
-    if (b_class < MAX_PC_CLASS)
-    {                           //通常
-        bj.job = b_class;
-        bj.upper = 0;
-    }
-    else if (b_class >= 4001 && b_class < 4023)
-    {                           //転生職
-        bj.job = b_class - 4001;
-        bj.upper = 1;
-    }
-    else if (b_class == 23 + 4023 - 1)
-    {                           //養子スパノビ
-        bj.job = b_class - (4023 - 1);
-        bj.upper = 2;
-    }
-    else
-    {                           //養子スパノビ以外の養子
-        bj.job = b_class - 4023;
-        bj.upper = 2;
-    }
-
-    if (battle_config.enable_upper_class == 0)
-    {                           //confで無効になっていたらupper=0
-        bj.upper = 0;
-    }
-
-    if (bj.job == 0)
-    {
-        bj.type = 0;
-    }
-    else if (bj.job < 7)
-    {
-        bj.type = 1;
-    }
-    else
-    {
-        bj.type = 2;
-    }
-
-    return bj;
-}
-
-/*==========================================
- * PCの攻撃 (timer関数)
- *------------------------------------------
- */
-void pc_attack_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd;
-    struct block_list *bl;
-    struct status_change *sc_data;
-    short *opt;
-    int  dist, skill, range;
-    int  attack_spell_delay;
-
-    sd = map_id2sd (id);
-    if (sd == NULL)
-        return;
-    if (sd->attacktimer != tid)
-    {
-        if (battle_config.error_log)
-            printf ("pc_attack_timer %d != %d\n", sd->attacktimer, tid);
-        return;
-    }
-    sd->attacktimer = -1;
-
-    if (sd->bl.prev == NULL)
-        return;
-
-    bl = map_id2bl (sd->attacktarget);
-    if (bl == NULL || bl->prev == NULL)
-        return;
-
-    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
-        return;
-
-    // 同じmapでないなら攻撃しない
-    // PCが死んでても攻撃しない
-    if (sd->bl.m != bl->m || pc_isdead (sd))
-        return;
-
-    if (sd->opt1 > 0 || sd->status.option & 2 || sd->status.option & 16388) // 異常などで攻撃できない
-        return;
-
-    if (sd->sc_data[SC_AUTOCOUNTER].timer != -1)
-        return;
-    if (sd->sc_data[SC_BLADESTOP].timer != -1)
-        return;
-
-    if ((opt = battle_get_option (bl)) != NULL && *opt & 0x46)
-        return;
-    if (((sc_data = battle_get_sc_data (bl)) != NULL
-         && sc_data[SC_TRICKDEAD].timer != -1)
-        || ((sc_data = battle_get_sc_data (bl)) != NULL
-            && sc_data[SC_BASILICA].timer != -1))
-        return;
-
-    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) <= 0)
-        return;
-
-    if (!battle_config.sdelay_attack_enable
-        && pc_checkskill (sd, SA_FREECAST) <= 0)
-    {
-        if (DIFF_TICK (tick, sd->canact_tick) < 0)
-        {
-            clif_skill_fail (sd, 1, 4, 0);
-            return;
-        }
-    }
-
-    if (sd->attackabletime > tick)
-        return;               // cannot attack yet
-
-    attack_spell_delay = sd->attack_spell_delay;
-    if (sd->attack_spell_override   // [Fate] If we have an active attack spell, use that
-        && spell_attack (id, sd->attacktarget))
-    {
-        // Return if the spell succeeded.  If the spell had disspiated, spell_attack() may fail.
-        sd->attackabletime = tick + attack_spell_delay;
-
-    }
-    else
-    {
-        dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y);
-        range = sd->attackrange;
-        if (sd->status.weapon != 11)
-            range++;
-        if (dist > range)
-        {                       // 届 かないので移動
-            //if(pc_can_reach(sd,bl->x,bl->y))
-            //clif_movetoattack(sd,bl);
-            return;
-        }
-
-        if (dist <= range && !battle_check_range (&sd->bl, bl, range))
-        {
-            if (pc_can_reach (sd, bl->x, bl->y) && sd->canmove_tick < tick
-                && (sd->sc_data[SC_ANKLE].timer == -1
-                    || sd->sc_data[SC_SPIDERWEB].timer == -1))
-                // TMW client doesn't support this
-                //pc_walktoxy(sd,bl->x,bl->y);
-                clif_movetoattack (sd, bl);
-            sd->attackabletime = tick + (sd->aspd << 1);
-        }
-        else
-        {
-            if (battle_config.pc_attack_direction_change)
-                sd->dir = sd->head_dir = map_calc_dir (&sd->bl, bl->x, bl->y);  // 向き設定
-
-            if (sd->walktimer != -1)
-                pc_stop_walking (sd, 1);
-
-            if (sd->sc_data[SC_COMBO].timer == -1)
-            {
-                map_freeblock_lock ();
-                pc_stop_walking (sd, 0);
-                sd->attacktarget_lv =
-                    battle_weapon_attack (&sd->bl, bl, tick, 0);
-                if (!(battle_config.pc_cloak_check_type & 2)
-                    && sd->sc_data[SC_CLOAKING].timer != -1)
-                    skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
-                map_freeblock_unlock ();
-                if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)  // フリーキャスト
-                    sd->attackabletime =
-                        tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
-                else
-                    sd->attackabletime = tick + (sd->aspd << 1);
-            }
-            else if (sd->attackabletime <= tick)
-            {
-                if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)  // フリーキャスト
-                    sd->attackabletime =
-                        tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
-                else
-                    sd->attackabletime = tick + (sd->aspd << 1);
-            }
-            if (sd->attackabletime <= tick)
-                sd->attackabletime = tick + (battle_config.max_aspd << 1);
-        }
-    }
-
-    if (sd->state.attack_continue)
-    {
-        sd->attacktimer =
-            add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
-    }
-}
-
-/*==========================================
- * 攻撃要求
- * typeが1なら継続攻撃
- *------------------------------------------
- */
-int pc_attack (struct map_session_data *sd, int target_id, int type)
-{
-    struct block_list *bl;
-    int  d;
-
-    nullpo_retr (0, sd);
-
-    bl = map_id2bl (target_id);
-    if (bl == NULL)
-        return 1;
-
-    if (bl->type == BL_NPC)
-    {                           // monster npcs [Valaris]
-        npc_click (sd, RFIFOL (sd->fd, 2));
-        return 0;
-    }
-
-    if (!battle_check_target (&sd->bl, bl, BCT_ENEMY))
-        return 1;
-    if (sd->attacktimer != -1)
-        pc_stopattack (sd);
-    sd->attacktarget = target_id;
-    sd->state.attack_continue = type;
-
-    d = DIFF_TICK (sd->attackabletime, gettick ());
-    if (d > 0 && d < 2000)
-    {                           // 攻撃delay中
-        sd->attacktimer =
-            add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
-    }
-    else
-    {
-        // 本来timer関数なので引数を合わせる
-        pc_attack_timer (-1, gettick (), sd->bl.id, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 継続攻撃停止
- *------------------------------------------
- */
-int pc_stopattack (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->attacktimer != -1)
-    {
-        delete_timer (sd->attacktimer, pc_attack_timer);
-        sd->attacktimer = -1;
-    }
-    sd->attacktarget = 0;
-    sd->state.attack_continue = 0;
-
-    return 0;
-}
-
-void pc_follow_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd, *bl;
-
-    sd = map_id2sd (id);
-    if (sd == NULL || sd->followtimer != tid)
-        return;
-
-    sd->followtimer = -1;
-
-    do
-    {
-        if (sd->bl.prev == NULL)
-            break;
-
-        bl = (struct map_session_data *) map_id2bl (sd->followtarget);
-
-        if (bl == NULL)
-            return;
-
-        if (bl->bl.prev == NULL)
-            break;
-
-        if (bl->bl.type == BL_PC
-            && pc_isdead ((struct map_session_data *) bl))
-            return;
-
-        if (sd->skilltimer == -1 && sd->attacktimer == -1
-            && sd->walktimer == -1)
-        {
-            if ((sd->bl.m == bl->bl.m)
-                && pc_can_reach (sd, bl->bl.x, bl->bl.y))
-            {
-                if (distance (sd->bl.x, sd->bl.y, bl->bl.x, bl->bl.y) > 5)
-                    pc_walktoxy (sd, bl->bl.x, bl->bl.y);
-            }
-            else
-                pc_setpos ((struct map_session_data *) sd, bl->mapname,
-                           bl->bl.x, bl->bl.y, 3);
-        }
-    }
-    while (0);
-
-    sd->followtimer =
-        add_timer (tick + sd->aspd, pc_follow_timer, sd->bl.id, 0);
-}
-
-int pc_follow (struct map_session_data *sd, int target_id)
-{
-    struct block_list *bl;
-
-    bl = map_id2bl (target_id);
-    if (bl == NULL)
-        return 1;
-    sd->followtarget = target_id;
-    if (sd->followtimer != -1)
-    {
-        delete_timer (sd->followtimer, pc_follow_timer);
-        sd->followtimer = -1;
-    }
-
-    pc_follow_timer (-1, gettick (), sd->bl.id, 0);
-
-    return 0;
-}
-
-int pc_checkbaselevelup (struct map_session_data *sd)
-{
-    int  next = pc_nextbaseexp (sd);
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.base_exp >= next && next > 0)
-    {
-        struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
-
-        // base側レベルアップ処理
-        sd->status.base_exp -= next;
-
-        sd->status.base_level++;
-        sd->status.status_point += (sd->status.base_level + 14) / 4;
-        clif_updatestatus (sd, SP_STATUSPOINT);
-        clif_updatestatus (sd, SP_BASELEVEL);
-        clif_updatestatus (sd, SP_NEXTBASEEXP);
-        pc_calcstatus (sd, 0);
-        pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
-
-        //スパノビはキリエ、イムポ、マニピ、グロ、サフラLv1がかかる
-        if (s_class.job == 23)
-        {
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable[PR_KYRIE], 1, 0,
-                                       0, 0, skill_get_time (PR_KYRIE, 1), 0);
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable[PR_IMPOSITIO],
-                                       1, 0, 0, 0,
-                                       skill_get_time (PR_IMPOSITIO, 1), 0);
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable[PR_MAGNIFICAT],
-                                       1, 0, 0, 0,
-                                       skill_get_time (PR_MAGNIFICAT, 1), 0);
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable[PR_GLORIA], 1,
-                                       0, 0, 0, skill_get_time (PR_GLORIA, 1),
-                                       0);
-            skill_status_change_start (&sd->bl,
-                                       SkillStatusChangeTable[PR_SUFFRAGIUM],
-                                       1, 0, 0, 0,
-                                       skill_get_time (PR_SUFFRAGIUM, 1), 0);
-        }
-
-        clif_misceffect (&sd->bl, 0);
-        //レベルアップしたのでパーティー情報を更新する
-        //(公平範囲チェック)
-        party_send_movemap (sd);
-        MAP_LOG_XP (sd, "LEVELUP") return 1;
-    }
-
-    return 0;
-}
-
-/*========================================
- * Compute the maximum for sd->skill_point, i.e., the max. number of skill points that can still be filled in
- *----------------------------------------
- */
-int pc_skillpt_potential (struct map_session_data *sd)
-{
-    int  skill_id;
-    int  potential = 0;
-
-#define RAISE_COST(x) (((x)*((x)-1))>>1)
-
-    for (skill_id = 0; skill_id < MAX_SKILL; skill_id++)
-        if (sd->status.skill[skill_id].id != 0
-            && sd->status.skill[skill_id].lv < skill_db[skill_id].max_raise)
-            potential += RAISE_COST (skill_db[skill_id].max_raise)
-                - RAISE_COST (sd->status.skill[skill_id].lv);
-#undef RAISE_COST
-
-    return potential;
-}
-
-int pc_checkjoblevelup (struct map_session_data *sd)
-{
-    int  next = pc_nextjobexp (sd);
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.job_exp >= next && next > 0)
-    {
-        if (pc_skillpt_potential (sd) < sd->status.skill_point)
-        {                       // [Fate] Bah, this is is painful.
-            // But the alternative is quite error-prone, and eAthena has far worse performance issues...
-            sd->status.job_exp = next - 1;
-            pc_calcstatus(sd,0);
-            return 0;
-        }
-
-        // job側レベルアップ処理
-        sd->status.job_exp -= next;
-        clif_updatestatus (sd, SP_NEXTJOBEXP);
-        sd->status.skill_point++;
-        clif_updatestatus (sd, SP_SKILLPOINT);
-        pc_calcstatus (sd, 0);
-
-        MAP_LOG_PC (sd, "SKILLPOINTS-UP %d", sd->status.skill_point);
-
-        if (sd->status.job_level < 250
-            && sd->status.job_level < sd->status.base_level * 2)
-            sd->status.job_level++; // Make levelling up a little harder
-
-        clif_misceffect (&sd->bl, 1);
-        return 1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 経験値取得
- *------------------------------------------
- */
-int pc_gainexp (struct map_session_data *sd, int base_exp, int job_exp)
-{
-    return pc_gainexp_reason (sd, base_exp, job_exp,
-                              PC_GAINEXP_REASON_KILLING);
-}
-
-int pc_gainexp_reason (struct map_session_data *sd, int base_exp, int job_exp,
-                       int reason)
-{
-    char output[256];
-    nullpo_retr (0, sd);
-
-    if (sd->bl.prev == NULL || pc_isdead (sd))
-        return 0;
-
-    if ((battle_config.pvp_exp == 0) && map[sd->bl.m].flag.pvp) // [MouseJstr]
-        return 0;               // no exp on pvp maps
-
-    MAP_LOG_PC (sd, "GAINXP %d %d %s", base_exp, job_exp,
-                ((reason ==
-                  2) ? "SCRIPTXP" : ((reason == 1) ? "HEALXP" : "KILLXP")));
-
-    if (sd->sc_data[SC_RICHMANKIM].timer != -1)
-    {                           // added bounds checking [Vaalris]
-        base_exp +=
-            base_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
-        job_exp +=
-            job_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
-    }
-
-    if (sd->status.guild_id > 0)
-    {                           // ギルドに上納
-        base_exp -= guild_payexp (sd, base_exp);
-        if (base_exp < 0)
-            base_exp = 0;
-    }
-
-    if (!battle_config.multi_level_up && pc_nextbaseafter (sd))
-    {
-        while (sd->status.base_exp + base_exp >= pc_nextbaseafter (sd)
-               && sd->status.base_exp <= pc_nextbaseexp (sd)
-               && pc_nextbaseafter (sd) > 0)
-        {
-            base_exp *= .90;
-        }
-    }
-
-    sd->status.base_exp += base_exp;
-
-    // [Fate] Adjust experience points that healers can extract from this character
-    if (reason != PC_GAINEXP_REASON_HEALING)
-    {
-        const int max_heal_xp =
-            20 + (sd->status.base_level * sd->status.base_level);
-
-        sd->heal_xp += base_exp;
-        if (sd->heal_xp > max_heal_xp)
-            sd->heal_xp = max_heal_xp;
-    }
-
-    if (sd->status.base_exp < 0)
-        sd->status.base_exp = 0;
-
-    while (pc_checkbaselevelup (sd));
-
-    clif_updatestatus (sd, SP_BASEEXP);
-    if (!battle_config.multi_level_up && pc_nextjobafter (sd))
-    {
-        while (sd->status.job_exp + job_exp >= pc_nextjobafter (sd)
-               && sd->status.job_exp <= pc_nextjobexp (sd)
-               && pc_nextjobafter (sd) > 0)
-        {
-            job_exp *= .90;
-        }
-    }
-
-    sd->status.job_exp += job_exp;
-    if (sd->status.job_exp < 0)
-        sd->status.job_exp = 0;
-
-    while (pc_checkjoblevelup (sd));
-
-    clif_updatestatus (sd, SP_JOBEXP);
-
-    if (battle_config.disp_experience)
-    {
-        sprintf (output,
-                 "Experienced Gained Base:%d Job:%d", base_exp, job_exp);
-        clif_disp_onlyself (sd, output, strlen (output));
-    }
-
-    return 0;
-}
-
-int pc_extract_healer_exp (struct map_session_data *sd, int max)
-{
-    int  amount;
-    nullpo_retr (0, sd);
-
-    amount = sd->heal_xp;
-    if (max < amount)
-        amount = max;
-
-    sd->heal_xp -= amount;
-    return amount;
-}
-
-/*==========================================
- * base level側必要経験値計算
- *------------------------------------------
- */
-int pc_nextbaseexp (struct map_session_data *sd)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
-        return 0;
-
-    if (sd->status.pc_class == 0)
-        i = 0;
-    else if (sd->status.pc_class <= 6)
-        i = 1;
-    else if (sd->status.pc_class <= 22)
-        i = 2;
-    else if (sd->status.pc_class == 23)
-        i = 3;
-    else if (sd->status.pc_class == 4001)
-        i = 4;
-    else if (sd->status.pc_class <= 4007)
-        i = 5;
-    else
-        i = 6;
-
-    return exp_table[i][sd->status.base_level - 1];
-}
-
-/*==========================================
- * job level側必要経験値計算
- *------------------------------------------
- */
-int pc_nextjobexp (struct map_session_data *sd)
-{
-    // [fate]  For normal levels, this ranges from 20k to 50k, depending on job level.
-    // Job level is at most twice the player's experience level (base_level).  Levelling
-    // from 2 to 9 is 44 points, i.e., 880k to 2.2M job experience points (this is per
-    // skill, obviously.)
-
-    return 20000 + sd->status.job_level * 150;
-}
-
-/*==========================================
- * base level after next [Valaris]
- *------------------------------------------
- */
-int pc_nextbaseafter (struct map_session_data *sd)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
-        return 0;
-
-    if (sd->status.pc_class == 0)
-        i = 0;
-    else if (sd->status.pc_class <= 6)
-        i = 1;
-    else if (sd->status.pc_class <= 22)
-        i = 2;
-    else if (sd->status.pc_class == 23)
-        i = 3;
-    else if (sd->status.pc_class == 4001)
-        i = 4;
-    else if (sd->status.pc_class <= 4007)
-        i = 5;
-    else
-        i = 6;
-
-    return exp_table[i][sd->status.base_level];
-}
-
-/*==========================================
- * job level after next [Valaris]
- *------------------------------------------
- */
-int pc_nextjobafter (struct map_session_data *sd)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.job_level >= MAX_LEVEL || sd->status.job_level <= 0)
-        return 0;
-
-    if (sd->status.pc_class == 0)
-        i = 7;
-    else if (sd->status.pc_class <= 6)
-        i = 8;
-    else if (sd->status.pc_class <= 22)
-        i = 9;
-    else if (sd->status.pc_class == 23)
-        i = 10;
-    else if (sd->status.pc_class == 4001)
-        i = 11;
-    else if (sd->status.pc_class <= 4007)
-        i = 12;
-    else
-        i = 13;
-
-    return exp_table[i][sd->status.job_level];
-}
-
-/*==========================================
-
- * 必要ステータスポイント計算
- *------------------------------------------
- */
-int pc_need_status_point (struct map_session_data *sd, int type)
-{
-    int  val;
-
-    nullpo_retr (-1, sd);
-
-    if (type < SP_STR || type > SP_LUK)
-        return -1;
-    val =
-        type == SP_STR ? sd->status.str :
-        type == SP_AGI ? sd->status.agi :
-        type == SP_VIT ? sd->status.vit :
-        type == SP_INT ? sd->status.int_ :
-        type == SP_DEX ? sd->status.dex : sd->status.luk;
-
-    return (val + 9) / 10 + 1;
-}
-
-/*==========================================
- * 能力値成長
- *------------------------------------------
- */
-int pc_statusup (struct map_session_data *sd, int type)
-{
-    int  need, val = 0;
-
-    nullpo_retr (0, sd);
-
-    switch (type)
-    {
-        case SP_STR:
-            val = sd->status.str;
-            break;
-        case SP_AGI:
-            val = sd->status.agi;
-            break;
-        case SP_VIT:
-            val = sd->status.vit;
-            break;
-        case SP_INT:
-            val = sd->status.int_;
-            break;
-        case SP_DEX:
-            val = sd->status.dex;
-            break;
-        case SP_LUK:
-            val = sd->status.luk;
-            break;
-    }
-
-    need = pc_need_status_point (sd, type);
-    if (type < SP_STR || type > SP_LUK || need < 0
-        || need > sd->status.status_point
-        || val >= battle_config.max_parameter)
-    {
-        clif_statusupack (sd, type, 0, val);
-        clif_updatestatus (sd, SP_STATUSPOINT);
-        return 1;
-    }
-    switch (type)
-    {
-        case SP_STR:
-            val = ++sd->status.str;
-            break;
-        case SP_AGI:
-            val = ++sd->status.agi;
-            break;
-        case SP_VIT:
-            val = ++sd->status.vit;
-            break;
-        case SP_INT:
-            val = ++sd->status.int_;
-            break;
-        case SP_DEX:
-            val = ++sd->status.dex;
-            break;
-        case SP_LUK:
-            val = ++sd->status.luk;
-            break;
-    }
-    sd->status.status_point -= need;
-    if (need != pc_need_status_point (sd, type))
-    {
-        clif_updatestatus (sd, type - SP_STR + SP_USTR);
-    }
-    clif_updatestatus (sd, SP_STATUSPOINT);
-    clif_updatestatus (sd, type);
-    pc_calcstatus (sd, 0);
-    clif_statusupack (sd, type, 1, val);
-
-    MAP_LOG_STATS (sd, "STATUP");
-
-    return 0;
-}
-
-/*==========================================
- * 能力値成長
- *------------------------------------------
- */
-int pc_statusup2 (struct map_session_data *sd, int type, int val)
-{
-    nullpo_retr (0, sd);
-
-    if (type < SP_STR || type > SP_LUK)
-    {
-        clif_statusupack (sd, type, 0, 0);
-        return 1;
-    }
-    switch (type)
-    {
-        case SP_STR:
-            if (sd->status.str + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.str + val < 1)
-                val = 1;
-            else
-                val += sd->status.str;
-            sd->status.str = val;
-            break;
-        case SP_AGI:
-            if (sd->status.agi + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.agi + val < 1)
-                val = 1;
-            else
-                val += sd->status.agi;
-            sd->status.agi = val;
-            break;
-        case SP_VIT:
-            if (sd->status.vit + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.vit + val < 1)
-                val = 1;
-            else
-                val += sd->status.vit;
-            sd->status.vit = val;
-            break;
-        case SP_INT:
-            if (sd->status.int_ + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.int_ + val < 1)
-                val = 1;
-            else
-                val += sd->status.int_;
-            sd->status.int_ = val;
-            break;
-        case SP_DEX:
-            if (sd->status.dex + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.dex + val < 1)
-                val = 1;
-            else
-                val += sd->status.dex;
-            sd->status.dex = val;
-            break;
-        case SP_LUK:
-            if (sd->status.luk + val >= battle_config.max_parameter)
-                val = battle_config.max_parameter;
-            else if (sd->status.luk + val < 1)
-                val = 1;
-            else
-                val = sd->status.luk + val;
-            sd->status.luk = val;
-            break;
-    }
-    clif_updatestatus (sd, type - SP_STR + SP_USTR);
-    clif_updatestatus (sd, type);
-    pc_calcstatus (sd, 0);
-    clif_statusupack (sd, type, 1, val);
-    MAP_LOG_STATS (sd, "STATUP2");
-
-    return 0;
-}
-
-/*==========================================
- * スキルポイント割り振り
- *------------------------------------------
- */
-int pc_skillup (struct map_session_data *sd, int skill_num)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->status.skill[skill_num].id != 0
-        && sd->status.skill_point >= sd->status.skill[skill_num].lv
-        && sd->status.skill[skill_num].lv < skill_db[skill_num].max_raise)
-    {
-        sd->status.skill_point -= sd->status.skill[skill_num].lv;
-        sd->status.skill[skill_num].lv++;
-
-        pc_calcstatus (sd, 0);
-        clif_skillup (sd, skill_num);
-        clif_updatestatus (sd, SP_SKILLPOINT);
-        clif_skillinfoblock (sd);
-        MAP_LOG_PC(sd, "SKILLUP %d %d %d",
-                   skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num));
-    }
-
-    return 0;
-}
-
-/*==========================================
- * /allskill
- *------------------------------------------
- */
-int pc_allskillup (struct map_session_data *sd)
-{
-    int  i, id;
-    int  c = 0, s = 0;
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-    c = s_class.job;
-    s = (s_class.upper == 1) ? 1 : 0;   //転生以外は通常のスキル?
-
-    for (i = 0; i < MAX_SKILL; i++)
-        sd->status.skill[i].id = 0;
-
-    if (battle_config.gm_allskill > 0
-        && pc_isGM (sd) >= battle_config.gm_allskill)
-    {
-        // 全てのスキル
-        for (i = 1; i < 158; i++)
-            sd->status.skill[i].lv = skill_get_max (i);
-        for (i = 210; i < 291; i++)
-            sd->status.skill[i].lv = skill_get_max (i);
-        for (i = 304; i < MAX_SKILL; i++)
-            sd->status.skill[i].lv = skill_get_max (i);
-    }
-    else
-    {
-        for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
-        {
-            if (sd->status.skill[id].id == 0 && skill_get_inf2 (id) & 0x01)
-                sd->status.skill[id].lv = skill_get_max (id);
-        }
-    }
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * /resetlvl
- *------------------------------------------
- */
-int pc_resetlvl (struct map_session_data *sd, int type)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 1; i < MAX_SKILL; i++)
-    {
-        sd->status.skill[i].lv = 0;
-    }
-
-    if (type == 1)
-    {
-        sd->status.skill_point = 0;
-        sd->status.base_level = 1;
-        sd->status.job_level = 1;
-        sd->status.base_exp = 0;
-        sd->status.job_exp = 0;
-        if (sd->status.option != 0)
-            sd->status.option = 0;
-
-        sd->status.str = 1;
-        sd->status.agi = 1;
-        sd->status.vit = 1;
-        sd->status.int_ = 1;
-        sd->status.dex = 1;
-        sd->status.luk = 1;
-        if (sd->status.pc_class == 4001)
-            sd->status.status_point = 100;
-    }
-
-    if (type == 2)
-    {
-        sd->status.skill_point = 0;
-        sd->status.base_level = 1;
-        sd->status.job_level = 1;
-        sd->status.base_exp = 0;
-        sd->status.job_exp = 0;
-    }
-    if (type == 3)
-    {
-        sd->status.base_level = 1;
-        sd->status.base_exp = 0;
-    }
-    if (type == 4)
-    {
-        sd->status.job_level = 1;
-        sd->status.job_exp = 0;
-    }
-
-    clif_updatestatus (sd, SP_STATUSPOINT);
-    clif_updatestatus (sd, SP_STR);
-    clif_updatestatus (sd, SP_AGI);
-    clif_updatestatus (sd, SP_VIT);
-    clif_updatestatus (sd, SP_INT);
-    clif_updatestatus (sd, SP_DEX);
-    clif_updatestatus (sd, SP_LUK);
-    clif_updatestatus (sd, SP_BASELEVEL);
-    clif_updatestatus (sd, SP_JOBLEVEL);
-    clif_updatestatus (sd, SP_STATUSPOINT);
-    clif_updatestatus (sd, SP_NEXTBASEEXP);
-    clif_updatestatus (sd, SP_NEXTJOBEXP);
-    clif_updatestatus (sd, SP_SKILLPOINT);
-
-    clif_updatestatus (sd, SP_USTR);    // Updates needed stat points - Valaris
-    clif_updatestatus (sd, SP_UAGI);
-    clif_updatestatus (sd, SP_UVIT);
-    clif_updatestatus (sd, SP_UINT);
-    clif_updatestatus (sd, SP_UDEX);
-    clif_updatestatus (sd, SP_ULUK);    // End Addition
-
-    for (i = 0; i < 11; i++)
-    {                           // unequip items that can't be equipped by base 1 [Valaris]
-        if (sd->equip_index[i] >= 0)
-            if (!pc_isequip (sd, sd->equip_index[i]))
-            {
-                pc_unequipitem (sd, sd->equip_index[i], 1);
-                sd->equip_index[i] = -1;
-            }
-    }
-
-    clif_skillinfoblock (sd);
-    pc_calcstatus (sd, 0);
-
-    MAP_LOG_STATS (sd, "STATRESET");
-
-    return 0;
-}
-
-/*==========================================
- * /resetstate
- *------------------------------------------
- */
-int pc_resetstate (struct map_session_data *sd)
-{
-#define sumsp(a) ((a)*((a-2)/10+2) - 5*((a-2)/10)*((a-2)/10) - 6*((a-2)/10) -2)
-//  int add=0; // Removed by Dexity
-
-    nullpo_retr (0, sd);
-
-//  New statpoint table used here - Dexity
-    sd->status.status_point = atoi (statp[sd->status.base_level - 1]);
-//  End addition
-
-//  Removed by Dexity - old count
-//  add += sumsp(sd->status.str);
-//  add += sumsp(sd->status.agi);
-//  add += sumsp(sd->status.vit);
-//  add += sumsp(sd->status.int_);
-//  add += sumsp(sd->status.dex);
-//  add += sumsp(sd->status.luk);
-//  sd->status.status_point+=add;
-
-    clif_updatestatus (sd, SP_STATUSPOINT);
-
-    sd->status.str = 1;
-    sd->status.agi = 1;
-    sd->status.vit = 1;
-    sd->status.int_ = 1;
-    sd->status.dex = 1;
-    sd->status.luk = 1;
-
-    clif_updatestatus (sd, SP_STR);
-    clif_updatestatus (sd, SP_AGI);
-    clif_updatestatus (sd, SP_VIT);
-    clif_updatestatus (sd, SP_INT);
-    clif_updatestatus (sd, SP_DEX);
-    clif_updatestatus (sd, SP_LUK);
-
-    clif_updatestatus (sd, SP_USTR);    // Updates needed stat points - Valaris
-    clif_updatestatus (sd, SP_UAGI);
-    clif_updatestatus (sd, SP_UVIT);
-    clif_updatestatus (sd, SP_UINT);
-    clif_updatestatus (sd, SP_UDEX);
-    clif_updatestatus (sd, SP_ULUK);    // End Addition
-
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * /resetskill
- *------------------------------------------
- */
-int pc_resetskill (struct map_session_data *sd)
-{
-    int  i, skill;
-
-    nullpo_retr (0, sd);
-
-    sd->status.skill_point += pc_calc_skillpoint (sd);
-
-    for (i = 1; i < MAX_SKILL; i++)
-        if ((skill = pc_checkskill (sd, i)) > 0)
-        {
-            sd->status.skill[i].lv = 0;
-            sd->status.skill[i].flags = 0;
-        }
-
-    clif_updatestatus (sd, SP_SKILLPOINT);
-    clif_skillinfoblock (sd);
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * pcにダメージを与える
- *------------------------------------------
- */
-int pc_damage (struct block_list *src, struct map_session_data *sd,
-               int damage)
-{
-    int  i = 0, j = 0;
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    //転生や養子の場合の元の職業を算出する
-    s_class = pc_calc_base_job (sd->status.pc_class);
-    // 既に死んでいたら無効
-    if (pc_isdead (sd))
-        return 0;
-    // 座ってたら立ち上がる
-    if (pc_issit (sd))
-    {
-        pc_setstand (sd);
-        skill_gangsterparadise (sd, 0);
-    }
-
-    if (src)
-    {
-        if (src->type == BL_PC)
-        {
-            MAP_LOG_PC (sd, "INJURED-BY PC%d FOR %d",
-                        ((struct map_session_data *) src)->status.char_id,
-                        damage);
-        }
-        else
-        {
-            MAP_LOG_PC (sd, "INJURED-BY MOB%d FOR %d", src->id, damage);
-        }
-    }
-    else
-        MAP_LOG_PC (sd, "INJURED-BY null FOR %d", damage);
-
-    // 歩 いていたら足を止める
-    if (sd->sc_data[SC_ENDURE].timer == -1
-        && !sd->special_state.infinite_endure)
-        pc_stop_walking (sd, 3);
-    // 演奏/ダンスの中断
-    if (damage > sd->status.max_hp >> 2)
-        skill_stop_dancing (&sd->bl, 0);
-
-    sd->status.hp -= damage;
-
-    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
-        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
-    if (sd->status.option & 2)
-        skill_status_change_end (&sd->bl, SC_HIDING, -1);
-    if (sd->status.option & 4)
-        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
-    if (sd->status.option & 16386)
-        skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
-
-    if (sd->status.hp > 0)
-    {
-        // まだ生きているならHP更新
-        clif_updatestatus (sd, SP_HP);
-
-        if (sd->status.hp < sd->status.max_hp >> 2
-            && pc_checkskill (sd, SM_AUTOBERSERK) > 0
-            && (sd->sc_data[SC_PROVOKE].timer == -1
-                || sd->sc_data[SC_PROVOKE].val2 == 0))
-            // オートバーサーク発動
-            skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0,
-                                       0);
-
-        sd->canlog_tick = gettick ();
-
-        if (sd->status.party_id > 0)
-        {                       // on-the-fly party hp updates [Valaris]
-            struct party *p = party_search (sd->status.party_id);
-            if (p != NULL)
-                clif_party_hp (p, sd);
-        }                       // end addition [Valaris]
-
-        return 0;
-    }
-
-    MAP_LOG_PC (sd, "DEAD%s", "");
-
-    // Character is dead!
-
-    sd->status.hp = 0;
-    // [Fate] Stop quickregen
-    sd->quick_regeneration_hp.amount = 0;
-    sd->quick_regeneration_sp.amount = 0;
-    skill_update_heal_animation (sd);
-
-    pc_setdead (sd);
-
-    pc_stop_walking (sd, 0);
-    skill_castcancel (&sd->bl, 0);  // 詠唱の中止
-    clif_clearchar_area (&sd->bl, 1);
-    skill_unit_out_all (&sd->bl, gettick (), 1);
-    if (sd->sc_data[SC_BLADESTOP].timer != -1)  //白刃は事前に解除
-        skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
-    pc_setglobalreg (sd, "PC_DIE_COUNTER", ++sd->die_counter);  //死にカウンター書き込み
-    skill_status_change_clear (&sd->bl, 0); // ステータス異常を解除する
-    clif_updatestatus (sd, SP_HP);
-    pc_calcstatus (sd, 0);
-    // [Fate] Reset magic
-    sd->cast_tick = gettick ();
-    magic_stop_completely (sd);
-
-    for (i = 0; i < 5; i++)
-        if (sd->dev.val1[i])
-        {
-            skill_status_change_end (&map_id2sd (sd->dev.val1[i])->bl,
-                                     SC_DEVOTION, -1);
-            sd->dev.val1[i] = sd->dev.val2[i] = 0;
-        }
-
-    if (battle_config.death_penalty_type > 0 && sd->status.base_level >= 20)
-    {                           // changed penalty options, added death by player if pk_mode [Valaris]
-        if (!map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg)
-        {
-            if (battle_config.death_penalty_type == 1
-                && battle_config.death_penalty_base > 0)
-                sd->status.base_exp -=
-                    (double) pc_nextbaseexp (sd) *
-                    (double) battle_config.death_penalty_base / 10000;
-            if (battle_config.pk_mode && src && src->type == BL_PC)
-                sd->status.base_exp -=
-                    (double) pc_nextbaseexp (sd) *
-                    (double) battle_config.death_penalty_base / 10000;
-            else if (battle_config.death_penalty_type == 2
-                     && battle_config.death_penalty_base > 0)
-            {
-                if (pc_nextbaseexp (sd) > 0)
-                    sd->status.base_exp -=
-                        (double) sd->status.base_exp *
-                        (double) battle_config.death_penalty_base / 10000;
-                if (battle_config.pk_mode && src && src->type == BL_PC)
-                    sd->status.base_exp -=
-                        (double) sd->status.base_exp *
-                        (double) battle_config.death_penalty_base / 10000;
-            }
-            if (sd->status.base_exp < 0)
-                sd->status.base_exp = 0;
-            clif_updatestatus (sd, SP_BASEEXP);
-
-            if (battle_config.death_penalty_type == 1
-                && battle_config.death_penalty_job > 0)
-                sd->status.job_exp -=
-                    (double) pc_nextjobexp (sd) *
-                    (double) battle_config.death_penalty_job / 10000;
-            if (battle_config.pk_mode && src && src->type == BL_PC)
-                sd->status.job_exp -=
-                    (double) pc_nextjobexp (sd) *
-                    (double) battle_config.death_penalty_job / 10000;
-            else if (battle_config.death_penalty_type == 2
-                     && battle_config.death_penalty_job > 0)
-            {
-                if (pc_nextjobexp (sd) > 0)
-                    sd->status.job_exp -=
-                        (double) sd->status.job_exp *
-                        (double) battle_config.death_penalty_job / 10000;
-                if (battle_config.pk_mode && src && src->type == BL_PC)
-                    sd->status.job_exp -=
-                        (double) sd->status.job_exp *
-                        (double) battle_config.death_penalty_job / 10000;
-            }
-            if (sd->status.job_exp < 0)
-                sd->status.job_exp = 0;
-            clif_updatestatus (sd, SP_JOBEXP);
-        }
-    }
-    //ナイトメアモードアイテムドロップ
-    if (map[sd->bl.m].flag.pvp_nightmaredrop)
-    {                           // Moved this outside so it works when PVP isnt enabled and during pk mode [Ancyker]
-        for (j = 0; j < MAX_DROP_PER_MAP; j++)
-        {
-            int  id = map[sd->bl.m].drop_list[j].drop_id;
-            int  type = map[sd->bl.m].drop_list[j].drop_type;
-            int  per = map[sd->bl.m].drop_list[j].drop_per;
-            if (id == 0)
-                continue;
-            if (id == -1)
-            {                   //ランダムドロップ
-                int  eq_num = 0, eq_n[MAX_INVENTORY];
-                memset (eq_n, 0, sizeof (eq_n));
-                //先ず装備しているアイテム数をカウント
-                for (i = 0; i < MAX_INVENTORY; i++)
-                {
-                    int  k;
-                    if ((type == 1 && !sd->status.inventory[i].equip)
-                        || (type == 2 && sd->status.inventory[i].equip)
-                        || type == 3)
-                    {
-                        //InventoryIndexを格納
-                        for (k = 0; k < MAX_INVENTORY; k++)
-                        {
-                            if (eq_n[k] <= 0)
-                            {
-                                eq_n[k] = i;
-                                break;
-                            }
-                        }
-                        eq_num++;
-                    }
-                }
-                if (eq_num > 0)
-                {
-                    int  n = eq_n[MRAND (eq_num)];  //該当アイテムの中からランダム
-                    if (MRAND (10000) < per)
-                    {
-                        if (sd->status.inventory[n].equip)
-                            pc_unequipitem (sd, n, 0);
-                        pc_dropitem (sd, n, 1);
-                    }
-                }
-            }
-            else if (id > 0)
-            {
-                for (i = 0; i < MAX_INVENTORY; i++)
-                {
-                    if (sd->status.inventory[i].nameid == id    //ItemIDが一致していて
-                        && MRAND (10000) < per  //ドロップ率判定もOKで
-                        && ((type == 1 && !sd->status.inventory[i].equip)   //タイプ判定もOKならドロップ
-                            || (type == 2 && sd->status.inventory[i].equip)
-                            || type == 3))
-                    {
-                        if (sd->status.inventory[i].equip)
-                            pc_unequipitem (sd, i, 0);
-                        pc_dropitem (sd, i, 1);
-                        break;
-                    }
-                }
-            }
-        }
-    }
-    // pvp
-    if (map[sd->bl.m].flag.pvp && !battle_config.pk_mode)
-    {                           // disable certain pvp functions on pk_mode [Valaris]
-        //ランキング計算
-        if (!map[sd->bl.m].flag.pvp_nocalcrank)
-        {
-            sd->pvp_point -= 5;
-            if (src && src->type == BL_PC)
-                ((struct map_session_data *) src)->pvp_point++;
-            //} //fixed wrong '{' placement by Lupus
-            pc_setdead (sd);
-        }
-        // 強制送還
-        if (sd->pvp_point < 0)
-        {
-            sd->pvp_point = 0;
-            pc_setstand (sd);
-            pc_setrestartvalue (sd, 3);
-            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
-                       sd->status.save_point.y, 0);
-        }
-    }
-    //GvG
-    if (map[sd->bl.m].flag.gvg)
-    {
-        pc_setstand (sd);
-        pc_setrestartvalue (sd, 3);
-        pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
-                   sd->status.save_point.y, 0);
-    }
-
-    if (src && src->type == BL_PC)
-    {
-        // [Fate] PK death, trigger scripts
-        argrec_t arg[3];
-        arg[0].name = "@killerrid";
-        arg[0].v.i = src->id;
-        arg[1].name = "@victimrid";
-        arg[1].v.i = sd->bl.id;
-        arg[2].name = "@victimlvl";
-        arg[2].v.i = sd->status.base_level;
-        npc_event_doall_l ("OnPCKilledEvent", sd->bl.id, 3, arg);
-        npc_event_doall_l ("OnPCKillEvent", src->id, 3, arg);
-    }
-    npc_event_doall_l ("OnPCDieEvent", sd->bl.id, 0, NULL);
-
-    return 0;
-}
-
-//
-// script関 連
-//
-/*==========================================
- * script用PCステータス読み出し
- *------------------------------------------
- */
-int pc_readparam (struct map_session_data *sd, int type)
-{
-    int  val = 0;
-    struct pc_base_job s_class;
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    nullpo_retr (0, sd);
-
-    switch (type)
-    {
-        case SP_SKILLPOINT:
-            val = sd->status.skill_point;
-            break;
-        case SP_STATUSPOINT:
-            val = sd->status.status_point;
-            break;
-        case SP_ZENY:
-            val = sd->status.zeny;
-            break;
-        case SP_BASELEVEL:
-            val = sd->status.base_level;
-            break;
-        case SP_JOBLEVEL:
-            val = sd->status.job_level;
-            break;
-        case SP_CLASS:
-            if (val >= 24 && val < 45)
-                val += 3978;
-            else
-                val = sd->status.pc_class;
-            break;
-        case SP_UPPER:
-            val = s_class.upper;
-            break;
-        case SP_SEX:
-            val = sd->sex;
-            break;
-        case SP_WEIGHT:
-            val = sd->weight;
-            break;
-        case SP_MAXWEIGHT:
-            val = sd->max_weight;
-            break;
-        case SP_BASEEXP:
-            val = sd->status.base_exp;
-            break;
-        case SP_JOBEXP:
-            val = sd->status.job_exp;
-            break;
-        case SP_NEXTBASEEXP:
-            val = pc_nextbaseexp (sd);
-            break;
-        case SP_NEXTJOBEXP:
-            val = pc_nextjobexp (sd);
-            break;
-        case SP_HP:
-            val = sd->status.hp;
-            break;
-        case SP_MAXHP:
-            val = sd->status.max_hp;
-            break;
-        case SP_SP:
-            val = sd->status.sp;
-            break;
-        case SP_MAXSP:
-            val = sd->status.max_sp;
-            break;
-        case SP_STR:
-            val = sd->status.str;
-            break;
-        case SP_AGI:
-            val = sd->status.agi;
-            break;
-        case SP_VIT:
-            val = sd->status.vit;
-            break;
-        case SP_INT:
-            val = sd->status.int_;
-            break;
-        case SP_DEX:
-            val = sd->status.dex;
-            break;
-        case SP_LUK:
-            val = sd->status.luk;
-            break;
-        case SP_FAME:
-            val = sd->fame;
-            break;
-    }
-
-    return val;
-}
-
-/*==========================================
- * script用PCステータス設定
- *------------------------------------------
- */
-int pc_setparam (struct map_session_data *sd, int type, int val)
-{
-    int  i = 0, up_level = 50;
-    struct pc_base_job s_class;
-
-    nullpo_retr (0, sd);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    switch (type)
-    {
-        case SP_BASELEVEL:
-            if (val > sd->status.base_level)
-            {
-                for (i = 1; i <= (val - sd->status.base_level); i++)
-                    sd->status.status_point +=
-                        (sd->status.base_level + i + 14) / 4;
-            }
-            sd->status.base_level = val;
-            sd->status.base_exp = 0;
-            clif_updatestatus (sd, SP_BASELEVEL);
-            clif_updatestatus (sd, SP_NEXTBASEEXP);
-            clif_updatestatus (sd, SP_STATUSPOINT);
-            clif_updatestatus (sd, SP_BASEEXP);
-            pc_calcstatus (sd, 0);
-            pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
-            break;
-        case SP_JOBLEVEL:
-            if (sd->status.pc_class == 0)
-                up_level -= 40;
-            if ((sd->status.pc_class == 23)
-                || (sd->status.pc_class >= 4001 && sd->status.pc_class <= 4022))
-                up_level += 20;
-            if (val >= sd->status.job_level)
-            {
-                if (val > up_level)
-                    val = up_level;
-                sd->status.skill_point += (val - sd->status.job_level);
-                sd->status.job_level = val;
-                sd->status.job_exp = 0;
-                clif_updatestatus (sd, SP_JOBLEVEL);
-                clif_updatestatus (sd, SP_NEXTJOBEXP);
-                clif_updatestatus (sd, SP_JOBEXP);
-                clif_updatestatus (sd, SP_SKILLPOINT);
-                pc_calcstatus (sd, 0);
-                clif_misceffect (&sd->bl, 1);
-            }
-            else
-            {
-                sd->status.job_level = val;
-                sd->status.job_exp = 0;
-                clif_updatestatus (sd, SP_JOBLEVEL);
-                clif_updatestatus (sd, SP_NEXTJOBEXP);
-                clif_updatestatus (sd, SP_JOBEXP);
-                pc_calcstatus (sd, 0);
-            }
-            clif_updatestatus (sd, type);
-            break;
-        case SP_SKILLPOINT:
-            sd->status.skill_point = val;
-            break;
-        case SP_STATUSPOINT:
-            sd->status.status_point = val;
-            break;
-        case SP_ZENY:
-            sd->status.zeny = val;
-            break;
-        case SP_BASEEXP:
-            if (pc_nextbaseexp (sd) > 0)
-            {
-                sd->status.base_exp = val;
-                if (sd->status.base_exp < 0)
-                    sd->status.base_exp = 0;
-                pc_checkbaselevelup (sd);
-            }
-            break;
-        case SP_JOBEXP:
-            if (pc_nextjobexp (sd) > 0)
-            {
-                sd->status.job_exp = val;
-                if (sd->status.job_exp < 0)
-                    sd->status.job_exp = 0;
-                pc_checkjoblevelup (sd);
-            }
-            break;
-        case SP_SEX:
-            sd->sex = val;
-            break;
-        case SP_WEIGHT:
-            sd->weight = val;
-            break;
-        case SP_MAXWEIGHT:
-            sd->max_weight = val;
-            break;
-        case SP_HP:
-            sd->status.hp = val;
-            break;
-        case SP_MAXHP:
-            sd->status.max_hp = val;
-            break;
-        case SP_SP:
-            sd->status.sp = val;
-            break;
-        case SP_MAXSP:
-            sd->status.max_sp = val;
-            break;
-        case SP_STR:
-            sd->status.str = val;
-            break;
-        case SP_AGI:
-            sd->status.agi = val;
-            break;
-        case SP_VIT:
-            sd->status.vit = val;
-            break;
-        case SP_INT:
-            sd->status.int_ = val;
-            break;
-        case SP_DEX:
-            sd->status.dex = val;
-            break;
-        case SP_LUK:
-            sd->status.luk = val;
-            break;
-        case SP_FAME:
-            sd->fame = val;
-            break;
-    }
-    clif_updatestatus (sd, type);
-
-    return 0;
-}
-
-/*==========================================
- * HP/SP回復
- *------------------------------------------
- */
-int pc_heal (struct map_session_data *sd, int hp, int sp)
-{
-//  if(battle_config.battle_log)
-//      printf("heal %d %d\n",hp,sp);
-
-    nullpo_retr (0, sd);
-
-    if (pc_checkoverhp (sd))
-    {
-        if (hp > 0)
-            hp = 0;
-    }
-    if (pc_checkoversp (sd))
-    {
-        if (sp > 0)
-            sp = 0;
-    }
-
-    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中は回復させないらしい
-        return 0;
-
-    if (hp + sd->status.hp > sd->status.max_hp)
-        hp = sd->status.max_hp - sd->status.hp;
-    if (sp + sd->status.sp > sd->status.max_sp)
-        sp = sd->status.max_sp - sd->status.sp;
-    sd->status.hp += hp;
-    if (sd->status.hp <= 0)
-    {
-        sd->status.hp = 0;
-        pc_damage (NULL, sd, 1);
-        hp = 0;
-    }
-    sd->status.sp += sp;
-    if (sd->status.sp <= 0)
-        sd->status.sp = 0;
-    if (hp)
-        clif_updatestatus (sd, SP_HP);
-    if (sp)
-        clif_updatestatus (sd, SP_SP);
-
-    if (sd->status.party_id > 0)
-    {                           // on-the-fly party hp updates [Valaris]
-        struct party *p = party_search (sd->status.party_id);
-        if (p != NULL)
-            clif_party_hp (p, sd);
-    }                           // end addition [Valaris]
-
-    return hp + sp;
-}
-
-/*==========================================
- * HP/SP回復
- *------------------------------------------
- */
-static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
-
-static int                      // Compute how quickly we regenerate (less is faster) for that amount
-pc_heal_quick_speed (int amount)
-{
-    if (amount >= 100)
-    {
-        if (amount >= 500)
-            return 0;
-        if (amount >= 250)
-            return 1;
-        return 2;
-    }
-    else
-    {                           // < 100
-        if (amount >= 50)
-            return 3;
-        if (amount >= 20)
-            return 4;
-        return 5;
-    }
-}
-
-static void
-pc_heal_quick_accumulate (int new_amount,
-                          struct quick_regeneration *quick_regen, int max)
-{
-    int  current_amount = quick_regen->amount;
-    int  current_speed = quick_regen->speed;
-    int  new_speed = pc_heal_quick_speed (new_amount);
-
-    int  average_speed = ((new_speed * new_amount) + (current_speed * current_amount)) / (current_amount + new_amount); // new_amount > 0, current_amount >= 0
-
-    quick_regen->speed = average_speed;
-    quick_regen->amount = MIN (current_amount + new_amount, max);
-
-    quick_regen->tickdelay = MIN (quick_regen->speed, quick_regen->tickdelay);
-}
-
-int pc_itemheal (struct map_session_data *sd, int hp, int sp)
-{
-    /* defer healing */
-    if (hp > 0)
-    {
-        pc_heal_quick_accumulate (hp,
-                                  &sd->quick_regeneration_hp,
-                                  sd->status.max_hp - sd->status.hp);
-        hp = 0;
-    }
-    if (sp > 0)
-    {
-        pc_heal_quick_accumulate (sp,
-                                  &sd->quick_regeneration_sp,
-                                  sd->status.max_sp - sd->status.sp);
-
-        sp = 0;
-    }
-
-    /* Hurt right away, if necessary */
-    if (hp < 0 || sp < 0)
-        pc_itemheal_effect (sd, hp, sp);
-
-    return 0;
-}
-
-/* pc_itemheal_effect is invoked once every 0.5s whenever the pc
- * has health recovery queued up (cf. pc_natural_heal_sub).
- */
-static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp)
-{
-    int  bonus;
-//  if(battle_config.battle_log)
-//      printf("heal %d %d\n",hp,sp);
-
-    nullpo_retr (0, sd);
-
-    if (sd->sc_data && sd->sc_data[SC_GOSPEL].timer != -1)  //バーサーク中は回復させないらしい
-        return 0;
-
-    if (sd->state.potionpitcher_flag)
-    {
-        sd->potion_hp = hp;
-        sd->potion_sp = sp;
-        return 0;
-    }
-
-    if (pc_checkoverhp (sd))
-    {
-        if (hp > 0)
-            hp = 0;
-    }
-    if (pc_checkoversp (sd))
-    {
-        if (sp > 0)
-            sp = 0;
-    }
-    if (hp > 0)
-    {
-        bonus =
-            (sd->paramc[2] << 1) + 100 + pc_checkskill (sd, SM_RECOVERY) * 10;
-        if (bonus != 100)
-            hp = hp * bonus / 100;
-        bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
-        if (bonus != 100)
-            hp = hp * bonus / 100;
-    }
-    if (sp > 0)
-    {
-        bonus =
-            (sd->paramc[3] << 1) + 100 + pc_checkskill (sd,
-                                                        MG_SRECOVERY) * 10;
-        if (bonus != 100)
-            sp = sp * bonus / 100;
-        bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
-        if (bonus != 100)
-            sp = sp * bonus / 100;
-    }
-    if (hp + sd->status.hp > sd->status.max_hp)
-        hp = sd->status.max_hp - sd->status.hp;
-    if (sp + sd->status.sp > sd->status.max_sp)
-        sp = sd->status.max_sp - sd->status.sp;
-    sd->status.hp += hp;
-    if (sd->status.hp <= 0)
-    {
-        sd->status.hp = 0;
-        pc_damage (NULL, sd, 1);
-        hp = 0;
-    }
-    sd->status.sp += sp;
-    if (sd->status.sp <= 0)
-        sd->status.sp = 0;
-    if (hp)
-        clif_updatestatus (sd, SP_HP);
-    if (sp)
-        clif_updatestatus (sd, SP_SP);
-
-    return 0;
-}
-
-/*==========================================
- * HP/SP回復
- *------------------------------------------
- */
-int pc_percentheal (struct map_session_data *sd, int hp, int sp)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->state.potionpitcher_flag)
-    {
-        sd->potion_per_hp = hp;
-        sd->potion_per_sp = sp;
-        return 0;
-    }
-
-    if (pc_checkoverhp (sd))
-    {
-        if (hp > 0)
-            hp = 0;
-    }
-    if (pc_checkoversp (sd))
-    {
-        if (sp > 0)
-            sp = 0;
-    }
-    if (hp)
-    {
-        if (hp >= 100)
-        {
-            sd->status.hp = sd->status.max_hp;
-        }
-        else if (hp <= -100)
-        {
-            sd->status.hp = 0;
-            pc_damage (NULL, sd, 1);
-        }
-        else
-        {
-            sd->status.hp += sd->status.max_hp * hp / 100;
-            if (sd->status.hp > sd->status.max_hp)
-                sd->status.hp = sd->status.max_hp;
-            if (sd->status.hp <= 0)
-            {
-                sd->status.hp = 0;
-                pc_damage (NULL, sd, 1);
-                hp = 0;
-            }
-        }
-    }
-    if (sp)
-    {
-        if (sp >= 100)
-        {
-            sd->status.sp = sd->status.max_sp;
-        }
-        else if (sp <= -100)
-        {
-            sd->status.sp = 0;
-        }
-        else
-        {
-            sd->status.sp += sd->status.max_sp * sp / 100;
-            if (sd->status.sp > sd->status.max_sp)
-                sd->status.sp = sd->status.max_sp;
-            if (sd->status.sp < 0)
-                sd->status.sp = 0;
-        }
-    }
-    if (hp)
-        clif_updatestatus (sd, SP_HP);
-    if (sp)
-        clif_updatestatus (sd, SP_SP);
-
-    return 0;
-}
-
-/*==========================================
- * 職変更
- * 引数		job 職業 0〜23
- *		upper 通常 0, 転生 1, 養子 2, そのまま -1
- *------------------------------------------
- */
-int pc_jobchange (struct map_session_data *sd, int job, int upper)
-{
-    int  i;
-    int  b_class = 0;
-    //転生や養子の場合の元の職業を算出する
-    struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
-
-    nullpo_retr (0, sd);
-
-    if ((job > 23) && (job < 68))
-        job += 3977;
-
-    if ((job > 69) && (job < 4000))
-        return 1;
-
-    if (upper < 0)              //現在転生かどうかを判断する
-        upper = s_class.upper;
-
-    if (upper == 0)
-    {                           //通常職ならjobそのまんま
-        b_class = job;
-    }
-    else if (upper == 1)
-    {
-        if (job == 23)
-        {                       //転生にスパノビは存在しないのでお断り
-            return 1;
-        }
-        else
-        {
-            b_class = job + 4001;
-        }
-    }
-    else if (upper == 2)
-    {                           //養子に結婚はないけどどうせ次で蹴られるからいいや
-        b_class = (job == 23) ? job + 4022 : job + 4023;
-    }
-    else
-    {
-        return 1;
-    }
-
-    if ((sd->status.sex == 0 && job == 19) || (sd->status.sex == 1 && job == 20) ||
-            (sd->status.sex == 0 && job == 4020) || (sd->status.sex == 1 && job == 4021) ||
-            job == 22 || sd->status.pc_class == b_class)   //♀はバードになれない、♂はダンサーになれない、結婚衣裳もお断り
-        return 1;
-
-    sd->status.pc_class = sd->view_class = b_class;
-
-    sd->status.job_level = 1;
-    sd->status.job_exp = 0;
-    clif_updatestatus (sd, SP_JOBLEVEL);
-    clif_updatestatus (sd, SP_JOBEXP);
-    clif_updatestatus (sd, SP_NEXTJOBEXP);
-
-    for (i = 0; i < 11; i++)
-    {
-        if (sd->equip_index[i] >= 0)
-            if (!pc_isequip (sd, sd->equip_index[i]))
-                pc_unequipitem (sd, sd->equip_index[i], 1); // 装備外し
-    }
-
-    clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);   // move sprite update to prevent client crashes with incompatible equipment [Valaris]
-    if (sd->status.clothes_color > 0)
-        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
-                         sd->status.clothes_color);
-    if (battle_config.muting_players && sd->status.manner < 0)
-        clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
-
-    pc_calcstatus (sd, 0);
-    pc_checkallowskill (sd);
-    pc_equiplookall (sd);
-    clif_equiplist (sd);
-
-    if (pc_isriding (sd))
-    {                           // remove peco status if changing into invalid class [Valaris]
-        if (!(pc_checkskill (sd, KN_RIDING)))
-            pc_setoption (sd, sd->status.option | -0x0000);
-        if (pc_checkskill (sd, KN_RIDING) > 0)
-            pc_setriding (sd);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 見た目変更
- *------------------------------------------
- */
-int pc_equiplookall (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    clif_changelook (&sd->bl, LOOK_WEAPON, 0);
-//  clif_changelook(&sd->bl,LOOK_SHOES,0);
-    clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
-    clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
-    clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
-
-    clif_changelook_accessories (&sd->bl, NULL);
-
-    return 0;
-}
-
-/*==========================================
- * 見た目変更
- *------------------------------------------
- */
-int pc_changelook (struct map_session_data *sd, int type, int val)
-{
-    nullpo_retr (0, sd);
-
-    switch (type)
-    {
-        case LOOK_HAIR:
-            sd->status.hair = val;
-            break;
-        case LOOK_WEAPON:
-            sd->status.weapon = val;
-            break;
-        case LOOK_HEAD_BOTTOM:
-            sd->status.head_bottom = val;
-            break;
-        case LOOK_HEAD_TOP:
-            sd->status.head_top = val;
-            break;
-        case LOOK_HEAD_MID:
-            sd->status.head_mid = val;
-            break;
-        case LOOK_HAIR_COLOR:
-            sd->status.hair_color = val;
-            break;
-        case LOOK_CLOTHES_COLOR:
-            sd->status.clothes_color = val;
-            break;
-        case LOOK_SHIELD:
-            sd->status.shield = val;
-            break;
-        case LOOK_SHOES:
-            break;
-    }
-    clif_changelook (&sd->bl, type, val);
-
-    return 0;
-}
-
-/*==========================================
- * 付属品(鷹,ペコ,カート)設定
- *------------------------------------------
- */
-int pc_setoption (struct map_session_data *sd, int type)
-{
-    nullpo_retr (0, sd);
-
-    sd->status.option = type;
-    clif_changeoption (&sd->bl);
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * カート設定
- *------------------------------------------
- */
-int pc_setcart (struct map_session_data *sd, int type)
-{
-    int  cart[6] = { 0x0000, 0x0008, 0x0080, 0x0100, 0x0200, 0x0400 };
-
-    nullpo_retr (0, sd);
-
-    if (pc_checkskill (sd, MC_PUSHCART) > 0)
-    {                           // プッシュカートスキル所持
-        if (!pc_iscarton (sd))
-        {                       // カートを付けていない
-            pc_setoption (sd, cart[type]);
-            clif_cart_itemlist (sd);
-            clif_cart_equiplist (sd);
-            clif_updatestatus (sd, SP_CARTINFO);
-            clif_status_change (&sd->bl, 0x0c, 0);
-        }
-        else
-        {
-            pc_setoption (sd, cart[type]);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 鷹設定
- *------------------------------------------
- */
-int pc_setfalcon (struct map_session_data *sd)
-{
-    if (pc_checkskill (sd, HT_FALCON) > 0)
-    {                           // ファルコンマスタリースキル所持
-        pc_setoption (sd, sd->status.option | 0x0010);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * ペコペコ設定
- *------------------------------------------
- */
-int pc_setriding (struct map_session_data *sd)
-{
-    if (sd->disguise > 0)
-    {                           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
-        clif_displaymessage (sd->fd,
-                             "Cannot mount a Peco while in disguise.");
-        return 0;
-    }
-
-    if ((pc_checkskill (sd, KN_RIDING) > 0))
-    {                           // ライディングスキル所持
-        pc_setoption (sd, sd->status.option | 0x0020);
-
-        if (sd->status.pc_class == 7)
-            sd->status.pc_class = sd->view_class = 13;
-
-        if (sd->status.pc_class == 14)
-            sd->status.pc_class = sd->view_class = 21;
-
-        if (sd->status.pc_class == 4008)
-            sd->status.pc_class = sd->view_class = 4014;
-
-        if (sd->status.pc_class == 4015)
-            sd->status.pc_class = sd->view_class = 4022;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * script用変数の値を読む
- *------------------------------------------
- */
-int pc_readreg (struct map_session_data *sd, int reg)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->reg_num; i++)
-        if (sd->reg[i].index == reg)
-            return sd->reg[i].data;
-
-    return 0;
-}
-
-/*==========================================
- * script用変数の値を設定
- *------------------------------------------
- */
-int pc_setreg (struct map_session_data *sd, int reg, int val)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->reg_num; i++)
-    {
-        if (sd->reg[i].index == reg)
-        {
-            sd->reg[i].data = val;
-            return 0;
-        }
-    }
-    sd->reg_num++;
-    RECREATE (sd->reg, struct script_reg, sd->reg_num);
-    sd->reg[i].index = reg;
-    sd->reg[i].data = val;
-
-    return 0;
-}
-
-/*==========================================
- * script用文字列変数の値を読む
- *------------------------------------------
- */
-char *pc_readregstr (struct map_session_data *sd, int reg)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->regstr_num; i++)
-        if (sd->regstr[i].index == reg)
-            return sd->regstr[i].data;
-
-    return NULL;
-}
-
-/*==========================================
- * script用文字列変数の値を設定
- *------------------------------------------
- */
-int pc_setregstr (struct map_session_data *sd, int reg, char *str)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (strlen (str) + 1 > sizeof (sd->regstr[0].data))
-    {
-        printf ("pc_setregstr(): String too long!\n");
-        return 0;
-    }
-
-    for (i = 0; i < sd->regstr_num; i++)
-        if (sd->regstr[i].index == reg)
-        {
-            strcpy (sd->regstr[i].data, str);
-            return 0;
-        }
-    sd->regstr_num++;
-    RECREATE (sd->regstr, struct script_regstr, sd->regstr_num);
-    sd->regstr[i].index = reg;
-    strcpy (sd->regstr[i].data, str);
-
-    return 0;
-}
-
-/*==========================================
- * script用グローバル変数の値を読む
- *------------------------------------------
- */
-int pc_readglobalreg (struct map_session_data *sd, char *reg)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->status.global_reg_num; i++)
-    {
-        if (strcmp (sd->status.global_reg[i].str, reg) == 0)
-            return sd->status.global_reg[i].value;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * script用グローバル変数の値を設定
- *------------------------------------------
- */
-int pc_setglobalreg (struct map_session_data *sd, char *reg, int val)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    //PC_DIE_COUNTERがスクリプトなどで変更された時の処理
-    if (strcmp (reg, "PC_DIE_COUNTER") == 0 && sd->die_counter != val)
-    {
-        sd->die_counter = val;
-        pc_calcstatus (sd, 0);
-    }
-    if (val == 0)
-    {
-        for (i = 0; i < sd->status.global_reg_num; i++)
-        {
-            if (strcmp (sd->status.global_reg[i].str, reg) == 0)
-            {
-                sd->status.global_reg[i] =
-                    sd->status.global_reg[sd->status.global_reg_num - 1];
-                sd->status.global_reg_num--;
-                break;
-            }
-        }
-        return 0;
-    }
-    for (i = 0; i < sd->status.global_reg_num; i++)
-    {
-        if (strcmp (sd->status.global_reg[i].str, reg) == 0)
-        {
-            sd->status.global_reg[i].value = val;
-            return 0;
-        }
-    }
-    if (sd->status.global_reg_num < GLOBAL_REG_NUM)
-    {
-        strcpy (sd->status.global_reg[i].str, reg);
-        sd->status.global_reg[i].value = val;
-        sd->status.global_reg_num++;
-        return 0;
-    }
-    if (battle_config.error_log)
-        printf ("pc_setglobalreg : couldn't set %s (GLOBAL_REG_NUM = %d)\n",
-                reg, GLOBAL_REG_NUM);
-
-    return 1;
-}
-
-/*==========================================
- * script用アカウント変数の値を読む
- *------------------------------------------
- */
-int pc_readaccountreg (struct map_session_data *sd, char *reg)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->status.account_reg_num; i++)
-    {
-        if (strcmp (sd->status.account_reg[i].str, reg) == 0)
-            return sd->status.account_reg[i].value;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * script用アカウント変数の値を設定
- *------------------------------------------
- */
-int pc_setaccountreg (struct map_session_data *sd, char *reg, int val)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    if (val == 0)
-    {
-        for (i = 0; i < sd->status.account_reg_num; i++)
-        {
-            if (strcmp (sd->status.account_reg[i].str, reg) == 0)
-            {
-                sd->status.account_reg[i] =
-                    sd->status.account_reg[sd->status.account_reg_num - 1];
-                sd->status.account_reg_num--;
-                break;
-            }
-        }
-        intif_saveaccountreg (sd);
-        return 0;
-    }
-    for (i = 0; i < sd->status.account_reg_num; i++)
-    {
-        if (strcmp (sd->status.account_reg[i].str, reg) == 0)
-        {
-            sd->status.account_reg[i].value = val;
-            intif_saveaccountreg (sd);
-            return 0;
-        }
-    }
-    if (sd->status.account_reg_num < ACCOUNT_REG_NUM)
-    {
-        strcpy (sd->status.account_reg[i].str, reg);
-        sd->status.account_reg[i].value = val;
-        sd->status.account_reg_num++;
-        intif_saveaccountreg (sd);
-        return 0;
-    }
-    if (battle_config.error_log)
-        printf ("pc_setaccountreg : couldn't set %s (ACCOUNT_REG_NUM = %d)\n",
-                reg, ACCOUNT_REG_NUM);
-
-    return 1;
-}
-
-/*==========================================
- * script用アカウント変数2の値を読む
- *------------------------------------------
- */
-int pc_readaccountreg2 (struct map_session_data *sd, char *reg)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < sd->status.account_reg2_num; i++)
-    {
-        if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
-            return sd->status.account_reg2[i].value;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * script用アカウント変数2の値を設定
- *------------------------------------------
- */
-int pc_setaccountreg2 (struct map_session_data *sd, char *reg, int val)
-{
-    int  i;
-
-    nullpo_retr (1, sd);
-
-    if (val == 0)
-    {
-        for (i = 0; i < sd->status.account_reg2_num; i++)
-        {
-            if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
-            {
-                sd->status.account_reg2[i] =
-                    sd->status.account_reg2[sd->status.account_reg2_num - 1];
-                sd->status.account_reg2_num--;
-                break;
-            }
-        }
-        chrif_saveaccountreg2 (sd);
-        return 0;
-    }
-    for (i = 0; i < sd->status.account_reg2_num; i++)
-    {
-        if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
-        {
-            sd->status.account_reg2[i].value = val;
-            chrif_saveaccountreg2 (sd);
-            return 0;
-        }
-    }
-    if (sd->status.account_reg2_num < ACCOUNT_REG2_NUM)
-    {
-        strcpy (sd->status.account_reg2[i].str, reg);
-        sd->status.account_reg2[i].value = val;
-        sd->status.account_reg2_num++;
-        chrif_saveaccountreg2 (sd);
-        return 0;
-    }
-    if (battle_config.error_log)
-        printf
-            ("pc_setaccountreg2 : couldn't set %s (ACCOUNT_REG2_NUM = %d)\n",
-             reg, ACCOUNT_REG2_NUM);
-
-    return 1;
-}
-
-/*==========================================
- * 精錬成功率
- *------------------------------------------
- */
-int pc_percentrefinery (struct map_session_data *sd, struct item *item)
-{
-    int  percent;
-
-    nullpo_retr (0, item);
-    percent = percentrefinery[itemdb_wlv (item->nameid)][(int) item->refine];
-
-    percent += pc_checkskill (sd, BS_WEAPONRESEARCH);   // 武器研究スキル所持
-
-    // 確率の有効範囲チェック
-    if (percent > 100)
-    {
-        percent = 100;
-    }
-    if (percent < 0)
-    {
-        percent = 0;
-    }
-
-    return percent;
-}
-
-/*==========================================
- * イベントタイマー処理
- *------------------------------------------
- */
-void pc_eventtimer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = map_id2sd (id);
-    int  i;
-    if (sd == NULL)
-        return;
-
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-    {
-        if (sd->eventtimer[i] == tid)
-        {
-            sd->eventtimer[i] = -1;
-            npc_event (sd, (const char *) data, 0);
-            break;
-        }
-    }
-    free ((void *) data);
-    if (i == MAX_EVENTTIMER)
-    {
-        if (battle_config.error_log)
-            printf ("pc_eventtimer: no such event timer\n");
-    }
-}
-
-/*==========================================
- * イベントタイマー追加
- *------------------------------------------
- */
-int pc_addeventtimer (struct map_session_data *sd, int tick, const char *name)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (sd->eventtimer[i] == -1)
-            break;
-
-    if (i < MAX_EVENTTIMER)
-    {
-        char *evname = (char *) calloc (24, 1);
-        strncpy (evname, name, 24);
-        evname[23] = '\0';
-        sd->eventtimer[i] = add_timer (gettick () + tick,
-                                       pc_eventtimer, sd->bl.id,
-                                       (int) evname);
-        return 1;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * イベントタイマー削除
- *------------------------------------------
- */
-int pc_deleventtimer (struct map_session_data *sd, const char *name)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (sd->eventtimer[i] != -1 && strcmp ((char
-                                                *) (get_timer (sd->eventtimer
-                                                               [i])->data),
-                                               name) == 0)
-        {
-            delete_timer (sd->eventtimer[i], pc_eventtimer);
-            sd->eventtimer[i] = -1;
-            break;
-        }
-
-    return 0;
-}
-
-/*==========================================
- * イベントタイマーカウント値追加
- *------------------------------------------
- */
-int pc_addeventtimercount (struct map_session_data *sd, const char *name,
-                           int tick)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (sd->eventtimer[i] != -1 && strcmp ((char
-                                                *) (get_timer (sd->eventtimer
-                                                               [i])->data),
-                                               name) == 0)
-        {
-            addtick_timer (sd->eventtimer[i], tick);
-            break;
-        }
-
-    return 0;
-}
-
-/*==========================================
- * イベントタイマー全削除
- *------------------------------------------
- */
-int pc_cleareventtimer (struct map_session_data *sd)
-{
-    int  i;
-
-    nullpo_retr (0, sd);
-
-    for (i = 0; i < MAX_EVENTTIMER; i++)
-        if (sd->eventtimer[i] != -1)
-        {
-            delete_timer (sd->eventtimer[i], pc_eventtimer);
-            sd->eventtimer[i] = -1;
-        }
-
-    return 0;
-}
-
-//
-// 装 備物
-//
-/*==========================================
- * アイテムを装備する
- *------------------------------------------
- */
-static int
-pc_signal_advanced_equipment_change (struct map_session_data *sd, int n)
-{
-    if (sd->status.inventory[n].equip & 0x0040)
-        clif_changelook (&sd->bl, LOOK_SHOES, 0);
-    if (sd->status.inventory[n].equip & 0x0004)
-        clif_changelook (&sd->bl, LOOK_GLOVES, 0);
-    if (sd->status.inventory[n].equip & 0x0008)
-        clif_changelook (&sd->bl, LOOK_CAPE, 0);
-    if (sd->status.inventory[n].equip & 0x0010)
-        clif_changelook (&sd->bl, LOOK_MISC1, 0);
-    if (sd->status.inventory[n].equip & 0x0080)
-        clif_changelook (&sd->bl, LOOK_MISC2, 0);
-    return 0;
-}
-
-int pc_equipitem (struct map_session_data *sd, int n, int pos)
-{
-    int  i, nameid, arrow, view;
-    struct item_data *id;
-    //ソス]ソスソスソスソスソス{ソスqソスフ場合ソスフ鯉ソスソスフ職ソスニゑソスソスZソスoソスソスソスソス
-
-    nullpo_retr (0, sd);
-
-    if (n < 0 || n >= MAX_INVENTORY)
-    {
-        clif_equipitemack (sd, 0, 0, 0);
-        return 0;
-    }
-
-    nameid = sd->status.inventory[n].nameid;
-    id = sd->inventory_data[n];
-    pos = pc_equippoint (sd, n);
-
-    if (battle_config.battle_log)
-        printf ("equip %d(%d) %x:%x\n", nameid, n, id->equip, pos);
-    if (!pc_isequip (sd, n) || !pos || sd->status.inventory[n].broken == 1)
-    {                           // [Valaris]
-        clif_equipitemack (sd, n, 0, 0);    // fail
-        return 0;
-    }
-
-// -- moonsoul (if player is berserk then cannot equip)
-//
-    if (sd->sc_data[SC_BERSERK].timer != -1)
-    {
-        clif_equipitemack (sd, n, 0, 0);    // fail
-        return 0;
-    }
-
-    if (pos == 0x88)
-    {                           // アクセサリ用例外処理
-        int  epor = 0;
-        if (sd->equip_index[0] >= 0)
-            epor |= sd->status.inventory[sd->equip_index[0]].equip;
-        if (sd->equip_index[1] >= 0)
-            epor |= sd->status.inventory[sd->equip_index[1]].equip;
-        epor &= 0x88;
-        pos = epor == 0x08 ? 0x80 : 0x08;
-    }
-
-    // 二刀流処理
-    if ((pos == 0x22)           // 一応、装備要求箇所が二刀流武器かチェックする
-        && (id->equip == 2)     // 単 手武器
-        && (pc_checkskill (sd, AS_LEFT) > 0 || sd->status.pc_class == 12)) // 左手修錬有
-    {
-        int  tpos = 0;
-        if (sd->equip_index[8] >= 0)
-            tpos |= sd->status.inventory[sd->equip_index[8]].equip;
-        if (sd->equip_index[9] >= 0)
-            tpos |= sd->status.inventory[sd->equip_index[9]].equip;
-        tpos &= 0x02;
-        pos = tpos == 0x02 ? 0x20 : 0x02;
-    }
-
-    arrow = pc_search_inventory (sd, pc_checkequip (sd, 9));    // Added by RoVeRT
-    for (i = 0; i < 11; i++)
-    {
-        if (pos & equip_pos[i])
-        {
-            if (sd->equip_index[i] >= 0)    //Slot taken, remove item from there.
-                pc_unequipitem (sd, sd->equip_index[i], 1);
-            sd->equip_index[i] = n;
-        }
-    }
-    // 弓矢装備
-    if (pos == 0x8000)
-    {
-        clif_arrowequip (sd, n);
-        clif_arrow_fail (sd, 3);    // 3=矢が装備できました
-    }
-    else
-    {
-        /* Don't update re-equipping if we're using a spell */
-        if (!(pos == 4 && sd->attack_spell_override))
-            clif_equipitemack (sd, n, pos, 1);
-    }
-
-    for (i = 0; i < 11; i++)
-    {
-        if (pos & equip_pos[i])
-            sd->equip_index[i] = n;
-    }
-    sd->status.inventory[n].equip = pos;
-
-    if (sd->inventory_data[n])
-    {
-        view = sd->inventory_data[n]->look;
-        if (view == 0)
-            view = sd->inventory_data[n]->nameid;
-    }
-    else
-    {
-        view = 0;
-    }
-
-    if (sd->status.inventory[n].equip & 0x0002)
-    {
-        sd->weapontype1 = view;
-        pc_calcweapontype (sd);
-        pc_set_weapon_look (sd);
-    }
-    if (sd->status.inventory[n].equip & 0x0020)
-    {
-        if (sd->inventory_data[n])
-        {
-            if (sd->inventory_data[n]->type == 4)
-            {
-                sd->status.shield = 0;
-                if (sd->status.inventory[n].equip == 0x0020)
-                    sd->weapontype2 = view;
-            }
-            else if (sd->inventory_data[n]->type == 5)
-            {
-                sd->status.shield = view;
-                sd->weapontype2 = 0;
-            }
-        }
-        else
-            sd->status.shield = sd->weapontype2 = 0;
-        pc_calcweapontype (sd);
-        clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
-    }
-    if (sd->status.inventory[n].equip & 0x0001)
-    {
-        sd->status.head_bottom = view;
-        clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
-    }
-    if (sd->status.inventory[n].equip & 0x0100)
-    {
-        sd->status.head_top = view;
-        clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
-    }
-    if (sd->status.inventory[n].equip & 0x0200)
-    {
-        sd->status.head_mid = view;
-        clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
-    }
-    pc_signal_advanced_equipment_change (sd, n);
-
-    pc_checkallowskill (sd);    // 装備品でスキルか解除されるかチェック
-    if (itemdb_look (sd->status.inventory[n].nameid) == 11 && arrow)
-    {                           // Added by RoVeRT
-        clif_arrowequip (sd, arrow);
-        sd->status.inventory[arrow].equip = 32768;
-    }
-    pc_calcstatus (sd, 0);
-
-    if (sd->special_state.infinite_endure)
-    {
-        if (sd->sc_data[SC_ENDURE].timer == -1)
-            skill_status_change_start (&sd->bl, SC_ENDURE, 10, 1, 0, 0, 0, 0);
-    }
-    else
-    {
-        if (sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
-            skill_status_change_end (&sd->bl, SC_ENDURE, -1);
-    }
-
-    if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
-        && !battle_check_undead (7, sd->def_ele))
-        skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
-    if (sd->sc_data[SC_DANCING].timer != -1
-        && (sd->status.weapon != 13 && sd->status.weapon != 14))
-        skill_stop_dancing (&sd->bl, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 装 備した物を外す
- *------------------------------------------
- */
-int pc_unequipitem (struct map_session_data *sd, int n, int type)
-{
-    nullpo_retr (0, sd);
-
-// -- moonsoul  (if player is berserk then cannot unequip)
-//
-    if (sd->sc_data[SC_BERSERK].timer != -1)
-    {
-        clif_unequipitemack (sd, n, 0, 0);
-        return 0;
-    }
-
-    if (battle_config.battle_log)
-        printf ("unequip %d %x:%x\n", n, pc_equippoint (sd, n),
-                sd->status.inventory[n].equip);
-    if (sd->status.inventory[n].equip)
-    {
-        int  i;
-        for (i = 0; i < 11; i++)
-        {
-            if (sd->status.inventory[n].equip & equip_pos[i])
-                sd->equip_index[i] = -1;
-        }
-        if (sd->status.inventory[n].equip & 0x0002)
-        {
-            sd->weapontype1 = 0;
-            sd->status.weapon = sd->weapontype2;
-            pc_calcweapontype (sd);
-            pc_set_weapon_look (sd);
-        }
-        if (sd->status.inventory[n].equip & 0x0020)
-        {
-            sd->status.shield = sd->weapontype2 = 0;
-            pc_calcweapontype (sd);
-            clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
-        }
-        if (sd->status.inventory[n].equip & 0x0001)
-        {
-            sd->status.head_bottom = 0;
-            clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM,
-                             sd->status.head_bottom);
-        }
-        if (sd->status.inventory[n].equip & 0x0100)
-        {
-            sd->status.head_top = 0;
-            clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
-        }
-        if (sd->status.inventory[n].equip & 0x0200)
-        {
-            sd->status.head_mid = 0;
-            clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
-        }
-        pc_signal_advanced_equipment_change (sd, n);
-
-        if (sd->sc_data[SC_BROKNWEAPON].timer != -1
-            && sd->status.inventory[n].equip & 0x0002
-            && sd->status.inventory[i].broken == 1)
-            skill_status_change_end (&sd->bl, SC_BROKNWEAPON, -1);
-
-        clif_unequipitemack (sd, n, sd->status.inventory[n].equip, 1);
-        sd->status.inventory[n].equip = 0;
-        if (!type)
-            pc_checkallowskill (sd);
-        if (sd->weapontype1 == 0 && sd->weapontype2 == 0)
-            skill_encchant_eremental_end (&sd->bl, -1); //武器持ち誓えは無条件で属性付与解除
-    }
-    else
-    {
-        clif_unequipitemack (sd, n, 0, 0);
-    }
-    if (!type)
-    {
-        pc_calcstatus (sd, 0);
-        if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
-            && !battle_check_undead (7, sd->def_ele))
-            skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
-    }
-
-    return 0;
-}
-
-int pc_unequipinvyitem (struct map_session_data *sd, int n, int type)
-{
-    int  i;
-
-    nullpo_retr (1, sd);
-
-    for (i = 0; i < 11; i++)
-    {
-        if (equip_pos[i] > 0 && sd->equip_index[i] == n)
-        {                       //Slot taken, remove item from there.
-            pc_unequipitem (sd, sd->equip_index[i], type);
-            sd->equip_index[i] = -1;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * アイテムのindex番号を詰めたり
- * 装 備品の装備可能チェックを行なう
- *------------------------------------------
- */
-int pc_checkitem (struct map_session_data *sd)
-{
-    int  i, j, k, id, calc_flag = 0;
-    struct item_data *it = NULL;
-
-    nullpo_retr (0, sd);
-
-    // 所持品空き詰め
-    for (i = j = 0; i < MAX_INVENTORY; i++)
-    {
-        if ((id = sd->status.inventory[i].nameid) == 0)
-            continue;
-        if (battle_config.item_check && !itemdb_available (id))
-        {
-            if (battle_config.error_log)
-                printf ("illeagal item id %d in %d[%s] inventory.\n", id,
-                        sd->bl.id, sd->status.name);
-            pc_delitem (sd, i, sd->status.inventory[i].amount, 3);
-            continue;
-        }
-        if (i > j)
-        {
-            memcpy (&sd->status.inventory[j], &sd->status.inventory[i],
-                    sizeof (struct item));
-            sd->inventory_data[j] = sd->inventory_data[i];
-        }
-        j++;
-    }
-    if (j < MAX_INVENTORY)
-        memset (&sd->status.inventory[j], 0,
-                sizeof (struct item) * (MAX_INVENTORY - j));
-    for (k = j; k < MAX_INVENTORY; k++)
-        sd->inventory_data[k] = NULL;
-
-    // カート内空き詰め
-    for (i = j = 0; i < MAX_CART; i++)
-    {
-        if ((id = sd->status.cart[i].nameid) == 0)
-            continue;
-        if (battle_config.item_check && !itemdb_available (id))
-        {
-            if (battle_config.error_log)
-                printf ("illeagal item id %d in %d[%s] cart.\n", id,
-                        sd->bl.id, sd->status.name);
-            pc_cart_delitem (sd, i, sd->status.cart[i].amount, 1);
-            continue;
-        }
-        if (i > j)
-        {
-            memcpy (&sd->status.cart[j], &sd->status.cart[i],
-                    sizeof (struct item));
-        }
-        j++;
-    }
-    if (j < MAX_CART)
-        memset (&sd->status.cart[j], 0,
-                sizeof (struct item) * (MAX_CART - j));
-
-    // 装 備位置チェック
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-
-        it = sd->inventory_data[i];
-
-        if (sd->status.inventory[i].nameid == 0)
-            continue;
-        if (sd->status.inventory[i].equip & ~pc_equippoint (sd, i))
-        {
-            sd->status.inventory[i].equip = 0;
-            calc_flag = 1;
-        }
-        //装備制限チェック
-        if (sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp
-            && (it->flag.no_equip == 1 || it->flag.no_equip == 3))
-        {                       //PvP制限
-            sd->status.inventory[i].equip = 0;
-            calc_flag = 1;
-        }
-        else if (sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg
-                 && (it->flag.no_equip == 2 || it->flag.no_equip == 3))
-        {                       //GvG制限
-            sd->status.inventory[i].equip = 0;
-            calc_flag = 1;
-        }
-    }
-
-    pc_setequipindex (sd);
-    if (calc_flag)
-        pc_calcstatus (sd, 2);
-
-    return 0;
-}
-
-int pc_checkoverhp (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->status.hp == sd->status.max_hp)
-        return 1;
-    if (sd->status.hp > sd->status.max_hp)
-    {
-        sd->status.hp = sd->status.max_hp;
-        clif_updatestatus (sd, SP_HP);
-        return 2;
-    }
-
-    return 0;
-}
-
-int pc_checkoversp (struct map_session_data *sd)
-{
-    nullpo_retr (0, sd);
-
-    if (sd->status.sp == sd->status.max_sp)
-        return 1;
-    if (sd->status.sp > sd->status.max_sp)
-    {
-        sd->status.sp = sd->status.max_sp;
-        clif_updatestatus (sd, SP_SP);
-        return 2;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * PVP順位計算用(foreachinarea)
- *------------------------------------------
- */
-int pc_calc_pvprank_sub (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd1, *sd2 = NULL;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd1 = (struct map_session_data *) bl);
-    nullpo_retr (0, sd2 = va_arg (ap, struct map_session_data *));
-
-    if (sd1->pvp_point > sd2->pvp_point)
-        sd2->pvp_rank++;
-    return 0;
-}
-
-/*==========================================
- * PVP順位計算
- *------------------------------------------
- */
-int pc_calc_pvprank (struct map_session_data *sd)
-{
-    int  old;
-    struct map_data *m;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, m = &map[sd->bl.m]);
-
-    old = sd->pvp_rank;
-
-    if (!(m->flag.pvp))
-        return 0;
-    sd->pvp_rank = 1;
-    map_foreachinarea (pc_calc_pvprank_sub, sd->bl.m, 0, 0, m->xs, m->ys,
-                       BL_PC, sd);
-    if (old != sd->pvp_rank || sd->pvp_lastusers != m->users)
-        clif_pvpset (sd, sd->pvp_rank, sd->pvp_lastusers = m->users, 0);
-    return sd->pvp_rank;
-}
-
-/*==========================================
- * PVP順位計算(timer)
- *------------------------------------------
- */
-void pc_calc_pvprank_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = NULL;
-    if (battle_config.pk_mode)  // disable pvp ranking if pk_mode on [Valaris]
-        return;
-
-    sd = map_id2sd (id);
-    if (sd == NULL)
-        return;
-    sd->pvp_timer = -1;
-    if (pc_calc_pvprank (sd) > 0)
-        sd->pvp_timer = add_timer (gettick () + PVP_CALCRANK_INTERVAL,
-                                   pc_calc_pvprank_timer, id, data);
-}
-
-/*==========================================
- * sdは結婚しているか(既婚の場合は相方のchar_idを返す)
- *------------------------------------------
- */
-int pc_ismarried (struct map_session_data *sd)
-{
-    if (sd == NULL)
-        return -1;
-    if (sd->status.partner_id > 0)
-        return sd->status.partner_id;
-    else
-        return 0;
-}
-
-/*==========================================
- * sdがdstsdと結婚(dstsd→sdの結婚処理も同時に行う)
- *------------------------------------------
- */
-int pc_marriage (struct map_session_data *sd, struct map_session_data *dstsd)
-{
-    if (sd == NULL || dstsd == NULL || sd->status.partner_id > 0
-        || dstsd->status.partner_id > 0)
-        return -1;
-    sd->status.partner_id = dstsd->status.char_id;
-    dstsd->status.partner_id = sd->status.char_id;
-    return 0;
-}
-
-/*==========================================
- * sdが離婚(相手はsd->status.partner_idに依る)(相手も同時に離婚・結婚指輪自動剥奪)
- *------------------------------------------
- */
-int pc_divorce (struct map_session_data *sd)
-{
-    struct map_session_data *p_sd = NULL;
-    if (sd == NULL || !pc_ismarried (sd))
-        return -1;
-
-    // If both are on map server we don't need to bother the char server
-    if ((p_sd =
-         map_nick2sd (map_charid2nick (sd->status.partner_id))) != NULL)
-    {
-        if (p_sd->status.partner_id != sd->status.char_id
-            || sd->status.partner_id != p_sd->status.char_id)
-        {
-            printf ("pc_divorce: Illegal partner_id sd=%d p_sd=%d\n",
-                    sd->status.partner_id, p_sd->status.partner_id);
-            return -1;
-        }
-        p_sd->status.partner_id = 0;
-        sd->status.partner_id = 0;
-
-        if (sd->npc_flags.divorce)
-        {
-            sd->npc_flags.divorce = 0;
-            map_scriptcont (sd, sd->npc_id);
-        }
-    }
-    else
-        chrif_send_divorce (sd->status.char_id);
-
-    return 0;
-}
-
-/*==========================================
- * sdの相方のmap_session_dataを返す
- *------------------------------------------
- */
-struct map_session_data *pc_get_partner (struct map_session_data *sd)
-{
-    struct map_session_data *p_sd = NULL;
-    char *nick;
-    if (sd == NULL || !pc_ismarried (sd))
-        return NULL;
-
-    nick = map_charid2nick (sd->status.partner_id);
-
-    if (nick == NULL)
-        return NULL;
-
-    if ((p_sd = map_nick2sd (nick)) == NULL)
-        return NULL;
-
-    return p_sd;
-}
-
-//
-// 自然回復物
-//
-/*==========================================
- * SP回復量計算
- *------------------------------------------
- */
-static int natural_heal_tick, natural_heal_prev_tick, natural_heal_diff_tick;
-static int pc_spheal (struct map_session_data *sd)
-{
-    int  a;
-    struct guild_castle *gc = NULL;
-
-    nullpo_retr (0, sd);
-
-    a = natural_heal_diff_tick;
-    if (pc_issit (sd))
-        a += a;
-    if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // マグニフィカート
-        a += a;
-
-    gc = guild_mapname2gc (sd->mapname);    // Increased guild castle regen [Valaris]
-    if (gc)
-    {
-        struct guild *g;
-        g = guild_search (sd->status.guild_id);
-        if (g && g->guild_id == gc->guild_id)
-            a += a;
-    }                           // end addition [Valaris]
-
-    return a;
-}
-
-/*==========================================
- * HP回復量計算
- *------------------------------------------
- */
-static int pc_hpheal (struct map_session_data *sd)
-{
-    int  a;
-    struct guild_castle *gc;
-
-    nullpo_retr (0, sd);
-
-    a = natural_heal_diff_tick;
-    if (pc_issit (sd))
-        a += a;
-    if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // Modified by RoVeRT
-        a += a;
-
-    gc = guild_mapname2gc (sd->mapname);    // Increased guild castle regen [Valaris]
-    if (gc)
-    {
-        struct guild *g;
-        g = guild_search (sd->status.guild_id);
-        if (g && g->guild_id == gc->guild_id)
-            a += a;
-    }                           // end addition [Valaris]
-
-    return a;
-}
-
-static int pc_natural_heal_hp (struct map_session_data *sd)
-{
-    int  bhp;
-    int  inc_num, bonus, skill, hp_flag;
-
-    nullpo_retr (0, sd);
-
-    if (sd->sc_data[SC_TRICKDEAD].timer != -1)  // Modified by RoVeRT
-        return 0;
-
-    if (pc_checkoverhp (sd))
-    {
-        sd->hp_sub = sd->inchealhptick = 0;
-        return 0;
-    }
-
-    bhp = sd->status.hp;
-    hp_flag = (pc_checkskill (sd, SM_MOVINGRECOVERY) > 0
-               && sd->walktimer != -1);
-
-    if (sd->walktimer == -1)
-    {
-        inc_num = pc_hpheal (sd);
-        if (sd->sc_data[SC_TENSIONRELAX].timer != -1)
-        {                       // テンションリラックス
-            sd->hp_sub += 2 * inc_num;
-            sd->inchealhptick += 3 * natural_heal_diff_tick;
-        }
-        else
-        {
-            sd->hp_sub += inc_num;
-            sd->inchealhptick += natural_heal_diff_tick;
-        }
-    }
-    else if (hp_flag)
-    {
-        inc_num = pc_hpheal (sd);
-        sd->hp_sub += inc_num;
-        sd->inchealhptick = 0;
-    }
-    else
-    {
-        sd->hp_sub = sd->inchealhptick = 0;
-        return 0;
-    }
-
-    if (sd->hp_sub >= battle_config.natural_healhp_interval)
-    {
-        bonus = sd->nhealhp;
-        if (hp_flag)
-        {
-            bonus >>= 2;
-            if (bonus <= 0)
-                bonus = 1;
-        }
-        while (sd->hp_sub >= battle_config.natural_healhp_interval)
-        {
-            sd->hp_sub -= battle_config.natural_healhp_interval;
-            if (sd->status.hp + bonus <= sd->status.max_hp)
-                sd->status.hp += bonus;
-            else
-            {
-                sd->status.hp = sd->status.max_hp;
-                sd->hp_sub = sd->inchealhptick = 0;
-            }
-        }
-    }
-    if (bhp != sd->status.hp)
-        clif_updatestatus (sd, SP_HP);
-
-    if (sd->nshealhp > 0)
-    {
-        if (sd->inchealhptick >= battle_config.natural_heal_skill_interval
-            && sd->status.hp < sd->status.max_hp)
-        {
-            bonus = sd->nshealhp;
-            while (sd->inchealhptick >=
-                   battle_config.natural_heal_skill_interval)
-            {
-                sd->inchealhptick -=
-                    battle_config.natural_heal_skill_interval;
-                if (sd->status.hp + bonus <= sd->status.max_hp)
-                    sd->status.hp += bonus;
-                else
-                {
-                    bonus = sd->status.max_hp - sd->status.hp;
-                    sd->status.hp = sd->status.max_hp;
-                    sd->hp_sub = sd->inchealhptick = 0;
-                }
-                clif_heal (sd->fd, SP_HP, bonus);
-            }
-        }
-    }
-    else
-        sd->inchealhptick = 0;
-
-    return 0;
-
-    if (sd->sc_data[SC_APPLEIDUN].timer != -1)
-    {                           // Apple of Idun
-        if (sd->inchealhptick >= 6000 && sd->status.hp < sd->status.max_hp)
-        {
-            bonus = skill * 20;
-            while (sd->inchealhptick >= 6000)
-            {
-                sd->inchealhptick -= 6000;
-                if (sd->status.hp + bonus <= sd->status.max_hp)
-                    sd->status.hp += bonus;
-                else
-                {
-                    bonus = sd->status.max_hp - sd->status.hp;
-                    sd->status.hp = sd->status.max_hp;
-                    sd->hp_sub = sd->inchealhptick = 0;
-                }
-                clif_heal (sd->fd, SP_HP, bonus);
-            }
-        }
-    }
-    else
-        sd->inchealhptick = 0;
-
-    return 0;
-}
-
-static int pc_natural_heal_sp (struct map_session_data *sd)
-{
-    int  bsp;
-    int  inc_num, bonus;
-
-    nullpo_retr (0, sd);
-
-    if (sd->sc_data[SC_TRICKDEAD].timer != -1)  // Modified by RoVeRT
-        return 0;
-
-    if (pc_checkoversp (sd))
-    {
-        sd->sp_sub = sd->inchealsptick = 0;
-        return 0;
-    }
-
-    bsp = sd->status.sp;
-
-    inc_num = pc_spheal (sd);
-    if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1)
-        sd->sp_sub += inc_num;
-    if (sd->walktimer == -1)
-        sd->inchealsptick += natural_heal_diff_tick;
-    else
-        sd->inchealsptick = 0;
-
-    if (sd->sp_sub >= battle_config.natural_healsp_interval)
-    {
-        bonus = sd->nhealsp;;
-        while (sd->sp_sub >= battle_config.natural_healsp_interval)
-        {
-            sd->sp_sub -= battle_config.natural_healsp_interval;
-            if (sd->status.sp + bonus <= sd->status.max_sp)
-                sd->status.sp += bonus;
-            else
-            {
-                sd->status.sp = sd->status.max_sp;
-                sd->sp_sub = sd->inchealsptick = 0;
-            }
-        }
-    }
-
-    if (bsp != sd->status.sp)
-        clif_updatestatus (sd, SP_SP);
-
-    if (sd->nshealsp > 0)
-    {
-        if (sd->inchealsptick >= battle_config.natural_heal_skill_interval
-            && sd->status.sp < sd->status.max_sp)
-        {
-            struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
-            if (sd->doridori_counter && s_class.job == 23)
-                bonus = sd->nshealsp * 2;
-            else
-                bonus = sd->nshealsp;
-            sd->doridori_counter = 0;
-            while (sd->inchealsptick >=
-                   battle_config.natural_heal_skill_interval)
-            {
-                sd->inchealsptick -=
-                    battle_config.natural_heal_skill_interval;
-                if (sd->status.sp + bonus <= sd->status.max_sp)
-                    sd->status.sp += bonus;
-                else
-                {
-                    bonus = sd->status.max_sp - sd->status.sp;
-                    sd->status.sp = sd->status.max_sp;
-                    sd->sp_sub = sd->inchealsptick = 0;
-                }
-                clif_heal (sd->fd, SP_SP, bonus);
-            }
-        }
-    }
-    else
-        sd->inchealsptick = 0;
-
-    return 0;
-}
-
-static int pc_spirit_heal_hp (struct map_session_data *sd, int level)
-{
-    int  bonus_hp, interval = battle_config.natural_heal_skill_interval;
-    struct status_change *sc_data = battle_get_sc_data (&sd->bl);
-
-    nullpo_retr (0, sd);
-
-    if (pc_checkoverhp (sd))
-    {
-        sd->inchealspirithptick = 0;
-        return 0;
-    }
-
-    sd->inchealspirithptick += natural_heal_diff_tick;
-
-    if (sd->weight * 100 / sd->max_weight >=
-        battle_config.natural_heal_weight_rate
-        && sc_data[SC_FLYING_BACKPACK].timer == -1)
-        interval += interval;
-
-    if (sd->inchealspirithptick >= interval)
-    {
-        bonus_hp = sd->nsshealhp;
-        while (sd->inchealspirithptick >= interval)
-        {
-            if (pc_issit (sd))
-            {
-                sd->inchealspirithptick -= interval;
-                if (sd->status.hp < sd->status.max_hp)
-                {
-                    if (sd->status.hp + bonus_hp <= sd->status.max_hp)
-                        sd->status.hp += bonus_hp;
-                    else
-                    {
-                        bonus_hp = sd->status.max_hp - sd->status.hp;
-                        sd->status.hp = sd->status.max_hp;
-                    }
-                    clif_heal (sd->fd, SP_HP, bonus_hp);
-                    sd->inchealspirithptick = 0;
-                }
-            }
-            else
-            {
-                sd->inchealspirithptick -= natural_heal_diff_tick;
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-static int pc_spirit_heal_sp (struct map_session_data *sd, int level)
-{
-    int  bonus_sp, interval = battle_config.natural_heal_skill_interval;
-
-    nullpo_retr (0, sd);
-
-    if (pc_checkoversp (sd))
-    {
-        sd->inchealspiritsptick = 0;
-        return 0;
-    }
-
-    sd->inchealspiritsptick += natural_heal_diff_tick;
-
-    if (sd->weight * 100 / sd->max_weight >=
-        battle_config.natural_heal_weight_rate)
-        interval += interval;
-
-    if (sd->inchealspiritsptick >= interval)
-    {
-        bonus_sp = sd->nsshealsp;
-        while (sd->inchealspiritsptick >= interval)
-        {
-            if (pc_issit (sd))
-            {
-                sd->inchealspiritsptick -= interval;
-                if (sd->status.sp < sd->status.max_sp)
-                {
-                    if (sd->status.sp + bonus_sp <= sd->status.max_sp)
-                        sd->status.sp += bonus_sp;
-                    else
-                    {
-                        bonus_sp = sd->status.max_sp - sd->status.sp;
-                        sd->status.sp = sd->status.max_sp;
-                    }
-                    clif_heal (sd->fd, SP_SP, bonus_sp);
-                    sd->inchealspiritsptick = 0;
-                }
-            }
-            else
-            {
-                sd->inchealspiritsptick -= natural_heal_diff_tick;
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * HP/SP 自然回復 各クライアント
- *------------------------------------------
- */
-static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
-
-static int
-pc_quickregenerate_effect (struct quick_regeneration *quick_regen,
-                           int heal_speed)
-{
-    if (!(quick_regen->tickdelay--))
-    {
-        int  bonus =
-            MIN (heal_speed * battle_config.itemheal_regeneration_factor,
-                 quick_regen->amount);
-
-        quick_regen->amount -= bonus;
-
-        quick_regen->tickdelay = quick_regen->speed;
-
-        return bonus;
-    }
-
-    return 0;
-}
-
-static int pc_natural_heal_sub (struct map_session_data *sd, va_list ap)
-{
-    int  skill;
-
-    nullpo_retr (0, sd);
-
-    if (sd->heal_xp > 0)
-    {
-        if (sd->heal_xp < 64)
-            --sd->heal_xp;      // [Fate] Slowly reduce XP that healers can get for healing this char
-        else
-            sd->heal_xp -= (sd->heal_xp >> 6);
-    }
-
-    // Hijack this callback:  Adjust spellpower bonus
-    if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
-    {
-        sd->spellpower_bonus_current = sd->spellpower_bonus_target;
-        pc_calcstatus (sd, 0);
-    }
-    else if (sd->spellpower_bonus_target > sd->spellpower_bonus_current)
-    {
-        sd->spellpower_bonus_current +=
-            1 +
-            ((sd->spellpower_bonus_target -
-              sd->spellpower_bonus_current) >> 5);
-        pc_calcstatus (sd, 0);
-    }
-
-    if (sd->sc_data[SC_HALT_REGENERATE].timer != -1)
-        return 0;
-
-    if (sd->quick_regeneration_hp.amount || sd->quick_regeneration_sp.amount)
-    {
-        int  hp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_hp,
-                                                   (sd->sc_data[SC_POISON].timer == -1 || sd->sc_data[SC_SLOWPOISON].timer != -1) ? sd->nhealhp : 1);   // [fate] slow down when poisoned
-        int  sp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_sp,
-                                                   sd->nhealsp);
-
-        pc_itemheal_effect (sd, hp_bonus, sp_bonus);
-    }
-    skill_update_heal_animation (sd);   // if needed.
-
-// -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
-    if ((sd->sc_data[SC_FLYING_BACKPACK].timer != -1
-         || battle_config.natural_heal_weight_rate > 100
-         || sd->weight * 100 / sd->max_weight <
-         battle_config.natural_heal_weight_rate) && !pc_isdead (sd)
-        && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1)
-    {
-        pc_natural_heal_hp (sd);
-        if (sd->sc_data && sd->sc_data[SC_EXTREMITYFIST].timer == -1 && //阿修羅状態ではSPが回復しない
-            sd->sc_data[SC_DANCING].timer == -1 &&  //ダンス状態ではSPが回復しない
-            sd->sc_data[SC_BERSERK].timer == -1 //バーサーク状態ではSPが回復しない
-            )
-            pc_natural_heal_sp (sd);
-    }
-    else
-    {
-        sd->hp_sub = sd->inchealhptick = 0;
-        sd->sp_sub = sd->inchealsptick = 0;
-    }
-    if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0
-        && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1
-        && sd->sc_data[SC_BERSERK].timer == -1)
-    {
-        pc_spirit_heal_hp (sd, skill);
-        pc_spirit_heal_sp (sd, skill);
-    }
-    else
-    {
-        sd->inchealspirithptick = 0;
-        sd->inchealspiritsptick = 0;
-    }
-    return 0;
-}
-
-/*==========================================
- * HP/SP自然回復 (interval timer関数)
- *------------------------------------------
- */
-void pc_natural_heal (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    natural_heal_tick = tick;
-    natural_heal_diff_tick =
-        DIFF_TICK (natural_heal_tick, natural_heal_prev_tick);
-    clif_foreachclient (pc_natural_heal_sub);
-
-    natural_heal_prev_tick = tick;
-}
-
-/*==========================================
- * セーブポイントの保存
- *------------------------------------------
- */
-int pc_setsavepoint (struct map_session_data *sd, char *mapname, int x, int y)
-{
-    nullpo_retr (0, sd);
-
-    strncpy (sd->status.save_point.map, mapname, 23);
-    sd->status.save_point.map[23] = '\0';
-    sd->status.save_point.x = x;
-    sd->status.save_point.y = y;
-
-    return 0;
-}
-
-/*==========================================
- * 自動セーブ 各クライアント
- *------------------------------------------
- */
-static int last_save_fd, save_flag;
-static int pc_autosave_sub (struct map_session_data *sd, va_list ap)
-{
-    nullpo_retr (0, sd);
-
-    if (save_flag == 0 && sd->fd > last_save_fd)
-    {
-        struct guild_castle *gc = NULL;
-        int  i;
-
-        pc_makesavestatus (sd);
-        chrif_save (sd);
-
-        for (i = 0; i < MAX_GUILDCASTLE; i++)
-        {
-            gc = guild_castle_search (i);
-            if (!gc)
-                continue;
-            if (gc->visibleG0 == 1)
-                guild_castledatasave (gc->castle_id, 18, gc->Ghp0);
-            if (gc->visibleG1 == 1)
-                guild_castledatasave (gc->castle_id, 19, gc->Ghp1);
-            if (gc->visibleG2 == 1)
-                guild_castledatasave (gc->castle_id, 20, gc->Ghp2);
-            if (gc->visibleG3 == 1)
-                guild_castledatasave (gc->castle_id, 21, gc->Ghp3);
-            if (gc->visibleG4 == 1)
-                guild_castledatasave (gc->castle_id, 22, gc->Ghp4);
-            if (gc->visibleG5 == 1)
-                guild_castledatasave (gc->castle_id, 23, gc->Ghp5);
-            if (gc->visibleG6 == 1)
-                guild_castledatasave (gc->castle_id, 24, gc->Ghp6);
-            if (gc->visibleG7 == 1)
-                guild_castledatasave (gc->castle_id, 25, gc->Ghp7);
-        }
-
-        save_flag = 1;
-        last_save_fd = sd->fd;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 自動セーブ (timer関数)
- *------------------------------------------
- */
-void pc_autosave (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  interval;
-
-    save_flag = 0;
-    clif_foreachclient (pc_autosave_sub);
-    if (save_flag == 0)
-        last_save_fd = 0;
-
-    interval = autosave_interval / (clif_countusers () + 1);
-    if (interval <= 0)
-        interval = 1;
-    add_timer (gettick () + interval, pc_autosave, 0, 0);
-}
-
-int pc_read_gm_account (int fd)
-{
-    int  i = 0;
-    if (gm_account != NULL)
-        free (gm_account);
-    GM_num = 0;
-
-    CREATE (gm_account, struct gm_account, (RFIFOW (fd, 2) - 4) / 5);
-    for (i = 4; i < RFIFOW (fd, 2); i = i + 5)
-    {
-        gm_account[GM_num].account_id = RFIFOL (fd, i);
-        gm_account[GM_num].level = (int) RFIFOB (fd, i + 4);
-        //printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
-        GM_num++;
-    }
-    return GM_num;
-}
-
-/*==========================================
- * timer to do the day
- *------------------------------------------
- */
-void map_day_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{                               // by [yor]
-    struct map_session_data *pl_sd = NULL;
-    int  i;
-    char tmpstr[1024];
-
-    if (battle_config.day_duration > 0)
-    {                           // if we want a day
-        if (night_flag != 0)
-        {
-            strcpy (tmpstr, msg_txt (502)); // The day has arrived!
-            night_flag = 0;     // 0=day, 1=night [Yor]
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                    && pl_sd->state.auth)
-                {
-                    pl_sd->opt2 &= ~STATE_BLIND;
-                    clif_changeoption (&pl_sd->bl);
-                    clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
-                                      strlen (tmpstr) + 1);
-                }
-            }
-        }
-    }
-}
-
-/*==========================================
- * timer to do the night
- *------------------------------------------
- */
-void map_night_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{                               // by [yor]
-    struct map_session_data *pl_sd = NULL;
-    int  i;
-    char tmpstr[1024];
-
-    if (battle_config.night_duration > 0)
-    {                           // if we want a night
-        if (night_flag == 0)
-        {
-            strcpy (tmpstr, msg_txt (503)); // The night has fallen...
-            night_flag = 1;     // 0=day, 1=night [Yor]
-            for (i = 0; i < fd_max; i++)
-            {
-                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                    && pl_sd->state.auth)
-                {
-                    pl_sd->opt2 |= STATE_BLIND;
-                    clif_changeoption (&pl_sd->bl);
-                    clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
-                                      strlen (tmpstr) + 1);
-                }
-            }
-        }
-    }
-}
-
-void pc_setstand (struct map_session_data *sd)
-{
-    nullpo_retv (sd);
-
-    if (sd->sc_data && sd->sc_data[SC_TENSIONRELAX].timer != -1)
-        skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1);
-
-    sd->state.dead_sit = 0;
-}
-
-//
-// 初期化物
-//
-/*==========================================
- * 設定ファイル読み込む
- * exp.txt 必要経験値
- * job_db1.txt 重量,hp,sp,攻撃速度
- * job_db2.txt job能力値ボーナス
- * skill_tree.txt 各職毎のスキルツリー
- * attr_fix.txt 属性修正テーブル
- * size_fix.txt サイズ補正テーブル
- * refine_db.txt 精錬データテーブル
- *------------------------------------------
- */
-int pc_readdb (void)
-{
-    int  i, j, k;
-    FILE *fp;
-    char line[1024], *p;
-
-    // 必要経験値読み込み
-
-    fp = fopen_ ("db/exp.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/exp.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        int  bn, b1, b2, b3, b4, b5, b6, jn, j1, j2, j3, j4, j5, j6;
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (sscanf
-            (line, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &bn, &b1, &b2,
-             &b3, &b4, &b5, &b6, &jn, &j1, &j2, &j3, &j4, &j5, &j6) != 14)
-            continue;
-        exp_table[0][i] = bn;
-        exp_table[1][i] = b1;
-        exp_table[2][i] = b2;
-        exp_table[3][i] = b3;
-        exp_table[4][i] = b4;
-        exp_table[5][i] = b5;
-        exp_table[6][i] = b6;
-        exp_table[7][i] = jn;
-        exp_table[8][i] = j1;
-        exp_table[9][i] = j2;
-        exp_table[10][i] = j3;
-        exp_table[11][i] = j4;
-        exp_table[12][i] = j5;
-        exp_table[13][i] = j6;
-        i++;
-        if (i >= battle_config.maximum_level)
-            break;
-    }
-    fclose_ (fp);
-    printf ("read db/exp.txt done\n");
-
-    // JOB補正数値1
-    fp = fopen_ ("db/job_db1.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/job_db1.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        char *split[50];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 21 && p; j++)
-        {
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (j < 21)
-            continue;
-        max_weight_base[i] = atoi (split[0]);
-        hp_coefficient[i] = atoi (split[1]);
-        hp_coefficient2[i] = atoi (split[2]);
-        sp_coefficient[i] = atoi (split[3]);
-        for (j = 0; j < 17; j++)
-            aspd_base[i][j] = atoi (split[j + 4]);
-        i++;
-// -- moonsoul (below two lines added to accommodate high numbered new class ids)
-        if (i == 24)
-            i = 4001;
-        if (i == MAX_PC_CLASS)
-            break;
-    }
-    fclose_ (fp);
-    printf ("read db/job_db1.txt done\n");
-
-    // JOBボーナス
-    fp = fopen_ ("db/job_db2.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/job_db2.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < MAX_LEVEL && p; j++)
-        {
-            if (sscanf (p, "%d", &k) == 0)
-                break;
-            job_bonus[0][i][j] = k;
-            job_bonus[2][i][j] = k; //養子職のボーナスは分からないので仮
-            p = strchr (p, ',');
-            if (p)
-                p++;
-        }
-        i++;
-// -- moonsoul (below two lines added to accommodate high numbered new class ids)
-        if (i == 24)
-            i = 4001;
-        if (i == MAX_PC_CLASS)
-            break;
-    }
-    fclose_ (fp);
-    printf ("read db/job_db2.txt done\n");
-
-    // JOBボーナス2 転生職用
-    fp = fopen_ ("db/job_db2-2.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/job_db2-2.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < MAX_LEVEL && p; j++)
-        {
-            if (sscanf (p, "%d", &k) == 0)
-                break;
-            job_bonus[1][i][j] = k;
-            p = strchr (p, ',');
-            if (p)
-                p++;
-        }
-        i++;
-        if (i == MAX_PC_CLASS)
-            break;
-    }
-    fclose_ (fp);
-    printf ("read db/job_db2-2.txt done\n");
-
-    // スキルツリー
-    memset (skill_tree, 0, sizeof (skill_tree));
-    fp = fopen_ ("db/skill_tree.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/skill_tree.txt\n");
-        return 1;
-    }
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        char *split[50];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 13 && p; j++)
-        {
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (j < 13)
-            continue;
-        i = atoi (split[0]);
-        for (j = 0; skill_tree[0][i][j].id; j++);
-        skill_tree[0][i][j].id = atoi (split[1]);
-        skill_tree[0][i][j].max = atoi (split[2]);
-        skill_tree[2][i][j].id = atoi (split[1]);   //養子職は良く分からないので暫定
-        skill_tree[2][i][j].max = atoi (split[2]);  //養子職は良く分からないので暫定
-        for (k = 0; k < 5; k++)
-        {
-            skill_tree[0][i][j].need[k].id = atoi (split[k * 2 + 3]);
-            skill_tree[0][i][j].need[k].lv = atoi (split[k * 2 + 4]);
-            skill_tree[2][i][j].need[k].id = atoi (split[k * 2 + 3]);   //養子職は良く分からないので暫定
-            skill_tree[2][i][j].need[k].lv = atoi (split[k * 2 + 4]);   //養子職は良く分からないので暫定
-        }
-    }
-    fclose_ (fp);
-    printf ("read db/skill_tree.txt done\n");
-
-    // 属性修正テーブル
-    for (i = 0; i < 4; i++)
-        for (j = 0; j < 10; j++)
-            for (k = 0; k < 10; k++)
-                attr_fix_table[i][j][k] = 100;
-    fp = fopen_ ("db/attr_fix.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/attr_fix.txt\n");
-        return 1;
-    }
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        char *split[10];
-        int  lv, n;
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 3 && p; j++)
-        {
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        lv = atoi (split[0]);
-        n = atoi (split[1]);
-//      printf("%d %d\n",lv,n);
-
-        for (i = 0; i < n;)
-        {
-            if (!fgets (line, sizeof (line) - 1, fp))
-                break;
-            if (line[0] == '/' && line[1] == '/')
-                continue;
-
-            for (j = 0, p = line; j < n && p; j++)
-            {
-                while (*p == 32 && *p > 0)
-                    p++;
-                attr_fix_table[lv - 1][i][j] = atoi (p);
-                if (battle_config.attr_recover == 0
-                    && attr_fix_table[lv - 1][i][j] < 0)
-                    attr_fix_table[lv - 1][i][j] = 0;
-                p = strchr (p, ',');
-                if (p)
-                    *p++ = 0;
-            }
-
-            i++;
-        }
-    }
-    fclose_ (fp);
-    printf ("read db/attr_fix.txt done\n");
-
-    // サイズ補正テーブル
-    for (i = 0; i < 3; i++)
-        for (j = 0; j < 20; j++)
-            atkmods[i][j] = 100;
-    fp = fopen_ ("db/size_fix.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/size_fix.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        char *split[20];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (atoi (line) <= 0)
-            continue;
-        memset (split, 0, sizeof (split));
-        for (j = 0, p = line; j < 20 && p; j++)
-        {
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        for (j = 0; j < 20 && split[j]; j++)
-            atkmods[i][j] = atoi (split[j]);
-        i++;
-    }
-    fclose_ (fp);
-    printf ("read db/size_fix.txt done\n");
-
-    // 精錬データテーブル
-    for (i = 0; i < 5; i++)
-    {
-        for (j = 0; j < 10; j++)
-            percentrefinery[i][j] = 100;
-        refinebonus[i][0] = 0;
-        refinebonus[i][1] = 0;
-        refinebonus[i][2] = 10;
-    }
-    fp = fopen_ ("db/refine_db.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/refine_db.txt\n");
-        return 1;
-    }
-    i = 0;
-    while (fgets (line, sizeof (line) - 1, fp))
-    {
-        char *split[16];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        if (atoi (line) <= 0)
-            continue;
-        memset (split, 0, sizeof (split));
-        for (j = 0, p = line; j < 16 && p; j++)
-        {
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        refinebonus[i][0] = atoi (split[0]);    // 精錬ボーナス
-        refinebonus[i][1] = atoi (split[1]);    // 過剰精錬ボーナス
-        refinebonus[i][2] = atoi (split[2]);    // 安全精錬限界
-        for (j = 0; j < 10 && split[j]; j++)
-            percentrefinery[i][j] = atoi (split[j + 3]);
-        i++;
-    }
-    fclose_ (fp);               //Lupus. close this file!!!
-    printf ("read db/refine_db.txt done\n");
-
-    return 0;
-}
-
-static int pc_calc_sigma (void)
-{
-    int  i, j, k;
-
-    for (i = 0; i < MAX_PC_CLASS; i++)
-    {
-        memset (hp_sigma_val[i], 0, sizeof (hp_sigma_val[i]));
-        for (k = 0, j = 2; j <= MAX_LEVEL; j++)
-        {
-            k += hp_coefficient[i] * j + 50;
-            k -= k % 100;
-            hp_sigma_val[i][j - 1] = k;
-        }
-    }
-    return 0;
-}
-
-static void pc_statpointdb (void)
-{
-    char *buf_stat;
-    int  i = 0, j = 0, k = 0, l = 0, end = 0;
-
-    FILE *stp;
-
-    stp = fopen_ ("db/statpoint.txt", "r");
-
-    if (stp == NULL)
-    {
-        printf ("can't read db/statpoint.txt\n");
-        return;
-    }
-
-    fseek (stp, 0, SEEK_END);
-    end = ftell (stp);
-    rewind (stp);
-
-    buf_stat = (char *) malloc (end + 1);
-    l = fread (buf_stat, 1, end, stp);
-    fclose_ (stp);
-    printf ("read db/statpoint.txt done (size=%d)\n", l);
-
-    for (i = 0; i < 255; i++)
-    {
-        j = 0;
-        while (*(buf_stat + k) != '\n')
-        {
-            statp[i][j] = *(buf_stat + k);
-            j++;
-            k++;
-        }
-        statp[i][j + 1] = '\0';
-        k++;
-    }
-
-    free (buf_stat);
-}
-
-/*==========================================
- * pc関 係初期化
- *------------------------------------------
- */
-int do_init_pc (void)
-{
-    pc_readdb ();
-    pc_statpointdb ();
-    pc_calc_sigma ();
-
-//  gm_account_db = numdb_init();
-
-    add_timer_interval ((natural_heal_prev_tick =
-                         gettick () + NATURAL_HEAL_INTERVAL), pc_natural_heal,
-                        0, 0, NATURAL_HEAL_INTERVAL);
-    add_timer (gettick () + autosave_interval, pc_autosave, 0, 0);
-
-    {
-        int  day_duration = battle_config.day_duration;
-        int  night_duration = battle_config.night_duration;
-        if (day_duration < 60000)
-            day_duration = 60000;
-        if (night_duration < 60000)
-            night_duration = 60000;
-        if (battle_config.night_at_start == 0)
-        {
-            night_flag = 0;     // 0=day, 1=night [Yor]
-            day_timer_tid =
-                add_timer_interval (gettick () + day_duration +
-                                    night_duration, map_day_timer, 0, 0,
-                                    day_duration + night_duration);
-            night_timer_tid =
-                add_timer_interval (gettick () + day_duration,
-                                    map_night_timer, 0, 0,
-                                    day_duration + night_duration);
-        }
-        else
-        {
-            night_flag = 1;     // 0=day, 1=night [Yor]
-            day_timer_tid =
-                add_timer_interval (gettick () + night_duration,
-                                    map_day_timer, 0, 0,
-                                    day_duration + night_duration);
-            night_timer_tid =
-                add_timer_interval (gettick () + day_duration +
-                                    night_duration, map_night_timer, 0, 0,
-                                    day_duration + night_duration);
-        }
-    }
-
-    return 0;
-}
-
-void pc_cleanup (struct map_session_data *sd)
-{
-    magic_stop_completely (sd);
-}
-
-void pc_invisibility (struct map_session_data *sd, int enabled)
-{
-    if (enabled && !(sd->status.option & OPTION_INVISIBILITY))
-    {
-        clif_clearchar_area (&sd->bl, 3);
-        sd->status.option |= OPTION_INVISIBILITY;
-        clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 1);
-    }
-    else if (!enabled)
-    {
-        sd->status.option &= ~OPTION_INVISIBILITY;
-        clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 0);
-        pc_setpos (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y, 3);
-    }
-}
-
-int pc_logout (struct map_session_data *sd) // [fate] Player logs out
-{
-    unsigned int tick = gettick ();
-
-    if (!sd)
-        return 0;
-
-    if (sd->sc_data[SC_POISON].timer != -1)
-        sd->status.hp = 1;      // Logging out while poisoned -> bad
-
-    /*
-     * Trying to rapidly sign out/in or switch characters to avoid a spell's
-     * cast time is also bad. [remoitnane]
-     */
-#if 0
-    // Removed because it's buggy, see above.
-    if (sd->cast_tick > tick)
-    {
-        if (pc_setglobalreg (sd, "MAGIC_CAST_TICK", sd->cast_tick - tick))
-            sd->status.sp = 1;
-    }
-    else
-#endif
-        pc_setglobalreg (sd, "MAGIC_CAST_TICK", 0);
-
-    MAP_LOG_STATS (sd, "LOGOUT") return 0;
-}
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
new file mode 100644
index 0000000..7d02545
--- /dev/null
+++ b/src/map/pc.cpp
@@ -0,0 +1,9032 @@
+// $Id: pc.c 101 2004-09-25 17:57:22Z Valaris $
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "../common/socket.hpp"             // [Valaris]
+#include "../common/timer.hpp"
+#include "../common/db.hpp"
+
+#include "../common/nullpo.hpp"
+#include "../common/mt_rand.hpp"
+
+#include "atcommand.hpp"
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+#include "trade.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define PVP_CALCRANK_INTERVAL 1000  // PVP順位計算の間隔
+
+//define it here, since the ifdef only occurs in this file
+#define USE_ASTRAL_SOUL_SKILL
+
+#define STATE_BLIND 0x10
+
+#ifdef USE_ASTRAL_SOUL_SKILL
+#define MAGIC_SKILL_THRESHOLD 200   // [fate] At this threshold, the Astral Soul skill kicks in
+#endif
+
+#define MAP_LOG_STATS(sd, suffix)	\
+        MAP_LOG_PC(sd, "STAT %d %d %d %d %d %d " suffix,            \
+                   sd->status.str, sd->status.agi, sd->status.vit, sd->status.int_, sd->status.dex, sd->status.luk)
+
+#define MAP_LOG_XP(sd, suffix)	\
+        MAP_LOG_PC(sd, "XP %d %d JOB %d %d %d ZENY %d + %d " suffix,		\
+                   sd->status.base_level, sd->status.base_exp, sd->status.job_level, sd->status.job_exp, sd->status.skill_point,  sd->status.zeny, pc_readaccountreg(sd, "BankAccount"))
+
+#define MAP_LOG_MAGIC(sd, suffix)	\
+        MAP_LOG_PC(sd, "MAGIC %d %d %d %d %d %d EXP %d %d " suffix,	\
+                   sd->status.skill[TMW_MAGIC].lv,                      \
+                   sd->status.skill[TMW_MAGIC_LIFE].lv,			\
+                   sd->status.skill[TMW_MAGIC_WAR].lv,			\
+                   sd->status.skill[TMW_MAGIC_TRANSMUTE].lv,		\
+                   sd->status.skill[TMW_MAGIC_NATURE].lv,               \
+                   sd->status.skill[TMW_MAGIC_ETHER].lv,                \
+                   pc_readglobalreg(sd, "MAGIC_EXPERIENCE") & 0xffff,	\
+                   (pc_readglobalreg(sd, "MAGIC_EXPERIENCE") >> 24) & 0xff)
+
+static int max_weight_base[MAX_PC_CLASS];
+static int hp_coefficient[MAX_PC_CLASS];
+static int hp_coefficient2[MAX_PC_CLASS];
+static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL];
+static int sp_coefficient[MAX_PC_CLASS];
+static int aspd_base[MAX_PC_CLASS][20];
+static char job_bonus[3][MAX_PC_CLASS][MAX_LEVEL];
+static int exp_table[14][MAX_LEVEL];
+static char statp[255][7];
+static struct
+{
+    int  id;
+    int  max;
+    struct
+    {
+        short id, lv;
+    } need[6];
+} skill_tree[3][MAX_PC_CLASS][100];
+
+static int atkmods[3][20];      // 武器ATKサイズ修正(size_fix.txt)
+static int refinebonus[5][3];   // 精錬ボーナステーブル(refine_db.txt)
+static int percentrefinery[5][10];  // 精錬成功率(refine_db.txt)
+
+static int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+static int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+
+static unsigned int equip_pos[11] =
+    { 0x0080, 0x0008, 0x0040, 0x0004, 0x0001, 0x0200, 0x0100, 0x0010, 0x0020,
+    0x0002, 0x8000
+};
+
+//static struct dbt *gm_account_db;
+static struct gm_account *gm_account = NULL;
+static int GM_num = 0;
+
+int pc_isGM (struct map_session_data *sd)
+{
+//  struct gm_account *p;
+    int  i;
+
+    nullpo_retr (0, sd);
+
+/*	p = numdb_search(gm_account_db, sd->status.account_id);
+	if (p == NULL)
+		return 0;
+	return p->level;*/
+
+    for (i = 0; i < GM_num; i++)
+        if (gm_account[i].account_id == sd->status.account_id)
+            return gm_account[i].level;
+    return 0;
+
+}
+
+int pc_iskiller (struct map_session_data *src,
+                 struct map_session_data *target)
+{
+    nullpo_retr (0, src);
+
+    if (src->bl.type != BL_PC)
+        return 0;
+    if (src->special_state.killer)
+        return 1;
+
+    if (target->bl.type != BL_PC)
+        return 0;
+    if (target->special_state.killable)
+        return 1;
+
+    return 0;
+}
+
+int pc_set_gm_level (int account_id, int level)
+{
+    int  i;
+    for (i = 0; i < GM_num; i++)
+    {
+        if (account_id == gm_account[i].account_id)
+        {
+            gm_account[i].level = level;
+            return 0;
+        }
+    }
+
+    GM_num++;
+    RECREATE (gm_account, struct gm_account, GM_num);
+    gm_account[GM_num - 1].account_id = account_id;
+    gm_account[GM_num - 1].level = level;
+    return 0;
+}
+
+int pc_getrefinebonus (int lv, int type)
+{
+    if (lv >= 0 && lv < 5 && type >= 0 && type < 3)
+        return refinebonus[lv][type];
+    return 0;
+}
+
+static int distance (int x0, int y0, int x1, int y1)
+{
+    int  dx, dy;
+
+    dx = abs (x0 - x1);
+    dy = abs (y0 - y1);
+    return dx > dy ? dx : dy;
+}
+
+static void pc_invincible_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd;
+
+    if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
+        || sd->bl.type != BL_PC)
+        return;
+
+    if (sd->invincible_timer != tid)
+    {
+        if (battle_config.error_log)
+            printf ("invincible_timer %d != %d\n", sd->invincible_timer, tid);
+        return;
+    }
+    sd->invincible_timer = -1;
+}
+
+int pc_setinvincibletimer (struct map_session_data *sd, int val)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->invincible_timer != -1)
+        delete_timer (sd->invincible_timer, pc_invincible_timer);
+    sd->invincible_timer =
+        add_timer (gettick () + val, pc_invincible_timer, sd->bl.id, 0);
+    return 0;
+}
+
+int pc_delinvincibletimer (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->invincible_timer != -1)
+    {
+        delete_timer (sd->invincible_timer, pc_invincible_timer);
+        sd->invincible_timer = -1;
+    }
+    return 0;
+}
+
+static void pc_spiritball_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd;
+    int  i;
+
+    if ((sd = (struct map_session_data *) map_id2sd (id)) == NULL
+        || sd->bl.type != BL_PC)
+        return;
+
+    if (sd->spirit_timer[0] != tid)
+    {
+        if (battle_config.error_log)
+            printf ("spirit_timer %d != %d\n", sd->spirit_timer[0], tid);
+        return;
+    }
+    sd->spirit_timer[0] = -1;
+    for (i = 1; i < sd->spiritball; i++)
+    {
+        sd->spirit_timer[i - 1] = sd->spirit_timer[i];
+        sd->spirit_timer[i] = -1;
+    }
+    sd->spiritball--;
+    if (sd->spiritball < 0)
+        sd->spiritball = 0;
+    clif_spiritball (sd);
+}
+
+int pc_addspiritball (struct map_session_data *sd, int interval, int max)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (max > MAX_SKILL_LEVEL)
+        max = MAX_SKILL_LEVEL;
+    if (sd->spiritball < 0)
+        sd->spiritball = 0;
+
+    if (sd->spiritball >= max)
+    {
+        if (sd->spirit_timer[0] != -1)
+        {
+            delete_timer (sd->spirit_timer[0], pc_spiritball_timer);
+            sd->spirit_timer[0] = -1;
+        }
+        for (i = 1; i < max; i++)
+        {
+            sd->spirit_timer[i - 1] = sd->spirit_timer[i];
+            sd->spirit_timer[i] = -1;
+        }
+    }
+    else
+        sd->spiritball++;
+
+    sd->spirit_timer[sd->spiritball - 1] =
+        add_timer (gettick () + interval, pc_spiritball_timer, sd->bl.id, 0);
+    clif_spiritball (sd);
+
+    return 0;
+}
+
+int pc_delspiritball (struct map_session_data *sd, int count, int type)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (sd->spiritball <= 0)
+    {
+        sd->spiritball = 0;
+        return 0;
+    }
+
+    if (count > sd->spiritball)
+        count = sd->spiritball;
+    sd->spiritball -= count;
+    if (count > MAX_SKILL_LEVEL)
+        count = MAX_SKILL_LEVEL;
+
+    for (i = 0; i < count; i++)
+    {
+        if (sd->spirit_timer[i] != -1)
+        {
+            delete_timer (sd->spirit_timer[i], pc_spiritball_timer);
+            sd->spirit_timer[i] = -1;
+        }
+    }
+    for (i = count; i < MAX_SKILL_LEVEL; i++)
+    {
+        sd->spirit_timer[i - count] = sd->spirit_timer[i];
+        sd->spirit_timer[i] = -1;
+    }
+
+    if (!type)
+        clif_spiritball (sd);
+
+    return 0;
+}
+
+int pc_setrestartvalue (struct map_session_data *sd, int type)
+{
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    //-----------------------
+    // 死亡した
+    if (sd->special_state.restart_full_recover)
+    {                           // オシリスカード
+        sd->status.hp = sd->status.max_hp;
+        sd->status.sp = sd->status.max_sp;
+    }
+    else
+    {
+        if (s_class.job == 0 && battle_config.restart_hp_rate < 50)
+        {                       //ノビは半分回復
+            sd->status.hp = (sd->status.max_hp) / 2;
+        }
+        else
+        {
+            if (battle_config.restart_hp_rate <= 0)
+                sd->status.hp = 1;
+            else
+            {
+                sd->status.hp =
+                    sd->status.max_hp * battle_config.restart_hp_rate / 100;
+                if (sd->status.hp <= 0)
+                    sd->status.hp = 1;
+            }
+        }
+        if (battle_config.restart_sp_rate > 0)
+        {
+            int  sp = sd->status.max_sp * battle_config.restart_sp_rate / 100;
+            if (sd->status.sp < sp)
+                sd->status.sp = sp;
+        }
+    }
+    if (type & 1)
+        clif_updatestatus (sd, SP_HP);
+    if (type & 1)
+        clif_updatestatus (sd, SP_SP);
+
+    /* removed exp penalty on spawn [Valaris] */
+
+    if (type & 2 && sd->status.pc_class != 0 && battle_config.zeny_penalty > 0
+        && !map[sd->bl.m].flag.nozenypenalty)
+    {
+        int  zeny =
+            (int) ((double) sd->status.zeny *
+                   (double) battle_config.zeny_penalty / 10000.);
+        if (zeny < 1)
+            zeny = 1;
+        sd->status.zeny -= zeny;
+        if (sd->status.zeny < 0)
+            sd->status.zeny = 0;
+        clif_updatestatus (sd, SP_ZENY);
+    }
+    sd->heal_xp = 0;            // [Fate] Set gainable xp for healing this player to 0
+
+    return 0;
+}
+
+/*==========================================
+ * 自分をロックしているMOBの数を数える(foreachclient)
+ *------------------------------------------
+ */
+static int pc_counttargeted_sub (struct block_list *bl, va_list ap)
+{
+    int  id, *c, target_lv;
+    struct block_list *src;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    id = va_arg (ap, int);
+
+    nullpo_retr (0, c = va_arg (ap, int *));
+
+    src = va_arg (ap, struct block_list *);
+    target_lv = va_arg (ap, int);
+    if (id == bl->id || (src && id == src->id))
+        return 0;
+    if (bl->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) bl;
+        if (sd && sd->attacktarget == id && sd->attacktimer != -1
+            && sd->attacktarget_lv >= target_lv)
+            (*c)++;
+    }
+    else if (bl->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) bl;
+        if (md && md->target_id == id && md->timer != -1
+            && md->state.state == MS_ATTACK && md->target_lv >= target_lv)
+
+            (*c)++;
+        //printf("md->target_lv:%d, target_lv:%d\n",((struct mob_data *)bl)->target_lv,target_lv);
+    }
+    return 0;
+}
+
+int pc_counttargeted (struct map_session_data *sd, struct block_list *src,
+                      int target_lv)
+{
+    int  c = 0;
+    map_foreachinarea (pc_counttargeted_sub, sd->bl.m,
+                       sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
+                       sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE, 0,
+                       sd->bl.id, &c, src, target_lv);
+    return c;
+}
+
+/*==========================================
+ * ローカルプロトタイプ宣言 (必要な物のみ)
+ *------------------------------------------
+ */
+static int pc_walktoxy_sub (struct map_session_data *);
+
+/*==========================================
+ * saveに必要なステータス修正を行なう
+ *------------------------------------------
+ */
+int pc_makesavestatus (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    // 服の色は色々弊害が多いので保存対象にはしない
+    if (!battle_config.save_clothcolor)
+        sd->status.clothes_color = 0;
+
+    // 死亡状態だったのでhpを1、位置をセーブ場所に変更
+    if (pc_isdead (sd))
+    {
+        pc_setrestartvalue (sd, 0);
+        memcpy (&sd->status.last_point, &sd->status.save_point,
+                sizeof (sd->status.last_point));
+    }
+    else
+    {
+        memcpy (sd->status.last_point.map, sd->mapname, 24);
+        sd->status.last_point.x = sd->bl.x;
+        sd->status.last_point.y = sd->bl.y;
+    }
+
+    // セーブ禁止マップだったので指定位置に移動
+    if (map[sd->bl.m].flag.nosave)
+    {
+        struct map_data *m = &map[sd->bl.m];
+        if (strcmp (m->save.map, "SavePoint") == 0)
+            memcpy (&sd->status.last_point, &sd->status.save_point,
+                    sizeof (sd->status.last_point));
+        else
+            memcpy (&sd->status.last_point, &m->save,
+                    sizeof (sd->status.last_point));
+    }
+
+    //マナーポイントがプラスだった場合0に
+    if (battle_config.muting_players && sd->status.manner > 0)
+        sd->status.manner = 0;
+    return 0;
+}
+
+/*==========================================
+ * 接続時の初期化
+ *------------------------------------------
+ */
+int pc_setnewpc (struct map_session_data *sd, int account_id, int char_id,
+                 int login_id1, int client_tick, int sex, int fd)
+{
+    nullpo_retr (0, sd);
+
+    sd->bl.id = account_id;
+    sd->char_id = char_id;
+    sd->login_id1 = login_id1;
+    sd->login_id2 = 0;          // at this point, we can not know the value :(
+    sd->client_tick = client_tick;
+    sd->sex = sex;
+    sd->state.auth = 0;
+    sd->bl.type = BL_PC;
+    sd->canact_tick = sd->canmove_tick = gettick ();
+    sd->canlog_tick = gettick ();
+    sd->state.waitingdisconnect = 0;
+
+    return 0;
+}
+
+int pc_equippoint (struct map_session_data *sd, int n)
+{
+    int  ep = 0;
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    if (!sd->inventory_data[n])
+        return 0;
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    ep = sd->inventory_data[n]->equip;
+    if ((sd->inventory_data[n]->look == 1 || sd->inventory_data[n]->look == 2
+         || sd->inventory_data[n]->look == 6) && (ep == 2
+                                                  &&
+                                                  (pc_checkskill (sd, AS_LEFT)
+                                                   > 0 || s_class.job == 12)))
+    {
+        return 34;
+    }
+
+    return ep;
+}
+
+int pc_setinventorydata (struct map_session_data *sd)
+{
+    int  i, id;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        id = sd->status.inventory[i].nameid;
+        sd->inventory_data[i] = itemdb_search (id);
+    }
+    return 0;
+}
+
+int pc_calcweapontype (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->weapontype1 != 0 && sd->weapontype2 == 0)
+        sd->status.weapon = sd->weapontype1;
+    if (sd->weapontype1 == 0 && sd->weapontype2 != 0)   // 左手武器 Only
+        sd->status.weapon = sd->weapontype2;
+    else if (sd->weapontype1 == 1 && sd->weapontype2 == 1)  // 双短剣
+        sd->status.weapon = 0x11;
+    else if (sd->weapontype1 == 2 && sd->weapontype2 == 2)  // 双単手剣
+        sd->status.weapon = 0x12;
+    else if (sd->weapontype1 == 6 && sd->weapontype2 == 6)  // 双単手斧
+        sd->status.weapon = 0x13;
+    else if ((sd->weapontype1 == 1 && sd->weapontype2 == 2) || (sd->weapontype1 == 2 && sd->weapontype2 == 1))  // 短剣 - 単手剣
+        sd->status.weapon = 0x14;
+    else if ((sd->weapontype1 == 1 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 1))  // 短剣 - 斧
+        sd->status.weapon = 0x15;
+    else if ((sd->weapontype1 == 2 && sd->weapontype2 == 6) || (sd->weapontype1 == 6 && sd->weapontype2 == 2))  // 単手剣 - 斧
+        sd->status.weapon = 0x16;
+    else
+        sd->status.weapon = sd->weapontype1;
+
+    return 0;
+}
+
+int pc_setequipindex (struct map_session_data *sd)
+{
+    int  i, j;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < 11; i++)
+        sd->equip_index[i] = -1;
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid <= 0)
+            continue;
+        if (sd->status.inventory[i].equip)
+        {
+            for (j = 0; j < 11; j++)
+                if (sd->status.inventory[i].equip & equip_pos[j])
+                    sd->equip_index[j] = i;
+            if (sd->status.inventory[i].equip & 0x0002)
+            {
+                if (sd->inventory_data[i])
+                    sd->weapontype1 = sd->inventory_data[i]->look;
+                else
+                    sd->weapontype1 = 0;
+            }
+            if (sd->status.inventory[i].equip & 0x0020)
+            {
+                if (sd->inventory_data[i])
+                {
+                    if (sd->inventory_data[i]->type == 4)
+                    {
+                        if (sd->status.inventory[i].equip == 0x0020)
+                            sd->weapontype2 = sd->inventory_data[i]->look;
+                        else
+                            sd->weapontype2 = 0;
+                    }
+                    else
+                        sd->weapontype2 = 0;
+                }
+                else
+                    sd->weapontype2 = 0;
+            }
+        }
+    }
+    pc_calcweapontype (sd);
+
+    return 0;
+}
+
+int pc_isequip (struct map_session_data *sd, int n)
+{
+    struct item_data *item;
+    struct status_change *sc_data;
+    //転生や養子の場合の元の職業を算出する
+
+    nullpo_retr (0, sd);
+
+    item = sd->inventory_data[n];
+    sc_data = battle_get_sc_data (&sd->bl);
+    //s_class = pc_calc_base_job(sd->status.class);
+
+    if (battle_config.gm_allequip > 0
+        && pc_isGM (sd) >= battle_config.gm_allequip)
+        return 1;
+
+    if (item == NULL)
+        return 0;
+    if (item->sex != 2 && sd->status.sex != item->sex)
+        return 0;
+    if (item->elv > 0 && sd->status.base_level < item->elv)
+        return 0;
+
+    if (map[sd->bl.m].flag.pvp
+        && (item->flag.no_equip == 1 || item->flag.no_equip == 3))
+        return 0;
+    if (map[sd->bl.m].flag.gvg
+        && (item->flag.no_equip == 2 || item->flag.no_equip == 3))
+        return 0;
+    if (item->equip & 0x0002 && sc_data
+        && sc_data[SC_STRIPWEAPON].timer != -1)
+        return 0;
+    if (item->equip & 0x0020 && sc_data
+        && sc_data[SC_STRIPSHIELD].timer != -1)
+        return 0;
+    if (item->equip & 0x0010 && sc_data && sc_data[SC_STRIPARMOR].timer != -1)
+        return 0;
+    if (item->equip & 0x0100 && sc_data && sc_data[SC_STRIPHELM].timer != -1)
+        return 0;
+    return 1;
+}
+
+/*==========================================
+ * Weapon Breaking [Valaris]
+ *------------------------------------------
+ */
+int pc_breakweapon (struct map_session_data *sd)
+{
+    struct item_data *item;
+    char output[255];
+    int  i;
+
+    if (sd == NULL)
+        return -1;
+    if (sd->unbreakable >= MRAND (100))
+        return 0;
+    if (sd->sc_data && sd->sc_data[SC_CP_WEAPON].timer != -1)
+        return 0;
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].equip
+            && sd->status.inventory[i].equip & 0x0002
+            && !sd->status.inventory[i].broken)
+        {
+            item = sd->inventory_data[i];
+            sd->status.inventory[i].broken = 1;
+            //pc_unequipitem(sd,i,0);
+            if (sd->status.inventory[i].equip
+                && sd->status.inventory[i].equip & 0x0002
+                && sd->status.inventory[i].broken == 1)
+            {
+                sprintf (output, "%s has broken.", item->jname);
+                clif_emotion (&sd->bl, 23);
+                clif_displaymessage (sd->fd, output);
+                clif_equiplist (sd);
+                skill_status_change_start (&sd->bl, SC_BROKNWEAPON, 0, 0, 0,
+                                           0, 0, 0);
+            }
+        }
+        if (sd->status.inventory[i].broken == 1)
+            return 0;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * Armor Breaking [Valaris]
+ *------------------------------------------
+ */
+int pc_breakarmor (struct map_session_data *sd)
+{
+    struct item_data *item;
+    char output[255];
+    int  i;
+
+    if (sd == NULL)
+        return -1;
+    if (sd->unbreakable >= MRAND (100))
+        return 0;
+    if (sd->sc_data && sd->sc_data[SC_CP_ARMOR].timer != -1)
+        return 0;
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].equip
+            && sd->status.inventory[i].equip & 0x0010
+            && !sd->status.inventory[i].broken)
+        {
+            item = sd->inventory_data[i];
+            sd->status.inventory[i].broken = 1;
+            //pc_unequipitem(sd,i,0);
+            if (sd->status.inventory[i].equip
+                && sd->status.inventory[i].equip & 0x0010
+                && sd->status.inventory[i].broken == 1)
+            {
+                sprintf (output, "%s has broken.", item->jname);
+                clif_emotion (&sd->bl, 23);
+                clif_displaymessage (sd->fd, output);
+                clif_equiplist (sd);
+                skill_status_change_start (&sd->bl, SC_BROKNARMOR, 0, 0, 0, 0,
+                                           0, 0);
+            }
+        }
+        if (sd->status.inventory[i].broken == 1)
+            return 0;
+    }
+    return 0;
+}
+
+/*==========================================
+ * session idに問題無し
+ * char鯖から送られてきたステータスを設定
+ *------------------------------------------
+ */
+int pc_authok (int id, int login_id2, time_t connect_until_time,
+               short tmw_version, struct mmo_charstatus *st)
+{
+    struct map_session_data *sd = NULL;
+
+    struct party *p;
+    struct guild *g;
+    int  i;
+    unsigned long tick = gettick ();
+    struct sockaddr_in sai;
+    socklen_t sa_len = sizeof(struct sockaddr);
+
+    sd = map_id2sd (id);
+    if (sd == NULL)
+        return 1;
+
+    sd->login_id2 = login_id2;
+    sd->tmw_version = tmw_version;
+
+    memcpy (&sd->status, st, sizeof (*st));
+
+    if (sd->status.sex != sd->sex)
+    {
+        clif_authfail_fd (sd->fd, 0);
+        return 1;
+    }
+
+    MAP_LOG_STATS (sd, "LOGIN");
+    MAP_LOG_XP (sd, "LOGIN");
+    MAP_LOG_MAGIC (sd, "LOGIN");
+
+    memset (&sd->state, 0, sizeof (sd->state));
+    // 基本的な初期化
+    sd->state.connect_new = 1;
+    sd->bl.prev = sd->bl.next = NULL;
+
+    sd->weapontype1 = sd->weapontype2 = 0;
+    sd->view_class = sd->status.pc_class;
+    sd->speed = DEFAULT_WALK_SPEED;
+    sd->state.dead_sit = 0;
+    sd->dir = 0;
+    sd->head_dir = 0;
+    sd->state.auth = 1;
+    sd->walktimer = -1;
+    sd->attacktimer = -1;
+    sd->followtimer = -1;       // [MouseJstr]
+    sd->skilltimer = -1;
+    sd->skillitem = -1;
+    sd->skillitemlv = -1;
+    sd->invincible_timer = -1;
+    sd->sg_count = 0;
+
+    sd->deal_locked = 0;
+    sd->trade_partner = 0;
+
+    sd->inchealhptick = 0;
+    sd->inchealsptick = 0;
+    sd->hp_sub = 0;
+    sd->sp_sub = 0;
+    sd->quick_regeneration_hp.amount = 0;
+    sd->quick_regeneration_sp.amount = 0;
+    sd->heal_xp = 0;
+    sd->inchealspirithptick = 0;
+    sd->inchealspiritsptick = 0;
+    sd->canact_tick = tick;
+    sd->canmove_tick = tick;
+    sd->attackabletime = tick;
+    /* We don't want players bypassing spell restrictions. [remoitnane] */
+    // Removed because it was buggy with the ~50 day wraparound,
+    // and there's already a limit on how fast you can log in and log out.
+    // -o11c
+    sd->cast_tick = tick; // + pc_readglobalreg (sd, "MAGIC_CAST_TICK");
+
+    sd->doridori_counter = 0;
+
+    sd->spiritball = 0;
+    for (i = 0; i < MAX_SKILL_LEVEL; i++)
+        sd->spirit_timer[i] = -1;
+    for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
+        sd->skilltimerskill[i].timer = -1;
+
+    memset (&sd->dev, 0, sizeof (struct square));
+    for (i = 0; i < 5; i++)
+    {
+        sd->dev.val1[i] = 0;
+        sd->dev.val2[i] = 0;
+    }
+
+    // アカウント変数の送信要求
+    intif_request_accountreg (sd);
+
+    // アイテムチェック
+    pc_setinventorydata (sd);
+    pc_checkitem (sd);
+
+    // ステータス異常の初期化
+    for (i = 0; i < MAX_STATUSCHANGE; i++)
+    {
+        sd->sc_data[i].timer = -1;
+        sd->sc_data[i].val1 = sd->sc_data[i].val2 = sd->sc_data[i].val3 =
+            sd->sc_data[i].val4 = 0;
+    }
+    sd->sc_count = 0;
+    if ((battle_config.atc_gmonly == 0 || pc_isGM (sd)) &&
+        (pc_isGM (sd) >= get_atcommand_level (AtCommand_Hide)))
+        sd->status.option &= (OPTION_MASK | OPTION_HIDE);
+    else
+        sd->status.option &= OPTION_MASK;
+
+    // スキルユニット関係の初期化
+    memset (sd->skillunit, 0, sizeof (sd->skillunit));
+    memset (sd->skillunittick, 0, sizeof (sd->skillunittick));
+
+    // init ignore list
+    memset (sd->ignore, 0, sizeof (sd->ignore));
+
+    // パーティー関係の初期化
+    sd->party_sended = 0;
+    sd->party_invite = 0;
+    sd->party_x = -1;
+    sd->party_y = -1;
+    sd->party_hp = -1;
+
+    // ギルド関係の初期化
+    sd->guild_sended = 0;
+    sd->guild_invite = 0;
+    sd->guild_alliance = 0;
+
+    // イベント関係の初期化
+    memset (sd->eventqueue, 0, sizeof (sd->eventqueue));
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        sd->eventtimer[i] = -1;
+
+    // 位置の設定
+    pc_setpos (sd, sd->status.last_point.map, sd->status.last_point.x,
+               sd->status.last_point.y, 0);
+
+    // パーティ、ギルドデータの要求
+    if (sd->status.party_id > 0
+        && (p = party_search (sd->status.party_id)) == NULL)
+        party_request_info (sd->status.party_id);
+    if (sd->status.guild_id > 0
+        && (g = guild_search (sd->status.guild_id)) == NULL)
+        guild_request_info (sd->status.guild_id);
+
+    // pvpの設定
+    sd->pvp_rank = 0;
+    sd->pvp_point = 0;
+    sd->pvp_timer = -1;
+
+    // 通知
+
+    clif_authok (sd);
+    map_addnickdb (sd);
+    if (map_charid2nick (sd->status.char_id) == NULL)
+        map_addchariddb (sd->status.char_id, sd->status.name);
+
+    //スパノビ用死にカウンターのスクリプト変数からの読み出しとsdへのセット
+    sd->die_counter = pc_readglobalreg (sd, "PC_DIE_COUNTER");
+
+    if (night_flag == 1)
+    {
+        char tmpstr[1024];
+        strcpy (tmpstr, msg_txt (500)); // Actually, it's the night...
+        clif_wis_message (sd->fd, wisp_server_name, tmpstr,
+                          strlen (tmpstr) + 1);
+        sd->opt2 |= STATE_BLIND;
+    }
+
+    // ステータス初期計算など
+    pc_calcstatus (sd, 1);
+
+    if (pc_isGM (sd))
+    {
+        printf
+            ("Connection accepted: character '%s' (account: %d; GM level %d).\n",
+             sd->status.name, sd->status.account_id, pc_isGM (sd));
+        clif_updatestatus (sd, SP_GM);
+    }
+    else
+        printf ("Connection accepted: Character '%s' (account: %d).\n",
+                sd->status.name, sd->status.account_id);
+
+    // Message of the Dayの送信
+    {
+        char buf[256];
+        FILE *fp;
+        if ((fp = fopen_ (motd_txt, "r")) != NULL)
+        {
+            while (fgets (buf, sizeof (buf) - 1, fp) != NULL)
+            {
+                int  i;
+                for (i = 0; buf[i]; i++)
+                {
+                    if (buf[i] == '\r' || buf[i] == '\n')
+                    {
+                        buf[i] = 0;
+                        break;
+                    }
+                }
+                clif_displaymessage (sd->fd, buf);
+            }
+            fclose_ (fp);
+        }
+    }
+
+    sd->auto_ban_info.in_progress = 0;
+
+    // Initialize antispam vars
+    sd->chat_reset_due = sd->chat_lines_in = sd->chat_total_repeats =
+        sd->chat_repeat_reset_due = 0;
+    sd->chat_lastmsg[0] = '\0';
+
+    memset(sd->flood_rates, 0, sizeof(sd->flood_rates));
+    sd->packet_flood_reset_due = sd->packet_flood_in = 0;
+
+    // Obtain IP address (if they are still connected)
+    if (!getpeername(sd->fd, (struct sockaddr *)&sai, &sa_len))
+        sd->ip = sai.sin_addr.s_addr;
+
+    // message of the limited time of the account
+    if (connect_until_time != 0)
+    {                           // don't display if it's unlimited or unknow value
+        char tmpstr[1024];
+        strftime (tmpstr, sizeof (tmpstr) - 1, msg_txt (501), gmtime (&connect_until_time));    // "Your account time limit is: %d-%m-%Y %H:%M:%S."
+        clif_wis_message (sd->fd, wisp_server_name, tmpstr,
+                          strlen (tmpstr) + 1);
+    }
+    pc_calcstatus (sd, 1);
+
+    return 0;
+}
+
+/*==========================================
+ * session idに問題ありなので後始末
+ *------------------------------------------
+ */
+int pc_authfail (int id)
+{
+    struct map_session_data *sd;
+
+    sd = map_id2sd (id);
+    if (sd == NULL)
+        return 1;
+
+    clif_authfail_fd (sd->fd, 0);
+
+    return 0;
+}
+
+static int pc_calc_skillpoint (struct map_session_data *sd)
+{
+    int  i, skill_points = 0;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < skill_pool_skills_size; i++) {
+        int lv = sd->status.skill[skill_pool_skills[i]].lv;
+        if (lv)
+            skill_points += ((lv * (lv - 1)) >> 1) - 1;
+    }
+
+    return skill_points;
+}
+
+/*==========================================
+ * 覚えられるスキルの計算
+ *------------------------------------------
+ */
+int pc_calc_skilltree (struct map_session_data *sd)
+{
+    int  i, id = 0, flag;
+    int  c = 0, s = 0;
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+    c = s_class.job;
+    s = (s_class.upper == 1) ? 1 : 0;   //ソ転生以外は通常のスキル?
+
+    if ((battle_config.skillup_limit)
+        && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023)
+            || (c >= 4023 && c < 4045)))
+    {
+        int  skill_point = pc_calc_skillpoint (sd);
+        if (skill_point < 9)
+            c = 0;
+        else if ((sd->status.skill_point >= sd->status.job_level
+                  && skill_point < 58) && ((c > 6 && c < 23) || (c > 4007
+                                                                 && c < 4023)
+                                           || (c > 4029 && c < 4045)))
+        {
+            switch (c)
+            {
+                case 7:
+                case 14:
+                    c = 1;
+                    break;
+                case 8:
+                case 15:
+                    c = 4;
+                    break;
+                case 9:
+                case 16:
+                    c = 2;
+                    break;
+                case 10:
+                case 18:
+                    c = 5;
+                    break;
+                case 11:
+                case 19:
+                case 20:
+                    c = 3;
+                    break;
+                case 12:
+                case 17:
+                    c = 6;
+                    break;
+                case 4008:
+                case 4015:
+                    c = 4002;
+                    break;
+                case 4009:
+                case 4016:
+                    c = 4005;
+                    break;
+                case 4010:
+                case 4017:
+                    c = 4003;
+                    break;
+                case 4011:
+                case 4019:
+                    c = 4006;
+                    break;
+                case 4012:
+                case 4020:
+                case 4021:
+                    c = 4004;
+                    break;
+                case 4013:
+                case 4018:
+                    c = 4007;
+                    break;
+                case 4030:
+                case 4037:
+                    c = 4024;
+                    break;
+                case 4031:
+                case 4038:
+                    c = 4027;
+                    break;
+                case 4032:
+                case 4039:
+                    c = 4025;
+                    break;
+                case 4033:
+                case 4040:
+                    c = 4028;
+                    break;
+                case 4034:
+                case 4041:
+                case 4042:
+                    c = 4026;
+                    break;
+                case 4035:
+                case 4043:
+                    c = 4029;
+                    break;
+
+            }
+        }
+    }
+
+    /*Comment this out for now, as we manage skills differently
+     * for(i=0;i<MAX_SKILL;i++)
+     * if (i < TMW_MAGIC || i > TMW_MAGIC_END){ // [Fate] This hack gets TMW magic working and persisted without bothering about the skill tree.
+     * if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
+     * if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
+     * sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2;   // 本当のlvに
+     * sd->status.skill[i].flag=0;  // flagは0にしておく
+     * }
+     * }
+     */
+
+    if (battle_config.gm_allskill > 0
+        && pc_isGM (sd) >= battle_config.gm_allskill)
+    {
+        // 全てのスキル
+        for (i = 1; i < 158; i++)
+            sd->status.skill[i].id = i;
+        for (i = 210; i < 291; i++)
+            sd->status.skill[i].id = i;
+        for (i = 304; i < 337; i++)
+            sd->status.skill[i].id = i;
+        if (battle_config.enable_upper_class)
+        {                       //confで無効でなければ読み込む
+            for (i = 355; i < MAX_SKILL; i++)
+                sd->status.skill[i].id = i;
+        }
+
+    }
+    else
+    {
+        // 通常の計算
+        do
+        {
+            flag = 0;
+            for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
+            {
+                int  j, f = 1;
+                if (!battle_config.skillfree)
+                {
+                    for (j = 0; j < 5; j++)
+                    {
+                        if (skill_tree[s][c][i].need[j].id &&
+                            pc_checkskill (sd,
+                                           skill_tree[s][c][i].need[j].id) <
+                            skill_tree[s][c][i].need[j].lv)
+                            f = 0;
+                    }
+                }
+                if (f && sd->status.skill[id].id == 0)
+                {
+                    sd->status.skill[id].id = id;
+                    flag = 1;
+                }
+            }
+        }
+        while (flag);
+    }
+//  if(battle_config.etc_log)
+//      printf("calc skill_tree\n");
+    return 0;
+}
+
+/*==========================================
+ * 重量アイコンの確認
+ *------------------------------------------
+ */
+int pc_checkweighticon (struct map_session_data *sd)
+{
+    int  flag = 0;
+
+    nullpo_retr (0, sd);
+
+    if (sd->weight * 2 >= sd->max_weight
+        && sd->sc_data[SC_FLYING_BACKPACK].timer == -1)
+        flag = 1;
+    if (sd->weight * 10 >= sd->max_weight * 9)
+        flag = 2;
+
+    if (flag == 1)
+    {
+        if (sd->sc_data[SC_WEIGHT50].timer == -1)
+            skill_status_change_start (&sd->bl, SC_WEIGHT50, 0, 0, 0, 0, 0,
+                                       0);
+    }
+    else
+    {
+        skill_status_change_end (&sd->bl, SC_WEIGHT50, -1);
+    }
+    if (flag == 2)
+    {
+        if (sd->sc_data[SC_WEIGHT90].timer == -1)
+            skill_status_change_start (&sd->bl, SC_WEIGHT90, 0, 0, 0, 0, 0,
+                                       0);
+    }
+    else
+    {
+        skill_status_change_end (&sd->bl, SC_WEIGHT90, -1);
+    }
+    return 0;
+}
+
+void pc_set_weapon_look (struct map_session_data *sd)
+{
+    if (sd->attack_spell_override)
+        clif_changelook (&sd->bl, LOOK_WEAPON,
+                         sd->attack_spell_look_override);
+    else
+        clif_changelook (&sd->bl, LOOK_WEAPON, sd->status.weapon);
+}
+
+/*==========================================
+ * パラメータ計算
+ * first==0の時、計算対象のパラメータが呼び出し前から
+ * 変 化した場合自動でsendするが、
+ * 能動的に変化させたパラメータは自前でsendするように
+ *------------------------------------------
+ */
+int pc_calcstatus (struct map_session_data *sd, int first)
+{
+    int  b_speed, b_max_hp, b_max_sp, b_hp, b_sp, b_weight, b_max_weight,
+        b_paramb[6], b_parame[6], b_hit, b_flee;
+    int  b_aspd, b_watk, b_def, b_watk2, b_def2, b_flee2, b_critical,
+        b_attackrange, b_matk1, b_matk2, b_mdef, b_mdef2, b_class;
+    int  b_base_atk;
+    struct skill b_skill[MAX_SKILL];
+    int  i, bl, index;
+    int  skill, aspd_rate, wele, wele_, def_ele, refinedef = 0;
+    int  str, dstr, dex;
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    //転生や養子の場合の元の職業を算出する
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    b_speed = sd->speed;
+    b_max_hp = sd->status.max_hp;
+    b_max_sp = sd->status.max_sp;
+    b_hp = sd->status.hp;
+    b_sp = sd->status.sp;
+    b_weight = sd->weight;
+    b_max_weight = sd->max_weight;
+    memcpy (b_paramb, &sd->paramb, sizeof (b_paramb));
+    memcpy (b_parame, &sd->paramc, sizeof (b_parame));
+    memcpy (b_skill, &sd->status.skill, sizeof (b_skill));
+    b_hit = sd->hit;
+    b_flee = sd->flee;
+    b_aspd = sd->aspd;
+    b_watk = sd->watk;
+    b_def = sd->def;
+    b_watk2 = sd->watk2;
+    b_def2 = sd->def2;
+    b_flee2 = sd->flee2;
+    b_critical = sd->critical;
+    b_attackrange = sd->attackrange;
+    b_matk1 = sd->matk1;
+    b_matk2 = sd->matk2;
+    b_mdef = sd->mdef;
+    b_mdef2 = sd->mdef2;
+    b_class = sd->view_class;
+    sd->view_class = sd->status.pc_class;
+    b_base_atk = sd->base_atk;
+
+    pc_calc_skilltree (sd);     // スキルツリーの計算
+
+    sd->max_weight = max_weight_base[s_class.job] + sd->status.str * 300;
+
+    if (first & 1)
+    {
+        sd->weight = 0;
+        for (i = 0; i < MAX_INVENTORY; i++)
+        {
+            if (sd->status.inventory[i].nameid == 0
+                || sd->inventory_data[i] == NULL)
+                continue;
+            sd->weight +=
+                sd->inventory_data[i]->weight *
+                sd->status.inventory[i].amount;
+        }
+        sd->cart_max_weight = battle_config.max_cart_weight;
+        sd->cart_weight = 0;
+        sd->cart_max_num = MAX_CART;
+        sd->cart_num = 0;
+        for (i = 0; i < MAX_CART; i++)
+        {
+            if (sd->status.cart[i].nameid == 0)
+                continue;
+            sd->cart_weight +=
+                itemdb_weight (sd->status.cart[i].nameid) *
+                sd->status.cart[i].amount;
+            sd->cart_num++;
+        }
+    }
+
+    memset (sd->paramb, 0, sizeof (sd->paramb));
+    memset (sd->parame, 0, sizeof (sd->parame));
+    sd->hit = 0;
+    sd->flee = 0;
+    sd->flee2 = 0;
+    sd->critical = 0;
+    sd->aspd = 0;
+    sd->watk = 0;
+    sd->def = 0;
+    sd->mdef = 0;
+    sd->watk2 = 0;
+    sd->def2 = 0;
+    sd->mdef2 = 0;
+    sd->status.max_hp = 0;
+    sd->status.max_sp = 0;
+    sd->attackrange = 0;
+    sd->attackrange_ = 0;
+    sd->atk_ele = 0;
+    sd->def_ele = 0;
+    sd->star = 0;
+    sd->overrefine = 0;
+    sd->matk1 = 0;
+    sd->matk2 = 0;
+    sd->speed = DEFAULT_WALK_SPEED;
+    sd->hprate = 100;
+    sd->sprate = 100;
+    sd->castrate = 100;
+    sd->dsprate = 100;
+    sd->base_atk = 0;
+    sd->arrow_atk = 0;
+    sd->arrow_ele = 0;
+    sd->arrow_hit = 0;
+    sd->arrow_range = 0;
+    sd->nhealhp = sd->nhealsp = sd->nshealhp = sd->nshealsp = sd->nsshealhp =
+        sd->nsshealsp = 0;
+    memset (sd->addele, 0, sizeof (sd->addele));
+    memset (sd->addrace, 0, sizeof (sd->addrace));
+    memset (sd->addsize, 0, sizeof (sd->addsize));
+    memset (sd->addele_, 0, sizeof (sd->addele_));
+    memset (sd->addrace_, 0, sizeof (sd->addrace_));
+    memset (sd->addsize_, 0, sizeof (sd->addsize_));
+    memset (sd->subele, 0, sizeof (sd->subele));
+    memset (sd->subrace, 0, sizeof (sd->subrace));
+    memset (sd->addeff, 0, sizeof (sd->addeff));
+    memset (sd->addeff2, 0, sizeof (sd->addeff2));
+    memset (sd->reseff, 0, sizeof (sd->reseff));
+    memset (&sd->special_state, 0, sizeof (sd->special_state));
+    memset (sd->weapon_coma_ele, 0, sizeof (sd->weapon_coma_ele));
+    memset (sd->weapon_coma_race, 0, sizeof (sd->weapon_coma_race));
+
+    sd->watk_ = 0;              //二刀流用(仮)
+    sd->watk_2 = 0;
+    sd->atk_ele_ = 0;
+    sd->star_ = 0;
+    sd->overrefine_ = 0;
+
+    sd->aspd_rate = 100;
+    sd->speed_rate = 100;
+    sd->hprecov_rate = 100;
+    sd->sprecov_rate = 100;
+    sd->critical_def = 0;
+    sd->double_rate = 0;
+    sd->near_attack_def_rate = sd->long_attack_def_rate = 0;
+    sd->atk_rate = sd->matk_rate = 100;
+    sd->ignore_def_ele = sd->ignore_def_race = 0;
+    sd->ignore_def_ele_ = sd->ignore_def_race_ = 0;
+    sd->ignore_mdef_ele = sd->ignore_mdef_race = 0;
+    sd->arrow_cri = 0;
+    sd->magic_def_rate = sd->misc_def_rate = 0;
+    memset (sd->arrow_addele, 0, sizeof (sd->arrow_addele));
+    memset (sd->arrow_addrace, 0, sizeof (sd->arrow_addrace));
+    memset (sd->arrow_addsize, 0, sizeof (sd->arrow_addsize));
+    memset (sd->arrow_addeff, 0, sizeof (sd->arrow_addeff));
+    memset (sd->arrow_addeff2, 0, sizeof (sd->arrow_addeff2));
+    memset (sd->magic_addele, 0, sizeof (sd->magic_addele));
+    memset (sd->magic_addrace, 0, sizeof (sd->magic_addrace));
+    memset (sd->magic_subrace, 0, sizeof (sd->magic_subrace));
+    sd->perfect_hit = 0;
+    sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
+    sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
+    sd->def_ratio_atk_ele = sd->def_ratio_atk_ele_ = 0;
+    sd->def_ratio_atk_race = sd->def_ratio_atk_race_ = 0;
+    sd->get_zeny_num = 0;
+    sd->add_damage_class_count = sd->add_damage_class_count_ =
+        sd->add_magic_damage_class_count = 0;
+    sd->add_def_class_count = sd->add_mdef_class_count = 0;
+    sd->monster_drop_item_count = 0;
+    memset (sd->add_damage_classrate, 0, sizeof (sd->add_damage_classrate));
+    memset (sd->add_damage_classrate_, 0, sizeof (sd->add_damage_classrate_));
+    memset (sd->add_magic_damage_classrate, 0,
+            sizeof (sd->add_magic_damage_classrate));
+    memset (sd->add_def_classrate, 0, sizeof (sd->add_def_classrate));
+    memset (sd->add_mdef_classrate, 0, sizeof (sd->add_mdef_classrate));
+    memset (sd->monster_drop_race, 0, sizeof (sd->monster_drop_race));
+    memset (sd->monster_drop_itemrate, 0, sizeof (sd->monster_drop_itemrate));
+    sd->speed_add_rate = sd->aspd_add_rate = 100;
+    sd->double_add_rate = sd->perfect_hit_add = sd->get_zeny_add_num = 0;
+    sd->splash_range = sd->splash_add_range = 0;
+    sd->autospell_id = sd->autospell_lv = sd->autospell_rate = 0;
+    sd->hp_drain_rate = sd->hp_drain_per = sd->sp_drain_rate =
+        sd->sp_drain_per = 0;
+    sd->hp_drain_rate_ = sd->hp_drain_per_ = sd->sp_drain_rate_ =
+        sd->sp_drain_per_ = 0;
+    sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
+    sd->magic_damage_return = 0;    //AppleGirl Was Here
+    sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
+
+    if (!sd->disguiseflag && sd->disguise)
+    {
+        sd->disguise = 0;
+        pc_set_weapon_look (sd);
+        clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
+        clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
+        clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
+        clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
+        clif_clearchar (&sd->bl, 9);
+        pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+    }
+
+    sd->spellpower_bonus_target = 0;
+
+    for (i = 0; i < 10; i++)
+    {
+        index = sd->equip_index[i];
+        if (index < 0)
+            continue;
+        if (i == 9 && sd->equip_index[8] == index)
+            continue;
+        if (i == 5 && sd->equip_index[4] == index)
+            continue;
+        if (i == 6
+            && (sd->equip_index[5] == index || sd->equip_index[4] == index))
+            continue;
+
+        if (sd->inventory_data[index])
+        {
+            sd->spellpower_bonus_target +=
+                sd->inventory_data[index]->magic_bonus;
+
+            if (sd->inventory_data[index]->type == 4)
+            {
+                if (sd->status.inventory[index].card[0] != 0x00ff
+                    && sd->status.inventory[index].card[0] != 0x00fe
+                    && sd->status.inventory[index].card[0] != (short) 0xff00)
+                {
+                    int  j;
+                    for (j = 0; j < sd->inventory_data[index]->slot; j++)
+                    {           // カード
+                        int  c = sd->status.inventory[index].card[j];
+                        if (c > 0)
+                        {
+                            argrec_t arg[2];
+                            arg[0].name = "@slotId";
+                            arg[0].v.i = i;
+                            arg[1].name = "@itemId";
+                            arg[1].v.i = sd->inventory_data[index]->nameid;
+                            if (i == 8
+                                && sd->status.inventory[index].equip == 0x20)
+                                sd->state.lr_flag = 1;
+                            run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
+                                        0, 2, arg);
+                            sd->state.lr_flag = 0;
+                        }
+                    }
+                }
+            }
+            else if (sd->inventory_data[index]->type == 5)
+            {                   // 防具
+                if (sd->status.inventory[index].card[0] != 0x00ff
+                    && sd->status.inventory[index].card[0] != 0x00fe
+                    && sd->status.inventory[index].card[0] != (short) 0xff00)
+                {
+                    int  j;
+                    for (j = 0; j < sd->inventory_data[index]->slot; j++)
+                    {           // カード
+                        int  c = sd->status.inventory[index].card[j];
+                        if (c > 0) {
+                            argrec_t arg[2];
+                            arg[0].name = "@slotId";
+                            arg[0].v.i = i;
+                            arg[1].name = "@itemId";
+                            arg[1].v.i = sd->inventory_data[index]->nameid;
+                            run_script_l (itemdb_equipscript (c), 0, sd->bl.id,
+                                        0, 2, arg);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+#ifdef USE_ASTRAL_SOUL_SKILL
+    if (sd->spellpower_bonus_target < 0)
+        sd->spellpower_bonus_target =
+            (sd->spellpower_bonus_target * 256) /
+            (MIN (128 + skill_power (sd, TMW_ASTRAL_SOUL), 256));
+#endif
+
+    if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
+        sd->spellpower_bonus_current = sd->spellpower_bonus_target;
+
+    wele = sd->atk_ele;
+    wele_ = sd->atk_ele_;
+    def_ele = sd->def_ele;
+    memcpy (sd->paramcard, sd->parame, sizeof (sd->paramcard));
+
+    // 装備品によるステータス変化はここで実行
+    for (i = 0; i < 10; i++)
+    {
+        index = sd->equip_index[i];
+        if (index < 0)
+            continue;
+        if (i == 9 && sd->equip_index[8] == index)
+            continue;
+        if (i == 5 && sd->equip_index[4] == index)
+            continue;
+        if (i == 6
+            && (sd->equip_index[5] == index || sd->equip_index[4] == index))
+            continue;
+        if (sd->inventory_data[index])
+        {
+            sd->def += sd->inventory_data[index]->def;
+            if (sd->inventory_data[index]->type == 4)
+            {
+                int  r, wlv = sd->inventory_data[index]->wlv;
+                if (i == 8 && sd->status.inventory[index].equip == 0x20)
+                {
+                    //二刀流用データ入力
+                    sd->watk_ += sd->inventory_data[index]->atk;
+                    sd->watk_2 = (r = sd->status.inventory[index].refine) * // 精錬攻撃力
+                        refinebonus[wlv][0];
+                    if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
+                        sd->overrefine_ = r * refinebonus[wlv][1];
+
+                    if (sd->status.inventory[index].card[0] == 0x00ff)
+                    {           // 製造武器
+                        sd->star_ = (sd->status.inventory[index].card[1] >> 8); // 星のかけら
+                        wele_ = (sd->status.inventory[index].card[1] & 0x0f);   // 属 性
+                    }
+                    sd->attackrange_ += sd->inventory_data[index]->range;
+                    sd->state.lr_flag = 1;
+                    {
+                        argrec_t arg[2];
+                        arg[0].name = "@slotId";
+                        arg[0].v.i = i;
+                        arg[1].name = "@itemId";
+                        arg[1].v.i = sd->inventory_data[index]->nameid;
+                        run_script_l (sd->inventory_data[index]->equip_script, 0,
+                                      sd->bl.id, 0, 2, arg);
+                    }
+                    sd->state.lr_flag = 0;
+                }
+                else
+                {               //二刀流武器以外
+                    argrec_t arg[2];
+                    arg[0].name = "@slotId";
+                    arg[0].v.i = i;
+                    arg[1].name = "@itemId";
+                    arg[1].v.i = sd->inventory_data[index]->nameid;
+                    sd->watk += sd->inventory_data[index]->atk;
+                    sd->watk2 += (r = sd->status.inventory[index].refine) * // 精錬攻撃力
+                        refinebonus[wlv][0];
+                    if ((r -= refinebonus[wlv][2]) > 0) // 過剰精錬ボーナス
+                        sd->overrefine += r * refinebonus[wlv][1];
+
+                    if (sd->status.inventory[index].card[0] == 0x00ff)
+                    {           // 製造武器
+                        sd->star += (sd->status.inventory[index].card[1] >> 8); // 星のかけら
+                        wele = (sd->status.inventory[index].card[1] & 0x0f);    // 属 性
+                    }
+                    sd->attackrange += sd->inventory_data[index]->range;
+                    run_script_l (sd->inventory_data[index]->equip_script, 0,
+                                  sd->bl.id, 0, 2, arg);
+                }
+            }
+            else if (sd->inventory_data[index]->type == 5)
+            {
+                argrec_t arg[2];
+                arg[0].name = "@slotId";
+                arg[0].v.i = i;
+                arg[1].name = "@itemId";
+                arg[1].v.i = sd->inventory_data[index]->nameid;
+                sd->watk += sd->inventory_data[index]->atk;
+                refinedef +=
+                    sd->status.inventory[index].refine * refinebonus[0][0];
+                run_script_l (sd->inventory_data[index]->equip_script, 0,
+                              sd->bl.id, 0, 2, arg);
+            }
+        }
+    }
+
+    if (battle_is_unarmed (&sd->bl))
+    {
+        sd->watk += skill_power (sd, TMW_BRAWLING) / 3; // +66 for 200
+        sd->watk2 += skill_power (sd, TMW_BRAWLING) >> 3;   // +25 for 200
+        sd->watk_ += skill_power (sd, TMW_BRAWLING) / 3;    // +66 for 200
+        sd->watk_2 += skill_power (sd, TMW_BRAWLING) >> 3;  // +25 for 200
+    }
+
+    if (sd->equip_index[10] >= 0)
+    {                           // 矢
+        index = sd->equip_index[10];
+        if (sd->inventory_data[index])
+        {                       //まだ属性が入っていない
+            argrec_t arg[2];
+            arg[0].name = "@slotId";
+            arg[0].v.i = i;
+            arg[1].name = "@itemId";
+            arg[1].v.i = sd->inventory_data[index]->nameid;
+            sd->state.lr_flag = 2;
+            run_script_l (sd->inventory_data[index]->equip_script, 0, sd->bl.id,
+                        0, 2, arg);
+            sd->state.lr_flag = 0;
+            sd->arrow_atk += sd->inventory_data[index]->atk;
+        }
+    }
+    sd->def += (refinedef + 50) / 100;
+
+    if (sd->attackrange < 1)
+        sd->attackrange = 1;
+    if (sd->attackrange_ < 1)
+        sd->attackrange_ = 1;
+    if (sd->attackrange < sd->attackrange_)
+        sd->attackrange = sd->attackrange_;
+    if (sd->status.weapon == 11)
+        sd->attackrange += sd->arrow_range;
+    if (wele > 0)
+        sd->atk_ele = wele;
+    if (wele_ > 0)
+        sd->atk_ele_ = wele_;
+    if (def_ele > 0)
+        sd->def_ele = def_ele;
+    sd->double_rate += sd->double_add_rate;
+    sd->perfect_hit += sd->perfect_hit_add;
+    sd->get_zeny_num += sd->get_zeny_add_num;
+    sd->splash_range += sd->splash_add_range;
+    if (sd->speed_add_rate != 100)
+        sd->speed_rate += sd->speed_add_rate - 100;
+    if (sd->aspd_add_rate != 100)
+        sd->aspd_rate += sd->aspd_add_rate - 100;
+
+    // 武器ATKサイズ補正 (右手)
+    sd->atkmods[0] = atkmods[0][sd->weapontype1];
+    sd->atkmods[1] = atkmods[1][sd->weapontype1];
+    sd->atkmods[2] = atkmods[2][sd->weapontype1];
+    //武器ATKサイズ補正 (左手)
+    sd->atkmods_[0] = atkmods[0][sd->weapontype2];
+    sd->atkmods_[1] = atkmods[1][sd->weapontype2];
+    sd->atkmods_[2] = atkmods[2][sd->weapontype2];
+
+/*
+	// jobボーナス分
+	for(i=0;i<sd->status.job_level && i<MAX_LEVEL;i++){
+		if(job_bonus[s_class.upper][s_class.job][i])
+			sd->paramb[job_bonus[s_class.upper][s_class.job][i]-1]++;
+	}
+*/
+
+    if ((skill = pc_checkskill (sd, MC_INCCARRY)) > 0)  // skill can be used with an item now, thanks to orn [Valaris]
+        sd->max_weight += skill * 1000;
+
+    // ステータス変化による基本パラメータ補正
+    if (sd->sc_count)
+    {
+        if (sd->sc_data[SC_CONCENTRATE].timer != -1
+            && sd->sc_data[SC_QUAGMIRE].timer == -1)
+        {                       // 集中力向上
+            sd->paramb[1] +=
+                (sd->status.agi + sd->paramb[1] + sd->parame[1] -
+                 sd->paramcard[1]) * (2 +
+                                      sd->sc_data[SC_CONCENTRATE].val1) / 100;
+            sd->paramb[4] +=
+                (sd->status.dex + sd->paramb[4] + sd->parame[4] -
+                 sd->paramcard[4]) * (2 +
+                                      sd->sc_data[SC_CONCENTRATE].val1) / 100;
+        }
+        if (sd->sc_data[SC_INCREASEAGI].timer != -1
+            && sd->sc_data[SC_QUAGMIRE].timer == -1
+            && sd->sc_data[SC_DONTFORGETME].timer == -1)
+        {                       // 速度増加
+            sd->paramb[1] += 2 + sd->sc_data[SC_INCREASEAGI].val1;
+            sd->speed -= sd->speed * 25 / 100;
+        }
+        if (sd->sc_data[SC_DECREASEAGI].timer != -1)    // 速度減少(agiはbattle.cで)
+            sd->speed = sd->speed * 125 / 100;
+        if (sd->sc_data[SC_CLOAKING].timer != -1)
+            sd->speed =
+                (sd->speed * (76 + (sd->sc_data[SC_INCREASEAGI].val1 * 3))) /
+                100;
+        if (sd->sc_data[SC_BLESSING].timer != -1)
+        {                       // ブレッシング
+            sd->paramb[0] += sd->sc_data[SC_BLESSING].val1;
+            sd->paramb[3] += sd->sc_data[SC_BLESSING].val1;
+            sd->paramb[4] += sd->sc_data[SC_BLESSING].val1;
+        }
+        if (sd->sc_data[SC_GLORIA].timer != -1) // グロリア
+            sd->paramb[5] += 30;
+        if (sd->sc_data[SC_LOUD].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1)   // ラウドボイス
+            sd->paramb[0] += 4;
+        if (sd->sc_data[SC_QUAGMIRE].timer != -1)
+        {                       // クァグマイア
+            sd->speed = sd->speed * 3 / 2;
+            sd->paramb[1] -=
+                (sd->status.agi + sd->paramb[1] + sd->parame[1]) / 2;
+            sd->paramb[4] -=
+                (sd->status.dex + sd->paramb[4] + sd->parame[4]) / 2;
+        }
+        if (sd->sc_data[SC_TRUESIGHT].timer != -1)
+        {                       // トゥルーサイト
+            sd->paramb[0] += 5;
+            sd->paramb[1] += 5;
+            sd->paramb[2] += 5;
+            sd->paramb[3] += 5;
+            sd->paramb[4] += 5;
+            sd->paramb[5] += 5;
+        }
+    }
+    sd->speed -= skill_power (sd, TMW_SPEED) >> 3;
+    sd->aspd_rate -= skill_power (sd, TMW_SPEED) / 10;
+    if (sd->aspd_rate < 20)
+        sd->aspd_rate = 20;
+
+/*
+	//1度も死んでないJob70スパノビに+10
+	if(s_class.job == 23 && sd->die_counter == 0 && sd->status.job_level >= 70){
+		sd->paramb[0]+= 15;
+		sd->paramb[1]+= 15;
+		sd->paramb[2]+= 15;
+		sd->paramb[3]+= 15;
+		sd->paramb[4]+= 15;
+		sd->paramb[5]+= 15;
+	}
+*/
+    sd->paramc[0] = sd->status.str + sd->paramb[0] + sd->parame[0];
+    sd->paramc[1] = sd->status.agi + sd->paramb[1] + sd->parame[1];
+    sd->paramc[2] = sd->status.vit + sd->paramb[2] + sd->parame[2];
+    sd->paramc[3] = sd->status.int_ + sd->paramb[3] + sd->parame[3];
+    sd->paramc[4] = sd->status.dex + sd->paramb[4] + sd->parame[4];
+    sd->paramc[5] = sd->status.luk + sd->paramb[5] + sd->parame[5];
+    for (i = 0; i < 6; i++)
+        if (sd->paramc[i] < 0)
+            sd->paramc[i] = 0;
+
+    if (sd->status.weapon == 11 || sd->status.weapon == 13
+        || sd->status.weapon == 14)
+    {
+        str = sd->paramc[4];
+        dex = sd->paramc[0];
+    }
+    else
+    {
+        str = sd->paramc[0];
+        dex = sd->paramc[4];
+        sd->critical += ((dex * 3) >> 1);
+    }
+    dstr = str / 10;
+    sd->base_atk += str + dstr * dstr + dex / 5 + sd->paramc[5] / 5;
+//fprintf(stderr, "baseatk = %d = x + %d + %d + %d + %d\n", sd->base_atk, str, dstr*dstr, dex/5, sd->paramc[5]/5);
+    sd->matk1 += sd->paramc[3] + (sd->paramc[3] / 5) * (sd->paramc[3] / 5);
+    sd->matk2 += sd->paramc[3] + (sd->paramc[3] / 7) * (sd->paramc[3] / 7);
+    if (sd->matk1 < sd->matk2)
+    {
+        int  temp = sd->matk2;
+        sd->matk2 = sd->matk1;
+        sd->matk1 = temp;
+    }
+    // [Fate] New tmw magic system
+    sd->matk1 += sd->status.base_level + sd->spellpower_bonus_current;
+#ifdef USE_ASTRAL_SOUL_SKILL
+    if (sd->matk1 > MAGIC_SKILL_THRESHOLD)
+    {
+        int  bonus = sd->matk1 - MAGIC_SKILL_THRESHOLD;
+        // Ok if you are above a certain threshold, you get only (1/8) of that matk1
+        // if you have Astral soul skill you can get the whole power again (and additionally the 1/8 added)
+        sd->matk1 = MAGIC_SKILL_THRESHOLD + (bonus>>3) + ((3*bonus*skill_power(sd, TMW_ASTRAL_SOUL))>>9);
+    }
+#endif
+    sd->matk2 = 0;
+    if (sd->matk1 < 0)
+        sd->matk1 = 0;
+
+    sd->hit += sd->paramc[4] + sd->status.base_level;
+    sd->flee += sd->paramc[1] + sd->status.base_level;
+    sd->def2 += sd->paramc[2];
+    sd->mdef2 += sd->paramc[3];
+    sd->flee2 += sd->paramc[5] + 10;
+    sd->critical += (sd->paramc[5] * 3) + 10;
+
+    // 200 is the maximum of the skill
+    // def2 is the defence gained by vit, whereas "def", which is gained by armor, stays as is
+    int spbsk = skill_power (sd, TMW_RAGING);
+    if (spbsk != 0 && sd->attackrange <= 2)
+    {
+        sd->critical += sd->critical * spbsk / 100;
+        sd->def2 = (sd->def2 * 256) / (256 + spbsk);
+    }
+
+    if (sd->base_atk < 1)
+        sd->base_atk = 1;
+    if (sd->critical_rate != 100)
+        sd->critical = (sd->critical * sd->critical_rate) / 100;
+    if (sd->critical < 10)
+        sd->critical = 10;
+    if (sd->hit_rate != 100)
+        sd->hit = (sd->hit * sd->hit_rate) / 100;
+    if (sd->hit < 1)
+        sd->hit = 1;
+    if (sd->flee_rate != 100)
+        sd->flee = (sd->flee * sd->flee_rate) / 100;
+    if (sd->flee < 1)
+        sd->flee = 1;
+    if (sd->flee2_rate != 100)
+        sd->flee2 = (sd->flee2 * sd->flee2_rate) / 100;
+    if (sd->flee2 < 10)
+        sd->flee2 = 10;
+    if (sd->def_rate != 100)
+        sd->def = (sd->def * sd->def_rate) / 100;
+    if (sd->def < 0)
+        sd->def = 0;
+    if (sd->def2_rate != 100)
+        sd->def2 = (sd->def2 * sd->def2_rate) / 100;
+    if (sd->def2 < 1)
+        sd->def2 = 1;
+    if (sd->mdef_rate != 100)
+        sd->mdef = (sd->mdef * sd->mdef_rate) / 100;
+    if (sd->mdef < 0)
+        sd->mdef = 0;
+    if (sd->mdef2_rate != 100)
+        sd->mdef2 = (sd->mdef2 * sd->mdef2_rate) / 100;
+    if (sd->mdef2 < 1)
+        sd->mdef2 = 1;
+
+    // 二刀流 ASPD 修正
+    if (sd->status.weapon <= 16)
+        sd->aspd +=
+            aspd_base[s_class.job][sd->status.weapon] - (sd->paramc[1] * 4 +
+                                                         sd->paramc[4]) *
+            aspd_base[s_class.job][sd->status.weapon] / 1000;
+    else
+        sd->aspd += ((aspd_base[s_class.job][sd->weapontype1] -
+                      (sd->paramc[1] * 4 +
+                       sd->paramc[4]) *
+                      aspd_base[s_class.job][sd->weapontype1] / 1000) +
+                     (aspd_base[s_class.job][sd->weapontype2] -
+                      (sd->paramc[1] * 4 +
+                       sd->paramc[4]) *
+                      aspd_base[s_class.job][sd->weapontype2] / 1000)) * 140 /
+            200;
+
+    aspd_rate = sd->aspd_rate;
+
+    //攻撃速度増加
+
+    if ((skill = pc_checkskill (sd, AC_VULTURE)) > 0)
+    {                           // ワシの目
+        sd->hit += skill;
+        if (sd->status.weapon == 11)
+            sd->attackrange += skill;
+    }
+
+    if (sd->attackrange > 2)
+    {                           // [fate] ranged weapon?
+        sd->attackrange += MIN (skill_power (sd, AC_OWL) / 60, 3);
+        sd->hit += skill_power (sd, AC_OWL) / 10;   // 20 for 200
+    }
+
+    if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0)    // 武器研究の命中率増加
+        sd->hit += skill * 2;
+    if (sd->status.option & 2 && (skill = pc_checkskill (sd, RG_TUNNELDRIVE)) > 0)  // トンネルドライブ
+        sd->speed += (1.2 * DEFAULT_WALK_SPEED - skill * 9);
+    if (pc_iscarton (sd) && (skill = pc_checkskill (sd, MC_PUSHCART)) > 0)  // カートによる速度低下
+        sd->speed += (10 - skill) * (DEFAULT_WALK_SPEED * 0.1);
+    else if (pc_isriding (sd))  // ペコペコ乗りによる速度増加
+        sd->speed -= (0.25 * DEFAULT_WALK_SPEED);
+    sd->max_weight += 1000;
+    if (sd->sc_count)
+    {
+        if (sd->sc_data[SC_WINDWALK].timer != -1)   //ウィンドウォーク時はLv*2%減算
+            sd->speed -=
+                sd->speed * (sd->sc_data[SC_WINDWALK].val1 * 2) / 100;
+        if (sd->sc_data[SC_CARTBOOST].timer != -1)  // カートブースト
+            sd->speed -= (DEFAULT_WALK_SPEED * 20) / 100;
+        if (sd->sc_data[SC_BERSERK].timer != -1)    //バーサーク中はIAと同じぐらい速い?
+            sd->speed -= sd->speed * 25 / 100;
+        if (sd->sc_data[SC_WEDDING].timer != -1)    //結婚中は歩くのが遅い
+            sd->speed = 2 * DEFAULT_WALK_SPEED;
+    }
+
+    if ((skill = pc_checkskill (sd, CR_TRUST)) > 0)
+    {                           // フェイス
+        sd->status.max_hp += skill * 200;
+        sd->subele[6] += skill * 5;
+    }
+    if ((skill = pc_checkskill (sd, BS_SKINTEMPER)) > 0)
+        sd->subele[3] += skill * 4;
+
+    bl = sd->status.base_level;
+
+    sd->status.max_hp +=
+        (3500 + bl * hp_coefficient2[s_class.job] +
+         hp_sigma_val[s_class.job][(bl > 0) ? bl - 1 : 0]) / 100 * (100 +
+                                                                    sd->paramc
+                                                                    [2]) /
+        100 + (sd->parame[2] - sd->paramcard[2]);
+    if (s_class.upper == 1)     // [MouseJstr]
+        sd->status.max_hp = sd->status.max_hp * 130 / 100;
+    if (sd->hprate != 100)
+        sd->status.max_hp = sd->status.max_hp * sd->hprate / 100;
+
+    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1)
+    {                           // バーサーク
+        sd->status.max_hp = sd->status.max_hp * 3;
+        sd->status.hp = sd->status.hp * 3;
+        if (sd->status.max_hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
+            sd->status.max_hp = battle_config.max_hp;
+        if (sd->status.hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
+            sd->status.hp = battle_config.max_hp;
+    }
+    if (s_class.job == 23 && sd->status.base_level >= 99)
+    {
+        sd->status.max_hp = sd->status.max_hp + 2000;
+    }
+
+    if (sd->status.max_hp > battle_config.max_hp)   // removed negative max hp bug by Valaris
+        sd->status.max_hp = battle_config.max_hp;
+    if (sd->status.max_hp <= 0)
+        sd->status.max_hp = 1;  // end
+
+    // 最大SP計算
+    sd->status.max_sp +=
+        ((sp_coefficient[s_class.job] * bl) + 1000) / 100 * (100 +
+                                                             sd->paramc[3]) /
+        100 + (sd->parame[3] - sd->paramcard[3]);
+    if (s_class.upper == 1)     // [MouseJstr]
+        sd->status.max_sp = sd->status.max_sp * 130 / 100;
+    if (sd->sprate != 100)
+        sd->status.max_sp = sd->status.max_sp * sd->sprate / 100;
+
+    if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ
+        sd->status.max_sp += sd->status.max_sp * skill / 100;
+    if ((skill = pc_checkskill (sd, HW_SOULDRAIN)) > 0) // ソウルドレイン
+        sd->status.max_sp += sd->status.max_sp * 2 * skill / 100;
+
+    if (sd->status.max_sp < 0 || sd->status.max_sp > battle_config.max_sp)
+        sd->status.max_sp = battle_config.max_sp;
+
+    //自然回復HP
+    sd->nhealhp = 1 + (sd->paramc[2] / 5) + (sd->status.max_hp / 200);
+    if ((skill = pc_checkskill (sd, SM_RECOVERY)) > 0)
+    {                           // HP回復力向上
+        sd->nshealhp = skill * 5 + (sd->status.max_hp * skill / 500);
+        if (sd->nshealhp > 0x7fff)
+            sd->nshealhp = 0x7fff;
+    }
+    //自然回復SP
+    sd->nhealsp = 1 + (sd->paramc[3] / 6) + (sd->status.max_sp / 100);
+    if (sd->paramc[3] >= 120)
+        sd->nhealsp += ((sd->paramc[3] - 120) >> 1) + 4;
+    if ((skill = pc_checkskill (sd, MG_SRECOVERY)) > 0)
+    {                           // SP回復力向上
+        sd->nshealsp = skill * 3 + (sd->status.max_sp * skill / 500);
+        if (sd->nshealsp > 0x7fff)
+            sd->nshealsp = 0x7fff;
+    }
+
+    if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0)
+    {
+        sd->nsshealhp = skill * 4 + (sd->status.max_hp * skill / 500);
+        sd->nsshealsp = skill * 2 + (sd->status.max_sp * skill / 500);
+        if (sd->nsshealhp > 0x7fff)
+            sd->nsshealhp = 0x7fff;
+        if (sd->nsshealsp > 0x7fff)
+            sd->nsshealsp = 0x7fff;
+    }
+    if (sd->hprecov_rate != 100)
+    {
+        sd->nhealhp = sd->nhealhp * sd->hprecov_rate / 100;
+        if (sd->nhealhp < 1)
+            sd->nhealhp = 1;
+    }
+    if (sd->sprecov_rate != 100)
+    {
+        sd->nhealsp = sd->nhealsp * sd->sprecov_rate / 100;
+        if (sd->nhealsp < 1)
+            sd->nhealsp = 1;
+    }
+    if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0)
+    {                           // メディテイティオはSPRではなく自然回復にかかる
+        sd->nhealsp += 3 * skill * (sd->status.max_sp) / 100;
+        if (sd->nhealsp > 0x7fff)
+            sd->nhealsp = 0x7fff;
+    }
+
+    // 種族耐性(これでいいの? ディバインプロテクションと同じ処理がいるかも)
+    if ((skill = pc_checkskill (sd, SA_DRAGONOLOGY)) > 0)
+    {                           // ドラゴノロジー
+        skill = skill * 4;
+        sd->addrace[9] += skill;
+        sd->addrace_[9] += skill;
+        sd->subrace[9] += skill;
+        sd->magic_addrace[9] += skill;
+        sd->magic_subrace[9] -= skill;
+    }
+
+    //Flee上昇
+    if ((skill = pc_checkskill (sd, TF_MISS)) > 0)
+    {                           // 回避率増加
+        if (sd->status.pc_class == 6 || sd->status.pc_class == 4007
+            || sd->status.pc_class == 23)
+        {
+            sd->flee += skill * 3;
+        }
+        if (sd->status.pc_class == 12 || sd->status.pc_class == 17
+            || sd->status.pc_class == 4013 || sd->status.pc_class == 4018)
+            sd->flee += skill * 4;
+        if (sd->status.pc_class == 12 || sd->status.pc_class == 4013)
+            sd->speed -= sd->speed * (skill * .5) / 100;
+    }
+    if ((skill = pc_checkskill (sd, MO_DODGE)) > 0) // 見切り
+        sd->flee += (skill * 3) >> 1;
+
+    // スキルやステータス異常による残りのパラメータ補正
+    if (sd->sc_count)
+    {
+        // ATK/DEF変化形
+        if (sd->sc_data[SC_ANGELUS].timer != -1)    // エンジェラス
+            sd->def2 =
+                sd->def2 * (110 + 5 * sd->sc_data[SC_ANGELUS].val1) / 100;
+        if (sd->sc_data[SC_IMPOSITIO].timer != -1)
+        {                       // インポシティオマヌス
+            sd->watk += sd->sc_data[SC_IMPOSITIO].val1 * 5;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 4)
+                sd->watk_ += sd->sc_data[SC_IMPOSITIO].val1 * 5;
+        }
+        if (sd->sc_data[SC_PROVOKE].timer != -1)
+        {                       // プロボック
+            sd->def2 =
+                sd->def2 * (100 - 6 * sd->sc_data[SC_PROVOKE].val1) / 100;
+            sd->base_atk =
+                sd->base_atk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
+            sd->watk =
+                sd->watk * (100 + 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 4)
+                sd->watk_ =
+                    sd->watk_ * (100 +
+                                 2 * sd->sc_data[SC_PROVOKE].val1) / 100;
+        }
+        if (sd->sc_data[SC_ENDURE].timer != -1)
+            sd->mdef2 += sd->sc_data[SC_ENDURE].val1;
+        if (sd->sc_data[SC_MINDBREAKER].timer != -1)
+        {                       // プロボック
+            sd->mdef2 =
+                sd->mdef2 * (100 -
+                             6 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
+            sd->matk1 =
+                sd->matk1 * (100 +
+                             2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
+            sd->matk2 =
+                sd->matk2 * (100 +
+                             2 * sd->sc_data[SC_MINDBREAKER].val1) / 100;
+        }
+        if (sd->sc_data[SC_POISON].timer != -1) // 毒状態
+            sd->def2 = sd->def2 * 75 / 100;
+        if (sd->sc_data[SC_DRUMBATTLE].timer != -1)
+        {                       // 戦太鼓の響き
+            sd->watk += sd->sc_data[SC_DRUMBATTLE].val2;
+            sd->def += sd->sc_data[SC_DRUMBATTLE].val3;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 4)
+                sd->watk_ += sd->sc_data[SC_DRUMBATTLE].val2;
+        }
+        if (sd->sc_data[SC_NIBELUNGEN].timer != -1)
+        {                       // ニーベルングの指輪
+            index = sd->equip_index[9];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->wlv == 3)
+                sd->watk += sd->sc_data[SC_NIBELUNGEN].val3;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->wlv == 3)
+                sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val3;
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->wlv == 4)
+                sd->watk += sd->sc_data[SC_NIBELUNGEN].val2;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->wlv == 4)
+                sd->watk_ += sd->sc_data[SC_NIBELUNGEN].val2;
+        }
+
+        if (sd->sc_data[SC_VOLCANO].timer != -1 && sd->def_ele == 3)
+        {                       // ボルケーノ
+            sd->watk += sd->sc_data[SC_VIOLENTGALE].val3;
+        }
+
+        if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1)
+            sd->def =
+                sd->def * (100 - sd->sc_data[SC_SIGNUMCRUCIS].val2) / 100;
+        if (sd->sc_data[SC_ETERNALCHAOS].timer != -1)   // エターナルカオス
+            sd->def = 0;
+
+        if (sd->sc_data[SC_CONCENTRATION].timer != -1)
+        {                       //コンセントレーション
+            sd->watk =
+                sd->watk * (100 +
+                            5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
+            index = sd->equip_index[8];
+            if (index >= 0 && sd->inventory_data[index]
+                && sd->inventory_data[index]->type == 4)
+                sd->watk_ =
+                    sd->watk * (100 +
+                                5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
+            sd->def =
+                sd->def * (100 -
+                           5 * sd->sc_data[SC_CONCENTRATION].val1) / 100;
+        }
+
+        if (sd->sc_data[SC_MAGICPOWER].timer != -1)
+        {                       //魔法力増幅
+            sd->matk1 =
+                sd->matk1 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
+            sd->matk2 =
+                sd->matk2 * (100 + 2 * sd->sc_data[SC_MAGICPOWER].val1) / 100;
+        }
+        if (sd->sc_data[SC_ATKPOT].timer != -1)
+            sd->watk += sd->sc_data[SC_ATKPOT].val1;
+        if (sd->sc_data[SC_MATKPOT].timer != -1)
+        {
+            sd->matk1 += sd->sc_data[SC_MATKPOT].val1;
+            sd->matk2 += sd->sc_data[SC_MATKPOT].val1;
+        }
+
+        // ASPD/移動速度変化系
+        if (sd->sc_data[SC_TWOHANDQUICKEN].timer != -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
+            aspd_rate -= 30;
+        if (sd->sc_data[SC_ADRENALINE].timer != -1
+            && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
+            && sd->sc_data[SC_QUAGMIRE].timer == -1
+            && sd->sc_data[SC_DONTFORGETME].timer == -1)
+        {                       // アドレナリンラッシュ
+            if (sd->sc_data[SC_ADRENALINE].val2
+                || !battle_config.party_skill_penaly)
+                aspd_rate -= 30;
+            else
+                aspd_rate -= 25;
+        }
+        if (sd->sc_data[SC_SPEARSQUICKEN].timer != -1 && sd->sc_data[SC_ADRENALINE].timer == -1 && sd->sc_data[SC_TWOHANDQUICKEN].timer == -1 && sd->sc_data[SC_QUAGMIRE].timer == -1 && sd->sc_data[SC_DONTFORGETME].timer == -1)  // スピアクィッケン
+            aspd_rate -= sd->sc_data[SC_SPEARSQUICKEN].val2;
+        if (sd->sc_data[SC_ASSNCROS].timer != -1 && // 夕陽のアサシンクロス
+            sd->sc_data[SC_TWOHANDQUICKEN].timer == -1
+            && sd->sc_data[SC_ADRENALINE].timer == -1
+            && sd->sc_data[SC_SPEARSQUICKEN].timer == -1
+            && sd->sc_data[SC_DONTFORGETME].timer == -1)
+            aspd_rate -=
+                5 + sd->sc_data[SC_ASSNCROS].val1 +
+                sd->sc_data[SC_ASSNCROS].val2 + sd->sc_data[SC_ASSNCROS].val3;
+        if (sd->sc_data[SC_DONTFORGETME].timer != -1)
+        {                       // 私を忘れないで
+            aspd_rate +=
+                sd->sc_data[SC_DONTFORGETME].val1 * 3 +
+                sd->sc_data[SC_DONTFORGETME].val2 +
+                (sd->sc_data[SC_DONTFORGETME].val3 >> 16);
+            sd->speed =
+                sd->speed * (100 + sd->sc_data[SC_DONTFORGETME].val1 * 2 +
+                             sd->sc_data[SC_DONTFORGETME].val2 +
+                             (sd->sc_data[SC_DONTFORGETME].val3 & 0xffff)) /
+                100;
+        }
+        if (sd->sc_data[i = SC_SPEEDPOTION2].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION1].timer != -1 || sd->sc_data[i = SC_SPEEDPOTION0].timer != -1)   // 増 速ポーション
+            aspd_rate -= sd->sc_data[i].val1;
+
+        if (sd->sc_data[SC_HASTE].timer != -1)
+            aspd_rate -= sd->sc_data[SC_HASTE].val1;
+
+        /* Slow down if protected */
+
+        if (sd->sc_data[SC_PHYS_SHIELD].timer != -1)
+            aspd_rate += sd->sc_data[SC_PHYS_SHIELD].val1;
+
+        // HIT/FLEE変化系
+        if (sd->sc_data[SC_WHISTLE].timer != -1)
+        {                       // 口笛
+            sd->flee += sd->flee * (sd->sc_data[SC_WHISTLE].val1
+                                    + sd->sc_data[SC_WHISTLE].val2 +
+                                    (sd->sc_data[SC_WHISTLE].val3 >> 16)) /
+                100;
+            sd->flee2 +=
+                (sd->sc_data[SC_WHISTLE].val1 + sd->sc_data[SC_WHISTLE].val2 +
+                 (sd->sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;
+        }
+        if (sd->sc_data[SC_HUMMING].timer != -1)    // ハミング
+            sd->hit +=
+                (sd->sc_data[SC_HUMMING].val1 * 2 +
+                 sd->sc_data[SC_HUMMING].val2 +
+                 sd->sc_data[SC_HUMMING].val3) * sd->hit / 100;
+        if (sd->sc_data[SC_VIOLENTGALE].timer != -1 && sd->def_ele == 4)
+        {                       // バイオレントゲイル
+            sd->flee += sd->flee * sd->sc_data[SC_VIOLENTGALE].val3 / 100;
+        }
+        if (sd->sc_data[SC_BLIND].timer != -1)
+        {                       // 暗黒
+            sd->hit -= sd->hit * 25 / 100;
+            sd->flee -= sd->flee * 25 / 100;
+        }
+        if (sd->sc_data[SC_WINDWALK].timer != -1)   // ウィンドウォーク
+            sd->flee += sd->flee * (sd->sc_data[SC_WINDWALK].val2) / 100;
+        if (sd->sc_data[SC_SPIDERWEB].timer != -1)  //スパイダーウェブ
+            sd->flee -= sd->flee * 50 / 100;
+        if (sd->sc_data[SC_TRUESIGHT].timer != -1)  //トゥルーサイト
+            sd->hit += 3 * (sd->sc_data[SC_TRUESIGHT].val1);
+        if (sd->sc_data[SC_CONCENTRATION].timer != -1)  //コンセントレーション
+            sd->hit += (10 * (sd->sc_data[SC_CONCENTRATION].val1));
+
+        // 耐性
+        if (sd->sc_data[SC_SIEGFRIED].timer != -1)
+        {                       // 不死身のジークフリード
+            sd->subele[1] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[2] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[3] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[4] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[5] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[6] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[7] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[8] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+            sd->subele[9] += sd->sc_data[SC_SIEGFRIED].val2;    // 水
+        }
+        if (sd->sc_data[SC_PROVIDENCE].timer != -1)
+        {                       // プロヴィデンス
+            sd->subele[6] += sd->sc_data[SC_PROVIDENCE].val2;   // 対 聖属性
+            sd->subrace[6] += sd->sc_data[SC_PROVIDENCE].val2;  // 対 悪魔
+        }
+
+        // その他
+        if (sd->sc_data[SC_APPLEIDUN].timer != -1)
+        {                       // イドゥンの林檎
+            sd->status.max_hp +=
+                ((5 + sd->sc_data[SC_APPLEIDUN].val1 * 2 +
+                  ((sd->sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
+                  sd->sc_data[SC_APPLEIDUN].val3 / 10) * sd->status.max_hp) /
+                100;
+            if (sd->status.max_hp < 0
+                || sd->status.max_hp > battle_config.max_hp)
+                sd->status.max_hp = battle_config.max_hp;
+        }
+        if (sd->sc_data[SC_DELUGE].timer != -1 && sd->def_ele == 1)
+        {                       // デリュージ
+            sd->status.max_hp +=
+                sd->status.max_hp * sd->sc_data[SC_DELUGE].val3 / 100;
+            if (sd->status.max_hp < 0
+                || sd->status.max_hp > battle_config.max_hp)
+                sd->status.max_hp = battle_config.max_hp;
+        }
+        if (sd->sc_data[SC_SERVICE4U].timer != -1)
+        {                       // サービスフォーユー
+            sd->status.max_sp +=
+                sd->status.max_sp * (10 + sd->sc_data[SC_SERVICE4U].val1 +
+                                     sd->sc_data[SC_SERVICE4U].val2 +
+                                     sd->sc_data[SC_SERVICE4U].val3) / 100;
+            if (sd->status.max_sp < 0
+                || sd->status.max_sp > battle_config.max_sp)
+                sd->status.max_sp = battle_config.max_sp;
+            sd->dsprate -=
+                (10 + sd->sc_data[SC_SERVICE4U].val1 * 3 +
+                 sd->sc_data[SC_SERVICE4U].val2 +
+                 sd->sc_data[SC_SERVICE4U].val3);
+            if (sd->dsprate < 0)
+                sd->dsprate = 0;
+        }
+
+        if (sd->sc_data[SC_FORTUNE].timer != -1)    // 幸運のキス
+            sd->critical +=
+                (10 + sd->sc_data[SC_FORTUNE].val1 +
+                 sd->sc_data[SC_FORTUNE].val2 +
+                 sd->sc_data[SC_FORTUNE].val3) * 10;
+
+        if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
+        {                       // 爆裂波動
+            if (s_class.job == 23)
+                sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val1 * 100;
+            else
+                sd->critical += sd->sc_data[SC_EXPLOSIONSPIRITS].val2;
+        }
+
+        if (sd->sc_data[SC_STEELBODY].timer != -1)
+        {                       // 金剛
+            sd->def = 90;
+            sd->mdef = 90;
+            aspd_rate += 25;
+            sd->speed = (sd->speed * 125) / 100;
+        }
+        if (sd->sc_data[SC_DEFENDER].timer != -1)
+        {
+            sd->aspd += (550 - sd->sc_data[SC_DEFENDER].val1 * 50);
+            sd->speed =
+                (sd->speed * (155 - sd->sc_data[SC_DEFENDER].val1 * 5)) / 100;
+        }
+        if (sd->sc_data[SC_ENCPOISON].timer != -1)
+            sd->addeff[4] += sd->sc_data[SC_ENCPOISON].val2;
+
+        if (sd->sc_data[SC_DANCING].timer != -1)
+        {                       // 演奏/ダンス使用中
+            sd->speed *= 4;
+            sd->nhealsp = 0;
+            sd->nshealsp = 0;
+            sd->nsshealsp = 0;
+        }
+        if (sd->sc_data[SC_CURSE].timer != -1)
+            sd->speed += 450;
+
+        if (sd->sc_data[SC_TRUESIGHT].timer != -1)  //トゥルーサイト
+            sd->critical +=
+                sd->critical * (sd->sc_data[SC_TRUESIGHT].val1) / 100;
+
+/*		if(sd->sc_data[SC_VOLCANO].timer!=-1)	// エンチャントポイズン(属性はbattle.cで)
+			sd->addeff[2]+=sd->sc_data[SC_VOLCANO].val2;//% of granting
+		if(sd->sc_data[SC_DELUGE].timer!=-1)	// エンチャントポイズン(属性はbattle.cで)
+			sd->addeff[0]+=sd->sc_data[SC_DELUGE].val2;//% of granting
+		*/
+    }
+
+    if (sd->speed_rate != 100)
+        sd->speed = sd->speed * sd->speed_rate / 100;
+    if (sd->speed < 1)
+        sd->speed = 1;
+    if (aspd_rate != 100)
+        sd->aspd = sd->aspd * aspd_rate / 100;
+    if (pc_isriding (sd))       // 騎兵修練
+        sd->aspd =
+            sd->aspd * (100 +
+                        10 * (5 -
+                              pc_checkskill (sd, KN_CAVALIERMASTERY))) / 100;
+
+    if (sd->attack_spell_override)
+        sd->aspd = sd->attack_spell_delay;
+
+    if (sd->aspd < battle_config.max_aspd)
+        sd->aspd = battle_config.max_aspd;
+    sd->amotion = sd->aspd;
+    sd->dmotion = 800 - sd->paramc[1] * 4;
+    if (sd->dmotion < 400)
+        sd->dmotion = 400;
+    if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)
+    {
+        sd->prev_speed = sd->speed;
+        sd->speed = sd->speed * (175 - skill * 5) / 100;
+    }
+
+    if (sd->status.hp > sd->status.max_hp)
+        sd->status.hp = sd->status.max_hp;
+    if (sd->status.sp > sd->status.max_sp)
+        sd->status.sp = sd->status.max_sp;
+
+    if (first & 4)
+        return 0;
+    if (first & 3)
+    {
+        clif_updatestatus (sd, SP_SPEED);
+        clif_updatestatus (sd, SP_MAXHP);
+        clif_updatestatus (sd, SP_MAXSP);
+        if (first & 1)
+        {
+            clif_updatestatus (sd, SP_HP);
+            clif_updatestatus (sd, SP_SP);
+        }
+        return 0;
+    }
+
+    if (b_class != sd->view_class)
+    {
+        clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);
+        clif_changelook (&sd->bl, LOOK_WEAPON, 0);
+    }
+
+    if (memcmp (b_skill, sd->status.skill, sizeof (sd->status.skill))
+        || b_attackrange != sd->attackrange)
+        clif_skillinfoblock (sd);   // スキル送信
+
+    if (b_speed != sd->speed)
+        clif_updatestatus (sd, SP_SPEED);
+    if (b_weight != sd->weight)
+        clif_updatestatus (sd, SP_WEIGHT);
+    if (b_max_weight != sd->max_weight)
+    {
+        clif_updatestatus (sd, SP_MAXWEIGHT);
+        pc_checkweighticon (sd);
+    }
+    for (i = 0; i < 6; i++)
+        if (b_paramb[i] + b_parame[i] != sd->paramb[i] + sd->parame[i])
+            clif_updatestatus (sd, SP_STR + i);
+    if (b_hit != sd->hit)
+        clif_updatestatus (sd, SP_HIT);
+    if (b_flee != sd->flee)
+        clif_updatestatus (sd, SP_FLEE1);
+    if (b_aspd != sd->aspd)
+        clif_updatestatus (sd, SP_ASPD);
+    if (b_watk != sd->watk || b_base_atk != sd->base_atk)
+        clif_updatestatus (sd, SP_ATK1);
+    if (b_def != sd->def)
+        clif_updatestatus (sd, SP_DEF1);
+    if (b_watk2 != sd->watk2)
+        clif_updatestatus (sd, SP_ATK2);
+    if (b_def2 != sd->def2)
+        clif_updatestatus (sd, SP_DEF2);
+    if (b_flee2 != sd->flee2)
+        clif_updatestatus (sd, SP_FLEE2);
+    if (b_critical != sd->critical)
+        clif_updatestatus (sd, SP_CRITICAL);
+    if (b_matk1 != sd->matk1)
+        clif_updatestatus (sd, SP_MATK1);
+    if (b_matk2 != sd->matk2)
+        clif_updatestatus (sd, SP_MATK2);
+    if (b_mdef != sd->mdef)
+        clif_updatestatus (sd, SP_MDEF1);
+    if (b_mdef2 != sd->mdef2)
+        clif_updatestatus (sd, SP_MDEF2);
+    if (b_attackrange != sd->attackrange)
+        clif_updatestatus (sd, SP_ATTACKRANGE);
+    if (b_max_hp != sd->status.max_hp)
+        clif_updatestatus (sd, SP_MAXHP);
+    if (b_max_sp != sd->status.max_sp)
+        clif_updatestatus (sd, SP_MAXSP);
+    if (b_hp != sd->status.hp)
+        clif_updatestatus (sd, SP_HP);
+    if (b_sp != sd->status.sp)
+        clif_updatestatus (sd, SP_SP);
+
+/*	if(before.cart_num != before.cart_num || before.cart_max_num != before.cart_max_num ||
+		before.cart_weight != before.cart_weight || before.cart_max_weight != before.cart_max_weight )
+		clif_updatestatus(sd,SP_CARTINFO);*/
+
+    if (sd->status.hp < sd->status.max_hp >> 2
+        && pc_checkskill (sd, SM_AUTOBERSERK) > 0
+        && (sd->sc_data[SC_PROVOKE].timer == -1
+            || sd->sc_data[SC_PROVOKE].val2 == 0) && !pc_isdead (sd))
+        // オートバーサーク発動
+        skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 装 備品による能力等のボーナス設定
+ *------------------------------------------
+ */
+int pc_bonus (struct map_session_data *sd, int type, int val)
+{
+    nullpo_retr (0, sd);
+
+    switch (type)
+    {
+        case SP_STR:
+        case SP_AGI:
+        case SP_VIT:
+        case SP_INT:
+        case SP_DEX:
+        case SP_LUK:
+            if (sd->state.lr_flag != 2)
+                sd->parame[type - SP_STR] += val;
+            break;
+        case SP_ATK1:
+            if (!sd->state.lr_flag)
+                sd->watk += val;
+            else if (sd->state.lr_flag == 1)
+                sd->watk_ += val;
+            break;
+        case SP_ATK2:
+            if (!sd->state.lr_flag)
+                sd->watk2 += val;
+            else if (sd->state.lr_flag == 1)
+                sd->watk_2 += val;
+            break;
+        case SP_BASE_ATK:
+            if (sd->state.lr_flag != 2)
+                sd->base_atk += val;
+            break;
+        case SP_MATK1:
+            if (sd->state.lr_flag != 2)
+                sd->matk1 += val;
+            break;
+        case SP_MATK2:
+            if (sd->state.lr_flag != 2)
+                sd->matk2 += val;
+            break;
+        case SP_MATK:
+            if (sd->state.lr_flag != 2)
+            {
+                sd->matk1 += val;
+                sd->matk2 += val;
+            }
+            break;
+        case SP_DEF1:
+            if (sd->state.lr_flag != 2)
+                sd->def += val;
+            break;
+        case SP_MDEF1:
+            if (sd->state.lr_flag != 2)
+                sd->mdef += val;
+            break;
+        case SP_MDEF2:
+            if (sd->state.lr_flag != 2)
+                sd->mdef += val;
+            break;
+        case SP_HIT:
+            if (sd->state.lr_flag != 2)
+                sd->hit += val;
+            else
+                sd->arrow_hit += val;
+            break;
+        case SP_FLEE1:
+            if (sd->state.lr_flag != 2)
+                sd->flee += val;
+            break;
+        case SP_FLEE2:
+            if (sd->state.lr_flag != 2)
+                sd->flee2 += val * 10;
+            break;
+        case SP_CRITICAL:
+            if (sd->state.lr_flag != 2)
+                sd->critical += val * 10;
+            else
+                sd->arrow_cri += val * 10;
+            break;
+        case SP_ATKELE:
+            if (!sd->state.lr_flag)
+                sd->atk_ele = val;
+            else if (sd->state.lr_flag == 1)
+                sd->atk_ele_ = val;
+            else if (sd->state.lr_flag == 2)
+                sd->arrow_ele = val;
+            break;
+        case SP_DEFELE:
+            if (sd->state.lr_flag != 2)
+                sd->def_ele = val;
+            break;
+        case SP_MAXHP:
+            if (sd->state.lr_flag != 2)
+                sd->status.max_hp += val;
+            break;
+        case SP_MAXSP:
+            if (sd->state.lr_flag != 2)
+                sd->status.max_sp += val;
+            break;
+        case SP_CASTRATE:
+            if (sd->state.lr_flag != 2)
+                sd->castrate += val;
+            break;
+        case SP_MAXHPRATE:
+            if (sd->state.lr_flag != 2)
+                sd->hprate += val;
+            break;
+        case SP_MAXSPRATE:
+            if (sd->state.lr_flag != 2)
+                sd->sprate += val;
+            break;
+        case SP_SPRATE:
+            if (sd->state.lr_flag != 2)
+                sd->dsprate += val;
+            break;
+        case SP_ATTACKRANGE:
+            if (!sd->state.lr_flag)
+                sd->attackrange += val;
+            else if (sd->state.lr_flag == 1)
+                sd->attackrange_ += val;
+            else if (sd->state.lr_flag == 2)
+                sd->arrow_range += val;
+            break;
+        case SP_ADD_SPEED:
+            if (sd->state.lr_flag != 2)
+                sd->speed -= val;
+            break;
+        case SP_SPEED_RATE:
+            if (sd->state.lr_flag != 2)
+            {
+                if (sd->speed_rate > 100 - val)
+                    sd->speed_rate = 100 - val;
+            }
+            break;
+        case SP_SPEED_ADDRATE:
+            if (sd->state.lr_flag != 2)
+                sd->speed_add_rate = sd->speed_add_rate * (100 - val) / 100;
+            break;
+        case SP_ASPD:
+            if (sd->state.lr_flag != 2)
+                sd->aspd -= val * 10;
+            break;
+        case SP_ASPD_RATE:
+            if (sd->state.lr_flag != 2)
+            {
+                if (sd->aspd_rate > 100 - val)
+                    sd->aspd_rate = 100 - val;
+            }
+            break;
+        case SP_ASPD_ADDRATE:
+            if (sd->state.lr_flag != 2)
+                sd->aspd_add_rate = sd->aspd_add_rate * (100 - val) / 100;
+            break;
+        case SP_HP_RECOV_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->hprecov_rate += val;
+            break;
+        case SP_SP_RECOV_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->sprecov_rate += val;
+            break;
+        case SP_CRITICAL_DEF:
+            if (sd->state.lr_flag != 2)
+                sd->critical_def += val;
+            break;
+        case SP_NEAR_ATK_DEF:
+            if (sd->state.lr_flag != 2)
+                sd->near_attack_def_rate += val;
+            break;
+        case SP_LONG_ATK_DEF:
+            if (sd->state.lr_flag != 2)
+                sd->long_attack_def_rate += val;
+            break;
+        case SP_DOUBLE_RATE:
+            if (sd->state.lr_flag == 0 && sd->double_rate < val)
+                sd->double_rate = val;
+            break;
+        case SP_DOUBLE_ADD_RATE:
+            if (sd->state.lr_flag == 0)
+                sd->double_add_rate += val;
+            break;
+        case SP_MATK_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->matk_rate += val;
+            break;
+        case SP_IGNORE_DEF_ELE:
+            if (!sd->state.lr_flag)
+                sd->ignore_def_ele |= 1 << val;
+            else if (sd->state.lr_flag == 1)
+                sd->ignore_def_ele_ |= 1 << val;
+            break;
+        case SP_IGNORE_DEF_RACE:
+            if (!sd->state.lr_flag)
+                sd->ignore_def_race |= 1 << val;
+            else if (sd->state.lr_flag == 1)
+                sd->ignore_def_race_ |= 1 << val;
+            break;
+        case SP_ATK_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->atk_rate += val;
+            break;
+        case SP_MAGIC_ATK_DEF:
+            if (sd->state.lr_flag != 2)
+                sd->magic_def_rate += val;
+            break;
+        case SP_MISC_ATK_DEF:
+            if (sd->state.lr_flag != 2)
+                sd->misc_def_rate += val;
+            break;
+        case SP_IGNORE_MDEF_ELE:
+            if (sd->state.lr_flag != 2)
+                sd->ignore_mdef_ele |= 1 << val;
+            break;
+        case SP_IGNORE_MDEF_RACE:
+            if (sd->state.lr_flag != 2)
+                sd->ignore_mdef_race |= 1 << val;
+            break;
+        case SP_PERFECT_HIT_RATE:
+            if (sd->state.lr_flag != 2 && sd->perfect_hit < val)
+                sd->perfect_hit = val;
+            break;
+        case SP_PERFECT_HIT_ADD_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->perfect_hit_add += val;
+            break;
+        case SP_CRITICAL_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->critical_rate += val;
+            break;
+        case SP_GET_ZENY_NUM:
+            if (sd->state.lr_flag != 2 && sd->get_zeny_num < val)
+                sd->get_zeny_num = val;
+            break;
+        case SP_ADD_GET_ZENY_NUM:
+            if (sd->state.lr_flag != 2)
+                sd->get_zeny_add_num += val;
+            break;
+        case SP_DEF_RATIO_ATK_ELE:
+            if (!sd->state.lr_flag)
+                sd->def_ratio_atk_ele |= 1 << val;
+            else if (sd->state.lr_flag == 1)
+                sd->def_ratio_atk_ele_ |= 1 << val;
+            break;
+        case SP_DEF_RATIO_ATK_RACE:
+            if (!sd->state.lr_flag)
+                sd->def_ratio_atk_race |= 1 << val;
+            else if (sd->state.lr_flag == 1)
+                sd->def_ratio_atk_race_ |= 1 << val;
+            break;
+        case SP_HIT_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->hit_rate += val;
+            break;
+        case SP_FLEE_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->flee_rate += val;
+            break;
+        case SP_FLEE2_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->flee2_rate += val;
+            break;
+        case SP_DEF_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->def_rate += val;
+            break;
+        case SP_DEF2_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->def2_rate += val;
+            break;
+        case SP_MDEF_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->mdef_rate += val;
+            break;
+        case SP_MDEF2_RATE:
+            if (sd->state.lr_flag != 2)
+                sd->mdef2_rate += val;
+            break;
+        case SP_RESTART_FULL_RECORVER:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.restart_full_recover = 1;
+            break;
+        case SP_NO_CASTCANCEL:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_castcancel = 1;
+            break;
+        case SP_NO_CASTCANCEL2:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_castcancel2 = 1;
+            break;
+        case SP_NO_SIZEFIX:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_sizefix = 1;
+            break;
+        case SP_NO_MAGIC_DAMAGE:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_magic_damage = 1;
+            break;
+        case SP_NO_WEAPON_DAMAGE:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_weapon_damage = 1;
+            break;
+        case SP_NO_GEMSTONE:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.no_gemstone = 1;
+            break;
+        case SP_INFINITE_ENDURE:
+            if (sd->state.lr_flag != 2)
+                sd->special_state.infinite_endure = 1;
+            break;
+        case SP_SPLASH_RANGE:
+            if (sd->state.lr_flag != 2 && sd->splash_range < val)
+                sd->splash_range = val;
+            break;
+        case SP_SPLASH_ADD_RANGE:
+            if (sd->state.lr_flag != 2)
+                sd->splash_add_range += val;
+            break;
+        case SP_SHORT_WEAPON_DAMAGE_RETURN:
+            if (sd->state.lr_flag != 2)
+                sd->short_weapon_damage_return += val;
+            break;
+        case SP_LONG_WEAPON_DAMAGE_RETURN:
+            if (sd->state.lr_flag != 2)
+                sd->long_weapon_damage_return += val;
+            break;
+        case SP_MAGIC_DAMAGE_RETURN:   //AppleGirl Was Here
+            if (sd->state.lr_flag != 2)
+                sd->magic_damage_return += val;
+            break;
+        case SP_ALL_STATS:     // [Valaris]
+            if (sd->state.lr_flag != 2)
+            {
+                sd->parame[SP_STR - SP_STR] += val;
+                sd->parame[SP_AGI - SP_STR] += val;
+                sd->parame[SP_VIT - SP_STR] += val;
+                sd->parame[SP_INT - SP_STR] += val;
+                sd->parame[SP_DEX - SP_STR] += val;
+                sd->parame[SP_LUK - SP_STR] += val;
+                clif_updatestatus (sd, 13);
+                clif_updatestatus (sd, 14);
+                clif_updatestatus (sd, 15);
+                clif_updatestatus (sd, 16);
+                clif_updatestatus (sd, 17);
+                clif_updatestatus (sd, 18);
+            }
+            break;
+        case SP_AGI_VIT:       // [Valaris]
+            if (sd->state.lr_flag != 2)
+            {
+                sd->parame[SP_AGI - SP_STR] += val;
+                sd->parame[SP_VIT - SP_STR] += val;
+                clif_updatestatus (sd, 14);
+                clif_updatestatus (sd, 15);
+            }
+            break;
+        case SP_AGI_DEX_STR:   // [Valaris]
+            if (sd->state.lr_flag != 2)
+            {
+                sd->parame[SP_AGI - SP_STR] += val;
+                sd->parame[SP_DEX - SP_STR] += val;
+                sd->parame[SP_STR - SP_STR] += val;
+                clif_updatestatus (sd, 14);
+                clif_updatestatus (sd, 17);
+                clif_updatestatus (sd, 13);
+            }
+            break;
+        case SP_PERFECT_HIDE:  // [Valaris]
+            if (sd->state.lr_flag != 2)
+            {
+                sd->perfect_hiding = 1;
+            }
+            break;
+        case SP_DISGUISE:      // Disguise script for items [Valaris]
+            if (sd->state.lr_flag != 2 && sd->disguiseflag == 0)
+            {
+                if (pc_isriding (sd))
+                {               // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+                    clif_displaymessage (sd->fd,
+                                         "Cannot wear disguise when riding a Peco.");
+                    break;
+                }
+                sd->disguise = val;
+                clif_clearchar (&sd->bl, 9);
+                pc_setpos (sd, sd->mapname, sd->bl.x, sd->bl.y, 3);
+            }
+            break;
+        case SP_UNBREAKABLE:
+            if (sd->state.lr_flag != 2)
+            {
+                sd->unbreakable += val;
+            }
+            break;
+        case SP_DEAF:
+            sd->special_state.deaf = 1;
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("pc_bonus: unknown type %d %d !\n", type, val);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * ソスソス ソスソスソスiソスノゑソスソスソスソス\ソスヘ難ソスソスフボソス[ソスiソスXソスン抵ソス
+ *------------------------------------------
+ */
+int pc_bonus2 (struct map_session_data *sd, int type, int type2, int val)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    switch (type)
+    {
+        case SP_ADDELE:
+            if (!sd->state.lr_flag)
+                sd->addele[type2] += val;
+            else if (sd->state.lr_flag == 1)
+                sd->addele_[type2] += val;
+            else if (sd->state.lr_flag == 2)
+                sd->arrow_addele[type2] += val;
+            break;
+        case SP_ADDRACE:
+            if (!sd->state.lr_flag)
+                sd->addrace[type2] += val;
+            else if (sd->state.lr_flag == 1)
+                sd->addrace_[type2] += val;
+            else if (sd->state.lr_flag == 2)
+                sd->arrow_addrace[type2] += val;
+            break;
+        case SP_ADDSIZE:
+            if (!sd->state.lr_flag)
+                sd->addsize[type2] += val;
+            else if (sd->state.lr_flag == 1)
+                sd->addsize_[type2] += val;
+            else if (sd->state.lr_flag == 2)
+                sd->arrow_addsize[type2] += val;
+            break;
+        case SP_SUBELE:
+            if (sd->state.lr_flag != 2)
+                sd->subele[type2] += val;
+            break;
+        case SP_SUBRACE:
+            if (sd->state.lr_flag != 2)
+                sd->subrace[type2] += val;
+            break;
+        case SP_ADDEFF:
+            if (sd->state.lr_flag != 2)
+                sd->addeff[type2] += val;
+            else
+                sd->arrow_addeff[type2] += val;
+            break;
+        case SP_ADDEFF2:
+            if (sd->state.lr_flag != 2)
+                sd->addeff2[type2] += val;
+            else
+                sd->arrow_addeff2[type2] += val;
+            break;
+        case SP_RESEFF:
+            if (sd->state.lr_flag != 2)
+                sd->reseff[type2] += val;
+            break;
+        case SP_MAGIC_ADDELE:
+            if (sd->state.lr_flag != 2)
+                sd->magic_addele[type2] += val;
+            break;
+        case SP_MAGIC_ADDRACE:
+            if (sd->state.lr_flag != 2)
+                sd->magic_addrace[type2] += val;
+            break;
+        case SP_MAGIC_SUBRACE:
+            if (sd->state.lr_flag != 2)
+                sd->magic_subrace[type2] += val;
+            break;
+        case SP_ADD_DAMAGE_CLASS:
+            if (!sd->state.lr_flag)
+            {
+                for (i = 0; i < sd->add_damage_class_count; i++)
+                {
+                    if (sd->add_damage_classid[i] == type2)
+                    {
+                        sd->add_damage_classrate[i] += val;
+                        break;
+                    }
+                }
+                if (i >= sd->add_damage_class_count
+                    && sd->add_damage_class_count < 10)
+                {
+                    sd->add_damage_classid[sd->add_damage_class_count] =
+                        type2;
+                    sd->add_damage_classrate[sd->add_damage_class_count] +=
+                        val;
+                    sd->add_damage_class_count++;
+                }
+            }
+            else if (sd->state.lr_flag == 1)
+            {
+                for (i = 0; i < sd->add_damage_class_count_; i++)
+                {
+                    if (sd->add_damage_classid_[i] == type2)
+                    {
+                        sd->add_damage_classrate_[i] += val;
+                        break;
+                    }
+                }
+                if (i >= sd->add_damage_class_count_
+                    && sd->add_damage_class_count_ < 10)
+                {
+                    sd->add_damage_classid_[sd->add_damage_class_count_] =
+                        type2;
+                    sd->add_damage_classrate_[sd->add_damage_class_count_] +=
+                        val;
+                    sd->add_damage_class_count_++;
+                }
+            }
+            break;
+        case SP_ADD_MAGIC_DAMAGE_CLASS:
+            if (sd->state.lr_flag != 2)
+            {
+                for (i = 0; i < sd->add_magic_damage_class_count; i++)
+                {
+                    if (sd->add_magic_damage_classid[i] == type2)
+                    {
+                        sd->add_magic_damage_classrate[i] += val;
+                        break;
+                    }
+                }
+                if (i >= sd->add_magic_damage_class_count
+                    && sd->add_magic_damage_class_count < 10)
+                {
+                    sd->add_magic_damage_classid
+                        [sd->add_magic_damage_class_count] = type2;
+                    sd->add_magic_damage_classrate
+                        [sd->add_magic_damage_class_count] += val;
+                    sd->add_magic_damage_class_count++;
+                }
+            }
+            break;
+        case SP_ADD_DEF_CLASS:
+            if (sd->state.lr_flag != 2)
+            {
+                for (i = 0; i < sd->add_def_class_count; i++)
+                {
+                    if (sd->add_def_classid[i] == type2)
+                    {
+                        sd->add_def_classrate[i] += val;
+                        break;
+                    }
+                }
+                if (i >= sd->add_def_class_count
+                    && sd->add_def_class_count < 10)
+                {
+                    sd->add_def_classid[sd->add_def_class_count] = type2;
+                    sd->add_def_classrate[sd->add_def_class_count] += val;
+                    sd->add_def_class_count++;
+                }
+            }
+            break;
+        case SP_ADD_MDEF_CLASS:
+            if (sd->state.lr_flag != 2)
+            {
+                for (i = 0; i < sd->add_mdef_class_count; i++)
+                {
+                    if (sd->add_mdef_classid[i] == type2)
+                    {
+                        sd->add_mdef_classrate[i] += val;
+                        break;
+                    }
+                }
+                if (i >= sd->add_mdef_class_count
+                    && sd->add_mdef_class_count < 10)
+                {
+                    sd->add_mdef_classid[sd->add_mdef_class_count] = type2;
+                    sd->add_mdef_classrate[sd->add_mdef_class_count] += val;
+                    sd->add_mdef_class_count++;
+                }
+            }
+            break;
+        case SP_HP_DRAIN_RATE:
+            if (!sd->state.lr_flag)
+            {
+                sd->hp_drain_rate += type2;
+                sd->hp_drain_per += val;
+            }
+            else if (sd->state.lr_flag == 1)
+            {
+                sd->hp_drain_rate_ += type2;
+                sd->hp_drain_per_ += val;
+            }
+            break;
+        case SP_SP_DRAIN_RATE:
+            if (!sd->state.lr_flag)
+            {
+                sd->sp_drain_rate += type2;
+                sd->sp_drain_per += val;
+            }
+            else if (sd->state.lr_flag == 1)
+            {
+                sd->sp_drain_rate_ += type2;
+                sd->sp_drain_per_ += val;
+            }
+            break;
+        case SP_WEAPON_COMA_ELE:
+            if (sd->state.lr_flag != 2)
+                sd->weapon_coma_ele[type2] += val;
+            break;
+        case SP_WEAPON_COMA_RACE:
+            if (sd->state.lr_flag != 2)
+                sd->weapon_coma_race[type2] += val;
+            break;
+        case SP_RANDOM_ATTACK_INCREASE:    // [Valaris]
+            if (sd->state.lr_flag != 2)
+            {
+                sd->random_attack_increase_add = type2;
+                sd->random_attack_increase_per += val;
+                break;
+            }                   // end addition
+        default:
+            if (battle_config.error_log)
+                printf ("pc_bonus2: unknown type %d %d %d!\n", type, type2,
+                        val);
+            break;
+    }
+    return 0;
+}
+
+int pc_bonus3 (struct map_session_data *sd, int type, int type2, int type3,
+               int val)
+{
+    int  i;
+    switch (type)
+    {
+        case SP_ADD_MONSTER_DROP_ITEM:
+            if (sd->state.lr_flag != 2)
+            {
+                for (i = 0; i < sd->monster_drop_item_count; i++)
+                {
+                    if (sd->monster_drop_itemid[i] == type2)
+                    {
+                        sd->monster_drop_race[i] |= 1 << type3;
+                        if (sd->monster_drop_itemrate[i] < val)
+                            sd->monster_drop_itemrate[i] = val;
+                        break;
+                    }
+                }
+                if (i >= sd->monster_drop_item_count
+                    && sd->monster_drop_item_count < 10)
+                {
+                    sd->monster_drop_itemid[sd->monster_drop_item_count] =
+                        type2;
+                    sd->monster_drop_race[sd->monster_drop_item_count] |=
+                        1 << type3;
+                    sd->monster_drop_itemrate[sd->monster_drop_item_count] =
+                        val;
+                    sd->monster_drop_item_count++;
+                }
+            }
+            break;
+        case SP_AUTOSPELL:
+            if (sd->state.lr_flag != 2)
+            {
+                sd->autospell_id = type2;
+                sd->autospell_lv = type3;
+                sd->autospell_rate = val;
+            }
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("pc_bonus3: unknown type %d %d %d %d!\n", type, type2,
+                        type3, val);
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スクリプトによるスキル所得
+ *------------------------------------------
+ */
+int pc_skill (struct map_session_data *sd, int id, int level, int flag)
+{
+    nullpo_retr (0, sd);
+
+    if (level > MAX_SKILL_LEVEL)
+    {
+        if (battle_config.error_log)
+            printf ("support card skill only!\n");
+        return 0;
+    }
+    if (!flag && (sd->status.skill[id].id == id || level == 0))
+    {                           // クエスト所得ならここで条件を確認して送信する
+        sd->status.skill[id].lv = level;
+        pc_calcstatus (sd, 0);
+        clif_skillinfoblock (sd);
+    }
+    else if (sd->status.skill[id].lv < level)
+    {                           // 覚えられるがlvが小さいなら
+        sd->status.skill[id].id = id;
+        sd->status.skill[id].lv = level;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * カード挿入
+ *------------------------------------------
+ */
+int pc_insert_card (struct map_session_data *sd, int idx_card, int idx_equip)
+{
+    nullpo_retr (0, sd);
+
+    if (idx_card >= 0 && idx_card < MAX_INVENTORY && idx_equip >= 0
+        && idx_equip < MAX_INVENTORY && sd->inventory_data[idx_card])
+    {
+        int  i;
+        int  nameid = sd->status.inventory[idx_equip].nameid;
+        int  cardid = sd->status.inventory[idx_card].nameid;
+        int  ep = sd->inventory_data[idx_card]->equip;
+
+        if (nameid <= 0 || sd->inventory_data[idx_equip] == NULL ||
+            (sd->inventory_data[idx_equip]->type != 4 && sd->inventory_data[idx_equip]->type != 5) ||   // 装 備じゃない
+            (sd->status.inventory[idx_equip].identify == 0) ||  // 未鑑定
+            (sd->status.inventory[idx_equip].card[0] == 0x00ff) ||  // 製造武器
+            (sd->status.inventory[idx_equip].card[0] == 0x00fe) ||
+            ((sd->inventory_data[idx_equip]->equip & ep) == 0) ||    // 装 備個所違い
+            (sd->inventory_data[idx_equip]->type == 4 && ep == 32) ||   // 両 手武器と盾カード
+            (sd->status.inventory[idx_equip].card[0] == (short) 0xff00)
+            || sd->status.inventory[idx_equip].equip)
+        {
+
+            clif_insert_card (sd, idx_equip, idx_card, 1);
+            return 0;
+        }
+        for (i = 0; i < sd->inventory_data[idx_equip]->slot; i++)
+        {
+            if (sd->status.inventory[idx_equip].card[i] == 0)
+            {
+                // 空きスロットがあったので差し込む
+                sd->status.inventory[idx_equip].card[i] = cardid;
+
+                // カードは減らす
+                clif_insert_card (sd, idx_equip, idx_card, 0);
+                pc_delitem (sd, idx_card, 1, 1);
+                return 0;
+            }
+        }
+    }
+    else
+        clif_insert_card (sd, idx_equip, idx_card, 1);
+
+    return 0;
+}
+
+//
+// アイテム物
+//
+
+/*==========================================
+ * スキルによる買い値修正
+ *------------------------------------------
+ */
+int pc_modifybuyvalue (struct map_session_data *sd, int orig_value)
+{
+    int  skill, val = orig_value, rate1 = 0, rate2 = 0;
+    if ((skill = pc_checkskill (sd, MC_DISCOUNT)) > 0)  // ディスカウント
+        rate1 = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
+    if ((skill = pc_checkskill (sd, RG_COMPULSION)) > 0)    // コムパルションディスカウント
+        rate2 = 5 + skill * 4;
+    if (rate1 < rate2)
+        rate1 = rate2;
+    if (rate1)
+        val = (int) ((double) orig_value * (double) (100 - rate1) / 100.);
+    if (val < 0)
+        val = 0;
+    if (orig_value > 0 && val < 1)
+        val = 1;
+
+    return val;
+}
+
+/*==========================================
+ * スキルによる売り値修正
+ *------------------------------------------
+ */
+int pc_modifysellvalue (struct map_session_data *sd, int orig_value)
+{
+    int  skill, val = orig_value, rate = 0;
+    if ((skill = pc_checkskill (sd, MC_OVERCHARGE)) > 0)    // オーバーチャージ
+        rate = 5 + skill * 2 - ((skill == 10) ? 1 : 0);
+    if (rate)
+        val = (int) ((double) orig_value * (double) (100 + rate) / 100.);
+    if (val < 0)
+        val = 0;
+    if (orig_value > 0 && val < 1)
+        val = 1;
+
+    return val;
+}
+
+/*==========================================
+ * アイテムを買った時に、新しいアイテム欄を使うか、
+ * 3万個制限にかかるか確認
+ *------------------------------------------
+ */
+int pc_checkadditem (struct map_session_data *sd, int nameid, int amount)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (itemdb_isequip (nameid))
+        return ADDITEM_NEW;
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid == nameid)
+        {
+            if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
+                return ADDITEM_OVERAMOUNT;
+            return ADDITEM_EXIST;
+        }
+    }
+
+    if (amount > MAX_AMOUNT)
+        return ADDITEM_OVERAMOUNT;
+    return ADDITEM_NEW;
+}
+
+/*==========================================
+ * 空きアイテム欄の個数
+ *------------------------------------------
+ */
+int pc_inventoryblank (struct map_session_data *sd)
+{
+    int  i, b;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0, b = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid == 0)
+            b++;
+    }
+
+    return b;
+}
+
+/*==========================================
+ * お金を払う
+ *------------------------------------------
+ */
+int pc_payzeny (struct map_session_data *sd, int zeny)
+{
+    double z;
+
+    nullpo_retr (0, sd);
+
+    z = (double) sd->status.zeny;
+    if (sd->status.zeny < zeny || z - (double) zeny > MAX_ZENY)
+        return 1;
+    sd->status.zeny -= zeny;
+    clif_updatestatus (sd, SP_ZENY);
+
+    return 0;
+}
+
+/*==========================================
+ * お金を得る
+ *------------------------------------------
+ */
+int pc_getzeny (struct map_session_data *sd, int zeny)
+{
+    double z;
+
+    nullpo_retr (0, sd);
+
+    z = (double) sd->status.zeny;
+    if (z + (double) zeny > MAX_ZENY)
+    {
+        zeny = 0;
+        sd->status.zeny = MAX_ZENY;
+    }
+    sd->status.zeny += zeny;
+    clif_updatestatus (sd, SP_ZENY);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムを探して、インデックスを返す
+ *------------------------------------------
+ */
+int pc_search_inventory (struct map_session_data *sd, int item_id)
+{
+    int  i;
+
+    nullpo_retr (-1, sd);
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid == item_id &&
+            (sd->status.inventory[i].amount > 0 || item_id == 0))
+            return i;
+    }
+
+    return -1;
+}
+
+int pc_count_all_items (struct map_session_data *player, int item_id)
+{
+    int  i;
+    int  count = 0;
+
+    nullpo_retr (0, player);
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (player->status.inventory[i].nameid == item_id)
+            count += player->status.inventory[i].amount;
+    }
+
+    return count;
+}
+
+int pc_remove_items (struct map_session_data *player, int item_id, int count)
+{
+    int  i;
+
+    nullpo_retr (0, player);
+
+    for (i = 0; i < MAX_INVENTORY && count; i++)
+    {
+        if (player->status.inventory[i].nameid == item_id)
+        {
+            int  to_delete = count;
+            /* only delete as much as we have */
+            if (to_delete > player->status.inventory[i].amount)
+                to_delete = player->status.inventory[i].amount;
+
+            count -= to_delete;
+
+            pc_delitem (player, i, to_delete,
+                        0 /* means `really delete and update status' */ );
+
+            if (!count)
+                return 0;
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * アイテム追加。個数のみitem構造体の数字を無視
+ *------------------------------------------
+ */
+int pc_additem (struct map_session_data *sd, struct item *item_data,
+                int amount)
+{
+    struct item_data *data;
+    int  i, w;
+
+    MAP_LOG_PC (sd, "PICKUP %d %d", item_data->nameid, amount);
+
+    nullpo_retr (1, sd);
+    nullpo_retr (1, item_data);
+
+    if (item_data->nameid <= 0 || amount <= 0)
+        return 1;
+    data = itemdb_search (item_data->nameid);
+    if ((w = data->weight * amount) + sd->weight > sd->max_weight)
+        return 2;
+
+    i = MAX_INVENTORY;
+
+    if (!itemdb_isequip2 (data))
+    {
+        // 装 備品ではないので、既所有品なら個数のみ変化させる
+        for (i = 0; i < MAX_INVENTORY; i++)
+            if (sd->status.inventory[i].nameid == item_data->nameid &&
+                sd->status.inventory[i].card[0] == item_data->card[0]
+                && sd->status.inventory[i].card[1] == item_data->card[1]
+                && sd->status.inventory[i].card[2] == item_data->card[2]
+                && sd->status.inventory[i].card[3] == item_data->card[3])
+            {
+                if (sd->status.inventory[i].amount + amount > MAX_AMOUNT)
+                    return 5;
+                sd->status.inventory[i].amount += amount;
+                clif_additem (sd, i, amount, 0);
+                break;
+            }
+    }
+    if (i >= MAX_INVENTORY)
+    {
+        // 装 備品か未所有品だったので空き欄へ追加
+        i = pc_search_inventory (sd, 0);
+        if (i >= 0)
+        {
+            memcpy (&sd->status.inventory[i], item_data,
+                    sizeof (sd->status.inventory[0]));
+
+            if (item_data->equip)
+                sd->status.inventory[i].equip = 0;
+
+            sd->status.inventory[i].amount = amount;
+            sd->inventory_data[i] = data;
+            clif_additem (sd, i, amount, 0);
+        }
+        else
+            return 4;
+    }
+    sd->weight += w;
+    clif_updatestatus (sd, SP_WEIGHT);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムを減らす
+ *------------------------------------------
+ */
+int pc_delitem (struct map_session_data *sd, int n, int amount, int type)
+{
+    nullpo_retr (1, sd);
+
+    if (sd->trade_partner != 0)
+        trade_tradecancel (sd);
+
+    if (sd->status.inventory[n].nameid == 0 || amount <= 0
+        || sd->status.inventory[n].amount < amount
+        || sd->inventory_data[n] == NULL)
+        return 1;
+
+    sd->status.inventory[n].amount -= amount;
+    sd->weight -= sd->inventory_data[n]->weight * amount;
+    if (sd->status.inventory[n].amount <= 0)
+    {
+        if (sd->status.inventory[n].equip)
+            pc_unequipitem (sd, n, 0);
+        memset (&sd->status.inventory[n], 0,
+                sizeof (sd->status.inventory[0]));
+        sd->inventory_data[n] = NULL;
+    }
+    if (!(type & 1))
+        clif_delitem (sd, n, amount);
+    if (!(type & 2))
+        clif_updatestatus (sd, SP_WEIGHT);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムを落す
+ *------------------------------------------
+ */
+int pc_dropitem (struct map_session_data *sd, int n, int amount)
+{
+    nullpo_retr (1, sd);
+
+    if (sd->trade_partner != 0 || sd->npc_id != 0 || sd->state.storage_flag)
+        return 0;               // no dropping while trading/npc/storage
+
+    if (n < 0 || n >= MAX_INVENTORY)
+        return 0;
+
+    if (amount <= 0)
+        return 0;
+
+    pc_unequipinvyitem (sd, n, 0);
+
+    if (sd->status.inventory[n].nameid <= 0 ||
+        sd->status.inventory[n].amount < amount ||
+        sd->trade_partner != 0 || sd->status.inventory[n].amount <= 0)
+        return 1;
+    map_addflooritem (&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x,
+                      sd->bl.y, NULL, NULL, NULL, 0);
+    pc_delitem (sd, n, amount, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムを拾う
+ *------------------------------------------
+ */
+
+static int can_pick_item_up_from (struct map_session_data *self, int other_id)
+{
+    struct party *p = party_search (self->status.party_id);
+
+    /* From ourselves or from no-one? */
+    if (!self || self->bl.id == other_id || !other_id)
+        return 1;
+
+    struct map_session_data *other = map_id2sd (other_id);
+
+    /* Other no longer exists? */
+    if (!other)
+        return 1;
+
+    /* From our partner? */
+    if (self->status.partner_id == other->status.char_id)
+        return 1;
+
+    /* From a party member? */
+    if (self->status.party_id
+        && self->status.party_id == other->status.party_id
+        && p && p->item != 0)
+        return 1;
+
+    /* From someone who is far away? */
+    /* On another map? */
+    if (other->bl.m != self->bl.m)
+        return 1;
+    else
+    {
+        int  distance_x = abs (other->bl.x - self->bl.x);
+        int  distance_y = abs (other->bl.y - self->bl.y);
+        int  distance = (distance_x > distance_y) ? distance_x : distance_y;
+
+        return distance > battle_config.drop_pickup_safety_zone;
+    }
+}
+
+int pc_takeitem (struct map_session_data *sd, struct flooritem_data *fitem)
+{
+    int  flag;
+    unsigned int tick = gettick ();
+    int  can_take;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, fitem);
+
+    /* Sometimes the owners reported to us are buggy: */
+
+    if (fitem->first_get_id == fitem->third_get_id
+        || fitem->second_get_id == fitem->third_get_id)
+        fitem->third_get_id = 0;
+
+    if (fitem->first_get_id == fitem->second_get_id)
+    {
+        fitem->second_get_id = fitem->third_get_id;
+        fitem->third_get_id = 0;
+    }
+
+    can_take = can_pick_item_up_from (sd, fitem->first_get_id);
+    if (!can_take)
+        can_take = fitem->first_get_tick <= tick
+            && can_pick_item_up_from (sd, fitem->second_get_id);
+
+    if (!can_take)
+        can_take = fitem->second_get_tick <= tick
+            && can_pick_item_up_from (sd, fitem->third_get_id);
+
+    if (!can_take)
+        can_take = fitem->third_get_tick <= tick;
+
+    if (can_take)
+    {
+        /* Can pick up */
+
+        if ((flag =
+             pc_additem (sd, &fitem->item_data, fitem->item_data.amount)))
+            // 重量overで取得失敗
+            clif_additem (sd, 0, 0, flag);
+        else
+        {
+            // 取得成功
+            if (sd->attacktimer != -1)
+                pc_stopattack (sd);
+            clif_takeitem (&sd->bl, &fitem->bl);
+            map_clearflooritem (fitem->bl.id);
+        }
+        return 0;
+    }
+
+    /* Otherwise, we can't pick up */
+    clif_additem (sd, 0, 0, 6);
+    return 0;
+}
+
+int pc_isUseitem (struct map_session_data *sd, int n)
+{
+    struct item_data *item;
+    int  nameid;
+
+    nullpo_retr (0, sd);
+
+    item = sd->inventory_data[n];
+    nameid = sd->status.inventory[n].nameid;
+
+    if (item == NULL)
+        return 0;
+    if (itemdb_type (nameid) != 0)
+        return 0;
+    if ((nameid == 605) && map[sd->bl.m].flag.gvg)
+        return 0;
+    if (nameid == 601
+        && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg))
+    {
+        clif_skill_teleportmessage (sd, 0);
+        return 0;
+    }
+
+    if (nameid == 602 && map[sd->bl.m].flag.noreturn)
+        return 0;
+    if (nameid == 604
+        && (map[sd->bl.m].flag.nobranch || map[sd->bl.m].flag.gvg))
+        return 0;
+    if (item->sex != 2 && sd->status.sex != item->sex)
+        return 0;
+    if (item->elv > 0 && sd->status.base_level < item->elv)
+        return 0;
+
+    return 1;
+}
+
+/*==========================================
+ * アイテムを使う
+ *------------------------------------------
+ */
+int pc_useitem (struct map_session_data *sd, int n)
+{
+    int  nameid, amount;
+
+    nullpo_retr (1, sd);
+
+    if (n >= 0 && n < MAX_INVENTORY && sd->inventory_data[n])
+    {
+        nameid = sd->status.inventory[n].nameid;
+        amount = sd->status.inventory[n].amount;
+        if (sd->status.inventory[n].nameid <= 0
+            || sd->status.inventory[n].amount <= 0
+            || sd->sc_data[SC_BERSERK].timer != -1 || !pc_isUseitem (sd, n))
+        {
+            clif_useitemack (sd, n, 0, 0);
+            return 1;
+        }
+
+        run_script (sd->inventory_data[n]->use_script, 0, sd->bl.id, 0);
+
+        clif_useitemack (sd, n, amount - 1, 1);
+        pc_delitem (sd, n, 1, 1);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * カートアイテム追加。個数のみitem構造体の数字を無視
+ *------------------------------------------
+ */
+int pc_cart_additem (struct map_session_data *sd, struct item *item_data,
+                     int amount)
+{
+    struct item_data *data;
+    int  i, w;
+
+    nullpo_retr (1, sd);
+    nullpo_retr (1, item_data);
+
+    if (item_data->nameid <= 0 || amount <= 0)
+        return 1;
+    data = itemdb_search (item_data->nameid);
+
+    if ((w = data->weight * amount) + sd->cart_weight > sd->cart_max_weight)
+        return 1;
+
+    i = MAX_CART;
+    if (!itemdb_isequip2 (data))
+    {
+        // 装 備品ではないので、既所有品なら個数のみ変化させる
+        for (i = 0; i < MAX_CART; i++)
+        {
+            if (sd->status.cart[i].nameid == item_data->nameid &&
+                sd->status.cart[i].card[0] == item_data->card[0]
+                && sd->status.cart[i].card[1] == item_data->card[1]
+                && sd->status.cart[i].card[2] == item_data->card[2]
+                && sd->status.cart[i].card[3] == item_data->card[3])
+            {
+                if (sd->status.cart[i].amount + amount > MAX_AMOUNT)
+                    return 1;
+                sd->status.cart[i].amount += amount;
+                clif_cart_additem (sd, i, amount, 0);
+                break;
+            }
+        }
+    }
+    if (i >= MAX_CART)
+    {
+        // 装 備品か未所有品だったので空き欄へ追加
+        for (i = 0; i < MAX_CART; i++)
+        {
+            if (sd->status.cart[i].nameid == 0)
+            {
+                memcpy (&sd->status.cart[i], item_data,
+                        sizeof (sd->status.cart[0]));
+                sd->status.cart[i].amount = amount;
+                sd->cart_num++;
+                clif_cart_additem (sd, i, amount, 0);
+                break;
+            }
+        }
+        if (i >= MAX_CART)
+            return 1;
+    }
+    sd->cart_weight += w;
+    clif_updatestatus (sd, SP_CARTINFO);
+
+    return 0;
+}
+
+/*==========================================
+ * カートアイテムを減らす
+ *------------------------------------------
+ */
+int pc_cart_delitem (struct map_session_data *sd, int n, int amount, int type)
+{
+    nullpo_retr (1, sd);
+
+    if (sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount)
+        return 1;
+
+    sd->status.cart[n].amount -= amount;
+    sd->cart_weight -= itemdb_weight (sd->status.cart[n].nameid) * amount;
+    if (sd->status.cart[n].amount <= 0)
+    {
+        memset (&sd->status.cart[n], 0, sizeof (sd->status.cart[0]));
+        sd->cart_num--;
+    }
+    if (!type)
+    {
+        clif_cart_delitem (sd, n, amount);
+        clif_updatestatus (sd, SP_CARTINFO);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * カートへアイテム移動
+ *------------------------------------------
+ */
+int pc_putitemtocart (struct map_session_data *sd, int idx, int amount)
+{
+    struct item *item_data;
+
+    nullpo_retr (0, sd);
+
+    if (idx < 0 || idx >= MAX_INVENTORY)
+        return 1;
+
+    nullpo_retr (0, item_data = &sd->status.inventory[idx]);
+
+    if (!pc_iscarton (sd))
+        return 1;
+    if (item_data->nameid == 0 || item_data->amount < amount)
+        return 1;
+    if (pc_cart_additem (sd, item_data, amount) == 0)
+        return pc_delitem (sd, idx, amount, 0);
+
+    return 1;
+}
+
+/*==========================================
+ * カート内のアイテム数確認(個数の差分を返す)
+ *------------------------------------------
+ */
+int pc_cartitem_amount (struct map_session_data *sd, int idx, int amount)
+{
+    struct item *item_data;
+
+    nullpo_retr (-1, sd);
+
+    if (idx < 0 || idx >= MAX_CART)
+        return -1;
+
+    nullpo_retr (-1, item_data = &sd->status.cart[idx]);
+
+    if (!pc_iscarton (sd))
+        return -1;
+    if (item_data->nameid == 0 || !item_data->amount)
+        return -1;
+    return item_data->amount - amount;
+}
+
+/*==========================================
+ * カートからアイテム移動
+ *------------------------------------------
+ */
+
+int pc_getitemfromcart (struct map_session_data *sd, int idx, int amount)
+{
+    struct item *item_data;
+    int  flag;
+
+    nullpo_retr (0, sd);
+
+    if (idx < 0 || idx >= MAX_CART)
+        return 1;
+
+    nullpo_retr (0, item_data = &sd->status.cart[idx]);
+
+    if (!pc_iscarton (sd))
+        return 1;
+    if (item_data->nameid == 0 || item_data->amount < amount)
+        return 1;
+    if ((flag = pc_additem (sd, item_data, amount)) == 0)
+        return pc_cart_delitem (sd, idx, amount, 0);
+
+    clif_additem (sd, 0, 0, flag);
+    return 1;
+}
+
+/*==========================================
+ * アイテム鑑定
+ *------------------------------------------
+ */
+int pc_item_identify (struct map_session_data *sd, int idx)
+{
+    int  flag = 1;
+
+    nullpo_retr (0, sd);
+
+    if (idx >= 0 && idx < MAX_INVENTORY)
+    {
+        if (sd->status.inventory[idx].nameid > 0
+            && sd->status.inventory[idx].identify == 0)
+        {
+            flag = 0;
+            sd->status.inventory[idx].identify = 1;
+        }
+        clif_item_identified (sd, idx, flag);
+    }
+    else
+        clif_item_identified (sd, idx, flag);
+
+    return !flag;
+}
+
+/*==========================================
+ * スティル品公開
+ *------------------------------------------
+ */
+int pc_show_steal (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+    int  itemid;
+    int  type;
+
+    struct item_data *item = NULL;
+    char output[100];
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = va_arg (ap, struct map_session_data *));
+
+    itemid = va_arg (ap, int);
+    type = va_arg (ap, int);
+
+    if (!type)
+    {
+        if ((item = itemdb_exists (itemid)) == NULL)
+            sprintf (output, "%s stole an Unknown_Item.", sd->status.name);
+        else
+            sprintf (output, "%s stole %s.", sd->status.name, item->jname);
+        clif_displaymessage (((struct map_session_data *) bl)->fd, output);
+    }
+    else
+    {
+        sprintf (output,
+                 "%s has not stolen the item because of being  overweight.",
+                 sd->status.name);
+        clif_displaymessage (((struct map_session_data *) bl)->fd, output);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+//** pc.c: Small Steal Item fix by fritz
+int pc_steal_item (struct map_session_data *sd, struct block_list *bl)
+{
+    if (sd != NULL && bl != NULL && bl->type == BL_MOB)
+    {
+        int  i, skill, rate, itemid, flag, count;
+        struct mob_data *md;
+        md = (struct mob_data *) bl;
+        if (!md->state.steal_flag && mob_db[md->mob_class].mexp <= 0 &&
+            !(mob_db[md->mob_class].mode & 0x20) &&
+            md->sc_data[SC_STONE].timer == -1 &&
+            md->sc_data[SC_FREEZE].timer == -1 &&
+            (!(md->mob_class > 1324 && md->mob_class < 1364)))   // prevent stealing from treasure boxes [Valaris]
+        {
+            skill = sd->paramc[4] - mob_db[md->mob_class].dex
+                + pc_checkskill (sd, TF_STEAL) + 10;
+
+            if (0 < skill)
+            {
+                for (count = 8; count <= 8 && count != 0; count--)
+                {
+                    i = rand () % 8;
+                    itemid = mob_db[md->mob_class].dropitem[i].nameid;
+
+                    if (itemid > 0 && itemdb_type (itemid) != 6)
+                    {
+                        rate =
+                            (mob_db[md->mob_class].dropitem[i].p /
+                             battle_config.item_rate_common * 100 * skill) /
+                            100;
+
+                        if (rand () % 10000 < rate)
+                        {
+                            struct item tmp_item;
+                            memset (&tmp_item, 0, sizeof (tmp_item));
+                            tmp_item.nameid = itemid;
+                            tmp_item.amount = 1;
+                            tmp_item.identify = 1;
+                            flag = pc_additem (sd, &tmp_item, 1);
+                            if (battle_config.show_steal_in_same_party)
+                            {
+                                party_foreachsamemap (pc_show_steal, sd, 1,
+                                                      sd, tmp_item.nameid, 0);
+                            }
+
+                            if (flag)
+                            {
+                                if (battle_config.show_steal_in_same_party)
+                                {
+                                    party_foreachsamemap (pc_show_steal, sd,
+                                                          1, sd,
+                                                          tmp_item.nameid, 1);
+                                }
+
+                                clif_additem (sd, 0, 0, flag);
+                            }
+                            md->state.steal_flag = 1;
+                            return 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int pc_steal_coin (struct map_session_data *sd, struct block_list *bl)
+{
+    if (sd != NULL && bl != NULL && bl->type == BL_MOB)
+    {
+        int  rate, skill;
+        struct mob_data *md = (struct mob_data *) bl;
+        if (md && !md->state.steal_coin_flag && md->sc_data
+            && md->sc_data[SC_STONE].timer == -1
+            && md->sc_data[SC_FREEZE].timer == -1)
+        {
+            skill = pc_checkskill (sd, RG_STEALCOIN) * 10;
+            rate =
+                skill + (sd->status.base_level - mob_db[md->mob_class].lv) * 3 +
+                sd->paramc[4] * 2 + sd->paramc[5] * 2;
+            if (MRAND (1000) < rate)
+            {
+                pc_getzeny (sd, mob_db[md->mob_class].lv * 10 + MRAND (100));
+                md->state.steal_coin_flag = 1;
+                return 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+//
+//
+//
+/*==========================================
+ * PCの位置設定
+ *------------------------------------------
+ */
+int pc_setpos (struct map_session_data *sd, char *mapname_org, int x, int y,
+               int clrtype)
+{
+    char mapname[24];
+    int  m = 0, c = 0, disguise = 0;
+
+    nullpo_retr (0, sd);
+
+    if (sd->chatID)             // チャットから出る
+        chat_leavechat (sd);
+    if (sd->trade_partner)      // 取引を中断する
+        trade_tradecancel (sd);
+    if (sd->state.storage_flag == 1)
+        storage_storage_quit (sd);  // 倉庫を開いてるなら保存する
+    else if (sd->state.storage_flag == 2)
+        storage_guild_storage_quit (sd, 0);
+
+    if (sd->party_invite > 0)   // パーティ勧誘を拒否する
+        party_reply_invite (sd, sd->party_invite_account, 0);
+    if (sd->guild_invite > 0)   // ギルド勧誘を拒否する
+        guild_reply_invite (sd, sd->guild_invite, 0);
+    if (sd->guild_alliance > 0) // ギルド同盟勧誘を拒否する
+        guild_reply_reqalliance (sd, sd->guild_alliance_account, 0);
+
+    skill_castcancel (&sd->bl, 0);  // 詠唱中断
+    pc_stop_walking (sd, 0);    // 歩行中断
+    pc_stopattack (sd);         // 攻撃中断
+
+    if (pc_issit (sd))
+    {
+//        pc_setstand (sd); // [fate] Nothing wrong with warping while sitting
+        skill_gangsterparadise (sd, 0);
+    }
+
+    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
+        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
+    if (sd->status.option & 2)
+        skill_status_change_end (&sd->bl, SC_HIDING, -1);
+    if (sd->status.option & 4)
+        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
+    if (sd->status.option & 16386)
+        skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
+    if (sd->sc_data[SC_BLADESTOP].timer != -1)
+        skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
+    if (sd->sc_data[SC_DANCING].timer != -1)    // clear dance effect when warping [Valaris]
+        skill_stop_dancing (&sd->bl, 0);
+
+    if (sd->disguise)
+    {                           // clear disguises when warping [Valaris]
+        clif_clearchar (&sd->bl, 9);
+        disguise = sd->disguise;
+        sd->disguise = 0;
+    }
+
+    memcpy (mapname, mapname_org, 24);
+    mapname[16] = 0;
+    if (strstr (mapname, ".gat") == NULL && strlen (mapname) < 16)
+    {
+        strcat (mapname, ".gat");
+    }
+
+    m = map_mapname2mapid (mapname);
+    if (m < 0)
+    {
+        if (sd->mapname[0])
+        {
+            int  ip, port;
+            if (map_mapname2ipport (mapname, &ip, &port) == 0)
+            {
+                skill_stop_dancing (&sd->bl, 1);
+                skill_unit_out_all (&sd->bl, gettick (), 1);
+                clif_clearchar_area (&sd->bl, clrtype & 0xffff);
+                skill_gangsterparadise (sd, 0);
+                map_delblock (&sd->bl);
+                memcpy (sd->mapname, mapname, 24);
+                sd->bl.x = x;
+                sd->bl.y = y;
+                sd->state.waitingdisconnect = 1;
+                pc_makesavestatus (sd);
+                //The storage close routines save the char data. [Skotlex]
+                if (!sd->state.storage_flag)
+                    chrif_save (sd);
+                else if (sd->state.storage_flag == 1)
+                    storage_storage_quit (sd);
+                else if (sd->state.storage_flag == 2)
+                    storage_guild_storage_quit (sd, 1);
+
+                chrif_changemapserver (sd, mapname, x, y, ip, port);
+                return 0;
+            }
+        }
+#if 0
+        clif_authfail_fd (sd->fd, 0);   // cancel
+        clif_setwaitclose (sd->fd);
+#endif
+        return 1;
+    }
+
+    if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys)
+        x = y = 0;
+    if ((x == 0 && y == 0) || (c = read_gat (m, x, y)) == 1 || c == 5)
+    {
+        if (x || y)
+        {
+            if (battle_config.error_log)
+                printf ("stacked (%d,%d)\n", x, y);
+        }
+        do
+        {
+            x = MRAND (map[m].xs - 2) + 1;
+            y = MRAND (map[m].ys - 2) + 1;
+        }
+        while ((c = read_gat (m, x, y)) == 1 || c == 5);
+    }
+
+    if (sd->mapname[0] && sd->bl.prev != NULL)
+    {
+        skill_unit_out_all (&sd->bl, gettick (), 1);
+        clif_clearchar_area (&sd->bl, clrtype & 0xffff);
+        skill_gangsterparadise (sd, 0);
+        map_delblock (&sd->bl);
+        clif_changemap (sd, map[m].name, x, y); // [MouseJstr]
+    }
+
+    if (disguise)               // disguise teleport fix [Valaris]
+        sd->disguise = disguise;
+
+    memcpy (sd->mapname, mapname, 24);
+    sd->bl.m = m;
+    sd->to_x = x;
+    sd->to_y = y;
+
+    // moved and changed dance effect stopping
+
+    sd->bl.x = x;
+    sd->bl.y = y;
+
+//  map_addblock(&sd->bl);  // ブロック登録とspawnは
+//  clif_spawnpc(sd);
+
+    return 0;
+}
+
+/*==========================================
+ * PCのランダムワープ
+ *------------------------------------------
+ */
+int pc_randomwarp (struct map_session_data *sd, int type)
+{
+    int  x, y, c, i = 0;
+    int  m;
+
+    nullpo_retr (0, sd);
+
+    m = sd->bl.m;
+
+    if (map[sd->bl.m].flag.noteleport)  // テレポート禁止
+        return 0;
+
+    do
+    {
+        x = MRAND (map[m].xs - 2) + 1;
+        y = MRAND (map[m].ys - 2) + 1;
+    }
+    while (((c = read_gat (m, x, y)) == 1 || c == 5) && (i++) < 1000);
+
+    if (i < 1000)
+        pc_setpos (sd, map[m].name, x, y, type);
+
+    return 0;
+}
+
+/*==========================================
+ * 現在位置のメモ
+ *------------------------------------------
+ */
+int pc_memo (struct map_session_data *sd, int i)
+{
+    int  skill;
+    int  j;
+
+    nullpo_retr (0, sd);
+
+    skill = pc_checkskill (sd, AL_WARP);
+
+    if (i >= MIN_PORTAL_MEMO)
+        i -= MIN_PORTAL_MEMO;
+    else if (map[sd->bl.m].flag.nomemo
+             || (map[sd->bl.m].flag.nowarpto
+                 && battle_config.any_warp_GM_min_level > pc_isGM (sd)))
+    {
+        clif_skill_teleportmessage (sd, 1);
+        return 0;
+    }
+
+    if (skill < 1)
+    {
+        clif_skill_memo (sd, 2);
+    }
+
+    if (skill < 2 || i < -1 || i > 2)
+    {
+        clif_skill_memo (sd, 1);
+        return 0;
+    }
+
+    for (j = 0; j < 3; j++)
+    {
+        if (strcmp (sd->status.memo_point[j].map, map[sd->bl.m].name) == 0)
+        {
+            i = j;
+            break;
+        }
+    }
+
+    if (i == -1)
+    {
+        for (i = skill - 3; i >= 0; i--)
+        {
+            memcpy (&sd->status.memo_point[i + 1], &sd->status.memo_point[i],
+                    sizeof (struct point));
+        }
+        i = 0;
+    }
+    memcpy (sd->status.memo_point[i].map, map[sd->bl.m].name, 24);
+    sd->status.memo_point[i].x = sd->bl.x;
+    sd->status.memo_point[i].y = sd->bl.y;
+
+    clif_skill_memo (sd, 0);
+
+    return 1;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int pc_can_reach (struct map_session_data *sd, int x, int y)
+{
+    struct walkpath_data wpd;
+
+    nullpo_retr (0, sd);
+
+    if (sd->bl.x == x && sd->bl.y == y) // 同じマス
+        return 1;
+
+    // 障害物判定
+    wpd.path_len = 0;
+    wpd.path_pos = 0;
+    wpd.path_half = 0;
+    return (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, x, y, 0) !=
+            -1) ? 1 : 0;
+}
+
+//
+// 歩 行物
+//
+/*==========================================
+ * 次の1歩にかかる時間を計算
+ *------------------------------------------
+ */
+static int calc_next_walk_step (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->walkpath.path_pos >= sd->walkpath.path_len)
+        return -1;
+    if (sd->walkpath.path[sd->walkpath.path_pos] & 1)
+        return sd->speed * 14 / 10;
+
+    return sd->speed;
+}
+
+/*==========================================
+ * 半歩進む(timer関数)
+ *------------------------------------------
+ */
+static void pc_walk (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd;
+    int  i, ctype;
+    int  moveblock;
+    int  x, y, dx, dy;
+
+    sd = map_id2sd (id);
+    if (sd == NULL)
+        return;
+
+    if (sd->walktimer != tid)
+    {
+        if (battle_config.error_log)
+            printf ("pc_walk %d != %d\n", sd->walktimer, tid);
+        return;
+    }
+    sd->walktimer = -1;
+    if (sd->walkpath.path_pos >= sd->walkpath.path_len
+        || sd->walkpath.path_pos != data)
+        return;
+
+    //歩いたので息吹のタイマーを初期化
+    sd->inchealspirithptick = 0;
+    sd->inchealspiritsptick = 0;
+
+    sd->walkpath.path_half ^= 1;
+    if (sd->walkpath.path_half == 0)
+    {                           // マス目中心へ到着
+        sd->walkpath.path_pos++;
+        if (sd->state.change_walk_target)
+        {
+            pc_walktoxy_sub (sd);
+            return;
+        }
+    }
+    else
+    {                           // マス目境界へ到着
+        if (sd->walkpath.path[sd->walkpath.path_pos] >= 8)
+            return;
+
+        x = sd->bl.x;
+        y = sd->bl.y;
+        ctype = map_getcell (sd->bl.m, x, y);
+        if (ctype == 1 || ctype == 5)
+        {
+            pc_stop_walking (sd, 1);
+            return;
+        }
+        sd->dir = sd->head_dir = sd->walkpath.path[sd->walkpath.path_pos];
+        dx = dirx[(int) sd->dir];
+        dy = diry[(int) sd->dir];
+        ctype = map_getcell (sd->bl.m, x + dx, y + dy);
+        if (ctype == 1 || ctype == 5)
+        {
+            pc_walktoxy_sub (sd);
+            return;
+        }
+
+        moveblock = (x / BLOCK_SIZE != (x + dx) / BLOCK_SIZE
+                     || y / BLOCK_SIZE != (y + dy) / BLOCK_SIZE);
+
+        sd->walktimer = 1;
+        map_foreachinmovearea (clif_pcoutsight, sd->bl.m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               dx, dy, 0, sd);
+
+        x += dx;
+        y += dy;
+
+        if (moveblock)
+            map_delblock (&sd->bl);
+        sd->bl.x = x;
+        sd->bl.y = y;
+        if (moveblock)
+            map_addblock (&sd->bl);
+
+        if (sd->sc_data[SC_DANCING].timer != -1)
+            skill_unit_move_unit_group ((struct skill_unit_group *)
+                                        sd->sc_data[SC_DANCING].val2,
+                                        sd->bl.m, dx, dy);
+
+        map_foreachinmovearea (clif_pcinsight, sd->bl.m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               -dx, -dy, 0, sd);
+        sd->walktimer = -1;
+
+        if (sd->status.party_id > 0)
+        {                       // パーティのHP情報通知検査
+            struct party *p = party_search (sd->status.party_id);
+            if (p != NULL)
+            {
+                int  p_flag = 0;
+                map_foreachinmovearea (party_send_hp_check, sd->bl.m,
+                                       x - AREA_SIZE, y - AREA_SIZE,
+                                       x + AREA_SIZE, y + AREA_SIZE, -dx, -dy,
+                                       BL_PC, sd->status.party_id, &p_flag);
+                if (p_flag)
+                    sd->party_hp = -1;
+            }
+        }
+        if (sd->status.option & 4)  // クローキングの消滅検査
+            skill_check_cloaking (&sd->bl);
+        // ディボーション検査
+        for (i = 0; i < 5; i++)
+            if (sd->dev.val1[i])
+            {
+                skill_devotion3 (&sd->bl, sd->dev.val1[i]);
+                break;
+            }
+        // 被ディボーション検査
+        if (sd->sc_data && sd->sc_data[SC_DEVOTION].val1)
+        {
+            skill_devotion2 (&sd->bl, sd->sc_data[SC_DEVOTION].val1);
+        }
+
+        skill_unit_move (&sd->bl, tick, 1); // スキルユニットの検査
+
+        if (map_getcell (sd->bl.m, x, y) & 0x80)
+            npc_touch_areanpc (sd, sd->bl.m, x, y);
+        else
+            sd->areanpc_id = 0;
+    }
+    if ((i = calc_next_walk_step (sd)) > 0)
+    {
+        i = i >> 1;
+        if (i < 1 && sd->walkpath.path_half == 0)
+            i = 1;
+        sd->walktimer =
+            add_timer (tick + i, pc_walk, id, sd->walkpath.path_pos);
+    }
+}
+
+/*==========================================
+ * 移動可能か確認して、可能なら歩行開始
+ *------------------------------------------
+ */
+static int pc_walktoxy_sub (struct map_session_data *sd)
+{
+    struct walkpath_data wpd;
+    int  i;
+
+    nullpo_retr (1, sd);
+
+    if (path_search
+        (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->to_x, sd->to_y, 0))
+        return 1;
+    memcpy (&sd->walkpath, &wpd, sizeof (wpd));
+
+    clif_walkok (sd);
+    sd->state.change_walk_target = 0;
+
+    if ((i = calc_next_walk_step (sd)) > 0)
+    {
+        i = i >> 2;
+        sd->walktimer = add_timer (gettick () + i, pc_walk, sd->bl.id, 0);
+    }
+    clif_movechar (sd);
+
+    return 0;
+}
+
+/*==========================================
+ * pc歩 行要求
+ *------------------------------------------
+ */
+int pc_walktoxy (struct map_session_data *sd, int x, int y)
+{
+
+    nullpo_retr (0, sd);
+
+    sd->to_x = x;
+    sd->to_y = y;
+
+    if (pc_issit (sd))
+        pc_setstand (sd);
+
+    if (sd->walktimer != -1 && sd->state.change_walk_target == 0)
+    {
+        // 現在歩いている最中の目的地変更なのでマス目の中心に来た時に
+        // timer関数からpc_walktoxy_subを呼ぶようにする
+        sd->state.change_walk_target = 1;
+    }
+    else
+    {
+        pc_walktoxy_sub (sd);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 歩 行停止
+ *------------------------------------------
+ */
+int pc_stop_walking (struct map_session_data *sd, int type)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->walktimer != -1)
+    {
+        delete_timer (sd->walktimer, pc_walk);
+        sd->walktimer = -1;
+    }
+    sd->walkpath.path_len = 0;
+    sd->to_x = sd->bl.x;
+    sd->to_y = sd->bl.y;
+    if (type & 0x01)
+        clif_fixpos (&sd->bl);
+    if (type & 0x02 && battle_config.pc_damage_delay)
+    {
+        unsigned int tick = gettick ();
+        int  delay = battle_get_dmotion (&sd->bl);
+        if (sd->canmove_tick < tick)
+            sd->canmove_tick = tick + delay;
+    }
+
+    return 0;
+}
+
+void pc_touch_all_relevant_npcs (struct map_session_data *sd)
+{
+    if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) & 0x80)
+        npc_touch_areanpc (sd, sd->bl.m, sd->bl.x, sd->bl.y);
+    else
+        sd->areanpc_id = 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int pc_movepos (struct map_session_data *sd, int dst_x, int dst_y)
+{
+    int  moveblock;
+    int  dx, dy, dist;
+
+    struct walkpath_data wpd;
+
+    nullpo_retr (0, sd);
+
+    if (path_search (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, dst_x, dst_y, 0))
+        return 1;
+
+    sd->dir = sd->head_dir = map_calc_dir (&sd->bl, dst_x, dst_y);
+
+    dx = dst_x - sd->bl.x;
+    dy = dst_y - sd->bl.y;
+    dist = distance (sd->bl.x, sd->bl.y, dst_x, dst_y);
+
+    moveblock = (sd->bl.x / BLOCK_SIZE != dst_x / BLOCK_SIZE
+                 || sd->bl.y / BLOCK_SIZE != dst_y / BLOCK_SIZE);
+
+    map_foreachinmovearea (clif_pcoutsight, sd->bl.m, sd->bl.x - AREA_SIZE,
+                           sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
+                           sd->bl.y + AREA_SIZE, dx, dy, 0, sd);
+
+    if (moveblock)
+        map_delblock (&sd->bl);
+    sd->bl.x = dst_x;
+    sd->bl.y = dst_y;
+    if (moveblock)
+        map_addblock (&sd->bl);
+
+    map_foreachinmovearea (clif_pcinsight, sd->bl.m, sd->bl.x - AREA_SIZE,
+                           sd->bl.y - AREA_SIZE, sd->bl.x + AREA_SIZE,
+                           sd->bl.y + AREA_SIZE, -dx, -dy, 0, sd);
+
+    if (sd->status.party_id > 0)
+    {                           // パーティのHP情報通知検査
+        struct party *p = party_search (sd->status.party_id);
+        if (p != NULL)
+        {
+            int  flag = 0;
+            map_foreachinmovearea (party_send_hp_check, sd->bl.m,
+                                   sd->bl.x - AREA_SIZE, sd->bl.y - AREA_SIZE,
+                                   sd->bl.x + AREA_SIZE, sd->bl.y + AREA_SIZE,
+                                   -dx, -dy, BL_PC, sd->status.party_id,
+                                   &flag);
+            if (flag)
+                sd->party_hp = -1;
+        }
+    }
+
+    if (sd->status.option & 4)  // クローキングの消滅検査
+        skill_check_cloaking (&sd->bl);
+
+    skill_unit_move (&sd->bl, gettick (), dist + 7);    // スキルユニットの検査
+
+    pc_touch_all_relevant_npcs (sd);
+    return 0;
+}
+
+//
+// 武器戦闘
+//
+/*==========================================
+ * スキルの検索 所有していた場合Lvが返る
+ *------------------------------------------
+ */
+int pc_checkskill (struct map_session_data *sd, int skill_id)
+{
+    if (sd == NULL)
+        return 0;
+    if (skill_id >= 10000)
+    {
+        struct guild *g;
+        if (sd->status.guild_id > 0
+            && (g = guild_search (sd->status.guild_id)) != NULL)
+            return guild_checkskill (g, skill_id);
+        return 0;
+    }
+
+    if (sd->status.skill[skill_id].id == skill_id)
+        return (sd->status.skill[skill_id].lv);
+
+    return 0;
+}
+
+/*==========================================
+ * 武器変更によるスキルの継続チェック
+ * 引数:
+ *   struct map_session_data *sd	セッションデータ
+ *   int nameid						装備品ID
+ * 返り値:
+ *   0		変更なし
+ *   -1		スキルを解除
+ *------------------------------------------
+ */
+int pc_checkallowskill (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->sc_data == NULL)
+        return 0;
+
+    if (!(skill_get_weapontype (KN_TWOHANDQUICKEN) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_TWOHANDQUICKEN].timer != -1)
+    {                           // 2HQ
+        skill_status_change_end (&sd->bl, SC_TWOHANDQUICKEN, -1);   // 2HQを解除
+        return -1;
+    }
+    if (!(skill_get_weapontype (LK_AURABLADE) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_AURABLADE].timer != -1)
+    {                           // オーラブレード
+        skill_status_change_end (&sd->bl, SC_AURABLADE, -1);    // オーラブレードを解除
+        return -1;
+    }
+    if (!(skill_get_weapontype (LK_PARRYING) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_PARRYING].timer != -1)
+    {                           // パリイング
+        skill_status_change_end (&sd->bl, SC_PARRYING, -1); // パリイングを解除
+        return -1;
+    }
+    if (!(skill_get_weapontype (LK_CONCENTRATION) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_CONCENTRATION].timer != -1)
+    {                           // コンセントレーション
+        skill_status_change_end (&sd->bl, SC_CONCENTRATION, -1);    // コンセントレーションを解除
+        return -1;
+    }
+    if (!(skill_get_weapontype (CR_SPEARQUICKEN) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_SPEARSQUICKEN].timer != -1)
+    {                           // スピアクィッケン
+        skill_status_change_end (&sd->bl, SC_SPEARSQUICKEN, -1);    // スピアクイッケンを解除
+        return -1;
+    }
+    if (!(skill_get_weapontype (BS_ADRENALINE) & (1 << sd->status.weapon))
+        && sd->sc_data[SC_ADRENALINE].timer != -1)
+    {                           // アドレナリンラッシュ
+        skill_status_change_end (&sd->bl, SC_ADRENALINE, -1);   // アドレナリンラッシュを解除
+        return -1;
+    }
+
+    if (sd->status.shield <= 0)
+    {
+        if (sd->sc_data[SC_AUTOGUARD].timer != -1)
+        {                       // オートガード
+            skill_status_change_end (&sd->bl, SC_AUTOGUARD, -1);
+            return -1;
+        }
+        if (sd->sc_data[SC_DEFENDER].timer != -1)
+        {                       // ディフェンダー
+            skill_status_change_end (&sd->bl, SC_DEFENDER, -1);
+            return -1;
+        }
+        if (sd->sc_data[SC_REFLECTSHIELD].timer != -1)
+        {                       //リフレクトシールド
+            skill_status_change_end (&sd->bl, SC_REFLECTSHIELD, -1);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 装 備品のチェック
+ *------------------------------------------
+ */
+int pc_checkequip (struct map_session_data *sd, int pos)
+{
+    int  i;
+
+    nullpo_retr (-1, sd);
+
+    for (i = 0; i < 11; i++)
+    {
+        if (pos & equip_pos[i])
+            return sd->equip_index[i];
+    }
+
+    return -1;
+}
+
+/*==========================================
+ * 転生職や養子職の元の職業を返す
+ *------------------------------------------
+ */
+struct pc_base_job pc_calc_base_job (int b_class)
+{
+    struct pc_base_job bj;
+    //転生や養子の場合の元の職業を算出する
+    if (b_class < MAX_PC_CLASS)
+    {                           //通常
+        bj.job = b_class;
+        bj.upper = 0;
+    }
+    else if (b_class >= 4001 && b_class < 4023)
+    {                           //転生職
+        bj.job = b_class - 4001;
+        bj.upper = 1;
+    }
+    else if (b_class == 23 + 4023 - 1)
+    {                           //養子スパノビ
+        bj.job = b_class - (4023 - 1);
+        bj.upper = 2;
+    }
+    else
+    {                           //養子スパノビ以外の養子
+        bj.job = b_class - 4023;
+        bj.upper = 2;
+    }
+
+    if (battle_config.enable_upper_class == 0)
+    {                           //confで無効になっていたらupper=0
+        bj.upper = 0;
+    }
+
+    if (bj.job == 0)
+    {
+        bj.type = 0;
+    }
+    else if (bj.job < 7)
+    {
+        bj.type = 1;
+    }
+    else
+    {
+        bj.type = 2;
+    }
+
+    return bj;
+}
+
+/*==========================================
+ * PCの攻撃 (timer関数)
+ *------------------------------------------
+ */
+void pc_attack_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd;
+    struct block_list *bl;
+    struct status_change *sc_data;
+    short *opt;
+    int  dist, skill, range;
+    int  attack_spell_delay;
+
+    sd = map_id2sd (id);
+    if (sd == NULL)
+        return;
+    if (sd->attacktimer != tid)
+    {
+        if (battle_config.error_log)
+            printf ("pc_attack_timer %d != %d\n", sd->attacktimer, tid);
+        return;
+    }
+    sd->attacktimer = -1;
+
+    if (sd->bl.prev == NULL)
+        return;
+
+    bl = map_id2bl (sd->attacktarget);
+    if (bl == NULL || bl->prev == NULL)
+        return;
+
+    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
+        return;
+
+    // 同じmapでないなら攻撃しない
+    // PCが死んでても攻撃しない
+    if (sd->bl.m != bl->m || pc_isdead (sd))
+        return;
+
+    if (sd->opt1 > 0 || sd->status.option & 2 || sd->status.option & 16388) // 異常などで攻撃できない
+        return;
+
+    if (sd->sc_data[SC_AUTOCOUNTER].timer != -1)
+        return;
+    if (sd->sc_data[SC_BLADESTOP].timer != -1)
+        return;
+
+    if ((opt = battle_get_option (bl)) != NULL && *opt & 0x46)
+        return;
+    if (((sc_data = battle_get_sc_data (bl)) != NULL
+         && sc_data[SC_TRICKDEAD].timer != -1)
+        || ((sc_data = battle_get_sc_data (bl)) != NULL
+            && sc_data[SC_BASILICA].timer != -1))
+        return;
+
+    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) <= 0)
+        return;
+
+    if (!battle_config.sdelay_attack_enable
+        && pc_checkskill (sd, SA_FREECAST) <= 0)
+    {
+        if (DIFF_TICK (tick, sd->canact_tick) < 0)
+        {
+            clif_skill_fail (sd, 1, 4, 0);
+            return;
+        }
+    }
+
+    if (sd->attackabletime > tick)
+        return;               // cannot attack yet
+
+    attack_spell_delay = sd->attack_spell_delay;
+    if (sd->attack_spell_override   // [Fate] If we have an active attack spell, use that
+        && spell_attack (id, sd->attacktarget))
+    {
+        // Return if the spell succeeded.  If the spell had disspiated, spell_attack() may fail.
+        sd->attackabletime = tick + attack_spell_delay;
+
+    }
+    else
+    {
+        dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y);
+        range = sd->attackrange;
+        if (sd->status.weapon != 11)
+            range++;
+        if (dist > range)
+        {                       // 届 かないので移動
+            //if(pc_can_reach(sd,bl->x,bl->y))
+            //clif_movetoattack(sd,bl);
+            return;
+        }
+
+        if (dist <= range && !battle_check_range (&sd->bl, bl, range))
+        {
+            if (pc_can_reach (sd, bl->x, bl->y) && sd->canmove_tick < tick
+                && (sd->sc_data[SC_ANKLE].timer == -1
+                    || sd->sc_data[SC_SPIDERWEB].timer == -1))
+                // TMW client doesn't support this
+                //pc_walktoxy(sd,bl->x,bl->y);
+                clif_movetoattack (sd, bl);
+            sd->attackabletime = tick + (sd->aspd << 1);
+        }
+        else
+        {
+            if (battle_config.pc_attack_direction_change)
+                sd->dir = sd->head_dir = map_calc_dir (&sd->bl, bl->x, bl->y);  // 向き設定
+
+            if (sd->walktimer != -1)
+                pc_stop_walking (sd, 1);
+
+            if (sd->sc_data[SC_COMBO].timer == -1)
+            {
+                map_freeblock_lock ();
+                pc_stop_walking (sd, 0);
+                sd->attacktarget_lv =
+                    battle_weapon_attack (&sd->bl, bl, tick, 0);
+                if (!(battle_config.pc_cloak_check_type & 2)
+                    && sd->sc_data[SC_CLOAKING].timer != -1)
+                    skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
+                map_freeblock_unlock ();
+                if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)  // フリーキャスト
+                    sd->attackabletime =
+                        tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
+                else
+                    sd->attackabletime = tick + (sd->aspd << 1);
+            }
+            else if (sd->attackabletime <= tick)
+            {
+                if (sd->skilltimer != -1 && (skill = pc_checkskill (sd, SA_FREECAST)) > 0)  // フリーキャスト
+                    sd->attackabletime =
+                        tick + ((sd->aspd << 1) * (150 - skill * 5) / 100);
+                else
+                    sd->attackabletime = tick + (sd->aspd << 1);
+            }
+            if (sd->attackabletime <= tick)
+                sd->attackabletime = tick + (battle_config.max_aspd << 1);
+        }
+    }
+
+    if (sd->state.attack_continue)
+    {
+        sd->attacktimer =
+            add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
+    }
+}
+
+/*==========================================
+ * 攻撃要求
+ * typeが1なら継続攻撃
+ *------------------------------------------
+ */
+int pc_attack (struct map_session_data *sd, int target_id, int type)
+{
+    struct block_list *bl;
+    int  d;
+
+    nullpo_retr (0, sd);
+
+    bl = map_id2bl (target_id);
+    if (bl == NULL)
+        return 1;
+
+    if (bl->type == BL_NPC)
+    {                           // monster npcs [Valaris]
+        npc_click (sd, RFIFOL (sd->fd, 2));
+        return 0;
+    }
+
+    if (!battle_check_target (&sd->bl, bl, BCT_ENEMY))
+        return 1;
+    if (sd->attacktimer != -1)
+        pc_stopattack (sd);
+    sd->attacktarget = target_id;
+    sd->state.attack_continue = type;
+
+    d = DIFF_TICK (sd->attackabletime, gettick ());
+    if (d > 0 && d < 2000)
+    {                           // 攻撃delay中
+        sd->attacktimer =
+            add_timer (sd->attackabletime, pc_attack_timer, sd->bl.id, 0);
+    }
+    else
+    {
+        // 本来timer関数なので引数を合わせる
+        pc_attack_timer (-1, gettick (), sd->bl.id, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 継続攻撃停止
+ *------------------------------------------
+ */
+int pc_stopattack (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->attacktimer != -1)
+    {
+        delete_timer (sd->attacktimer, pc_attack_timer);
+        sd->attacktimer = -1;
+    }
+    sd->attacktarget = 0;
+    sd->state.attack_continue = 0;
+
+    return 0;
+}
+
+void pc_follow_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd, *bl;
+
+    sd = map_id2sd (id);
+    if (sd == NULL || sd->followtimer != tid)
+        return;
+
+    sd->followtimer = -1;
+
+    do
+    {
+        if (sd->bl.prev == NULL)
+            break;
+
+        bl = (struct map_session_data *) map_id2bl (sd->followtarget);
+
+        if (bl == NULL)
+            return;
+
+        if (bl->bl.prev == NULL)
+            break;
+
+        if (bl->bl.type == BL_PC
+            && pc_isdead ((struct map_session_data *) bl))
+            return;
+
+        if (sd->skilltimer == -1 && sd->attacktimer == -1
+            && sd->walktimer == -1)
+        {
+            if ((sd->bl.m == bl->bl.m)
+                && pc_can_reach (sd, bl->bl.x, bl->bl.y))
+            {
+                if (distance (sd->bl.x, sd->bl.y, bl->bl.x, bl->bl.y) > 5)
+                    pc_walktoxy (sd, bl->bl.x, bl->bl.y);
+            }
+            else
+                pc_setpos ((struct map_session_data *) sd, bl->mapname,
+                           bl->bl.x, bl->bl.y, 3);
+        }
+    }
+    while (0);
+
+    sd->followtimer =
+        add_timer (tick + sd->aspd, pc_follow_timer, sd->bl.id, 0);
+}
+
+int pc_follow (struct map_session_data *sd, int target_id)
+{
+    struct block_list *bl;
+
+    bl = map_id2bl (target_id);
+    if (bl == NULL)
+        return 1;
+    sd->followtarget = target_id;
+    if (sd->followtimer != -1)
+    {
+        delete_timer (sd->followtimer, pc_follow_timer);
+        sd->followtimer = -1;
+    }
+
+    pc_follow_timer (-1, gettick (), sd->bl.id, 0);
+
+    return 0;
+}
+
+int pc_checkbaselevelup (struct map_session_data *sd)
+{
+    int  next = pc_nextbaseexp (sd);
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.base_exp >= next && next > 0)
+    {
+        struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
+
+        // base側レベルアップ処理
+        sd->status.base_exp -= next;
+
+        sd->status.base_level++;
+        sd->status.status_point += (sd->status.base_level + 14) / 4;
+        clif_updatestatus (sd, SP_STATUSPOINT);
+        clif_updatestatus (sd, SP_BASELEVEL);
+        clif_updatestatus (sd, SP_NEXTBASEEXP);
+        pc_calcstatus (sd, 0);
+        pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
+
+        //スパノビはキリエ、イムポ、マニピ、グロ、サフラLv1がかかる
+        if (s_class.job == 23)
+        {
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable[PR_KYRIE], 1, 0,
+                                       0, 0, skill_get_time (PR_KYRIE, 1), 0);
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable[PR_IMPOSITIO],
+                                       1, 0, 0, 0,
+                                       skill_get_time (PR_IMPOSITIO, 1), 0);
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable[PR_MAGNIFICAT],
+                                       1, 0, 0, 0,
+                                       skill_get_time (PR_MAGNIFICAT, 1), 0);
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable[PR_GLORIA], 1,
+                                       0, 0, 0, skill_get_time (PR_GLORIA, 1),
+                                       0);
+            skill_status_change_start (&sd->bl,
+                                       SkillStatusChangeTable[PR_SUFFRAGIUM],
+                                       1, 0, 0, 0,
+                                       skill_get_time (PR_SUFFRAGIUM, 1), 0);
+        }
+
+        clif_misceffect (&sd->bl, 0);
+        //レベルアップしたのでパーティー情報を更新する
+        //(公平範囲チェック)
+        party_send_movemap (sd);
+        MAP_LOG_XP (sd, "LEVELUP") return 1;
+    }
+
+    return 0;
+}
+
+/*========================================
+ * Compute the maximum for sd->skill_point, i.e., the max. number of skill points that can still be filled in
+ *----------------------------------------
+ */
+int pc_skillpt_potential (struct map_session_data *sd)
+{
+    int  skill_id;
+    int  potential = 0;
+
+#define RAISE_COST(x) (((x)*((x)-1))>>1)
+
+    for (skill_id = 0; skill_id < MAX_SKILL; skill_id++)
+        if (sd->status.skill[skill_id].id != 0
+            && sd->status.skill[skill_id].lv < skill_db[skill_id].max_raise)
+            potential += RAISE_COST (skill_db[skill_id].max_raise)
+                - RAISE_COST (sd->status.skill[skill_id].lv);
+#undef RAISE_COST
+
+    return potential;
+}
+
+int pc_checkjoblevelup (struct map_session_data *sd)
+{
+    int  next = pc_nextjobexp (sd);
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.job_exp >= next && next > 0)
+    {
+        if (pc_skillpt_potential (sd) < sd->status.skill_point)
+        {                       // [Fate] Bah, this is is painful.
+            // But the alternative is quite error-prone, and eAthena has far worse performance issues...
+            sd->status.job_exp = next - 1;
+            pc_calcstatus(sd,0);
+            return 0;
+        }
+
+        // job側レベルアップ処理
+        sd->status.job_exp -= next;
+        clif_updatestatus (sd, SP_NEXTJOBEXP);
+        sd->status.skill_point++;
+        clif_updatestatus (sd, SP_SKILLPOINT);
+        pc_calcstatus (sd, 0);
+
+        MAP_LOG_PC (sd, "SKILLPOINTS-UP %d", sd->status.skill_point);
+
+        if (sd->status.job_level < 250
+            && sd->status.job_level < sd->status.base_level * 2)
+            sd->status.job_level++; // Make levelling up a little harder
+
+        clif_misceffect (&sd->bl, 1);
+        return 1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 経験値取得
+ *------------------------------------------
+ */
+int pc_gainexp (struct map_session_data *sd, int base_exp, int job_exp)
+{
+    return pc_gainexp_reason (sd, base_exp, job_exp,
+                              PC_GAINEXP_REASON_KILLING);
+}
+
+int pc_gainexp_reason (struct map_session_data *sd, int base_exp, int job_exp,
+                       int reason)
+{
+    char output[256];
+    nullpo_retr (0, sd);
+
+    if (sd->bl.prev == NULL || pc_isdead (sd))
+        return 0;
+
+    if ((battle_config.pvp_exp == 0) && map[sd->bl.m].flag.pvp) // [MouseJstr]
+        return 0;               // no exp on pvp maps
+
+    MAP_LOG_PC (sd, "GAINXP %d %d %s", base_exp, job_exp,
+                ((reason ==
+                  2) ? "SCRIPTXP" : ((reason == 1) ? "HEALXP" : "KILLXP")));
+
+    if (sd->sc_data[SC_RICHMANKIM].timer != -1)
+    {                           // added bounds checking [Vaalris]
+        base_exp +=
+            base_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
+        job_exp +=
+            job_exp * (25 + sd->sc_data[SC_RICHMANKIM].val1 * 25) / 100;
+    }
+
+    if (sd->status.guild_id > 0)
+    {                           // ギルドに上納
+        base_exp -= guild_payexp (sd, base_exp);
+        if (base_exp < 0)
+            base_exp = 0;
+    }
+
+    if (!battle_config.multi_level_up && pc_nextbaseafter (sd))
+    {
+        while (sd->status.base_exp + base_exp >= pc_nextbaseafter (sd)
+               && sd->status.base_exp <= pc_nextbaseexp (sd)
+               && pc_nextbaseafter (sd) > 0)
+        {
+            base_exp *= .90;
+        }
+    }
+
+    sd->status.base_exp += base_exp;
+
+    // [Fate] Adjust experience points that healers can extract from this character
+    if (reason != PC_GAINEXP_REASON_HEALING)
+    {
+        const int max_heal_xp =
+            20 + (sd->status.base_level * sd->status.base_level);
+
+        sd->heal_xp += base_exp;
+        if (sd->heal_xp > max_heal_xp)
+            sd->heal_xp = max_heal_xp;
+    }
+
+    if (sd->status.base_exp < 0)
+        sd->status.base_exp = 0;
+
+    while (pc_checkbaselevelup (sd));
+
+    clif_updatestatus (sd, SP_BASEEXP);
+    if (!battle_config.multi_level_up && pc_nextjobafter (sd))
+    {
+        while (sd->status.job_exp + job_exp >= pc_nextjobafter (sd)
+               && sd->status.job_exp <= pc_nextjobexp (sd)
+               && pc_nextjobafter (sd) > 0)
+        {
+            job_exp *= .90;
+        }
+    }
+
+    sd->status.job_exp += job_exp;
+    if (sd->status.job_exp < 0)
+        sd->status.job_exp = 0;
+
+    while (pc_checkjoblevelup (sd));
+
+    clif_updatestatus (sd, SP_JOBEXP);
+
+    if (battle_config.disp_experience)
+    {
+        sprintf (output,
+                 "Experienced Gained Base:%d Job:%d", base_exp, job_exp);
+        clif_disp_onlyself (sd, output, strlen (output));
+    }
+
+    return 0;
+}
+
+int pc_extract_healer_exp (struct map_session_data *sd, int max)
+{
+    int  amount;
+    nullpo_retr (0, sd);
+
+    amount = sd->heal_xp;
+    if (max < amount)
+        amount = max;
+
+    sd->heal_xp -= amount;
+    return amount;
+}
+
+/*==========================================
+ * base level側必要経験値計算
+ *------------------------------------------
+ */
+int pc_nextbaseexp (struct map_session_data *sd)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
+        return 0;
+
+    if (sd->status.pc_class == 0)
+        i = 0;
+    else if (sd->status.pc_class <= 6)
+        i = 1;
+    else if (sd->status.pc_class <= 22)
+        i = 2;
+    else if (sd->status.pc_class == 23)
+        i = 3;
+    else if (sd->status.pc_class == 4001)
+        i = 4;
+    else if (sd->status.pc_class <= 4007)
+        i = 5;
+    else
+        i = 6;
+
+    return exp_table[i][sd->status.base_level - 1];
+}
+
+/*==========================================
+ * job level側必要経験値計算
+ *------------------------------------------
+ */
+int pc_nextjobexp (struct map_session_data *sd)
+{
+    // [fate]  For normal levels, this ranges from 20k to 50k, depending on job level.
+    // Job level is at most twice the player's experience level (base_level).  Levelling
+    // from 2 to 9 is 44 points, i.e., 880k to 2.2M job experience points (this is per
+    // skill, obviously.)
+
+    return 20000 + sd->status.job_level * 150;
+}
+
+/*==========================================
+ * base level after next [Valaris]
+ *------------------------------------------
+ */
+int pc_nextbaseafter (struct map_session_data *sd)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.base_level >= MAX_LEVEL || sd->status.base_level <= 0)
+        return 0;
+
+    if (sd->status.pc_class == 0)
+        i = 0;
+    else if (sd->status.pc_class <= 6)
+        i = 1;
+    else if (sd->status.pc_class <= 22)
+        i = 2;
+    else if (sd->status.pc_class == 23)
+        i = 3;
+    else if (sd->status.pc_class == 4001)
+        i = 4;
+    else if (sd->status.pc_class <= 4007)
+        i = 5;
+    else
+        i = 6;
+
+    return exp_table[i][sd->status.base_level];
+}
+
+/*==========================================
+ * job level after next [Valaris]
+ *------------------------------------------
+ */
+int pc_nextjobafter (struct map_session_data *sd)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.job_level >= MAX_LEVEL || sd->status.job_level <= 0)
+        return 0;
+
+    if (sd->status.pc_class == 0)
+        i = 7;
+    else if (sd->status.pc_class <= 6)
+        i = 8;
+    else if (sd->status.pc_class <= 22)
+        i = 9;
+    else if (sd->status.pc_class == 23)
+        i = 10;
+    else if (sd->status.pc_class == 4001)
+        i = 11;
+    else if (sd->status.pc_class <= 4007)
+        i = 12;
+    else
+        i = 13;
+
+    return exp_table[i][sd->status.job_level];
+}
+
+/*==========================================
+
+ * 必要ステータスポイント計算
+ *------------------------------------------
+ */
+int pc_need_status_point (struct map_session_data *sd, int type)
+{
+    int  val;
+
+    nullpo_retr (-1, sd);
+
+    if (type < SP_STR || type > SP_LUK)
+        return -1;
+    val =
+        type == SP_STR ? sd->status.str :
+        type == SP_AGI ? sd->status.agi :
+        type == SP_VIT ? sd->status.vit :
+        type == SP_INT ? sd->status.int_ :
+        type == SP_DEX ? sd->status.dex : sd->status.luk;
+
+    return (val + 9) / 10 + 1;
+}
+
+/*==========================================
+ * 能力値成長
+ *------------------------------------------
+ */
+int pc_statusup (struct map_session_data *sd, int type)
+{
+    int  need, val = 0;
+
+    nullpo_retr (0, sd);
+
+    switch (type)
+    {
+        case SP_STR:
+            val = sd->status.str;
+            break;
+        case SP_AGI:
+            val = sd->status.agi;
+            break;
+        case SP_VIT:
+            val = sd->status.vit;
+            break;
+        case SP_INT:
+            val = sd->status.int_;
+            break;
+        case SP_DEX:
+            val = sd->status.dex;
+            break;
+        case SP_LUK:
+            val = sd->status.luk;
+            break;
+    }
+
+    need = pc_need_status_point (sd, type);
+    if (type < SP_STR || type > SP_LUK || need < 0
+        || need > sd->status.status_point
+        || val >= battle_config.max_parameter)
+    {
+        clif_statusupack (sd, type, 0, val);
+        clif_updatestatus (sd, SP_STATUSPOINT);
+        return 1;
+    }
+    switch (type)
+    {
+        case SP_STR:
+            val = ++sd->status.str;
+            break;
+        case SP_AGI:
+            val = ++sd->status.agi;
+            break;
+        case SP_VIT:
+            val = ++sd->status.vit;
+            break;
+        case SP_INT:
+            val = ++sd->status.int_;
+            break;
+        case SP_DEX:
+            val = ++sd->status.dex;
+            break;
+        case SP_LUK:
+            val = ++sd->status.luk;
+            break;
+    }
+    sd->status.status_point -= need;
+    if (need != pc_need_status_point (sd, type))
+    {
+        clif_updatestatus (sd, type - SP_STR + SP_USTR);
+    }
+    clif_updatestatus (sd, SP_STATUSPOINT);
+    clif_updatestatus (sd, type);
+    pc_calcstatus (sd, 0);
+    clif_statusupack (sd, type, 1, val);
+
+    MAP_LOG_STATS (sd, "STATUP");
+
+    return 0;
+}
+
+/*==========================================
+ * 能力値成長
+ *------------------------------------------
+ */
+int pc_statusup2 (struct map_session_data *sd, int type, int val)
+{
+    nullpo_retr (0, sd);
+
+    if (type < SP_STR || type > SP_LUK)
+    {
+        clif_statusupack (sd, type, 0, 0);
+        return 1;
+    }
+    switch (type)
+    {
+        case SP_STR:
+            if (sd->status.str + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.str + val < 1)
+                val = 1;
+            else
+                val += sd->status.str;
+            sd->status.str = val;
+            break;
+        case SP_AGI:
+            if (sd->status.agi + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.agi + val < 1)
+                val = 1;
+            else
+                val += sd->status.agi;
+            sd->status.agi = val;
+            break;
+        case SP_VIT:
+            if (sd->status.vit + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.vit + val < 1)
+                val = 1;
+            else
+                val += sd->status.vit;
+            sd->status.vit = val;
+            break;
+        case SP_INT:
+            if (sd->status.int_ + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.int_ + val < 1)
+                val = 1;
+            else
+                val += sd->status.int_;
+            sd->status.int_ = val;
+            break;
+        case SP_DEX:
+            if (sd->status.dex + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.dex + val < 1)
+                val = 1;
+            else
+                val += sd->status.dex;
+            sd->status.dex = val;
+            break;
+        case SP_LUK:
+            if (sd->status.luk + val >= battle_config.max_parameter)
+                val = battle_config.max_parameter;
+            else if (sd->status.luk + val < 1)
+                val = 1;
+            else
+                val = sd->status.luk + val;
+            sd->status.luk = val;
+            break;
+    }
+    clif_updatestatus (sd, type - SP_STR + SP_USTR);
+    clif_updatestatus (sd, type);
+    pc_calcstatus (sd, 0);
+    clif_statusupack (sd, type, 1, val);
+    MAP_LOG_STATS (sd, "STATUP2");
+
+    return 0;
+}
+
+/*==========================================
+ * スキルポイント割り振り
+ *------------------------------------------
+ */
+int pc_skillup (struct map_session_data *sd, int skill_num)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->status.skill[skill_num].id != 0
+        && sd->status.skill_point >= sd->status.skill[skill_num].lv
+        && sd->status.skill[skill_num].lv < skill_db[skill_num].max_raise)
+    {
+        sd->status.skill_point -= sd->status.skill[skill_num].lv;
+        sd->status.skill[skill_num].lv++;
+
+        pc_calcstatus (sd, 0);
+        clif_skillup (sd, skill_num);
+        clif_updatestatus (sd, SP_SKILLPOINT);
+        clif_skillinfoblock (sd);
+        MAP_LOG_PC(sd, "SKILLUP %d %d %d",
+                   skill_num, sd->status.skill[skill_num].lv, skill_power(sd, skill_num));
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * /allskill
+ *------------------------------------------
+ */
+int pc_allskillup (struct map_session_data *sd)
+{
+    int  i, id;
+    int  c = 0, s = 0;
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+    c = s_class.job;
+    s = (s_class.upper == 1) ? 1 : 0;   //転生以外は通常のスキル?
+
+    for (i = 0; i < MAX_SKILL; i++)
+        sd->status.skill[i].id = 0;
+
+    if (battle_config.gm_allskill > 0
+        && pc_isGM (sd) >= battle_config.gm_allskill)
+    {
+        // 全てのスキル
+        for (i = 1; i < 158; i++)
+            sd->status.skill[i].lv = skill_get_max (i);
+        for (i = 210; i < 291; i++)
+            sd->status.skill[i].lv = skill_get_max (i);
+        for (i = 304; i < MAX_SKILL; i++)
+            sd->status.skill[i].lv = skill_get_max (i);
+    }
+    else
+    {
+        for (i = 0; (id = skill_tree[s][c][i].id) > 0; i++)
+        {
+            if (sd->status.skill[id].id == 0 && skill_get_inf2 (id) & 0x01)
+                sd->status.skill[id].lv = skill_get_max (id);
+        }
+    }
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * /resetlvl
+ *------------------------------------------
+ */
+int pc_resetlvl (struct map_session_data *sd, int type)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 1; i < MAX_SKILL; i++)
+    {
+        sd->status.skill[i].lv = 0;
+    }
+
+    if (type == 1)
+    {
+        sd->status.skill_point = 0;
+        sd->status.base_level = 1;
+        sd->status.job_level = 1;
+        sd->status.base_exp = 0;
+        sd->status.job_exp = 0;
+        if (sd->status.option != 0)
+            sd->status.option = 0;
+
+        sd->status.str = 1;
+        sd->status.agi = 1;
+        sd->status.vit = 1;
+        sd->status.int_ = 1;
+        sd->status.dex = 1;
+        sd->status.luk = 1;
+        if (sd->status.pc_class == 4001)
+            sd->status.status_point = 100;
+    }
+
+    if (type == 2)
+    {
+        sd->status.skill_point = 0;
+        sd->status.base_level = 1;
+        sd->status.job_level = 1;
+        sd->status.base_exp = 0;
+        sd->status.job_exp = 0;
+    }
+    if (type == 3)
+    {
+        sd->status.base_level = 1;
+        sd->status.base_exp = 0;
+    }
+    if (type == 4)
+    {
+        sd->status.job_level = 1;
+        sd->status.job_exp = 0;
+    }
+
+    clif_updatestatus (sd, SP_STATUSPOINT);
+    clif_updatestatus (sd, SP_STR);
+    clif_updatestatus (sd, SP_AGI);
+    clif_updatestatus (sd, SP_VIT);
+    clif_updatestatus (sd, SP_INT);
+    clif_updatestatus (sd, SP_DEX);
+    clif_updatestatus (sd, SP_LUK);
+    clif_updatestatus (sd, SP_BASELEVEL);
+    clif_updatestatus (sd, SP_JOBLEVEL);
+    clif_updatestatus (sd, SP_STATUSPOINT);
+    clif_updatestatus (sd, SP_NEXTBASEEXP);
+    clif_updatestatus (sd, SP_NEXTJOBEXP);
+    clif_updatestatus (sd, SP_SKILLPOINT);
+
+    clif_updatestatus (sd, SP_USTR);    // Updates needed stat points - Valaris
+    clif_updatestatus (sd, SP_UAGI);
+    clif_updatestatus (sd, SP_UVIT);
+    clif_updatestatus (sd, SP_UINT);
+    clif_updatestatus (sd, SP_UDEX);
+    clif_updatestatus (sd, SP_ULUK);    // End Addition
+
+    for (i = 0; i < 11; i++)
+    {                           // unequip items that can't be equipped by base 1 [Valaris]
+        if (sd->equip_index[i] >= 0)
+            if (!pc_isequip (sd, sd->equip_index[i]))
+            {
+                pc_unequipitem (sd, sd->equip_index[i], 1);
+                sd->equip_index[i] = -1;
+            }
+    }
+
+    clif_skillinfoblock (sd);
+    pc_calcstatus (sd, 0);
+
+    MAP_LOG_STATS (sd, "STATRESET");
+
+    return 0;
+}
+
+/*==========================================
+ * /resetstate
+ *------------------------------------------
+ */
+int pc_resetstate (struct map_session_data *sd)
+{
+#define sumsp(a) ((a)*((a-2)/10+2) - 5*((a-2)/10)*((a-2)/10) - 6*((a-2)/10) -2)
+//  int add=0; // Removed by Dexity
+
+    nullpo_retr (0, sd);
+
+//  New statpoint table used here - Dexity
+    sd->status.status_point = atoi (statp[sd->status.base_level - 1]);
+//  End addition
+
+//  Removed by Dexity - old count
+//  add += sumsp(sd->status.str);
+//  add += sumsp(sd->status.agi);
+//  add += sumsp(sd->status.vit);
+//  add += sumsp(sd->status.int_);
+//  add += sumsp(sd->status.dex);
+//  add += sumsp(sd->status.luk);
+//  sd->status.status_point+=add;
+
+    clif_updatestatus (sd, SP_STATUSPOINT);
+
+    sd->status.str = 1;
+    sd->status.agi = 1;
+    sd->status.vit = 1;
+    sd->status.int_ = 1;
+    sd->status.dex = 1;
+    sd->status.luk = 1;
+
+    clif_updatestatus (sd, SP_STR);
+    clif_updatestatus (sd, SP_AGI);
+    clif_updatestatus (sd, SP_VIT);
+    clif_updatestatus (sd, SP_INT);
+    clif_updatestatus (sd, SP_DEX);
+    clif_updatestatus (sd, SP_LUK);
+
+    clif_updatestatus (sd, SP_USTR);    // Updates needed stat points - Valaris
+    clif_updatestatus (sd, SP_UAGI);
+    clif_updatestatus (sd, SP_UVIT);
+    clif_updatestatus (sd, SP_UINT);
+    clif_updatestatus (sd, SP_UDEX);
+    clif_updatestatus (sd, SP_ULUK);    // End Addition
+
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * /resetskill
+ *------------------------------------------
+ */
+int pc_resetskill (struct map_session_data *sd)
+{
+    int  i, skill;
+
+    nullpo_retr (0, sd);
+
+    sd->status.skill_point += pc_calc_skillpoint (sd);
+
+    for (i = 1; i < MAX_SKILL; i++)
+        if ((skill = pc_checkskill (sd, i)) > 0)
+        {
+            sd->status.skill[i].lv = 0;
+            sd->status.skill[i].flags = 0;
+        }
+
+    clif_updatestatus (sd, SP_SKILLPOINT);
+    clif_skillinfoblock (sd);
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * pcにダメージを与える
+ *------------------------------------------
+ */
+int pc_damage (struct block_list *src, struct map_session_data *sd,
+               int damage)
+{
+    int  i = 0, j = 0;
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    //転生や養子の場合の元の職業を算出する
+    s_class = pc_calc_base_job (sd->status.pc_class);
+    // 既に死んでいたら無効
+    if (pc_isdead (sd))
+        return 0;
+    // 座ってたら立ち上がる
+    if (pc_issit (sd))
+    {
+        pc_setstand (sd);
+        skill_gangsterparadise (sd, 0);
+    }
+
+    if (src)
+    {
+        if (src->type == BL_PC)
+        {
+            MAP_LOG_PC (sd, "INJURED-BY PC%d FOR %d",
+                        ((struct map_session_data *) src)->status.char_id,
+                        damage);
+        }
+        else
+        {
+            MAP_LOG_PC (sd, "INJURED-BY MOB%d FOR %d", src->id, damage);
+        }
+    }
+    else
+        MAP_LOG_PC (sd, "INJURED-BY null FOR %d", damage);
+
+    // 歩 いていたら足を止める
+    if (sd->sc_data[SC_ENDURE].timer == -1
+        && !sd->special_state.infinite_endure)
+        pc_stop_walking (sd, 3);
+    // 演奏/ダンスの中断
+    if (damage > sd->status.max_hp >> 2)
+        skill_stop_dancing (&sd->bl, 0);
+
+    sd->status.hp -= damage;
+
+    if (sd->sc_data[SC_TRICKDEAD].timer != -1)
+        skill_status_change_end (&sd->bl, SC_TRICKDEAD, -1);
+    if (sd->status.option & 2)
+        skill_status_change_end (&sd->bl, SC_HIDING, -1);
+    if (sd->status.option & 4)
+        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
+    if (sd->status.option & 16386)
+        skill_status_change_end (&sd->bl, SC_CHASEWALK, -1);
+
+    if (sd->status.hp > 0)
+    {
+        // まだ生きているならHP更新
+        clif_updatestatus (sd, SP_HP);
+
+        if (sd->status.hp < sd->status.max_hp >> 2
+            && pc_checkskill (sd, SM_AUTOBERSERK) > 0
+            && (sd->sc_data[SC_PROVOKE].timer == -1
+                || sd->sc_data[SC_PROVOKE].val2 == 0))
+            // オートバーサーク発動
+            skill_status_change_start (&sd->bl, SC_PROVOKE, 10, 1, 0, 0, 0,
+                                       0);
+
+        sd->canlog_tick = gettick ();
+
+        if (sd->status.party_id > 0)
+        {                       // on-the-fly party hp updates [Valaris]
+            struct party *p = party_search (sd->status.party_id);
+            if (p != NULL)
+                clif_party_hp (p, sd);
+        }                       // end addition [Valaris]
+
+        return 0;
+    }
+
+    MAP_LOG_PC (sd, "DEAD%s", "");
+
+    // Character is dead!
+
+    sd->status.hp = 0;
+    // [Fate] Stop quickregen
+    sd->quick_regeneration_hp.amount = 0;
+    sd->quick_regeneration_sp.amount = 0;
+    skill_update_heal_animation (sd);
+
+    pc_setdead (sd);
+
+    pc_stop_walking (sd, 0);
+    skill_castcancel (&sd->bl, 0);  // 詠唱の中止
+    clif_clearchar_area (&sd->bl, 1);
+    skill_unit_out_all (&sd->bl, gettick (), 1);
+    if (sd->sc_data[SC_BLADESTOP].timer != -1)  //白刃は事前に解除
+        skill_status_change_end (&sd->bl, SC_BLADESTOP, -1);
+    pc_setglobalreg (sd, "PC_DIE_COUNTER", ++sd->die_counter);  //死にカウンター書き込み
+    skill_status_change_clear (&sd->bl, 0); // ステータス異常を解除する
+    clif_updatestatus (sd, SP_HP);
+    pc_calcstatus (sd, 0);
+    // [Fate] Reset magic
+    sd->cast_tick = gettick ();
+    magic_stop_completely (sd);
+
+    for (i = 0; i < 5; i++)
+        if (sd->dev.val1[i])
+        {
+            skill_status_change_end (&map_id2sd (sd->dev.val1[i])->bl,
+                                     SC_DEVOTION, -1);
+            sd->dev.val1[i] = sd->dev.val2[i] = 0;
+        }
+
+    if (battle_config.death_penalty_type > 0 && sd->status.base_level >= 20)
+    {                           // changed penalty options, added death by player if pk_mode [Valaris]
+        if (!map[sd->bl.m].flag.nopenalty && !map[sd->bl.m].flag.gvg)
+        {
+            if (battle_config.death_penalty_type == 1
+                && battle_config.death_penalty_base > 0)
+                sd->status.base_exp -=
+                    (double) pc_nextbaseexp (sd) *
+                    (double) battle_config.death_penalty_base / 10000;
+            if (battle_config.pk_mode && src && src->type == BL_PC)
+                sd->status.base_exp -=
+                    (double) pc_nextbaseexp (sd) *
+                    (double) battle_config.death_penalty_base / 10000;
+            else if (battle_config.death_penalty_type == 2
+                     && battle_config.death_penalty_base > 0)
+            {
+                if (pc_nextbaseexp (sd) > 0)
+                    sd->status.base_exp -=
+                        (double) sd->status.base_exp *
+                        (double) battle_config.death_penalty_base / 10000;
+                if (battle_config.pk_mode && src && src->type == BL_PC)
+                    sd->status.base_exp -=
+                        (double) sd->status.base_exp *
+                        (double) battle_config.death_penalty_base / 10000;
+            }
+            if (sd->status.base_exp < 0)
+                sd->status.base_exp = 0;
+            clif_updatestatus (sd, SP_BASEEXP);
+
+            if (battle_config.death_penalty_type == 1
+                && battle_config.death_penalty_job > 0)
+                sd->status.job_exp -=
+                    (double) pc_nextjobexp (sd) *
+                    (double) battle_config.death_penalty_job / 10000;
+            if (battle_config.pk_mode && src && src->type == BL_PC)
+                sd->status.job_exp -=
+                    (double) pc_nextjobexp (sd) *
+                    (double) battle_config.death_penalty_job / 10000;
+            else if (battle_config.death_penalty_type == 2
+                     && battle_config.death_penalty_job > 0)
+            {
+                if (pc_nextjobexp (sd) > 0)
+                    sd->status.job_exp -=
+                        (double) sd->status.job_exp *
+                        (double) battle_config.death_penalty_job / 10000;
+                if (battle_config.pk_mode && src && src->type == BL_PC)
+                    sd->status.job_exp -=
+                        (double) sd->status.job_exp *
+                        (double) battle_config.death_penalty_job / 10000;
+            }
+            if (sd->status.job_exp < 0)
+                sd->status.job_exp = 0;
+            clif_updatestatus (sd, SP_JOBEXP);
+        }
+    }
+    //ナイトメアモードアイテムドロップ
+    if (map[sd->bl.m].flag.pvp_nightmaredrop)
+    {                           // Moved this outside so it works when PVP isnt enabled and during pk mode [Ancyker]
+        for (j = 0; j < MAX_DROP_PER_MAP; j++)
+        {
+            int  id = map[sd->bl.m].drop_list[j].drop_id;
+            int  type = map[sd->bl.m].drop_list[j].drop_type;
+            int  per = map[sd->bl.m].drop_list[j].drop_per;
+            if (id == 0)
+                continue;
+            if (id == -1)
+            {                   //ランダムドロップ
+                int  eq_num = 0, eq_n[MAX_INVENTORY];
+                memset (eq_n, 0, sizeof (eq_n));
+                //先ず装備しているアイテム数をカウント
+                for (i = 0; i < MAX_INVENTORY; i++)
+                {
+                    int  k;
+                    if ((type == 1 && !sd->status.inventory[i].equip)
+                        || (type == 2 && sd->status.inventory[i].equip)
+                        || type == 3)
+                    {
+                        //InventoryIndexを格納
+                        for (k = 0; k < MAX_INVENTORY; k++)
+                        {
+                            if (eq_n[k] <= 0)
+                            {
+                                eq_n[k] = i;
+                                break;
+                            }
+                        }
+                        eq_num++;
+                    }
+                }
+                if (eq_num > 0)
+                {
+                    int  n = eq_n[MRAND (eq_num)];  //該当アイテムの中からランダム
+                    if (MRAND (10000) < per)
+                    {
+                        if (sd->status.inventory[n].equip)
+                            pc_unequipitem (sd, n, 0);
+                        pc_dropitem (sd, n, 1);
+                    }
+                }
+            }
+            else if (id > 0)
+            {
+                for (i = 0; i < MAX_INVENTORY; i++)
+                {
+                    if (sd->status.inventory[i].nameid == id    //ItemIDが一致していて
+                        && MRAND (10000) < per  //ドロップ率判定もOKで
+                        && ((type == 1 && !sd->status.inventory[i].equip)   //タイプ判定もOKならドロップ
+                            || (type == 2 && sd->status.inventory[i].equip)
+                            || type == 3))
+                    {
+                        if (sd->status.inventory[i].equip)
+                            pc_unequipitem (sd, i, 0);
+                        pc_dropitem (sd, i, 1);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    // pvp
+    if (map[sd->bl.m].flag.pvp && !battle_config.pk_mode)
+    {                           // disable certain pvp functions on pk_mode [Valaris]
+        //ランキング計算
+        if (!map[sd->bl.m].flag.pvp_nocalcrank)
+        {
+            sd->pvp_point -= 5;
+            if (src && src->type == BL_PC)
+                ((struct map_session_data *) src)->pvp_point++;
+            //} //fixed wrong '{' placement by Lupus
+            pc_setdead (sd);
+        }
+        // 強制送還
+        if (sd->pvp_point < 0)
+        {
+            sd->pvp_point = 0;
+            pc_setstand (sd);
+            pc_setrestartvalue (sd, 3);
+            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
+                       sd->status.save_point.y, 0);
+        }
+    }
+    //GvG
+    if (map[sd->bl.m].flag.gvg)
+    {
+        pc_setstand (sd);
+        pc_setrestartvalue (sd, 3);
+        pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
+                   sd->status.save_point.y, 0);
+    }
+
+    if (src && src->type == BL_PC)
+    {
+        // [Fate] PK death, trigger scripts
+        argrec_t arg[3];
+        arg[0].name = "@killerrid";
+        arg[0].v.i = src->id;
+        arg[1].name = "@victimrid";
+        arg[1].v.i = sd->bl.id;
+        arg[2].name = "@victimlvl";
+        arg[2].v.i = sd->status.base_level;
+        npc_event_doall_l ("OnPCKilledEvent", sd->bl.id, 3, arg);
+        npc_event_doall_l ("OnPCKillEvent", src->id, 3, arg);
+    }
+    npc_event_doall_l ("OnPCDieEvent", sd->bl.id, 0, NULL);
+
+    return 0;
+}
+
+//
+// script関 連
+//
+/*==========================================
+ * script用PCステータス読み出し
+ *------------------------------------------
+ */
+int pc_readparam (struct map_session_data *sd, int type)
+{
+    int  val = 0;
+    struct pc_base_job s_class;
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    nullpo_retr (0, sd);
+
+    switch (type)
+    {
+        case SP_SKILLPOINT:
+            val = sd->status.skill_point;
+            break;
+        case SP_STATUSPOINT:
+            val = sd->status.status_point;
+            break;
+        case SP_ZENY:
+            val = sd->status.zeny;
+            break;
+        case SP_BASELEVEL:
+            val = sd->status.base_level;
+            break;
+        case SP_JOBLEVEL:
+            val = sd->status.job_level;
+            break;
+        case SP_CLASS:
+            if (val >= 24 && val < 45)
+                val += 3978;
+            else
+                val = sd->status.pc_class;
+            break;
+        case SP_UPPER:
+            val = s_class.upper;
+            break;
+        case SP_SEX:
+            val = sd->sex;
+            break;
+        case SP_WEIGHT:
+            val = sd->weight;
+            break;
+        case SP_MAXWEIGHT:
+            val = sd->max_weight;
+            break;
+        case SP_BASEEXP:
+            val = sd->status.base_exp;
+            break;
+        case SP_JOBEXP:
+            val = sd->status.job_exp;
+            break;
+        case SP_NEXTBASEEXP:
+            val = pc_nextbaseexp (sd);
+            break;
+        case SP_NEXTJOBEXP:
+            val = pc_nextjobexp (sd);
+            break;
+        case SP_HP:
+            val = sd->status.hp;
+            break;
+        case SP_MAXHP:
+            val = sd->status.max_hp;
+            break;
+        case SP_SP:
+            val = sd->status.sp;
+            break;
+        case SP_MAXSP:
+            val = sd->status.max_sp;
+            break;
+        case SP_STR:
+            val = sd->status.str;
+            break;
+        case SP_AGI:
+            val = sd->status.agi;
+            break;
+        case SP_VIT:
+            val = sd->status.vit;
+            break;
+        case SP_INT:
+            val = sd->status.int_;
+            break;
+        case SP_DEX:
+            val = sd->status.dex;
+            break;
+        case SP_LUK:
+            val = sd->status.luk;
+            break;
+        case SP_FAME:
+            val = sd->fame;
+            break;
+    }
+
+    return val;
+}
+
+/*==========================================
+ * script用PCステータス設定
+ *------------------------------------------
+ */
+int pc_setparam (struct map_session_data *sd, int type, int val)
+{
+    int  i = 0, up_level = 50;
+    struct pc_base_job s_class;
+
+    nullpo_retr (0, sd);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    switch (type)
+    {
+        case SP_BASELEVEL:
+            if (val > sd->status.base_level)
+            {
+                for (i = 1; i <= (val - sd->status.base_level); i++)
+                    sd->status.status_point +=
+                        (sd->status.base_level + i + 14) / 4;
+            }
+            sd->status.base_level = val;
+            sd->status.base_exp = 0;
+            clif_updatestatus (sd, SP_BASELEVEL);
+            clif_updatestatus (sd, SP_NEXTBASEEXP);
+            clif_updatestatus (sd, SP_STATUSPOINT);
+            clif_updatestatus (sd, SP_BASEEXP);
+            pc_calcstatus (sd, 0);
+            pc_heal (sd, sd->status.max_hp, sd->status.max_sp);
+            break;
+        case SP_JOBLEVEL:
+            if (sd->status.pc_class == 0)
+                up_level -= 40;
+            if ((sd->status.pc_class == 23)
+                || (sd->status.pc_class >= 4001 && sd->status.pc_class <= 4022))
+                up_level += 20;
+            if (val >= sd->status.job_level)
+            {
+                if (val > up_level)
+                    val = up_level;
+                sd->status.skill_point += (val - sd->status.job_level);
+                sd->status.job_level = val;
+                sd->status.job_exp = 0;
+                clif_updatestatus (sd, SP_JOBLEVEL);
+                clif_updatestatus (sd, SP_NEXTJOBEXP);
+                clif_updatestatus (sd, SP_JOBEXP);
+                clif_updatestatus (sd, SP_SKILLPOINT);
+                pc_calcstatus (sd, 0);
+                clif_misceffect (&sd->bl, 1);
+            }
+            else
+            {
+                sd->status.job_level = val;
+                sd->status.job_exp = 0;
+                clif_updatestatus (sd, SP_JOBLEVEL);
+                clif_updatestatus (sd, SP_NEXTJOBEXP);
+                clif_updatestatus (sd, SP_JOBEXP);
+                pc_calcstatus (sd, 0);
+            }
+            clif_updatestatus (sd, type);
+            break;
+        case SP_SKILLPOINT:
+            sd->status.skill_point = val;
+            break;
+        case SP_STATUSPOINT:
+            sd->status.status_point = val;
+            break;
+        case SP_ZENY:
+            sd->status.zeny = val;
+            break;
+        case SP_BASEEXP:
+            if (pc_nextbaseexp (sd) > 0)
+            {
+                sd->status.base_exp = val;
+                if (sd->status.base_exp < 0)
+                    sd->status.base_exp = 0;
+                pc_checkbaselevelup (sd);
+            }
+            break;
+        case SP_JOBEXP:
+            if (pc_nextjobexp (sd) > 0)
+            {
+                sd->status.job_exp = val;
+                if (sd->status.job_exp < 0)
+                    sd->status.job_exp = 0;
+                pc_checkjoblevelup (sd);
+            }
+            break;
+        case SP_SEX:
+            sd->sex = val;
+            break;
+        case SP_WEIGHT:
+            sd->weight = val;
+            break;
+        case SP_MAXWEIGHT:
+            sd->max_weight = val;
+            break;
+        case SP_HP:
+            sd->status.hp = val;
+            break;
+        case SP_MAXHP:
+            sd->status.max_hp = val;
+            break;
+        case SP_SP:
+            sd->status.sp = val;
+            break;
+        case SP_MAXSP:
+            sd->status.max_sp = val;
+            break;
+        case SP_STR:
+            sd->status.str = val;
+            break;
+        case SP_AGI:
+            sd->status.agi = val;
+            break;
+        case SP_VIT:
+            sd->status.vit = val;
+            break;
+        case SP_INT:
+            sd->status.int_ = val;
+            break;
+        case SP_DEX:
+            sd->status.dex = val;
+            break;
+        case SP_LUK:
+            sd->status.luk = val;
+            break;
+        case SP_FAME:
+            sd->fame = val;
+            break;
+    }
+    clif_updatestatus (sd, type);
+
+    return 0;
+}
+
+/*==========================================
+ * HP/SP回復
+ *------------------------------------------
+ */
+int pc_heal (struct map_session_data *sd, int hp, int sp)
+{
+//  if(battle_config.battle_log)
+//      printf("heal %d %d\n",hp,sp);
+
+    nullpo_retr (0, sd);
+
+    if (pc_checkoverhp (sd))
+    {
+        if (hp > 0)
+            hp = 0;
+    }
+    if (pc_checkoversp (sd))
+    {
+        if (sp > 0)
+            sp = 0;
+    }
+
+    if (sd->sc_data && sd->sc_data[SC_BERSERK].timer != -1) //バーサーク中は回復させないらしい
+        return 0;
+
+    if (hp + sd->status.hp > sd->status.max_hp)
+        hp = sd->status.max_hp - sd->status.hp;
+    if (sp + sd->status.sp > sd->status.max_sp)
+        sp = sd->status.max_sp - sd->status.sp;
+    sd->status.hp += hp;
+    if (sd->status.hp <= 0)
+    {
+        sd->status.hp = 0;
+        pc_damage (NULL, sd, 1);
+        hp = 0;
+    }
+    sd->status.sp += sp;
+    if (sd->status.sp <= 0)
+        sd->status.sp = 0;
+    if (hp)
+        clif_updatestatus (sd, SP_HP);
+    if (sp)
+        clif_updatestatus (sd, SP_SP);
+
+    if (sd->status.party_id > 0)
+    {                           // on-the-fly party hp updates [Valaris]
+        struct party *p = party_search (sd->status.party_id);
+        if (p != NULL)
+            clif_party_hp (p, sd);
+    }                           // end addition [Valaris]
+
+    return hp + sp;
+}
+
+/*==========================================
+ * HP/SP回復
+ *------------------------------------------
+ */
+static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
+
+static int                      // Compute how quickly we regenerate (less is faster) for that amount
+pc_heal_quick_speed (int amount)
+{
+    if (amount >= 100)
+    {
+        if (amount >= 500)
+            return 0;
+        if (amount >= 250)
+            return 1;
+        return 2;
+    }
+    else
+    {                           // < 100
+        if (amount >= 50)
+            return 3;
+        if (amount >= 20)
+            return 4;
+        return 5;
+    }
+}
+
+static void
+pc_heal_quick_accumulate (int new_amount,
+                          struct quick_regeneration *quick_regen, int max)
+{
+    int  current_amount = quick_regen->amount;
+    int  current_speed = quick_regen->speed;
+    int  new_speed = pc_heal_quick_speed (new_amount);
+
+    int  average_speed = ((new_speed * new_amount) + (current_speed * current_amount)) / (current_amount + new_amount); // new_amount > 0, current_amount >= 0
+
+    quick_regen->speed = average_speed;
+    quick_regen->amount = MIN (current_amount + new_amount, max);
+
+    quick_regen->tickdelay = MIN (quick_regen->speed, quick_regen->tickdelay);
+}
+
+int pc_itemheal (struct map_session_data *sd, int hp, int sp)
+{
+    /* defer healing */
+    if (hp > 0)
+    {
+        pc_heal_quick_accumulate (hp,
+                                  &sd->quick_regeneration_hp,
+                                  sd->status.max_hp - sd->status.hp);
+        hp = 0;
+    }
+    if (sp > 0)
+    {
+        pc_heal_quick_accumulate (sp,
+                                  &sd->quick_regeneration_sp,
+                                  sd->status.max_sp - sd->status.sp);
+
+        sp = 0;
+    }
+
+    /* Hurt right away, if necessary */
+    if (hp < 0 || sp < 0)
+        pc_itemheal_effect (sd, hp, sp);
+
+    return 0;
+}
+
+/* pc_itemheal_effect is invoked once every 0.5s whenever the pc
+ * has health recovery queued up (cf. pc_natural_heal_sub).
+ */
+static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp)
+{
+    int  bonus;
+//  if(battle_config.battle_log)
+//      printf("heal %d %d\n",hp,sp);
+
+    nullpo_retr (0, sd);
+
+    if (sd->sc_data && sd->sc_data[SC_GOSPEL].timer != -1)  //バーサーク中は回復させないらしい
+        return 0;
+
+    if (sd->state.potionpitcher_flag)
+    {
+        sd->potion_hp = hp;
+        sd->potion_sp = sp;
+        return 0;
+    }
+
+    if (pc_checkoverhp (sd))
+    {
+        if (hp > 0)
+            hp = 0;
+    }
+    if (pc_checkoversp (sd))
+    {
+        if (sp > 0)
+            sp = 0;
+    }
+    if (hp > 0)
+    {
+        bonus =
+            (sd->paramc[2] << 1) + 100 + pc_checkskill (sd, SM_RECOVERY) * 10;
+        if (bonus != 100)
+            hp = hp * bonus / 100;
+        bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
+        if (bonus != 100)
+            hp = hp * bonus / 100;
+    }
+    if (sp > 0)
+    {
+        bonus =
+            (sd->paramc[3] << 1) + 100 + pc_checkskill (sd,
+                                                        MG_SRECOVERY) * 10;
+        if (bonus != 100)
+            sp = sp * bonus / 100;
+        bonus = 100 + pc_checkskill (sd, AM_LEARNINGPOTION) * 5;
+        if (bonus != 100)
+            sp = sp * bonus / 100;
+    }
+    if (hp + sd->status.hp > sd->status.max_hp)
+        hp = sd->status.max_hp - sd->status.hp;
+    if (sp + sd->status.sp > sd->status.max_sp)
+        sp = sd->status.max_sp - sd->status.sp;
+    sd->status.hp += hp;
+    if (sd->status.hp <= 0)
+    {
+        sd->status.hp = 0;
+        pc_damage (NULL, sd, 1);
+        hp = 0;
+    }
+    sd->status.sp += sp;
+    if (sd->status.sp <= 0)
+        sd->status.sp = 0;
+    if (hp)
+        clif_updatestatus (sd, SP_HP);
+    if (sp)
+        clif_updatestatus (sd, SP_SP);
+
+    return 0;
+}
+
+/*==========================================
+ * HP/SP回復
+ *------------------------------------------
+ */
+int pc_percentheal (struct map_session_data *sd, int hp, int sp)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->state.potionpitcher_flag)
+    {
+        sd->potion_per_hp = hp;
+        sd->potion_per_sp = sp;
+        return 0;
+    }
+
+    if (pc_checkoverhp (sd))
+    {
+        if (hp > 0)
+            hp = 0;
+    }
+    if (pc_checkoversp (sd))
+    {
+        if (sp > 0)
+            sp = 0;
+    }
+    if (hp)
+    {
+        if (hp >= 100)
+        {
+            sd->status.hp = sd->status.max_hp;
+        }
+        else if (hp <= -100)
+        {
+            sd->status.hp = 0;
+            pc_damage (NULL, sd, 1);
+        }
+        else
+        {
+            sd->status.hp += sd->status.max_hp * hp / 100;
+            if (sd->status.hp > sd->status.max_hp)
+                sd->status.hp = sd->status.max_hp;
+            if (sd->status.hp <= 0)
+            {
+                sd->status.hp = 0;
+                pc_damage (NULL, sd, 1);
+                hp = 0;
+            }
+        }
+    }
+    if (sp)
+    {
+        if (sp >= 100)
+        {
+            sd->status.sp = sd->status.max_sp;
+        }
+        else if (sp <= -100)
+        {
+            sd->status.sp = 0;
+        }
+        else
+        {
+            sd->status.sp += sd->status.max_sp * sp / 100;
+            if (sd->status.sp > sd->status.max_sp)
+                sd->status.sp = sd->status.max_sp;
+            if (sd->status.sp < 0)
+                sd->status.sp = 0;
+        }
+    }
+    if (hp)
+        clif_updatestatus (sd, SP_HP);
+    if (sp)
+        clif_updatestatus (sd, SP_SP);
+
+    return 0;
+}
+
+/*==========================================
+ * 職変更
+ * 引数		job 職業 0〜23
+ *		upper 通常 0, 転生 1, 養子 2, そのまま -1
+ *------------------------------------------
+ */
+int pc_jobchange (struct map_session_data *sd, int job, int upper)
+{
+    int  i;
+    int  b_class = 0;
+    //転生や養子の場合の元の職業を算出する
+    struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
+
+    nullpo_retr (0, sd);
+
+    if ((job > 23) && (job < 68))
+        job += 3977;
+
+    if ((job > 69) && (job < 4000))
+        return 1;
+
+    if (upper < 0)              //現在転生かどうかを判断する
+        upper = s_class.upper;
+
+    if (upper == 0)
+    {                           //通常職ならjobそのまんま
+        b_class = job;
+    }
+    else if (upper == 1)
+    {
+        if (job == 23)
+        {                       //転生にスパノビは存在しないのでお断り
+            return 1;
+        }
+        else
+        {
+            b_class = job + 4001;
+        }
+    }
+    else if (upper == 2)
+    {                           //養子に結婚はないけどどうせ次で蹴られるからいいや
+        b_class = (job == 23) ? job + 4022 : job + 4023;
+    }
+    else
+    {
+        return 1;
+    }
+
+    if ((sd->status.sex == 0 && job == 19) || (sd->status.sex == 1 && job == 20) ||
+            (sd->status.sex == 0 && job == 4020) || (sd->status.sex == 1 && job == 4021) ||
+            job == 22 || sd->status.pc_class == b_class)   //♀はバードになれない、♂はダンサーになれない、結婚衣裳もお断り
+        return 1;
+
+    sd->status.pc_class = sd->view_class = b_class;
+
+    sd->status.job_level = 1;
+    sd->status.job_exp = 0;
+    clif_updatestatus (sd, SP_JOBLEVEL);
+    clif_updatestatus (sd, SP_JOBEXP);
+    clif_updatestatus (sd, SP_NEXTJOBEXP);
+
+    for (i = 0; i < 11; i++)
+    {
+        if (sd->equip_index[i] >= 0)
+            if (!pc_isequip (sd, sd->equip_index[i]))
+                pc_unequipitem (sd, sd->equip_index[i], 1); // 装備外し
+    }
+
+    clif_changelook (&sd->bl, LOOK_BASE, sd->view_class);   // move sprite update to prevent client crashes with incompatible equipment [Valaris]
+    if (sd->status.clothes_color > 0)
+        clif_changelook (&sd->bl, LOOK_CLOTHES_COLOR,
+                         sd->status.clothes_color);
+    if (battle_config.muting_players && sd->status.manner < 0)
+        clif_changestatus (&sd->bl, SP_MANNER, sd->status.manner);
+
+    pc_calcstatus (sd, 0);
+    pc_checkallowskill (sd);
+    pc_equiplookall (sd);
+    clif_equiplist (sd);
+
+    if (pc_isriding (sd))
+    {                           // remove peco status if changing into invalid class [Valaris]
+        if (!(pc_checkskill (sd, KN_RIDING)))
+            pc_setoption (sd, sd->status.option | -0x0000);
+        if (pc_checkskill (sd, KN_RIDING) > 0)
+            pc_setriding (sd);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 見た目変更
+ *------------------------------------------
+ */
+int pc_equiplookall (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    clif_changelook (&sd->bl, LOOK_WEAPON, 0);
+//  clif_changelook(&sd->bl,LOOK_SHOES,0);
+    clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
+    clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
+    clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
+
+    clif_changelook_accessories (&sd->bl, NULL);
+
+    return 0;
+}
+
+/*==========================================
+ * 見た目変更
+ *------------------------------------------
+ */
+int pc_changelook (struct map_session_data *sd, int type, int val)
+{
+    nullpo_retr (0, sd);
+
+    switch (type)
+    {
+        case LOOK_HAIR:
+            sd->status.hair = val;
+            break;
+        case LOOK_WEAPON:
+            sd->status.weapon = val;
+            break;
+        case LOOK_HEAD_BOTTOM:
+            sd->status.head_bottom = val;
+            break;
+        case LOOK_HEAD_TOP:
+            sd->status.head_top = val;
+            break;
+        case LOOK_HEAD_MID:
+            sd->status.head_mid = val;
+            break;
+        case LOOK_HAIR_COLOR:
+            sd->status.hair_color = val;
+            break;
+        case LOOK_CLOTHES_COLOR:
+            sd->status.clothes_color = val;
+            break;
+        case LOOK_SHIELD:
+            sd->status.shield = val;
+            break;
+        case LOOK_SHOES:
+            break;
+    }
+    clif_changelook (&sd->bl, type, val);
+
+    return 0;
+}
+
+/*==========================================
+ * 付属品(鷹,ペコ,カート)設定
+ *------------------------------------------
+ */
+int pc_setoption (struct map_session_data *sd, int type)
+{
+    nullpo_retr (0, sd);
+
+    sd->status.option = type;
+    clif_changeoption (&sd->bl);
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * カート設定
+ *------------------------------------------
+ */
+int pc_setcart (struct map_session_data *sd, int type)
+{
+    int  cart[6] = { 0x0000, 0x0008, 0x0080, 0x0100, 0x0200, 0x0400 };
+
+    nullpo_retr (0, sd);
+
+    if (pc_checkskill (sd, MC_PUSHCART) > 0)
+    {                           // プッシュカートスキル所持
+        if (!pc_iscarton (sd))
+        {                       // カートを付けていない
+            pc_setoption (sd, cart[type]);
+            clif_cart_itemlist (sd);
+            clif_cart_equiplist (sd);
+            clif_updatestatus (sd, SP_CARTINFO);
+            clif_status_change (&sd->bl, 0x0c, 0);
+        }
+        else
+        {
+            pc_setoption (sd, cart[type]);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 鷹設定
+ *------------------------------------------
+ */
+int pc_setfalcon (struct map_session_data *sd)
+{
+    if (pc_checkskill (sd, HT_FALCON) > 0)
+    {                           // ファルコンマスタリースキル所持
+        pc_setoption (sd, sd->status.option | 0x0010);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * ペコペコ設定
+ *------------------------------------------
+ */
+int pc_setriding (struct map_session_data *sd)
+{
+    if (sd->disguise > 0)
+    {                           // temporary prevention of crash caused by peco + disguise, will look into a better solution [Valaris]
+        clif_displaymessage (sd->fd,
+                             "Cannot mount a Peco while in disguise.");
+        return 0;
+    }
+
+    if ((pc_checkskill (sd, KN_RIDING) > 0))
+    {                           // ライディングスキル所持
+        pc_setoption (sd, sd->status.option | 0x0020);
+
+        if (sd->status.pc_class == 7)
+            sd->status.pc_class = sd->view_class = 13;
+
+        if (sd->status.pc_class == 14)
+            sd->status.pc_class = sd->view_class = 21;
+
+        if (sd->status.pc_class == 4008)
+            sd->status.pc_class = sd->view_class = 4014;
+
+        if (sd->status.pc_class == 4015)
+            sd->status.pc_class = sd->view_class = 4022;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * script用変数の値を読む
+ *------------------------------------------
+ */
+int pc_readreg (struct map_session_data *sd, int reg)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->reg_num; i++)
+        if (sd->reg[i].index == reg)
+            return sd->reg[i].data;
+
+    return 0;
+}
+
+/*==========================================
+ * script用変数の値を設定
+ *------------------------------------------
+ */
+int pc_setreg (struct map_session_data *sd, int reg, int val)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->reg_num; i++)
+    {
+        if (sd->reg[i].index == reg)
+        {
+            sd->reg[i].data = val;
+            return 0;
+        }
+    }
+    sd->reg_num++;
+    RECREATE (sd->reg, struct script_reg, sd->reg_num);
+    sd->reg[i].index = reg;
+    sd->reg[i].data = val;
+
+    return 0;
+}
+
+/*==========================================
+ * script用文字列変数の値を読む
+ *------------------------------------------
+ */
+char *pc_readregstr (struct map_session_data *sd, int reg)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->regstr_num; i++)
+        if (sd->regstr[i].index == reg)
+            return sd->regstr[i].data;
+
+    return NULL;
+}
+
+/*==========================================
+ * script用文字列変数の値を設定
+ *------------------------------------------
+ */
+int pc_setregstr (struct map_session_data *sd, int reg, char *str)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (strlen (str) + 1 > sizeof (sd->regstr[0].data))
+    {
+        printf ("pc_setregstr(): String too long!\n");
+        return 0;
+    }
+
+    for (i = 0; i < sd->regstr_num; i++)
+        if (sd->regstr[i].index == reg)
+        {
+            strcpy (sd->regstr[i].data, str);
+            return 0;
+        }
+    sd->regstr_num++;
+    RECREATE (sd->regstr, struct script_regstr, sd->regstr_num);
+    sd->regstr[i].index = reg;
+    strcpy (sd->regstr[i].data, str);
+
+    return 0;
+}
+
+/*==========================================
+ * script用グローバル変数の値を読む
+ *------------------------------------------
+ */
+int pc_readglobalreg (struct map_session_data *sd, char *reg)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->status.global_reg_num; i++)
+    {
+        if (strcmp (sd->status.global_reg[i].str, reg) == 0)
+            return sd->status.global_reg[i].value;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * script用グローバル変数の値を設定
+ *------------------------------------------
+ */
+int pc_setglobalreg (struct map_session_data *sd, char *reg, int val)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    //PC_DIE_COUNTERがスクリプトなどで変更された時の処理
+    if (strcmp (reg, "PC_DIE_COUNTER") == 0 && sd->die_counter != val)
+    {
+        sd->die_counter = val;
+        pc_calcstatus (sd, 0);
+    }
+    if (val == 0)
+    {
+        for (i = 0; i < sd->status.global_reg_num; i++)
+        {
+            if (strcmp (sd->status.global_reg[i].str, reg) == 0)
+            {
+                sd->status.global_reg[i] =
+                    sd->status.global_reg[sd->status.global_reg_num - 1];
+                sd->status.global_reg_num--;
+                break;
+            }
+        }
+        return 0;
+    }
+    for (i = 0; i < sd->status.global_reg_num; i++)
+    {
+        if (strcmp (sd->status.global_reg[i].str, reg) == 0)
+        {
+            sd->status.global_reg[i].value = val;
+            return 0;
+        }
+    }
+    if (sd->status.global_reg_num < GLOBAL_REG_NUM)
+    {
+        strcpy (sd->status.global_reg[i].str, reg);
+        sd->status.global_reg[i].value = val;
+        sd->status.global_reg_num++;
+        return 0;
+    }
+    if (battle_config.error_log)
+        printf ("pc_setglobalreg : couldn't set %s (GLOBAL_REG_NUM = %d)\n",
+                reg, GLOBAL_REG_NUM);
+
+    return 1;
+}
+
+/*==========================================
+ * script用アカウント変数の値を読む
+ *------------------------------------------
+ */
+int pc_readaccountreg (struct map_session_data *sd, char *reg)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->status.account_reg_num; i++)
+    {
+        if (strcmp (sd->status.account_reg[i].str, reg) == 0)
+            return sd->status.account_reg[i].value;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * script用アカウント変数の値を設定
+ *------------------------------------------
+ */
+int pc_setaccountreg (struct map_session_data *sd, char *reg, int val)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    if (val == 0)
+    {
+        for (i = 0; i < sd->status.account_reg_num; i++)
+        {
+            if (strcmp (sd->status.account_reg[i].str, reg) == 0)
+            {
+                sd->status.account_reg[i] =
+                    sd->status.account_reg[sd->status.account_reg_num - 1];
+                sd->status.account_reg_num--;
+                break;
+            }
+        }
+        intif_saveaccountreg (sd);
+        return 0;
+    }
+    for (i = 0; i < sd->status.account_reg_num; i++)
+    {
+        if (strcmp (sd->status.account_reg[i].str, reg) == 0)
+        {
+            sd->status.account_reg[i].value = val;
+            intif_saveaccountreg (sd);
+            return 0;
+        }
+    }
+    if (sd->status.account_reg_num < ACCOUNT_REG_NUM)
+    {
+        strcpy (sd->status.account_reg[i].str, reg);
+        sd->status.account_reg[i].value = val;
+        sd->status.account_reg_num++;
+        intif_saveaccountreg (sd);
+        return 0;
+    }
+    if (battle_config.error_log)
+        printf ("pc_setaccountreg : couldn't set %s (ACCOUNT_REG_NUM = %d)\n",
+                reg, ACCOUNT_REG_NUM);
+
+    return 1;
+}
+
+/*==========================================
+ * script用アカウント変数2の値を読む
+ *------------------------------------------
+ */
+int pc_readaccountreg2 (struct map_session_data *sd, char *reg)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < sd->status.account_reg2_num; i++)
+    {
+        if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
+            return sd->status.account_reg2[i].value;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * script用アカウント変数2の値を設定
+ *------------------------------------------
+ */
+int pc_setaccountreg2 (struct map_session_data *sd, char *reg, int val)
+{
+    int  i;
+
+    nullpo_retr (1, sd);
+
+    if (val == 0)
+    {
+        for (i = 0; i < sd->status.account_reg2_num; i++)
+        {
+            if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
+            {
+                sd->status.account_reg2[i] =
+                    sd->status.account_reg2[sd->status.account_reg2_num - 1];
+                sd->status.account_reg2_num--;
+                break;
+            }
+        }
+        chrif_saveaccountreg2 (sd);
+        return 0;
+    }
+    for (i = 0; i < sd->status.account_reg2_num; i++)
+    {
+        if (strcmp (sd->status.account_reg2[i].str, reg) == 0)
+        {
+            sd->status.account_reg2[i].value = val;
+            chrif_saveaccountreg2 (sd);
+            return 0;
+        }
+    }
+    if (sd->status.account_reg2_num < ACCOUNT_REG2_NUM)
+    {
+        strcpy (sd->status.account_reg2[i].str, reg);
+        sd->status.account_reg2[i].value = val;
+        sd->status.account_reg2_num++;
+        chrif_saveaccountreg2 (sd);
+        return 0;
+    }
+    if (battle_config.error_log)
+        printf
+            ("pc_setaccountreg2 : couldn't set %s (ACCOUNT_REG2_NUM = %d)\n",
+             reg, ACCOUNT_REG2_NUM);
+
+    return 1;
+}
+
+/*==========================================
+ * 精錬成功率
+ *------------------------------------------
+ */
+int pc_percentrefinery (struct map_session_data *sd, struct item *item)
+{
+    int  percent;
+
+    nullpo_retr (0, item);
+    percent = percentrefinery[itemdb_wlv (item->nameid)][(int) item->refine];
+
+    percent += pc_checkskill (sd, BS_WEAPONRESEARCH);   // 武器研究スキル所持
+
+    // 確率の有効範囲チェック
+    if (percent > 100)
+    {
+        percent = 100;
+    }
+    if (percent < 0)
+    {
+        percent = 0;
+    }
+
+    return percent;
+}
+
+/*==========================================
+ * イベントタイマー処理
+ *------------------------------------------
+ */
+void pc_eventtimer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = map_id2sd (id);
+    int  i;
+    if (sd == NULL)
+        return;
+
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+    {
+        if (sd->eventtimer[i] == tid)
+        {
+            sd->eventtimer[i] = -1;
+            npc_event (sd, (const char *) data, 0);
+            break;
+        }
+    }
+    free ((void *) data);
+    if (i == MAX_EVENTTIMER)
+    {
+        if (battle_config.error_log)
+            printf ("pc_eventtimer: no such event timer\n");
+    }
+}
+
+/*==========================================
+ * イベントタイマー追加
+ *------------------------------------------
+ */
+int pc_addeventtimer (struct map_session_data *sd, int tick, const char *name)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (sd->eventtimer[i] == -1)
+            break;
+
+    if (i < MAX_EVENTTIMER)
+    {
+        char *evname = (char *) calloc (24, 1);
+        strncpy (evname, name, 24);
+        evname[23] = '\0';
+        sd->eventtimer[i] = add_timer (gettick () + tick,
+                                       pc_eventtimer, sd->bl.id,
+                                       (int) evname);
+        return 1;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマー削除
+ *------------------------------------------
+ */
+int pc_deleventtimer (struct map_session_data *sd, const char *name)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (sd->eventtimer[i] != -1 && strcmp ((char
+                                                *) (get_timer (sd->eventtimer
+                                                               [i])->data),
+                                               name) == 0)
+        {
+            delete_timer (sd->eventtimer[i], pc_eventtimer);
+            sd->eventtimer[i] = -1;
+            break;
+        }
+
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマーカウント値追加
+ *------------------------------------------
+ */
+int pc_addeventtimercount (struct map_session_data *sd, const char *name,
+                           int tick)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (sd->eventtimer[i] != -1 && strcmp ((char
+                                                *) (get_timer (sd->eventtimer
+                                                               [i])->data),
+                                               name) == 0)
+        {
+            addtick_timer (sd->eventtimer[i], tick);
+            break;
+        }
+
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマー全削除
+ *------------------------------------------
+ */
+int pc_cleareventtimer (struct map_session_data *sd)
+{
+    int  i;
+
+    nullpo_retr (0, sd);
+
+    for (i = 0; i < MAX_EVENTTIMER; i++)
+        if (sd->eventtimer[i] != -1)
+        {
+            delete_timer (sd->eventtimer[i], pc_eventtimer);
+            sd->eventtimer[i] = -1;
+        }
+
+    return 0;
+}
+
+//
+// 装 備物
+//
+/*==========================================
+ * アイテムを装備する
+ *------------------------------------------
+ */
+static int
+pc_signal_advanced_equipment_change (struct map_session_data *sd, int n)
+{
+    if (sd->status.inventory[n].equip & 0x0040)
+        clif_changelook (&sd->bl, LOOK_SHOES, 0);
+    if (sd->status.inventory[n].equip & 0x0004)
+        clif_changelook (&sd->bl, LOOK_GLOVES, 0);
+    if (sd->status.inventory[n].equip & 0x0008)
+        clif_changelook (&sd->bl, LOOK_CAPE, 0);
+    if (sd->status.inventory[n].equip & 0x0010)
+        clif_changelook (&sd->bl, LOOK_MISC1, 0);
+    if (sd->status.inventory[n].equip & 0x0080)
+        clif_changelook (&sd->bl, LOOK_MISC2, 0);
+    return 0;
+}
+
+int pc_equipitem (struct map_session_data *sd, int n, int pos)
+{
+    int  i, nameid, arrow, view;
+    struct item_data *id;
+    //ソス]ソスソスソスソスソス{ソスqソスフ場合ソスフ鯉ソスソスフ職ソスニゑソスソスZソスoソスソスソスソス
+
+    nullpo_retr (0, sd);
+
+    if (n < 0 || n >= MAX_INVENTORY)
+    {
+        clif_equipitemack (sd, 0, 0, 0);
+        return 0;
+    }
+
+    nameid = sd->status.inventory[n].nameid;
+    id = sd->inventory_data[n];
+    pos = pc_equippoint (sd, n);
+
+    if (battle_config.battle_log)
+        printf ("equip %d(%d) %x:%x\n", nameid, n, id->equip, pos);
+    if (!pc_isequip (sd, n) || !pos || sd->status.inventory[n].broken == 1)
+    {                           // [Valaris]
+        clif_equipitemack (sd, n, 0, 0);    // fail
+        return 0;
+    }
+
+// -- moonsoul (if player is berserk then cannot equip)
+//
+    if (sd->sc_data[SC_BERSERK].timer != -1)
+    {
+        clif_equipitemack (sd, n, 0, 0);    // fail
+        return 0;
+    }
+
+    if (pos == 0x88)
+    {                           // アクセサリ用例外処理
+        int  epor = 0;
+        if (sd->equip_index[0] >= 0)
+            epor |= sd->status.inventory[sd->equip_index[0]].equip;
+        if (sd->equip_index[1] >= 0)
+            epor |= sd->status.inventory[sd->equip_index[1]].equip;
+        epor &= 0x88;
+        pos = epor == 0x08 ? 0x80 : 0x08;
+    }
+
+    // 二刀流処理
+    if ((pos == 0x22)           // 一応、装備要求箇所が二刀流武器かチェックする
+        && (id->equip == 2)     // 単 手武器
+        && (pc_checkskill (sd, AS_LEFT) > 0 || sd->status.pc_class == 12)) // 左手修錬有
+    {
+        int  tpos = 0;
+        if (sd->equip_index[8] >= 0)
+            tpos |= sd->status.inventory[sd->equip_index[8]].equip;
+        if (sd->equip_index[9] >= 0)
+            tpos |= sd->status.inventory[sd->equip_index[9]].equip;
+        tpos &= 0x02;
+        pos = tpos == 0x02 ? 0x20 : 0x02;
+    }
+
+    arrow = pc_search_inventory (sd, pc_checkequip (sd, 9));    // Added by RoVeRT
+    for (i = 0; i < 11; i++)
+    {
+        if (pos & equip_pos[i])
+        {
+            if (sd->equip_index[i] >= 0)    //Slot taken, remove item from there.
+                pc_unequipitem (sd, sd->equip_index[i], 1);
+            sd->equip_index[i] = n;
+        }
+    }
+    // 弓矢装備
+    if (pos == 0x8000)
+    {
+        clif_arrowequip (sd, n);
+        clif_arrow_fail (sd, 3);    // 3=矢が装備できました
+    }
+    else
+    {
+        /* Don't update re-equipping if we're using a spell */
+        if (!(pos == 4 && sd->attack_spell_override))
+            clif_equipitemack (sd, n, pos, 1);
+    }
+
+    for (i = 0; i < 11; i++)
+    {
+        if (pos & equip_pos[i])
+            sd->equip_index[i] = n;
+    }
+    sd->status.inventory[n].equip = pos;
+
+    if (sd->inventory_data[n])
+    {
+        view = sd->inventory_data[n]->look;
+        if (view == 0)
+            view = sd->inventory_data[n]->nameid;
+    }
+    else
+    {
+        view = 0;
+    }
+
+    if (sd->status.inventory[n].equip & 0x0002)
+    {
+        sd->weapontype1 = view;
+        pc_calcweapontype (sd);
+        pc_set_weapon_look (sd);
+    }
+    if (sd->status.inventory[n].equip & 0x0020)
+    {
+        if (sd->inventory_data[n])
+        {
+            if (sd->inventory_data[n]->type == 4)
+            {
+                sd->status.shield = 0;
+                if (sd->status.inventory[n].equip == 0x0020)
+                    sd->weapontype2 = view;
+            }
+            else if (sd->inventory_data[n]->type == 5)
+            {
+                sd->status.shield = view;
+                sd->weapontype2 = 0;
+            }
+        }
+        else
+            sd->status.shield = sd->weapontype2 = 0;
+        pc_calcweapontype (sd);
+        clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
+    }
+    if (sd->status.inventory[n].equip & 0x0001)
+    {
+        sd->status.head_bottom = view;
+        clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM, sd->status.head_bottom);
+    }
+    if (sd->status.inventory[n].equip & 0x0100)
+    {
+        sd->status.head_top = view;
+        clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
+    }
+    if (sd->status.inventory[n].equip & 0x0200)
+    {
+        sd->status.head_mid = view;
+        clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
+    }
+    pc_signal_advanced_equipment_change (sd, n);
+
+    pc_checkallowskill (sd);    // 装備品でスキルか解除されるかチェック
+    if (itemdb_look (sd->status.inventory[n].nameid) == 11 && arrow)
+    {                           // Added by RoVeRT
+        clif_arrowequip (sd, arrow);
+        sd->status.inventory[arrow].equip = 32768;
+    }
+    pc_calcstatus (sd, 0);
+
+    if (sd->special_state.infinite_endure)
+    {
+        if (sd->sc_data[SC_ENDURE].timer == -1)
+            skill_status_change_start (&sd->bl, SC_ENDURE, 10, 1, 0, 0, 0, 0);
+    }
+    else
+    {
+        if (sd->sc_data[SC_ENDURE].timer != -1 && sd->sc_data[SC_ENDURE].val2)
+            skill_status_change_end (&sd->bl, SC_ENDURE, -1);
+    }
+
+    if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
+        && !battle_check_undead (7, sd->def_ele))
+        skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
+    if (sd->sc_data[SC_DANCING].timer != -1
+        && (sd->status.weapon != 13 && sd->status.weapon != 14))
+        skill_stop_dancing (&sd->bl, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 装 備した物を外す
+ *------------------------------------------
+ */
+int pc_unequipitem (struct map_session_data *sd, int n, int type)
+{
+    nullpo_retr (0, sd);
+
+// -- moonsoul  (if player is berserk then cannot unequip)
+//
+    if (sd->sc_data[SC_BERSERK].timer != -1)
+    {
+        clif_unequipitemack (sd, n, 0, 0);
+        return 0;
+    }
+
+    if (battle_config.battle_log)
+        printf ("unequip %d %x:%x\n", n, pc_equippoint (sd, n),
+                sd->status.inventory[n].equip);
+    if (sd->status.inventory[n].equip)
+    {
+        int  i;
+        for (i = 0; i < 11; i++)
+        {
+            if (sd->status.inventory[n].equip & equip_pos[i])
+                sd->equip_index[i] = -1;
+        }
+        if (sd->status.inventory[n].equip & 0x0002)
+        {
+            sd->weapontype1 = 0;
+            sd->status.weapon = sd->weapontype2;
+            pc_calcweapontype (sd);
+            pc_set_weapon_look (sd);
+        }
+        if (sd->status.inventory[n].equip & 0x0020)
+        {
+            sd->status.shield = sd->weapontype2 = 0;
+            pc_calcweapontype (sd);
+            clif_changelook (&sd->bl, LOOK_SHIELD, sd->status.shield);
+        }
+        if (sd->status.inventory[n].equip & 0x0001)
+        {
+            sd->status.head_bottom = 0;
+            clif_changelook (&sd->bl, LOOK_HEAD_BOTTOM,
+                             sd->status.head_bottom);
+        }
+        if (sd->status.inventory[n].equip & 0x0100)
+        {
+            sd->status.head_top = 0;
+            clif_changelook (&sd->bl, LOOK_HEAD_TOP, sd->status.head_top);
+        }
+        if (sd->status.inventory[n].equip & 0x0200)
+        {
+            sd->status.head_mid = 0;
+            clif_changelook (&sd->bl, LOOK_HEAD_MID, sd->status.head_mid);
+        }
+        pc_signal_advanced_equipment_change (sd, n);
+
+        if (sd->sc_data[SC_BROKNWEAPON].timer != -1
+            && sd->status.inventory[n].equip & 0x0002
+            && sd->status.inventory[i].broken == 1)
+            skill_status_change_end (&sd->bl, SC_BROKNWEAPON, -1);
+
+        clif_unequipitemack (sd, n, sd->status.inventory[n].equip, 1);
+        sd->status.inventory[n].equip = 0;
+        if (!type)
+            pc_checkallowskill (sd);
+        if (sd->weapontype1 == 0 && sd->weapontype2 == 0)
+            skill_encchant_eremental_end (&sd->bl, -1); //武器持ち誓えは無条件で属性付与解除
+    }
+    else
+    {
+        clif_unequipitemack (sd, n, 0, 0);
+    }
+    if (!type)
+    {
+        pc_calcstatus (sd, 0);
+        if (sd->sc_data[SC_SIGNUMCRUCIS].timer != -1
+            && !battle_check_undead (7, sd->def_ele))
+            skill_status_change_end (&sd->bl, SC_SIGNUMCRUCIS, -1);
+    }
+
+    return 0;
+}
+
+int pc_unequipinvyitem (struct map_session_data *sd, int n, int type)
+{
+    int  i;
+
+    nullpo_retr (1, sd);
+
+    for (i = 0; i < 11; i++)
+    {
+        if (equip_pos[i] > 0 && sd->equip_index[i] == n)
+        {                       //Slot taken, remove item from there.
+            pc_unequipitem (sd, sd->equip_index[i], type);
+            sd->equip_index[i] = -1;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * アイテムのindex番号を詰めたり
+ * 装 備品の装備可能チェックを行なう
+ *------------------------------------------
+ */
+int pc_checkitem (struct map_session_data *sd)
+{
+    int  i, j, k, id, calc_flag = 0;
+    struct item_data *it = NULL;
+
+    nullpo_retr (0, sd);
+
+    // 所持品空き詰め
+    for (i = j = 0; i < MAX_INVENTORY; i++)
+    {
+        if ((id = sd->status.inventory[i].nameid) == 0)
+            continue;
+        if (battle_config.item_check && !itemdb_available (id))
+        {
+            if (battle_config.error_log)
+                printf ("illeagal item id %d in %d[%s] inventory.\n", id,
+                        sd->bl.id, sd->status.name);
+            pc_delitem (sd, i, sd->status.inventory[i].amount, 3);
+            continue;
+        }
+        if (i > j)
+        {
+            memcpy (&sd->status.inventory[j], &sd->status.inventory[i],
+                    sizeof (struct item));
+            sd->inventory_data[j] = sd->inventory_data[i];
+        }
+        j++;
+    }
+    if (j < MAX_INVENTORY)
+        memset (&sd->status.inventory[j], 0,
+                sizeof (struct item) * (MAX_INVENTORY - j));
+    for (k = j; k < MAX_INVENTORY; k++)
+        sd->inventory_data[k] = NULL;
+
+    // カート内空き詰め
+    for (i = j = 0; i < MAX_CART; i++)
+    {
+        if ((id = sd->status.cart[i].nameid) == 0)
+            continue;
+        if (battle_config.item_check && !itemdb_available (id))
+        {
+            if (battle_config.error_log)
+                printf ("illeagal item id %d in %d[%s] cart.\n", id,
+                        sd->bl.id, sd->status.name);
+            pc_cart_delitem (sd, i, sd->status.cart[i].amount, 1);
+            continue;
+        }
+        if (i > j)
+        {
+            memcpy (&sd->status.cart[j], &sd->status.cart[i],
+                    sizeof (struct item));
+        }
+        j++;
+    }
+    if (j < MAX_CART)
+        memset (&sd->status.cart[j], 0,
+                sizeof (struct item) * (MAX_CART - j));
+
+    // 装 備位置チェック
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+
+        it = sd->inventory_data[i];
+
+        if (sd->status.inventory[i].nameid == 0)
+            continue;
+        if (sd->status.inventory[i].equip & ~pc_equippoint (sd, i))
+        {
+            sd->status.inventory[i].equip = 0;
+            calc_flag = 1;
+        }
+        //装備制限チェック
+        if (sd->status.inventory[i].equip && map[sd->bl.m].flag.pvp
+            && (it->flag.no_equip == 1 || it->flag.no_equip == 3))
+        {                       //PvP制限
+            sd->status.inventory[i].equip = 0;
+            calc_flag = 1;
+        }
+        else if (sd->status.inventory[i].equip && map[sd->bl.m].flag.gvg
+                 && (it->flag.no_equip == 2 || it->flag.no_equip == 3))
+        {                       //GvG制限
+            sd->status.inventory[i].equip = 0;
+            calc_flag = 1;
+        }
+    }
+
+    pc_setequipindex (sd);
+    if (calc_flag)
+        pc_calcstatus (sd, 2);
+
+    return 0;
+}
+
+int pc_checkoverhp (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->status.hp == sd->status.max_hp)
+        return 1;
+    if (sd->status.hp > sd->status.max_hp)
+    {
+        sd->status.hp = sd->status.max_hp;
+        clif_updatestatus (sd, SP_HP);
+        return 2;
+    }
+
+    return 0;
+}
+
+int pc_checkoversp (struct map_session_data *sd)
+{
+    nullpo_retr (0, sd);
+
+    if (sd->status.sp == sd->status.max_sp)
+        return 1;
+    if (sd->status.sp > sd->status.max_sp)
+    {
+        sd->status.sp = sd->status.max_sp;
+        clif_updatestatus (sd, SP_SP);
+        return 2;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * PVP順位計算用(foreachinarea)
+ *------------------------------------------
+ */
+int pc_calc_pvprank_sub (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd1, *sd2 = NULL;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd1 = (struct map_session_data *) bl);
+    nullpo_retr (0, sd2 = va_arg (ap, struct map_session_data *));
+
+    if (sd1->pvp_point > sd2->pvp_point)
+        sd2->pvp_rank++;
+    return 0;
+}
+
+/*==========================================
+ * PVP順位計算
+ *------------------------------------------
+ */
+int pc_calc_pvprank (struct map_session_data *sd)
+{
+    int  old;
+    struct map_data *m;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, m = &map[sd->bl.m]);
+
+    old = sd->pvp_rank;
+
+    if (!(m->flag.pvp))
+        return 0;
+    sd->pvp_rank = 1;
+    map_foreachinarea (pc_calc_pvprank_sub, sd->bl.m, 0, 0, m->xs, m->ys,
+                       BL_PC, sd);
+    if (old != sd->pvp_rank || sd->pvp_lastusers != m->users)
+        clif_pvpset (sd, sd->pvp_rank, sd->pvp_lastusers = m->users, 0);
+    return sd->pvp_rank;
+}
+
+/*==========================================
+ * PVP順位計算(timer)
+ *------------------------------------------
+ */
+void pc_calc_pvprank_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = NULL;
+    if (battle_config.pk_mode)  // disable pvp ranking if pk_mode on [Valaris]
+        return;
+
+    sd = map_id2sd (id);
+    if (sd == NULL)
+        return;
+    sd->pvp_timer = -1;
+    if (pc_calc_pvprank (sd) > 0)
+        sd->pvp_timer = add_timer (gettick () + PVP_CALCRANK_INTERVAL,
+                                   pc_calc_pvprank_timer, id, data);
+}
+
+/*==========================================
+ * sdは結婚しているか(既婚の場合は相方のchar_idを返す)
+ *------------------------------------------
+ */
+int pc_ismarried (struct map_session_data *sd)
+{
+    if (sd == NULL)
+        return -1;
+    if (sd->status.partner_id > 0)
+        return sd->status.partner_id;
+    else
+        return 0;
+}
+
+/*==========================================
+ * sdがdstsdと結婚(dstsd→sdの結婚処理も同時に行う)
+ *------------------------------------------
+ */
+int pc_marriage (struct map_session_data *sd, struct map_session_data *dstsd)
+{
+    if (sd == NULL || dstsd == NULL || sd->status.partner_id > 0
+        || dstsd->status.partner_id > 0)
+        return -1;
+    sd->status.partner_id = dstsd->status.char_id;
+    dstsd->status.partner_id = sd->status.char_id;
+    return 0;
+}
+
+/*==========================================
+ * sdが離婚(相手はsd->status.partner_idに依る)(相手も同時に離婚・結婚指輪自動剥奪)
+ *------------------------------------------
+ */
+int pc_divorce (struct map_session_data *sd)
+{
+    struct map_session_data *p_sd = NULL;
+    if (sd == NULL || !pc_ismarried (sd))
+        return -1;
+
+    // If both are on map server we don't need to bother the char server
+    if ((p_sd =
+         map_nick2sd (map_charid2nick (sd->status.partner_id))) != NULL)
+    {
+        if (p_sd->status.partner_id != sd->status.char_id
+            || sd->status.partner_id != p_sd->status.char_id)
+        {
+            printf ("pc_divorce: Illegal partner_id sd=%d p_sd=%d\n",
+                    sd->status.partner_id, p_sd->status.partner_id);
+            return -1;
+        }
+        p_sd->status.partner_id = 0;
+        sd->status.partner_id = 0;
+
+        if (sd->npc_flags.divorce)
+        {
+            sd->npc_flags.divorce = 0;
+            map_scriptcont (sd, sd->npc_id);
+        }
+    }
+    else
+        chrif_send_divorce (sd->status.char_id);
+
+    return 0;
+}
+
+/*==========================================
+ * sdの相方のmap_session_dataを返す
+ *------------------------------------------
+ */
+struct map_session_data *pc_get_partner (struct map_session_data *sd)
+{
+    struct map_session_data *p_sd = NULL;
+    char *nick;
+    if (sd == NULL || !pc_ismarried (sd))
+        return NULL;
+
+    nick = map_charid2nick (sd->status.partner_id);
+
+    if (nick == NULL)
+        return NULL;
+
+    if ((p_sd = map_nick2sd (nick)) == NULL)
+        return NULL;
+
+    return p_sd;
+}
+
+//
+// 自然回復物
+//
+/*==========================================
+ * SP回復量計算
+ *------------------------------------------
+ */
+static int natural_heal_tick, natural_heal_prev_tick, natural_heal_diff_tick;
+static int pc_spheal (struct map_session_data *sd)
+{
+    int  a;
+    struct guild_castle *gc = NULL;
+
+    nullpo_retr (0, sd);
+
+    a = natural_heal_diff_tick;
+    if (pc_issit (sd))
+        a += a;
+    if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // マグニフィカート
+        a += a;
+
+    gc = guild_mapname2gc (sd->mapname);    // Increased guild castle regen [Valaris]
+    if (gc)
+    {
+        struct guild *g;
+        g = guild_search (sd->status.guild_id);
+        if (g && g->guild_id == gc->guild_id)
+            a += a;
+    }                           // end addition [Valaris]
+
+    return a;
+}
+
+/*==========================================
+ * HP回復量計算
+ *------------------------------------------
+ */
+static int pc_hpheal (struct map_session_data *sd)
+{
+    int  a;
+    struct guild_castle *gc;
+
+    nullpo_retr (0, sd);
+
+    a = natural_heal_diff_tick;
+    if (pc_issit (sd))
+        a += a;
+    if (sd->sc_data[SC_MAGNIFICAT].timer != -1) // Modified by RoVeRT
+        a += a;
+
+    gc = guild_mapname2gc (sd->mapname);    // Increased guild castle regen [Valaris]
+    if (gc)
+    {
+        struct guild *g;
+        g = guild_search (sd->status.guild_id);
+        if (g && g->guild_id == gc->guild_id)
+            a += a;
+    }                           // end addition [Valaris]
+
+    return a;
+}
+
+static int pc_natural_heal_hp (struct map_session_data *sd)
+{
+    int  bhp;
+    int  inc_num, bonus, skill, hp_flag;
+
+    nullpo_retr (0, sd);
+
+    if (sd->sc_data[SC_TRICKDEAD].timer != -1)  // Modified by RoVeRT
+        return 0;
+
+    if (pc_checkoverhp (sd))
+    {
+        sd->hp_sub = sd->inchealhptick = 0;
+        return 0;
+    }
+
+    bhp = sd->status.hp;
+    hp_flag = (pc_checkskill (sd, SM_MOVINGRECOVERY) > 0
+               && sd->walktimer != -1);
+
+    if (sd->walktimer == -1)
+    {
+        inc_num = pc_hpheal (sd);
+        if (sd->sc_data[SC_TENSIONRELAX].timer != -1)
+        {                       // テンションリラックス
+            sd->hp_sub += 2 * inc_num;
+            sd->inchealhptick += 3 * natural_heal_diff_tick;
+        }
+        else
+        {
+            sd->hp_sub += inc_num;
+            sd->inchealhptick += natural_heal_diff_tick;
+        }
+    }
+    else if (hp_flag)
+    {
+        inc_num = pc_hpheal (sd);
+        sd->hp_sub += inc_num;
+        sd->inchealhptick = 0;
+    }
+    else
+    {
+        sd->hp_sub = sd->inchealhptick = 0;
+        return 0;
+    }
+
+    if (sd->hp_sub >= battle_config.natural_healhp_interval)
+    {
+        bonus = sd->nhealhp;
+        if (hp_flag)
+        {
+            bonus >>= 2;
+            if (bonus <= 0)
+                bonus = 1;
+        }
+        while (sd->hp_sub >= battle_config.natural_healhp_interval)
+        {
+            sd->hp_sub -= battle_config.natural_healhp_interval;
+            if (sd->status.hp + bonus <= sd->status.max_hp)
+                sd->status.hp += bonus;
+            else
+            {
+                sd->status.hp = sd->status.max_hp;
+                sd->hp_sub = sd->inchealhptick = 0;
+            }
+        }
+    }
+    if (bhp != sd->status.hp)
+        clif_updatestatus (sd, SP_HP);
+
+    if (sd->nshealhp > 0)
+    {
+        if (sd->inchealhptick >= battle_config.natural_heal_skill_interval
+            && sd->status.hp < sd->status.max_hp)
+        {
+            bonus = sd->nshealhp;
+            while (sd->inchealhptick >=
+                   battle_config.natural_heal_skill_interval)
+            {
+                sd->inchealhptick -=
+                    battle_config.natural_heal_skill_interval;
+                if (sd->status.hp + bonus <= sd->status.max_hp)
+                    sd->status.hp += bonus;
+                else
+                {
+                    bonus = sd->status.max_hp - sd->status.hp;
+                    sd->status.hp = sd->status.max_hp;
+                    sd->hp_sub = sd->inchealhptick = 0;
+                }
+                clif_heal (sd->fd, SP_HP, bonus);
+            }
+        }
+    }
+    else
+        sd->inchealhptick = 0;
+
+    return 0;
+
+    if (sd->sc_data[SC_APPLEIDUN].timer != -1)
+    {                           // Apple of Idun
+        if (sd->inchealhptick >= 6000 && sd->status.hp < sd->status.max_hp)
+        {
+            bonus = skill * 20;
+            while (sd->inchealhptick >= 6000)
+            {
+                sd->inchealhptick -= 6000;
+                if (sd->status.hp + bonus <= sd->status.max_hp)
+                    sd->status.hp += bonus;
+                else
+                {
+                    bonus = sd->status.max_hp - sd->status.hp;
+                    sd->status.hp = sd->status.max_hp;
+                    sd->hp_sub = sd->inchealhptick = 0;
+                }
+                clif_heal (sd->fd, SP_HP, bonus);
+            }
+        }
+    }
+    else
+        sd->inchealhptick = 0;
+
+    return 0;
+}
+
+static int pc_natural_heal_sp (struct map_session_data *sd)
+{
+    int  bsp;
+    int  inc_num, bonus;
+
+    nullpo_retr (0, sd);
+
+    if (sd->sc_data[SC_TRICKDEAD].timer != -1)  // Modified by RoVeRT
+        return 0;
+
+    if (pc_checkoversp (sd))
+    {
+        sd->sp_sub = sd->inchealsptick = 0;
+        return 0;
+    }
+
+    bsp = sd->status.sp;
+
+    inc_num = pc_spheal (sd);
+    if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1)
+        sd->sp_sub += inc_num;
+    if (sd->walktimer == -1)
+        sd->inchealsptick += natural_heal_diff_tick;
+    else
+        sd->inchealsptick = 0;
+
+    if (sd->sp_sub >= battle_config.natural_healsp_interval)
+    {
+        bonus = sd->nhealsp;;
+        while (sd->sp_sub >= battle_config.natural_healsp_interval)
+        {
+            sd->sp_sub -= battle_config.natural_healsp_interval;
+            if (sd->status.sp + bonus <= sd->status.max_sp)
+                sd->status.sp += bonus;
+            else
+            {
+                sd->status.sp = sd->status.max_sp;
+                sd->sp_sub = sd->inchealsptick = 0;
+            }
+        }
+    }
+
+    if (bsp != sd->status.sp)
+        clif_updatestatus (sd, SP_SP);
+
+    if (sd->nshealsp > 0)
+    {
+        if (sd->inchealsptick >= battle_config.natural_heal_skill_interval
+            && sd->status.sp < sd->status.max_sp)
+        {
+            struct pc_base_job s_class = pc_calc_base_job (sd->status.pc_class);
+            if (sd->doridori_counter && s_class.job == 23)
+                bonus = sd->nshealsp * 2;
+            else
+                bonus = sd->nshealsp;
+            sd->doridori_counter = 0;
+            while (sd->inchealsptick >=
+                   battle_config.natural_heal_skill_interval)
+            {
+                sd->inchealsptick -=
+                    battle_config.natural_heal_skill_interval;
+                if (sd->status.sp + bonus <= sd->status.max_sp)
+                    sd->status.sp += bonus;
+                else
+                {
+                    bonus = sd->status.max_sp - sd->status.sp;
+                    sd->status.sp = sd->status.max_sp;
+                    sd->sp_sub = sd->inchealsptick = 0;
+                }
+                clif_heal (sd->fd, SP_SP, bonus);
+            }
+        }
+    }
+    else
+        sd->inchealsptick = 0;
+
+    return 0;
+}
+
+static int pc_spirit_heal_hp (struct map_session_data *sd, int level)
+{
+    int  bonus_hp, interval = battle_config.natural_heal_skill_interval;
+    struct status_change *sc_data = battle_get_sc_data (&sd->bl);
+
+    nullpo_retr (0, sd);
+
+    if (pc_checkoverhp (sd))
+    {
+        sd->inchealspirithptick = 0;
+        return 0;
+    }
+
+    sd->inchealspirithptick += natural_heal_diff_tick;
+
+    if (sd->weight * 100 / sd->max_weight >=
+        battle_config.natural_heal_weight_rate
+        && sc_data[SC_FLYING_BACKPACK].timer == -1)
+        interval += interval;
+
+    if (sd->inchealspirithptick >= interval)
+    {
+        bonus_hp = sd->nsshealhp;
+        while (sd->inchealspirithptick >= interval)
+        {
+            if (pc_issit (sd))
+            {
+                sd->inchealspirithptick -= interval;
+                if (sd->status.hp < sd->status.max_hp)
+                {
+                    if (sd->status.hp + bonus_hp <= sd->status.max_hp)
+                        sd->status.hp += bonus_hp;
+                    else
+                    {
+                        bonus_hp = sd->status.max_hp - sd->status.hp;
+                        sd->status.hp = sd->status.max_hp;
+                    }
+                    clif_heal (sd->fd, SP_HP, bonus_hp);
+                    sd->inchealspirithptick = 0;
+                }
+            }
+            else
+            {
+                sd->inchealspirithptick -= natural_heal_diff_tick;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int pc_spirit_heal_sp (struct map_session_data *sd, int level)
+{
+    int  bonus_sp, interval = battle_config.natural_heal_skill_interval;
+
+    nullpo_retr (0, sd);
+
+    if (pc_checkoversp (sd))
+    {
+        sd->inchealspiritsptick = 0;
+        return 0;
+    }
+
+    sd->inchealspiritsptick += natural_heal_diff_tick;
+
+    if (sd->weight * 100 / sd->max_weight >=
+        battle_config.natural_heal_weight_rate)
+        interval += interval;
+
+    if (sd->inchealspiritsptick >= interval)
+    {
+        bonus_sp = sd->nsshealsp;
+        while (sd->inchealspiritsptick >= interval)
+        {
+            if (pc_issit (sd))
+            {
+                sd->inchealspiritsptick -= interval;
+                if (sd->status.sp < sd->status.max_sp)
+                {
+                    if (sd->status.sp + bonus_sp <= sd->status.max_sp)
+                        sd->status.sp += bonus_sp;
+                    else
+                    {
+                        bonus_sp = sd->status.max_sp - sd->status.sp;
+                        sd->status.sp = sd->status.max_sp;
+                    }
+                    clif_heal (sd->fd, SP_SP, bonus_sp);
+                    sd->inchealspiritsptick = 0;
+                }
+            }
+            else
+            {
+                sd->inchealspiritsptick -= natural_heal_diff_tick;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * HP/SP 自然回復 各クライアント
+ *------------------------------------------
+ */
+static int pc_itemheal_effect (struct map_session_data *sd, int hp, int sp);
+
+static int
+pc_quickregenerate_effect (struct quick_regeneration *quick_regen,
+                           int heal_speed)
+{
+    if (!(quick_regen->tickdelay--))
+    {
+        int  bonus =
+            MIN (heal_speed * battle_config.itemheal_regeneration_factor,
+                 quick_regen->amount);
+
+        quick_regen->amount -= bonus;
+
+        quick_regen->tickdelay = quick_regen->speed;
+
+        return bonus;
+    }
+
+    return 0;
+}
+
+static int pc_natural_heal_sub (struct map_session_data *sd, va_list ap)
+{
+    int  skill;
+
+    nullpo_retr (0, sd);
+
+    if (sd->heal_xp > 0)
+    {
+        if (sd->heal_xp < 64)
+            --sd->heal_xp;      // [Fate] Slowly reduce XP that healers can get for healing this char
+        else
+            sd->heal_xp -= (sd->heal_xp >> 6);
+    }
+
+    // Hijack this callback:  Adjust spellpower bonus
+    if (sd->spellpower_bonus_target < sd->spellpower_bonus_current)
+    {
+        sd->spellpower_bonus_current = sd->spellpower_bonus_target;
+        pc_calcstatus (sd, 0);
+    }
+    else if (sd->spellpower_bonus_target > sd->spellpower_bonus_current)
+    {
+        sd->spellpower_bonus_current +=
+            1 +
+            ((sd->spellpower_bonus_target -
+              sd->spellpower_bonus_current) >> 5);
+        pc_calcstatus (sd, 0);
+    }
+
+    if (sd->sc_data[SC_HALT_REGENERATE].timer != -1)
+        return 0;
+
+    if (sd->quick_regeneration_hp.amount || sd->quick_regeneration_sp.amount)
+    {
+        int  hp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_hp,
+                                                   (sd->sc_data[SC_POISON].timer == -1 || sd->sc_data[SC_SLOWPOISON].timer != -1) ? sd->nhealhp : 1);   // [fate] slow down when poisoned
+        int  sp_bonus = pc_quickregenerate_effect (&sd->quick_regeneration_sp,
+                                                   sd->nhealsp);
+
+        pc_itemheal_effect (sd, hp_bonus, sp_bonus);
+    }
+    skill_update_heal_animation (sd);   // if needed.
+
+// -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
+    if ((sd->sc_data[SC_FLYING_BACKPACK].timer != -1
+         || battle_config.natural_heal_weight_rate > 100
+         || sd->weight * 100 / sd->max_weight <
+         battle_config.natural_heal_weight_rate) && !pc_isdead (sd)
+        && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1)
+    {
+        pc_natural_heal_hp (sd);
+        if (sd->sc_data && sd->sc_data[SC_EXTREMITYFIST].timer == -1 && //阿修羅状態ではSPが回復しない
+            sd->sc_data[SC_DANCING].timer == -1 &&  //ダンス状態ではSPが回復しない
+            sd->sc_data[SC_BERSERK].timer == -1 //バーサーク状態ではSPが回復しない
+            )
+            pc_natural_heal_sp (sd);
+    }
+    else
+    {
+        sd->hp_sub = sd->inchealhptick = 0;
+        sd->sp_sub = sd->inchealsptick = 0;
+    }
+    if ((skill = pc_checkskill (sd, MO_SPIRITSRECOVERY)) > 0
+        && !pc_ishiding (sd) && sd->sc_data[SC_POISON].timer == -1
+        && sd->sc_data[SC_BERSERK].timer == -1)
+    {
+        pc_spirit_heal_hp (sd, skill);
+        pc_spirit_heal_sp (sd, skill);
+    }
+    else
+    {
+        sd->inchealspirithptick = 0;
+        sd->inchealspiritsptick = 0;
+    }
+    return 0;
+}
+
+/*==========================================
+ * HP/SP自然回復 (interval timer関数)
+ *------------------------------------------
+ */
+void pc_natural_heal (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    natural_heal_tick = tick;
+    natural_heal_diff_tick =
+        DIFF_TICK (natural_heal_tick, natural_heal_prev_tick);
+    clif_foreachclient (pc_natural_heal_sub);
+
+    natural_heal_prev_tick = tick;
+}
+
+/*==========================================
+ * セーブポイントの保存
+ *------------------------------------------
+ */
+int pc_setsavepoint (struct map_session_data *sd, char *mapname, int x, int y)
+{
+    nullpo_retr (0, sd);
+
+    strncpy (sd->status.save_point.map, mapname, 23);
+    sd->status.save_point.map[23] = '\0';
+    sd->status.save_point.x = x;
+    sd->status.save_point.y = y;
+
+    return 0;
+}
+
+/*==========================================
+ * 自動セーブ 各クライアント
+ *------------------------------------------
+ */
+static int last_save_fd, save_flag;
+static int pc_autosave_sub (struct map_session_data *sd, va_list ap)
+{
+    nullpo_retr (0, sd);
+
+    if (save_flag == 0 && sd->fd > last_save_fd)
+    {
+        struct guild_castle *gc = NULL;
+        int  i;
+
+        pc_makesavestatus (sd);
+        chrif_save (sd);
+
+        for (i = 0; i < MAX_GUILDCASTLE; i++)
+        {
+            gc = guild_castle_search (i);
+            if (!gc)
+                continue;
+            if (gc->visibleG0 == 1)
+                guild_castledatasave (gc->castle_id, 18, gc->Ghp0);
+            if (gc->visibleG1 == 1)
+                guild_castledatasave (gc->castle_id, 19, gc->Ghp1);
+            if (gc->visibleG2 == 1)
+                guild_castledatasave (gc->castle_id, 20, gc->Ghp2);
+            if (gc->visibleG3 == 1)
+                guild_castledatasave (gc->castle_id, 21, gc->Ghp3);
+            if (gc->visibleG4 == 1)
+                guild_castledatasave (gc->castle_id, 22, gc->Ghp4);
+            if (gc->visibleG5 == 1)
+                guild_castledatasave (gc->castle_id, 23, gc->Ghp5);
+            if (gc->visibleG6 == 1)
+                guild_castledatasave (gc->castle_id, 24, gc->Ghp6);
+            if (gc->visibleG7 == 1)
+                guild_castledatasave (gc->castle_id, 25, gc->Ghp7);
+        }
+
+        save_flag = 1;
+        last_save_fd = sd->fd;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 自動セーブ (timer関数)
+ *------------------------------------------
+ */
+void pc_autosave (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  interval;
+
+    save_flag = 0;
+    clif_foreachclient (pc_autosave_sub);
+    if (save_flag == 0)
+        last_save_fd = 0;
+
+    interval = autosave_interval / (clif_countusers () + 1);
+    if (interval <= 0)
+        interval = 1;
+    add_timer (gettick () + interval, pc_autosave, 0, 0);
+}
+
+int pc_read_gm_account (int fd)
+{
+    int  i = 0;
+    if (gm_account != NULL)
+        free (gm_account);
+    GM_num = 0;
+
+    CREATE (gm_account, struct gm_account, (RFIFOW (fd, 2) - 4) / 5);
+    for (i = 4; i < RFIFOW (fd, 2); i = i + 5)
+    {
+        gm_account[GM_num].account_id = RFIFOL (fd, i);
+        gm_account[GM_num].level = (int) RFIFOB (fd, i + 4);
+        //printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
+        GM_num++;
+    }
+    return GM_num;
+}
+
+/*==========================================
+ * timer to do the day
+ *------------------------------------------
+ */
+void map_day_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{                               // by [yor]
+    struct map_session_data *pl_sd = NULL;
+    int  i;
+    char tmpstr[1024];
+
+    if (battle_config.day_duration > 0)
+    {                           // if we want a day
+        if (night_flag != 0)
+        {
+            strcpy (tmpstr, msg_txt (502)); // The day has arrived!
+            night_flag = 0;     // 0=day, 1=night [Yor]
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                    && pl_sd->state.auth)
+                {
+                    pl_sd->opt2 &= ~STATE_BLIND;
+                    clif_changeoption (&pl_sd->bl);
+                    clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
+                                      strlen (tmpstr) + 1);
+                }
+            }
+        }
+    }
+}
+
+/*==========================================
+ * timer to do the night
+ *------------------------------------------
+ */
+void map_night_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{                               // by [yor]
+    struct map_session_data *pl_sd = NULL;
+    int  i;
+    char tmpstr[1024];
+
+    if (battle_config.night_duration > 0)
+    {                           // if we want a night
+        if (night_flag == 0)
+        {
+            strcpy (tmpstr, msg_txt (503)); // The night has fallen...
+            night_flag = 1;     // 0=day, 1=night [Yor]
+            for (i = 0; i < fd_max; i++)
+            {
+                if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                    && pl_sd->state.auth)
+                {
+                    pl_sd->opt2 |= STATE_BLIND;
+                    clif_changeoption (&pl_sd->bl);
+                    clif_wis_message (pl_sd->fd, wisp_server_name, tmpstr,
+                                      strlen (tmpstr) + 1);
+                }
+            }
+        }
+    }
+}
+
+void pc_setstand (struct map_session_data *sd)
+{
+    nullpo_retv (sd);
+
+    if (sd->sc_data && sd->sc_data[SC_TENSIONRELAX].timer != -1)
+        skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1);
+
+    sd->state.dead_sit = 0;
+}
+
+//
+// 初期化物
+//
+/*==========================================
+ * 設定ファイル読み込む
+ * exp.txt 必要経験値
+ * job_db1.txt 重量,hp,sp,攻撃速度
+ * job_db2.txt job能力値ボーナス
+ * skill_tree.txt 各職毎のスキルツリー
+ * attr_fix.txt 属性修正テーブル
+ * size_fix.txt サイズ補正テーブル
+ * refine_db.txt 精錬データテーブル
+ *------------------------------------------
+ */
+int pc_readdb (void)
+{
+    int  i, j, k;
+    FILE *fp;
+    char line[1024], *p;
+
+    // 必要経験値読み込み
+
+    fp = fopen_ ("db/exp.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/exp.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        int  bn, b1, b2, b3, b4, b5, b6, jn, j1, j2, j3, j4, j5, j6;
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (sscanf
+            (line, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &bn, &b1, &b2,
+             &b3, &b4, &b5, &b6, &jn, &j1, &j2, &j3, &j4, &j5, &j6) != 14)
+            continue;
+        exp_table[0][i] = bn;
+        exp_table[1][i] = b1;
+        exp_table[2][i] = b2;
+        exp_table[3][i] = b3;
+        exp_table[4][i] = b4;
+        exp_table[5][i] = b5;
+        exp_table[6][i] = b6;
+        exp_table[7][i] = jn;
+        exp_table[8][i] = j1;
+        exp_table[9][i] = j2;
+        exp_table[10][i] = j3;
+        exp_table[11][i] = j4;
+        exp_table[12][i] = j5;
+        exp_table[13][i] = j6;
+        i++;
+        if (i >= battle_config.maximum_level)
+            break;
+    }
+    fclose_ (fp);
+    printf ("read db/exp.txt done\n");
+
+    // JOB補正数値1
+    fp = fopen_ ("db/job_db1.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/job_db1.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        char *split[50];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 21 && p; j++)
+        {
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (j < 21)
+            continue;
+        max_weight_base[i] = atoi (split[0]);
+        hp_coefficient[i] = atoi (split[1]);
+        hp_coefficient2[i] = atoi (split[2]);
+        sp_coefficient[i] = atoi (split[3]);
+        for (j = 0; j < 17; j++)
+            aspd_base[i][j] = atoi (split[j + 4]);
+        i++;
+// -- moonsoul (below two lines added to accommodate high numbered new class ids)
+        if (i == 24)
+            i = 4001;
+        if (i == MAX_PC_CLASS)
+            break;
+    }
+    fclose_ (fp);
+    printf ("read db/job_db1.txt done\n");
+
+    // JOBボーナス
+    fp = fopen_ ("db/job_db2.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/job_db2.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < MAX_LEVEL && p; j++)
+        {
+            if (sscanf (p, "%d", &k) == 0)
+                break;
+            job_bonus[0][i][j] = k;
+            job_bonus[2][i][j] = k; //養子職のボーナスは分からないので仮
+            p = strchr (p, ',');
+            if (p)
+                p++;
+        }
+        i++;
+// -- moonsoul (below two lines added to accommodate high numbered new class ids)
+        if (i == 24)
+            i = 4001;
+        if (i == MAX_PC_CLASS)
+            break;
+    }
+    fclose_ (fp);
+    printf ("read db/job_db2.txt done\n");
+
+    // JOBボーナス2 転生職用
+    fp = fopen_ ("db/job_db2-2.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/job_db2-2.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < MAX_LEVEL && p; j++)
+        {
+            if (sscanf (p, "%d", &k) == 0)
+                break;
+            job_bonus[1][i][j] = k;
+            p = strchr (p, ',');
+            if (p)
+                p++;
+        }
+        i++;
+        if (i == MAX_PC_CLASS)
+            break;
+    }
+    fclose_ (fp);
+    printf ("read db/job_db2-2.txt done\n");
+
+    // スキルツリー
+    memset (skill_tree, 0, sizeof (skill_tree));
+    fp = fopen_ ("db/skill_tree.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/skill_tree.txt\n");
+        return 1;
+    }
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        char *split[50];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 13 && p; j++)
+        {
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (j < 13)
+            continue;
+        i = atoi (split[0]);
+        for (j = 0; skill_tree[0][i][j].id; j++);
+        skill_tree[0][i][j].id = atoi (split[1]);
+        skill_tree[0][i][j].max = atoi (split[2]);
+        skill_tree[2][i][j].id = atoi (split[1]);   //養子職は良く分からないので暫定
+        skill_tree[2][i][j].max = atoi (split[2]);  //養子職は良く分からないので暫定
+        for (k = 0; k < 5; k++)
+        {
+            skill_tree[0][i][j].need[k].id = atoi (split[k * 2 + 3]);
+            skill_tree[0][i][j].need[k].lv = atoi (split[k * 2 + 4]);
+            skill_tree[2][i][j].need[k].id = atoi (split[k * 2 + 3]);   //養子職は良く分からないので暫定
+            skill_tree[2][i][j].need[k].lv = atoi (split[k * 2 + 4]);   //養子職は良く分からないので暫定
+        }
+    }
+    fclose_ (fp);
+    printf ("read db/skill_tree.txt done\n");
+
+    // 属性修正テーブル
+    for (i = 0; i < 4; i++)
+        for (j = 0; j < 10; j++)
+            for (k = 0; k < 10; k++)
+                attr_fix_table[i][j][k] = 100;
+    fp = fopen_ ("db/attr_fix.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/attr_fix.txt\n");
+        return 1;
+    }
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        char *split[10];
+        int  lv, n;
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 3 && p; j++)
+        {
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        lv = atoi (split[0]);
+        n = atoi (split[1]);
+//      printf("%d %d\n",lv,n);
+
+        for (i = 0; i < n;)
+        {
+            if (!fgets (line, sizeof (line) - 1, fp))
+                break;
+            if (line[0] == '/' && line[1] == '/')
+                continue;
+
+            for (j = 0, p = line; j < n && p; j++)
+            {
+                while (*p == 32 && *p > 0)
+                    p++;
+                attr_fix_table[lv - 1][i][j] = atoi (p);
+                if (battle_config.attr_recover == 0
+                    && attr_fix_table[lv - 1][i][j] < 0)
+                    attr_fix_table[lv - 1][i][j] = 0;
+                p = strchr (p, ',');
+                if (p)
+                    *p++ = 0;
+            }
+
+            i++;
+        }
+    }
+    fclose_ (fp);
+    printf ("read db/attr_fix.txt done\n");
+
+    // サイズ補正テーブル
+    for (i = 0; i < 3; i++)
+        for (j = 0; j < 20; j++)
+            atkmods[i][j] = 100;
+    fp = fopen_ ("db/size_fix.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/size_fix.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        char *split[20];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (atoi (line) <= 0)
+            continue;
+        memset (split, 0, sizeof (split));
+        for (j = 0, p = line; j < 20 && p; j++)
+        {
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        for (j = 0; j < 20 && split[j]; j++)
+            atkmods[i][j] = atoi (split[j]);
+        i++;
+    }
+    fclose_ (fp);
+    printf ("read db/size_fix.txt done\n");
+
+    // 精錬データテーブル
+    for (i = 0; i < 5; i++)
+    {
+        for (j = 0; j < 10; j++)
+            percentrefinery[i][j] = 100;
+        refinebonus[i][0] = 0;
+        refinebonus[i][1] = 0;
+        refinebonus[i][2] = 10;
+    }
+    fp = fopen_ ("db/refine_db.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/refine_db.txt\n");
+        return 1;
+    }
+    i = 0;
+    while (fgets (line, sizeof (line) - 1, fp))
+    {
+        char *split[16];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        if (atoi (line) <= 0)
+            continue;
+        memset (split, 0, sizeof (split));
+        for (j = 0, p = line; j < 16 && p; j++)
+        {
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        refinebonus[i][0] = atoi (split[0]);    // 精錬ボーナス
+        refinebonus[i][1] = atoi (split[1]);    // 過剰精錬ボーナス
+        refinebonus[i][2] = atoi (split[2]);    // 安全精錬限界
+        for (j = 0; j < 10 && split[j]; j++)
+            percentrefinery[i][j] = atoi (split[j + 3]);
+        i++;
+    }
+    fclose_ (fp);               //Lupus. close this file!!!
+    printf ("read db/refine_db.txt done\n");
+
+    return 0;
+}
+
+static int pc_calc_sigma (void)
+{
+    int  i, j, k;
+
+    for (i = 0; i < MAX_PC_CLASS; i++)
+    {
+        memset (hp_sigma_val[i], 0, sizeof (hp_sigma_val[i]));
+        for (k = 0, j = 2; j <= MAX_LEVEL; j++)
+        {
+            k += hp_coefficient[i] * j + 50;
+            k -= k % 100;
+            hp_sigma_val[i][j - 1] = k;
+        }
+    }
+    return 0;
+}
+
+static void pc_statpointdb (void)
+{
+    char *buf_stat;
+    int  i = 0, j = 0, k = 0, l = 0, end = 0;
+
+    FILE *stp;
+
+    stp = fopen_ ("db/statpoint.txt", "r");
+
+    if (stp == NULL)
+    {
+        printf ("can't read db/statpoint.txt\n");
+        return;
+    }
+
+    fseek (stp, 0, SEEK_END);
+    end = ftell (stp);
+    rewind (stp);
+
+    buf_stat = (char *) malloc (end + 1);
+    l = fread (buf_stat, 1, end, stp);
+    fclose_ (stp);
+    printf ("read db/statpoint.txt done (size=%d)\n", l);
+
+    for (i = 0; i < 255; i++)
+    {
+        j = 0;
+        while (*(buf_stat + k) != '\n')
+        {
+            statp[i][j] = *(buf_stat + k);
+            j++;
+            k++;
+        }
+        statp[i][j + 1] = '\0';
+        k++;
+    }
+
+    free (buf_stat);
+}
+
+/*==========================================
+ * pc関 係初期化
+ *------------------------------------------
+ */
+int do_init_pc (void)
+{
+    pc_readdb ();
+    pc_statpointdb ();
+    pc_calc_sigma ();
+
+//  gm_account_db = numdb_init();
+
+    add_timer_interval ((natural_heal_prev_tick =
+                         gettick () + NATURAL_HEAL_INTERVAL), pc_natural_heal,
+                        0, 0, NATURAL_HEAL_INTERVAL);
+    add_timer (gettick () + autosave_interval, pc_autosave, 0, 0);
+
+    {
+        int  day_duration = battle_config.day_duration;
+        int  night_duration = battle_config.night_duration;
+        if (day_duration < 60000)
+            day_duration = 60000;
+        if (night_duration < 60000)
+            night_duration = 60000;
+        if (battle_config.night_at_start == 0)
+        {
+            night_flag = 0;     // 0=day, 1=night [Yor]
+            day_timer_tid =
+                add_timer_interval (gettick () + day_duration +
+                                    night_duration, map_day_timer, 0, 0,
+                                    day_duration + night_duration);
+            night_timer_tid =
+                add_timer_interval (gettick () + day_duration,
+                                    map_night_timer, 0, 0,
+                                    day_duration + night_duration);
+        }
+        else
+        {
+            night_flag = 1;     // 0=day, 1=night [Yor]
+            day_timer_tid =
+                add_timer_interval (gettick () + night_duration,
+                                    map_day_timer, 0, 0,
+                                    day_duration + night_duration);
+            night_timer_tid =
+                add_timer_interval (gettick () + day_duration +
+                                    night_duration, map_night_timer, 0, 0,
+                                    day_duration + night_duration);
+        }
+    }
+
+    return 0;
+}
+
+void pc_cleanup (struct map_session_data *sd)
+{
+    magic_stop_completely (sd);
+}
+
+void pc_invisibility (struct map_session_data *sd, int enabled)
+{
+    if (enabled && !(sd->status.option & OPTION_INVISIBILITY))
+    {
+        clif_clearchar_area (&sd->bl, 3);
+        sd->status.option |= OPTION_INVISIBILITY;
+        clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 1);
+    }
+    else if (!enabled)
+    {
+        sd->status.option &= ~OPTION_INVISIBILITY;
+        clif_status_change (&sd->bl, CLIF_OPTION_SC_INVISIBILITY, 0);
+        pc_setpos (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y, 3);
+    }
+}
+
+int pc_logout (struct map_session_data *sd) // [fate] Player logs out
+{
+    unsigned int tick = gettick ();
+
+    if (!sd)
+        return 0;
+
+    if (sd->sc_data[SC_POISON].timer != -1)
+        sd->status.hp = 1;      // Logging out while poisoned -> bad
+
+    /*
+     * Trying to rapidly sign out/in or switch characters to avoid a spell's
+     * cast time is also bad. [remoitnane]
+     */
+#if 0
+    // Removed because it's buggy, see above.
+    if (sd->cast_tick > tick)
+    {
+        if (pc_setglobalreg (sd, "MAGIC_CAST_TICK", sd->cast_tick - tick))
+            sd->status.sp = 1;
+    }
+    else
+#endif
+        pc_setglobalreg (sd, "MAGIC_CAST_TICK", 0);
+
+    MAP_LOG_STATS (sd, "LOGOUT") return 0;
+}
diff --git a/src/map/pc.h b/src/map/pc.h
deleted file mode 100644
index 742d9d4..0000000
--- a/src/map/pc.h
+++ /dev/null
@@ -1,210 +0,0 @@
-// $Id: pc.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
-
-#ifndef _PC_H_
-#define _PC_H_
-
-#include "map.h"
-
-#define OPTION_MASK 0xd7b8
-#define CART_MASK 0x788
-
-#define pc_setdead(sd) ((sd)->state.dead_sit = 1)
-#define pc_setsit(sd) ((sd)->state.dead_sit = 2)
-//#define pc_setstand(sd) ((sd)->state.dead_sit = 0)
-#define pc_isdead(sd) ((sd)->state.dead_sit == 1)
-#define pc_issit(sd) ((sd)->state.dead_sit == 2)
-#define pc_setdir(sd,b) ((sd)->dir = (b))
-#define pc_setchatid(sd,n) ((sd)->chatID = n)
-#define pc_ishiding(sd) ((sd)->status.option&0x4006)
-#define pc_iscarton(sd) ((sd)->status.option&CART_MASK)
-#define pc_isfalcon(sd) ((sd)->status.option&0x0010)
-#define pc_isriding(sd) ((sd)->status.option&0x0020)
-#define pc_isinvisible(sd) ((sd)->status.option&0x0040)
-#define pc_is50overweight(sd) (sd->weight*2 >= sd->max_weight)
-#define pc_is90overweight(sd) (sd->weight*10 >= sd->max_weight*9)
-
-void pc_touch_all_relevant_npcs (struct map_session_data *sd);  /* Checks all npcs/warps at the same location to see whether they
-                                                                 ** should do something with the specified player. */
-
-int  pc_isGM (struct map_session_data *sd);
-int  pc_iskiller (struct map_session_data *src, struct map_session_data *target);   // [MouseJstr]
-int  pc_getrefinebonus (int lv, int type);
-
-void pc_invisibility (struct map_session_data *sd, int enabled);    // [Fate]
-int  pc_counttargeted (struct map_session_data *sd, struct block_list *src,
-                       int target_lv);
-int  pc_setrestartvalue (struct map_session_data *sd, int type);
-int  pc_makesavestatus (struct map_session_data *);
-int  pc_setnewpc (struct map_session_data *, int, int, int, int, int, int);
-int  pc_authok (int, int, time_t, short tmw_version, struct mmo_charstatus *);
-int  pc_authfail (int);
-
-int  pc_isequip (struct map_session_data *sd, int n);
-int  pc_equippoint (struct map_session_data *sd, int n);
-
-int  pc_breakweapon (struct map_session_data *sd);  // weapon breaking [Valaris]
-int  pc_breakarmor (struct map_session_data *sd);   // armor breaking [Valaris]
-
-int  pc_checkskill (struct map_session_data *sd, int skill_id);
-int  pc_checkallowskill (struct map_session_data *sd);
-int  pc_checkequip (struct map_session_data *sd, int pos);
-
-int  pc_checkoverhp (struct map_session_data *);
-int  pc_checkoversp (struct map_session_data *);
-
-int  pc_can_reach (struct map_session_data *, int, int);
-int  pc_walktoxy (struct map_session_data *, int, int);
-int  pc_stop_walking (struct map_session_data *, int);
-int  pc_movepos (struct map_session_data *, int, int);
-int  pc_setpos (struct map_session_data *, char *, int, int, int);
-int  pc_setsavepoint (struct map_session_data *, char *, int, int);
-int  pc_randomwarp (struct map_session_data *sd, int type);
-int  pc_memo (struct map_session_data *sd, int i);
-
-int  pc_checkadditem (struct map_session_data *, int, int);
-int  pc_inventoryblank (struct map_session_data *);
-int  pc_search_inventory (struct map_session_data *sd, int item_id);
-int  pc_payzeny (struct map_session_data *, int);
-int  pc_additem (struct map_session_data *, struct item *, int);
-int  pc_getzeny (struct map_session_data *, int);
-int  pc_delitem (struct map_session_data *, int, int, int);
-int  pc_checkitem (struct map_session_data *);
-int  pc_count_all_items (struct map_session_data *player, int item_id);
-int  pc_remove_items (struct map_session_data *player, int item_id,
-                      int count);
-
-int  pc_cart_additem (struct map_session_data *sd, struct item *item_data,
-                      int amount);
-int  pc_cart_delitem (struct map_session_data *sd, int n, int amount,
-                      int type);
-int  pc_putitemtocart (struct map_session_data *sd, int idx, int amount);
-int  pc_getitemfromcart (struct map_session_data *sd, int idx, int amount);
-int  pc_cartitem_amount (struct map_session_data *sd, int idx, int amount);
-
-int  pc_takeitem (struct map_session_data *, struct flooritem_data *);
-int  pc_dropitem (struct map_session_data *, int, int);
-
-int  pc_checkweighticon (struct map_session_data *sd);
-
-int  pc_calcstatus (struct map_session_data *, int);
-int  pc_bonus (struct map_session_data *, int, int);
-int  pc_bonus2 (struct map_session_data *sd, int, int, int);
-int  pc_bonus3 (struct map_session_data *sd, int, int, int, int);
-int  pc_skill (struct map_session_data *, int, int, int);
-
-int  pc_insert_card (struct map_session_data *sd, int idx_card,
-                     int idx_equip);
-
-int  pc_item_identify (struct map_session_data *sd, int idx);
-int  pc_steal_item (struct map_session_data *sd, struct block_list *bl);
-int  pc_steal_coin (struct map_session_data *sd, struct block_list *bl);
-
-int  pc_modifybuyvalue (struct map_session_data *, int);
-int  pc_modifysellvalue (struct map_session_data *, int);
-
-int  pc_attack (struct map_session_data *, int, int);
-int  pc_stopattack (struct map_session_data *);
-
-int  pc_follow (struct map_session_data *, int);    // [MouseJstr]
-
-int  pc_checkbaselevelup (struct map_session_data *sd);
-int  pc_checkjoblevelup (struct map_session_data *sd);
-int  pc_gainexp (struct map_session_data *, int, int);
-
-#define PC_GAINEXP_REASON_KILLING	0
-#define PC_GAINEXP_REASON_HEALING	1
-#define PC_GAINEXP_REASON_SCRIPT	2
-int  pc_gainexp_reason (struct map_session_data *, int, int, int reason);
-int  pc_extract_healer_exp (struct map_session_data *, int max);    // [Fate] Used by healers: extract healer-xp from the target, return result (up to max)
-
-int  pc_nextbaseexp (struct map_session_data *);
-int  pc_nextbaseafter (struct map_session_data *);  // [Valaris]
-int  pc_nextjobexp (struct map_session_data *);
-int  pc_nextjobafter (struct map_session_data *);   // [Valaris]
-int  pc_need_status_point (struct map_session_data *, int);
-int  pc_statusup (struct map_session_data *, int);
-int  pc_statusup2 (struct map_session_data *, int, int);
-int  pc_skillup (struct map_session_data *, int);
-int  pc_allskillup (struct map_session_data *);
-int  pc_resetlvl (struct map_session_data *, int type);
-int  pc_resetstate (struct map_session_data *);
-int  pc_resetskill (struct map_session_data *);
-int  pc_equipitem (struct map_session_data *, int, int);
-int  pc_unequipitem (struct map_session_data *, int, int);
-int  pc_unequipinvyitem (struct map_session_data *, int, int);
-int  pc_checkitem (struct map_session_data *);
-int  pc_useitem (struct map_session_data *, int);
-
-int  pc_damage (struct block_list *, struct map_session_data *, int);
-int  pc_heal (struct map_session_data *, int, int);
-int  pc_itemheal (struct map_session_data *sd, int hp, int sp);
-int  pc_percentheal (struct map_session_data *sd, int, int);
-int  pc_jobchange (struct map_session_data *, int, int);
-int  pc_setoption (struct map_session_data *, int);
-int  pc_setcart (struct map_session_data *sd, int type);
-int  pc_setfalcon (struct map_session_data *sd);
-int  pc_setriding (struct map_session_data *sd);
-int  pc_changelook (struct map_session_data *, int, int);
-int  pc_equiplookall (struct map_session_data *sd);
-
-int  pc_readparam (struct map_session_data *, int);
-int  pc_setparam (struct map_session_data *, int, int);
-int  pc_readreg (struct map_session_data *, int);
-int  pc_setreg (struct map_session_data *, int, int);
-char *pc_readregstr (struct map_session_data *sd, int reg);
-int  pc_setregstr (struct map_session_data *sd, int reg, char *str);
-int  pc_readglobalreg (struct map_session_data *, char *);
-int  pc_setglobalreg (struct map_session_data *, char *, int);
-int  pc_readaccountreg (struct map_session_data *, char *);
-int  pc_setaccountreg (struct map_session_data *, char *, int);
-int  pc_readaccountreg2 (struct map_session_data *, char *);
-int  pc_setaccountreg2 (struct map_session_data *, char *, int);
-int  pc_percentrefinery (struct map_session_data *sd, struct item *item);
-
-int  pc_addeventtimer (struct map_session_data *sd, int tick,
-                       const char *name);
-int  pc_deleventtimer (struct map_session_data *sd, const char *name);
-int  pc_cleareventtimer (struct map_session_data *sd);
-int  pc_addeventtimercount (struct map_session_data *sd, const char *name,
-                            int tick);
-
-int  pc_calc_pvprank (struct map_session_data *sd);
-void pc_calc_pvprank_timer (timer_id, tick_t, custom_id_t, custom_data_t);
-
-int  pc_ismarried (struct map_session_data *sd);
-int  pc_marriage (struct map_session_data *sd,
-                  struct map_session_data *dstsd);
-int  pc_divorce (struct map_session_data *sd);
-struct map_session_data *pc_get_partner (struct map_session_data *sd);
-int  pc_set_gm_level (int account_id, int level);
-void pc_setstand (struct map_session_data *sd);
-void pc_cleanup (struct map_session_data *sd);  // [Fate] Clean up after a logged-out PC
-
-struct pc_base_job
-{
-    int  job;                   //職業、ただし転生職や養子職の場合は元の職業を返す(廃プリ→プリ)
-    int  type;                  //ノビ 0, 一次職 1, 二次職 2, スパノビ 3
-    int  upper;                 //通常 0, 転生 1, 養子 2
-};
-
-struct pc_base_job pc_calc_base_job (int b_class);  //転生や養子職の元の職業を返す
-
-int  pc_read_gm_account (int fd);
-int  pc_setinvincibletimer (struct map_session_data *sd, int);
-int  pc_delinvincibletimer (struct map_session_data *sd);
-int  pc_addspiritball (struct map_session_data *sd, int, int);
-int  pc_delspiritball (struct map_session_data *sd, int, int);
-int  pc_logout (struct map_session_data *sd);   // [fate] Player logs out
-
-int  do_init_pc (void);
-
-enum
-{ ADDITEM_EXIST, ADDITEM_NEW, ADDITEM_OVERAMOUNT };
-
-// timer for night.day
-timer_id day_timer_tid;
-timer_id night_timer_tid;
-void map_day_timer (timer_id, tick_t, custom_id_t, custom_data_t);   // by [yor]
-void map_night_timer (timer_id, tick_t, custom_id_t, custom_data_t); // by [yor]
-
-#endif
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
new file mode 100644
index 0000000..7237957
--- /dev/null
+++ b/src/map/pc.hpp
@@ -0,0 +1,210 @@
+// $Id: pc.h,v 1.4 2004/09/25 05:32:18 MouseJstr Exp $
+
+#ifndef PC_HPP
+#define PC_HPP
+
+#include "map.hpp"
+
+#define OPTION_MASK 0xd7b8
+#define CART_MASK 0x788
+
+#define pc_setdead(sd) ((sd)->state.dead_sit = 1)
+#define pc_setsit(sd) ((sd)->state.dead_sit = 2)
+//#define pc_setstand(sd) ((sd)->state.dead_sit = 0)
+#define pc_isdead(sd) ((sd)->state.dead_sit == 1)
+#define pc_issit(sd) ((sd)->state.dead_sit == 2)
+#define pc_setdir(sd,b) ((sd)->dir = (b))
+#define pc_setchatid(sd,n) ((sd)->chatID = n)
+#define pc_ishiding(sd) ((sd)->status.option&0x4006)
+#define pc_iscarton(sd) ((sd)->status.option&CART_MASK)
+#define pc_isfalcon(sd) ((sd)->status.option&0x0010)
+#define pc_isriding(sd) ((sd)->status.option&0x0020)
+#define pc_isinvisible(sd) ((sd)->status.option&0x0040)
+#define pc_is50overweight(sd) (sd->weight*2 >= sd->max_weight)
+#define pc_is90overweight(sd) (sd->weight*10 >= sd->max_weight*9)
+
+void pc_touch_all_relevant_npcs (struct map_session_data *sd);  /* Checks all npcs/warps at the same location to see whether they
+                                                                 ** should do something with the specified player. */
+
+int  pc_isGM (struct map_session_data *sd);
+int  pc_iskiller (struct map_session_data *src, struct map_session_data *target);   // [MouseJstr]
+int  pc_getrefinebonus (int lv, int type);
+
+void pc_invisibility (struct map_session_data *sd, int enabled);    // [Fate]
+int  pc_counttargeted (struct map_session_data *sd, struct block_list *src,
+                       int target_lv);
+int  pc_setrestartvalue (struct map_session_data *sd, int type);
+int  pc_makesavestatus (struct map_session_data *);
+int  pc_setnewpc (struct map_session_data *, int, int, int, int, int, int);
+int  pc_authok (int, int, time_t, short tmw_version, struct mmo_charstatus *);
+int  pc_authfail (int);
+
+int  pc_isequip (struct map_session_data *sd, int n);
+int  pc_equippoint (struct map_session_data *sd, int n);
+
+int  pc_breakweapon (struct map_session_data *sd);  // weapon breaking [Valaris]
+int  pc_breakarmor (struct map_session_data *sd);   // armor breaking [Valaris]
+
+int  pc_checkskill (struct map_session_data *sd, int skill_id);
+int  pc_checkallowskill (struct map_session_data *sd);
+int  pc_checkequip (struct map_session_data *sd, int pos);
+
+int  pc_checkoverhp (struct map_session_data *);
+int  pc_checkoversp (struct map_session_data *);
+
+int  pc_can_reach (struct map_session_data *, int, int);
+int  pc_walktoxy (struct map_session_data *, int, int);
+int  pc_stop_walking (struct map_session_data *, int);
+int  pc_movepos (struct map_session_data *, int, int);
+int  pc_setpos (struct map_session_data *, char *, int, int, int);
+int  pc_setsavepoint (struct map_session_data *, char *, int, int);
+int  pc_randomwarp (struct map_session_data *sd, int type);
+int  pc_memo (struct map_session_data *sd, int i);
+
+int  pc_checkadditem (struct map_session_data *, int, int);
+int  pc_inventoryblank (struct map_session_data *);
+int  pc_search_inventory (struct map_session_data *sd, int item_id);
+int  pc_payzeny (struct map_session_data *, int);
+int  pc_additem (struct map_session_data *, struct item *, int);
+int  pc_getzeny (struct map_session_data *, int);
+int  pc_delitem (struct map_session_data *, int, int, int);
+int  pc_checkitem (struct map_session_data *);
+int  pc_count_all_items (struct map_session_data *player, int item_id);
+int  pc_remove_items (struct map_session_data *player, int item_id,
+                      int count);
+
+int  pc_cart_additem (struct map_session_data *sd, struct item *item_data,
+                      int amount);
+int  pc_cart_delitem (struct map_session_data *sd, int n, int amount,
+                      int type);
+int  pc_putitemtocart (struct map_session_data *sd, int idx, int amount);
+int  pc_getitemfromcart (struct map_session_data *sd, int idx, int amount);
+int  pc_cartitem_amount (struct map_session_data *sd, int idx, int amount);
+
+int  pc_takeitem (struct map_session_data *, struct flooritem_data *);
+int  pc_dropitem (struct map_session_data *, int, int);
+
+int  pc_checkweighticon (struct map_session_data *sd);
+
+int  pc_calcstatus (struct map_session_data *, int);
+int  pc_bonus (struct map_session_data *, int, int);
+int  pc_bonus2 (struct map_session_data *sd, int, int, int);
+int  pc_bonus3 (struct map_session_data *sd, int, int, int, int);
+int  pc_skill (struct map_session_data *, int, int, int);
+
+int  pc_insert_card (struct map_session_data *sd, int idx_card,
+                     int idx_equip);
+
+int  pc_item_identify (struct map_session_data *sd, int idx);
+int  pc_steal_item (struct map_session_data *sd, struct block_list *bl);
+int  pc_steal_coin (struct map_session_data *sd, struct block_list *bl);
+
+int  pc_modifybuyvalue (struct map_session_data *, int);
+int  pc_modifysellvalue (struct map_session_data *, int);
+
+int  pc_attack (struct map_session_data *, int, int);
+int  pc_stopattack (struct map_session_data *);
+
+int  pc_follow (struct map_session_data *, int);    // [MouseJstr]
+
+int  pc_checkbaselevelup (struct map_session_data *sd);
+int  pc_checkjoblevelup (struct map_session_data *sd);
+int  pc_gainexp (struct map_session_data *, int, int);
+
+#define PC_GAINEXP_REASON_KILLING	0
+#define PC_GAINEXP_REASON_HEALING	1
+#define PC_GAINEXP_REASON_SCRIPT	2
+int  pc_gainexp_reason (struct map_session_data *, int, int, int reason);
+int  pc_extract_healer_exp (struct map_session_data *, int max);    // [Fate] Used by healers: extract healer-xp from the target, return result (up to max)
+
+int  pc_nextbaseexp (struct map_session_data *);
+int  pc_nextbaseafter (struct map_session_data *);  // [Valaris]
+int  pc_nextjobexp (struct map_session_data *);
+int  pc_nextjobafter (struct map_session_data *);   // [Valaris]
+int  pc_need_status_point (struct map_session_data *, int);
+int  pc_statusup (struct map_session_data *, int);
+int  pc_statusup2 (struct map_session_data *, int, int);
+int  pc_skillup (struct map_session_data *, int);
+int  pc_allskillup (struct map_session_data *);
+int  pc_resetlvl (struct map_session_data *, int type);
+int  pc_resetstate (struct map_session_data *);
+int  pc_resetskill (struct map_session_data *);
+int  pc_equipitem (struct map_session_data *, int, int);
+int  pc_unequipitem (struct map_session_data *, int, int);
+int  pc_unequipinvyitem (struct map_session_data *, int, int);
+int  pc_checkitem (struct map_session_data *);
+int  pc_useitem (struct map_session_data *, int);
+
+int  pc_damage (struct block_list *, struct map_session_data *, int);
+int  pc_heal (struct map_session_data *, int, int);
+int  pc_itemheal (struct map_session_data *sd, int hp, int sp);
+int  pc_percentheal (struct map_session_data *sd, int, int);
+int  pc_jobchange (struct map_session_data *, int, int);
+int  pc_setoption (struct map_session_data *, int);
+int  pc_setcart (struct map_session_data *sd, int type);
+int  pc_setfalcon (struct map_session_data *sd);
+int  pc_setriding (struct map_session_data *sd);
+int  pc_changelook (struct map_session_data *, int, int);
+int  pc_equiplookall (struct map_session_data *sd);
+
+int  pc_readparam (struct map_session_data *, int);
+int  pc_setparam (struct map_session_data *, int, int);
+int  pc_readreg (struct map_session_data *, int);
+int  pc_setreg (struct map_session_data *, int, int);
+char *pc_readregstr (struct map_session_data *sd, int reg);
+int  pc_setregstr (struct map_session_data *sd, int reg, char *str);
+int  pc_readglobalreg (struct map_session_data *, char *);
+int  pc_setglobalreg (struct map_session_data *, char *, int);
+int  pc_readaccountreg (struct map_session_data *, char *);
+int  pc_setaccountreg (struct map_session_data *, char *, int);
+int  pc_readaccountreg2 (struct map_session_data *, char *);
+int  pc_setaccountreg2 (struct map_session_data *, char *, int);
+int  pc_percentrefinery (struct map_session_data *sd, struct item *item);
+
+int  pc_addeventtimer (struct map_session_data *sd, int tick,
+                       const char *name);
+int  pc_deleventtimer (struct map_session_data *sd, const char *name);
+int  pc_cleareventtimer (struct map_session_data *sd);
+int  pc_addeventtimercount (struct map_session_data *sd, const char *name,
+                            int tick);
+
+int  pc_calc_pvprank (struct map_session_data *sd);
+void pc_calc_pvprank_timer (timer_id, tick_t, custom_id_t, custom_data_t);
+
+int  pc_ismarried (struct map_session_data *sd);
+int  pc_marriage (struct map_session_data *sd,
+                  struct map_session_data *dstsd);
+int  pc_divorce (struct map_session_data *sd);
+struct map_session_data *pc_get_partner (struct map_session_data *sd);
+int  pc_set_gm_level (int account_id, int level);
+void pc_setstand (struct map_session_data *sd);
+void pc_cleanup (struct map_session_data *sd);  // [Fate] Clean up after a logged-out PC
+
+struct pc_base_job
+{
+    int  job;                   //職業、ただし転生職や養子職の場合は元の職業を返す(廃プリ→プリ)
+    int  type;                  //ノビ 0, 一次職 1, 二次職 2, スパノビ 3
+    int  upper;                 //通常 0, 転生 1, 養子 2
+};
+
+struct pc_base_job pc_calc_base_job (int b_class);  //転生や養子職の元の職業を返す
+
+int  pc_read_gm_account (int fd);
+int  pc_setinvincibletimer (struct map_session_data *sd, int);
+int  pc_delinvincibletimer (struct map_session_data *sd);
+int  pc_addspiritball (struct map_session_data *sd, int, int);
+int  pc_delspiritball (struct map_session_data *sd, int, int);
+int  pc_logout (struct map_session_data *sd);   // [fate] Player logs out
+
+int  do_init_pc (void);
+
+enum
+{ ADDITEM_EXIST, ADDITEM_NEW, ADDITEM_OVERAMOUNT };
+
+// timer for night.day
+timer_id day_timer_tid;
+timer_id night_timer_tid;
+void map_day_timer (timer_id, tick_t, custom_id_t, custom_data_t);   // by [yor]
+void map_night_timer (timer_id, tick_t, custom_id_t, custom_data_t); // by [yor]
+
+#endif
diff --git a/src/map/script.c b/src/map/script.c
deleted file mode 100644
index 12fbab2..0000000
--- a/src/map/script.c
+++ /dev/null
@@ -1,8145 +0,0 @@
-// $Id: script.c 148 2004-09-30 14:05:37Z MouseJstr $
-//#define DEBUG_FUNCIN
-//#define DEBUG_DISP
-//#define DEBUG_RUN
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifndef LCCWIN32
-#include <sys/time.h>
-#endif
-
-#include <time.h>
-#include <math.h>
-
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/lock.h"
-#include "../common/mt_rand.h"
-
-#include "atcommand.h"
-#include "battle.h"
-#include "chat.h"
-#include "chrif.h"
-#include "clif.h"
-#include "../common/db.h"
-#include "guild.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "../common/lock.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "storage.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define SCRIPT_BLOCK_SIZE 256
-enum
-{ LABEL_NEXTLINE = 1, LABEL_START };
-static unsigned char *script_buf;
-static int script_pos, script_size;
-
-char *str_buf;
-int  str_pos, str_size;
-static struct str_data_t
-{
-    int  type;
-    int  str;
-    int  backpatch;
-    int  label;
-    int  (*func) (struct script_state *);
-    int  val;
-    int  next;
-}   *str_data;
-int  str_num = LABEL_START, str_data_size;
-int  str_hash[16];
-
-static struct dbt *mapreg_db = NULL;
-static struct dbt *mapregstr_db = NULL;
-static int mapreg_dirty = -1;
-char mapreg_txt[256] = "save/mapreg.txt";
-#define MAPREG_AUTOSAVE_INTERVAL	(10*1000)
-
-static struct dbt *scriptlabel_db = NULL;
-static struct dbt *userfunc_db = NULL;
-
-struct dbt *script_get_label_db (void)
-{
-    return scriptlabel_db;
-}
-
-struct dbt *script_get_userfunc_db (void)
-{
-    if (!userfunc_db)
-        userfunc_db = strdb_init (50);
-    return userfunc_db;
-}
-
-static char pos[11][100] =
-    { "頭", "体", "左手", "右手", "ローブ", "靴", "アクセサリー1",
-    "アクセサリー2", "頭2", "頭3", "装着していない"
-};
-
-static struct Script_Config
-{
-    int  warn_func_no_comma;
-    int  warn_cmd_no_comma;
-    int  warn_func_mismatch_paramnum;
-    int  warn_cmd_mismatch_paramnum;
-    int  check_cmdcount;
-    int  check_gotocount;
-} script_config;
-static int parse_cmd_if = 0;
-static int parse_cmd;
-
-/*==========================================
- * ローカルプロトタイプ宣言 (必要な物のみ)
- *------------------------------------------
- */
-unsigned char *parse_subexpr (unsigned char *, int);
-int  buildin_mes (struct script_state *st);
-int  buildin_goto (struct script_state *st);
-int  buildin_callsub (struct script_state *st);
-int  buildin_callfunc (struct script_state *st);
-int  buildin_return (struct script_state *st);
-int  buildin_getarg (struct script_state *st);
-int  buildin_next (struct script_state *st);
-int  buildin_close (struct script_state *st);
-int  buildin_close2 (struct script_state *st);
-int  buildin_menu (struct script_state *st);
-int  buildin_rand (struct script_state *st);
-int  buildin_pow (struct script_state *st);
-int  buildin_warp (struct script_state *st);
-int  buildin_isat (struct script_state *st);
-int  buildin_areawarp (struct script_state *st);
-int  buildin_heal (struct script_state *st);
-int  buildin_itemheal (struct script_state *st);
-int  buildin_percentheal (struct script_state *st);
-int  buildin_jobchange (struct script_state *st);
-int  buildin_input (struct script_state *st);
-int  buildin_setlook (struct script_state *st);
-int  buildin_set (struct script_state *st);
-int  buildin_setarray (struct script_state *st);
-int  buildin_cleararray (struct script_state *st);
-int  buildin_copyarray (struct script_state *st);
-int  buildin_getarraysize (struct script_state *st);
-int  buildin_deletearray (struct script_state *st);
-int  buildin_getelementofarray (struct script_state *st);
-int  buildin_if (struct script_state *st);
-int  buildin_getitem (struct script_state *st);
-int  buildin_getitem2 (struct script_state *st);
-int  buildin_makeitem (struct script_state *st);
-int  buildin_delitem (struct script_state *st);
-int  buildin_viewpoint (struct script_state *st);
-int  buildin_countitem (struct script_state *st);
-int  buildin_checkweight (struct script_state *st);
-int  buildin_readparam (struct script_state *st);
-int  buildin_getcharid (struct script_state *st);
-int  buildin_getpartyname (struct script_state *st);
-int  buildin_getpartymember (struct script_state *st);
-int  buildin_getguildname (struct script_state *st);
-int  buildin_getguildmaster (struct script_state *st);
-int  buildin_getguildmasterid (struct script_state *st);
-int  buildin_strcharinfo (struct script_state *st);
-int  buildin_getequipid (struct script_state *st);
-int  buildin_getequipname (struct script_state *st);
-int  buildin_getbrokenid (struct script_state *st); // [Valaris]
-int  buildin_repair (struct script_state *st);  // [Valaris]
-int  buildin_getequipisequiped (struct script_state *st);
-int  buildin_getequipisenableref (struct script_state *st);
-int  buildin_getequipisidentify (struct script_state *st);
-int  buildin_getequiprefinerycnt (struct script_state *st);
-int  buildin_getequipweaponlv (struct script_state *st);
-int  buildin_getequippercentrefinery (struct script_state *st);
-int  buildin_successrefitem (struct script_state *st);
-int  buildin_failedrefitem (struct script_state *st);
-int  buildin_cutin (struct script_state *st);
-int  buildin_cutincard (struct script_state *st);
-int  buildin_statusup (struct script_state *st);
-int  buildin_statusup2 (struct script_state *st);
-int  buildin_bonus (struct script_state *st);
-int  buildin_bonus2 (struct script_state *st);
-int  buildin_bonus3 (struct script_state *st);
-int  buildin_skill (struct script_state *st);
-int  buildin_setskill (struct script_state *st);
-int  buildin_guildskill (struct script_state *st);
-int  buildin_getskilllv (struct script_state *st);
-int  buildin_getgdskilllv (struct script_state *st);
-int  buildin_basicskillcheck (struct script_state *st);
-int  buildin_getgmlevel (struct script_state *st);
-int  buildin_end (struct script_state *st);
-int  buildin_getopt2 (struct script_state *st);
-int  buildin_setopt2 (struct script_state *st);
-int  buildin_checkoption (struct script_state *st);
-int  buildin_setoption (struct script_state *st);
-int  buildin_setcart (struct script_state *st);
-int  buildin_checkcart (struct script_state *st);   // check cart [Valaris]
-int  buildin_setfalcon (struct script_state *st);
-int  buildin_checkfalcon (struct script_state *st); // check falcon [Valaris]
-int  buildin_setriding (struct script_state *st);
-int  buildin_checkriding (struct script_state *st); // check for pecopeco [Valaris]
-int  buildin_savepoint (struct script_state *st);
-int  buildin_gettimetick (struct script_state *st);
-int  buildin_gettime (struct script_state *st);
-int  buildin_gettimestr (struct script_state *st);
-int  buildin_openstorage (struct script_state *st);
-int  buildin_guildopenstorage (struct script_state *st);
-int  buildin_itemskill (struct script_state *st);
-int  buildin_monster (struct script_state *st);
-int  buildin_areamonster (struct script_state *st);
-int  buildin_killmonster (struct script_state *st);
-int  buildin_killmonsterall (struct script_state *st);
-int  buildin_doevent (struct script_state *st);
-int  buildin_donpcevent (struct script_state *st);
-int  buildin_addtimer (struct script_state *st);
-int  buildin_deltimer (struct script_state *st);
-int  buildin_addtimercount (struct script_state *st);
-int  buildin_initnpctimer (struct script_state *st);
-int  buildin_stopnpctimer (struct script_state *st);
-int  buildin_startnpctimer (struct script_state *st);
-int  buildin_setnpctimer (struct script_state *st);
-int  buildin_getnpctimer (struct script_state *st);
-int  buildin_announce (struct script_state *st);
-int  buildin_mapannounce (struct script_state *st);
-int  buildin_areaannounce (struct script_state *st);
-int  buildin_getusers (struct script_state *st);
-int  buildin_getmapusers (struct script_state *st);
-int  buildin_getareausers (struct script_state *st);
-int  buildin_getareadropitem (struct script_state *st);
-int  buildin_enablenpc (struct script_state *st);
-int  buildin_disablenpc (struct script_state *st);
-int  buildin_enablearena (struct script_state *st); // Added by RoVeRT
-int  buildin_disablearena (struct script_state *st);    // Added by RoVeRT
-int  buildin_hideoffnpc (struct script_state *st);
-int  buildin_hideonnpc (struct script_state *st);
-int  buildin_sc_start (struct script_state *st);
-int  buildin_sc_start2 (struct script_state *st);
-int  buildin_sc_end (struct script_state *st);
-int  buildin_sc_check (struct script_state *st);    // [Fate]
-int  buildin_getscrate (struct script_state *st);
-int  buildin_debugmes (struct script_state *st);
-int  buildin_resetlvl (struct script_state *st);
-int  buildin_resetstatus (struct script_state *st);
-int  buildin_resetskill (struct script_state *st);
-int  buildin_changebase (struct script_state *st);
-int  buildin_changesex (struct script_state *st);
-int  buildin_waitingroom (struct script_state *st);
-int  buildin_delwaitingroom (struct script_state *st);
-int  buildin_enablewaitingroomevent (struct script_state *st);
-int  buildin_disablewaitingroomevent (struct script_state *st);
-int  buildin_getwaitingroomstate (struct script_state *st);
-int  buildin_warpwaitingpc (struct script_state *st);
-int  buildin_attachrid (struct script_state *st);
-int  buildin_detachrid (struct script_state *st);
-int  buildin_isloggedin (struct script_state *st);
-int  buildin_setmapflagnosave (struct script_state *st);
-int  buildin_setmapflag (struct script_state *st);
-int  buildin_removemapflag (struct script_state *st);
-int  buildin_pvpon (struct script_state *st);
-int  buildin_pvpoff (struct script_state *st);
-int  buildin_gvgon (struct script_state *st);
-int  buildin_gvgoff (struct script_state *st);
-int  buildin_emotion (struct script_state *st);
-int  buildin_maprespawnguildid (struct script_state *st);
-int  buildin_agitstart (struct script_state *st);   // <Agit>
-int  buildin_agitend (struct script_state *st);
-int  buildin_agitcheck (struct script_state *st);   // <Agitcheck>
-int  buildin_flagemblem (struct script_state *st);  // Flag Emblem
-int  buildin_getcastlename (struct script_state *st);
-int  buildin_getcastledata (struct script_state *st);
-int  buildin_setcastledata (struct script_state *st);
-int  buildin_requestguildinfo (struct script_state *st);
-int  buildin_getequipcardcnt (struct script_state *st);
-int  buildin_successremovecards (struct script_state *st);
-int  buildin_failedremovecards (struct script_state *st);
-int  buildin_marriage (struct script_state *st);
-int  buildin_wedding_effect (struct script_state *st);
-int  buildin_divorce (struct script_state *st);
-int  buildin_getitemname (struct script_state *st);
-int  buildin_getspellinvocation (struct script_state *st);  // [Fate]
-int  buildin_getanchorinvocation (struct script_state *st); // [Fate]
-int  buildin_getexp (struct script_state *st);
-int  buildin_getinventorylist (struct script_state *st);
-int  buildin_getskilllist (struct script_state *st);
-int  buildin_get_pool_skills (struct script_state *st); // [fate]
-int  buildin_get_activated_pool_skills (struct script_state *st);   // [fate]
-int  buildin_get_unactivated_pool_skills (struct script_state *st);   // [PO]
-int  buildin_activate_pool_skill (struct script_state *st); // [fate]
-int  buildin_deactivate_pool_skill (struct script_state *st);   // [fate]
-int  buildin_check_pool_skill (struct script_state *st);    // [fate]
-int  buildin_getskilllist (struct script_state *st);
-int  buildin_getskilllist (struct script_state *st);
-int  buildin_clearitem (struct script_state *st);
-int  buildin_classchange (struct script_state *st);
-int  buildin_misceffect (struct script_state *st);
-int  buildin_soundeffect (struct script_state *st);
-int  buildin_setcastledata (struct script_state *st);
-int  buildin_mapwarp (struct script_state *st);
-int  buildin_inittimer (struct script_state *st);
-int  buildin_stoptimer (struct script_state *st);
-int  buildin_cmdothernpc (struct script_state *st);
-int  buildin_mobcount (struct script_state *st);
-int  buildin_strmobinfo (struct script_state *st);  // Script for displaying mob info [Valaris]
-int  buildin_guardian (struct script_state *st);    // Script for displaying mob info [Valaris]
-int  buildin_guardianinfo (struct script_state *st);    // Script for displaying mob info [Valaris]
-int  buildin_npcskilleffect (struct script_state *st);  // skill effects for npcs [Valaris]
-int  buildin_specialeffect (struct script_state *st);   // special effect script [Valaris]
-int  buildin_specialeffect2 (struct script_state *st);  // special effect script [Valaris]
-int  buildin_nude (struct script_state *st);    // nude [Valaris]
-int  buildin_gmcommand (struct script_state *st);   // [MouseJstr]
-int  buildin_movenpc (struct script_state *st); // [MouseJstr]
-int  buildin_npcwarp (struct script_state *st); // [remoitnane]
-int  buildin_message (struct script_state *st); // [MouseJstr]
-int  buildin_npctalk (struct script_state *st); // [Valaris]
-int  buildin_hasitems (struct script_state *st);    // [Valaris]
-int  buildin_getlook (struct script_state *st); //Lorky [Lupus]
-int  buildin_getsavepoint (struct script_state *st);    //Lorky [Lupus]
-int  buildin_getpartnerid (struct script_state *st);    // [Fate]
-int  buildin_areatimer (struct script_state *st);   // [Jaxad0127]
-int  buildin_isin (struct script_state *st);    // [Jaxad0127]
-int  buildin_shop (struct script_state *st);    // [MadCamel]
-int  buildin_isdead (struct script_state *st);  // [Jaxad0127]
-int  buildin_fakenpcname (struct script_state *st); //[Kage]
-int  buildin_unequip_by_id (struct script_state *st);   // [Freeyorp]
-int  buildin_getx (struct script_state *st);  // [Kage]
-int  buildin_gety (struct script_state *st);  // [Kage]
-
-
-void push_val (struct script_stack *stack, int type, int val);
-int  run_func (struct script_state *st);
-
-int  mapreg_setreg (int num, int val);
-int  mapreg_setregstr (int num, const char *str);
-
-struct
-{
-    int  (*func) (struct script_state *);
-    char *name;
-    char *arg;
-} buildin_func[] =
-{
-    {
-    buildin_mes, "mes", "s"},
-    {
-    buildin_next, "next", ""},
-    {
-    buildin_close, "close", ""},
-    {
-    buildin_close2, "close2", ""},
-    {
-    buildin_menu, "menu", "sL*"},
-    {
-    buildin_goto, "goto", "L"},
-    {
-    buildin_callsub, "callsub", "L*"},
-    {
-    buildin_callfunc, "callfunc", "F*"},
-    {
-    buildin_return, "return", "*"},
-    {
-    buildin_getarg, "getarg", "i"},
-    {
-    buildin_jobchange, "jobchange", "i*"},
-    {
-    buildin_input, "input", "N"},
-    {
-    buildin_warp, "warp", "Mxy"},
-    {
-    buildin_isat, "isat", "Mxy"},
-    {
-    buildin_areawarp, "areawarp", "MxyxyMxy"},
-    {
-    buildin_setlook, "setlook", "ii"},
-    {
-    buildin_set, "set", "Ne"},
-    {
-    buildin_setarray, "setarray", "Ne*"},
-    {
-    buildin_cleararray, "cleararray", "Nei"},
-    {
-    buildin_copyarray, "copyarray", "NNi"},
-    {
-    buildin_getarraysize, "getarraysize", "N"},
-    {
-    buildin_deletearray, "deletearray", "N*"},
-    {
-    buildin_getelementofarray, "getelementofarray", "Ni"},
-    {
-    buildin_if, "if", "iF*"},
-    {
-    buildin_getitem, "getitem", "Ii**"},
-    {
-    buildin_getitem2, "getitem2", "iiiiiiiii*"},
-    {
-    buildin_makeitem, "makeitem", "IiMxy"},
-    {
-    buildin_delitem, "delitem", "Ii"},
-    {
-    buildin_cutin, "cutin", "si"},
-    {
-    buildin_cutincard, "cutincard", "i"},
-    {
-    buildin_viewpoint, "viewpoint", "iiiii"},
-    {
-    buildin_heal, "heal", "ii"},
-    {
-    buildin_itemheal, "itemheal", "ii"},
-    {
-    buildin_percentheal, "percentheal", "ii"},
-    {
-    buildin_rand, "rand", "i*"},
-    {
-    buildin_pow, "pow", "ii"},
-    {
-    buildin_countitem, "countitem", "I"},
-    {
-    buildin_checkweight, "checkweight", "Ii"},
-    {
-    buildin_readparam, "readparam", "i*"},
-    {
-    buildin_getcharid, "getcharid", "i*"},
-    {
-    buildin_getpartyname, "getpartyname", "i"},
-    {
-    buildin_getpartymember, "getpartymember", "i"},
-    {
-    buildin_getguildname, "getguildname", "i"},
-    {
-    buildin_getguildmaster, "getguildmaster", "i"},
-    {
-    buildin_getguildmasterid, "getguildmasterid", "i"},
-    {
-    buildin_strcharinfo, "strcharinfo", "i"},
-    {
-    buildin_getequipid, "getequipid", "i"},
-    {
-    buildin_getequipname, "getequipname", "i"},
-    {
-    buildin_getbrokenid, "getbrokenid", "i"},   // [Valaris]
-    {
-    buildin_repair, "repair", "i"}, // [Valaris]
-    {
-    buildin_getequipisequiped, "getequipisequiped", "i"},
-    {
-    buildin_getequipisenableref, "getequipisenableref", "i"},
-    {
-    buildin_getequipisidentify, "getequipisidentify", "i"},
-    {
-    buildin_getequiprefinerycnt, "getequiprefinerycnt", "i"},
-    {
-    buildin_getequipweaponlv, "getequipweaponlv", "i"},
-    {
-    buildin_getequippercentrefinery, "getequippercentrefinery", "i"},
-    {
-    buildin_successrefitem, "successrefitem", "i"},
-    {
-    buildin_failedrefitem, "failedrefitem", "i"},
-    {
-    buildin_statusup, "statusup", "i"},
-    {
-    buildin_statusup2, "statusup2", "ii"},
-    {
-    buildin_bonus, "bonus", "ii"},
-    {
-    buildin_bonus2, "bonus2", "iii"},
-    {
-    buildin_bonus3, "bonus3", "iiii"},
-    {
-    buildin_skill, "skill", "ii*"},
-    {
-    buildin_setskill, "setskill", "ii"},    // [Fate]
-    {
-    buildin_guildskill, "guildskill", "ii"},
-    {
-    buildin_getskilllv, "getskilllv", "i"},
-    {
-    buildin_getgdskilllv, "getgdskilllv", "ii"},
-    {
-    buildin_basicskillcheck, "basicskillcheck", "*"},
-    {
-    buildin_getgmlevel, "getgmlevel", ""},
-    {
-    buildin_end, "end", ""},
-    {
-    buildin_getopt2, "getopt2", ""},
-    {
-    buildin_setopt2, "setopt2", "i"},
-    {
-    buildin_end, "break", ""},
-    {
-    buildin_checkoption, "checkoption", "i"},
-    {
-    buildin_setoption, "setoption", "i"},
-    {
-    buildin_setcart, "setcart", ""},
-    {
-    buildin_checkcart, "checkcart", "*"},   //fixed by Lupus (added '*')
-    {
-    buildin_setfalcon, "setfalcon", ""},
-    {
-    buildin_checkfalcon, "checkfalcon", "*"},   //fixed by Lupus (fixed wrong pointer, added '*')
-    {
-    buildin_setriding, "setriding", ""},
-    {
-    buildin_checkriding, "checkriding", "*"},   //fixed by Lupus (fixed wrong pointer, added '*')
-    {
-    buildin_savepoint, "save", "sii"},
-    {
-    buildin_savepoint, "savepoint", "Mxy"},
-    {
-    buildin_gettimetick, "gettimetick", "i"},
-    {
-    buildin_gettime, "gettime", "i"},
-    {
-    buildin_gettimestr, "gettimestr", "si"},
-    {
-    buildin_openstorage, "openstorage", "*"},
-    {
-    buildin_guildopenstorage, "guildopenstorage", "*"},
-    {
-    buildin_itemskill, "itemskill", "iis"},
-    {
-    buildin_monster, "monster", "Mxysmi*"},
-    {
-    buildin_areamonster, "areamonster", "Mxyxysmi*"},
-    {
-    buildin_killmonster, "killmonster", "ME"},
-    {
-    buildin_killmonsterall, "killmonsterall", "M"},
-    {
-    buildin_doevent, "doevent", "E"},
-    {
-    buildin_donpcevent, "donpcevent", "E"},
-    {
-    buildin_addtimer, "addtimer", "tE"},
-    {
-    buildin_deltimer, "deltimer", "E"},
-    {
-    buildin_addtimercount, "addtimercount", "si"},
-    {
-    buildin_initnpctimer, "initnpctimer", ""},
-    {
-    buildin_stopnpctimer, "stopnpctimer", ""},
-    {
-    buildin_startnpctimer, "startnpctimer", "*"},
-    {
-    buildin_setnpctimer, "setnpctimer", "i"},
-    {
-    buildin_getnpctimer, "getnpctimer", "i"},
-    {
-    buildin_announce, "announce", "si"},
-    {
-    buildin_mapannounce, "mapannounce", "Msi"},
-    {
-    buildin_areaannounce, "areaannounce", "Mxyxysi"},
-    {
-    buildin_getusers, "getusers", "i"},
-    {
-    buildin_getmapusers, "getmapusers", "M"},
-    {
-    buildin_getareausers, "getareausers", "Mxyxy*"},
-    {
-    buildin_getareadropitem, "getareadropitem", "Mxyxyi*"},
-    {
-    buildin_enablenpc, "enablenpc", "s"},
-    {
-    buildin_disablenpc, "disablenpc", "s"},
-    {
-    buildin_enablearena, "enablearena", ""},    // Added by RoVeRT
-    {
-    buildin_disablearena, "disablearena", ""},  // Added by RoVeRT
-    {
-    buildin_hideoffnpc, "hideoffnpc", "s"},
-    {
-    buildin_hideonnpc, "hideonnpc", "s"},
-    {
-    buildin_sc_start, "sc_start", "iTi*"},
-    {
-    buildin_sc_start2, "sc_start2", "iTii*"},
-    {
-    buildin_sc_end, "sc_end", "i"},
-    {
-    buildin_sc_check, "sc_check", "i"},
-    {
-    buildin_getscrate, "getscrate", "ii*"},
-    {
-    buildin_debugmes, "debugmes", "s"},
-    {
-    buildin_resetlvl, "resetlvl", "i"},
-    {
-    buildin_resetstatus, "resetstatus", ""},
-    {
-    buildin_resetskill, "resetskill", ""},
-    {
-    buildin_changebase, "changebase", "i"},
-    {
-    buildin_changesex, "changesex", ""},
-    {
-    buildin_waitingroom, "waitingroom", "si*"},
-    {
-    buildin_warpwaitingpc, "warpwaitingpc", "sii"},
-    {
-    buildin_delwaitingroom, "delwaitingroom", "*"},
-    {
-    buildin_enablewaitingroomevent, "enablewaitingroomevent", "*"},
-    {
-    buildin_disablewaitingroomevent, "disablewaitingroomevent", "*"},
-    {
-    buildin_getwaitingroomstate, "getwaitingroomstate", "i*"},
-    {
-    buildin_warpwaitingpc, "warpwaitingpc", "sii*"},
-    {
-    buildin_attachrid, "attachrid", "i"},
-    {
-    buildin_detachrid, "detachrid", ""},
-    {
-    buildin_isloggedin, "isloggedin", "i"},
-    {
-    buildin_setmapflagnosave, "setmapflagnosave", "MMxy"},
-    {
-    buildin_setmapflag, "setmapflag", "Mi"},
-    {
-    buildin_removemapflag, "removemapflag", "Mi"},
-    {
-    buildin_pvpon, "pvpon", "M"},
-    {
-    buildin_pvpoff, "pvpoff", "M"},
-    {
-    buildin_gvgon, "gvgon", "s"},
-    {
-    buildin_gvgoff, "gvgoff", "s"},
-    {
-    buildin_emotion, "emotion", "i"},
-    {
-    buildin_maprespawnguildid, "maprespawnguildid", "sii"},
-    {
-    buildin_agitstart, "agitstart", ""},    // <Agit>
-    {
-    buildin_agitend, "agitend", ""},
-    {
-    buildin_agitcheck, "agitcheck", "i"},   // <Agitcheck>
-    {
-    buildin_flagemblem, "flagemblem", "i"}, // Flag Emblem
-    {
-    buildin_getcastlename, "getcastlename", "s"},
-    {
-    buildin_getcastledata, "getcastledata", "si*"},
-    {
-    buildin_setcastledata, "setcastledata", "sii"},
-    {
-    buildin_requestguildinfo, "requestguildinfo", "i*"},
-    {
-    buildin_getequipcardcnt, "getequipcardcnt", "i"},
-    {
-    buildin_successremovecards, "successremovecards", "i"},
-    {
-    buildin_failedremovecards, "failedremovecards", "ii"},
-    {
-    buildin_marriage, "marriage", "P"},
-    {
-    buildin_wedding_effect, "wedding", ""},
-    {
-    buildin_divorce, "divorce", ""},
-    {
-    buildin_getitemname, "getitemname", "I"},
-    {
-    buildin_getspellinvocation, "getspellinvocation", "s"},
-    {
-    buildin_getanchorinvocation, "getanchorinvocation", "s"},
-    {
-    buildin_getpartnerid, "getpartnerid2", ""},
-    {
-    buildin_getexp, "getexp", "ii"},
-    {
-    buildin_getinventorylist, "getinventorylist", ""},
-    {
-    buildin_getskilllist, "getskilllist", ""},
-    {
-    buildin_get_pool_skills, "getpoolskilllist", ""},
-    {
-    buildin_get_activated_pool_skills, "getactivatedpoolskilllist", ""},
-    {
-    buildin_get_unactivated_pool_skills, "getunactivatedpoolskilllist", ""},
-    {
-    buildin_activate_pool_skill, "poolskill", "i"},
-    {
-    buildin_deactivate_pool_skill, "unpoolskill", "i"},
-    {
-    buildin_check_pool_skill, "checkpoolskill", "i"},
-    {
-    buildin_clearitem, "clearitem", ""},
-    {
-    buildin_classchange, "classchange", "ii"},
-    {
-    buildin_misceffect, "misceffect", "i*"},
-    {
-    buildin_soundeffect, "soundeffect", "si"},
-    {
-    buildin_strmobinfo, "strmobinfo", "im"},    // display mob data [Valaris]
-    {
-    buildin_guardian, "guardian", "siisii*i"},  // summon guardians
-    {
-    buildin_guardianinfo, "guardianinfo", "i"}, // display guardian data [Valaris]
-    {
-    buildin_npcskilleffect, "npcskilleffect", "iiii"},  // npc skill effect [Valaris]
-    {
-    buildin_specialeffect, "specialeffect", "i"},   // npc skill effect [Valaris]
-    {
-    buildin_specialeffect2, "specialeffect2", "i"}, // skill effect on players[Valaris]
-    {
-    buildin_nude, "nude", ""},  // nude command [Valaris]
-    {
-    buildin_mapwarp, "mapwarp", "MMxy"},    // Added by RoVeRT
-    {
-    buildin_inittimer, "inittimer", ""},
-    {
-    buildin_stoptimer, "stoptimer", ""},
-    {
-    buildin_cmdothernpc, "cmdothernpc", "ss"},
-    {
-    buildin_gmcommand, "gmcommand", "s"},   // [MouseJstr]
-//  {buildin_movenpc,"movenpc","siis"}, // [MouseJstr]
-    {
-    buildin_npcwarp, "npcwarp", "xys"}, // [remoitnane]
-    {
-    buildin_message, "message", "Ps"},  // [MouseJstr]
-    {
-    buildin_npctalk, "npctalk", "s"},   // [Valaris]
-    {
-    buildin_hasitems, "hasitems", ""}, // [Valaris]
-    {
-    buildin_mobcount, "mobcount", "ME"},
-    {
-    buildin_getlook, "getlook", "i"},
-    {
-    buildin_getsavepoint, "getsavepoint", "i"},
-    {
-    buildin_areatimer, "areatimer", "MxyxytE"},
-    {
-    buildin_isin, "isin", "Mxyxy"},
-    {
-    buildin_shop, "shop", "s"},
-    {
-    buildin_isdead, "isdead", ""},
-    {
-    buildin_fakenpcname, "fakenpcname", "ssi"},
-    {
-    buildin_unequip_by_id, "unequipbyid", "i"}, // [Freeyorp]
-    {
-    buildin_getx, "getx", ""}, // [Kage]
-    {
-    buildin_gety, "gety", ""}, // [Kage]
-        // End Additions
-    {
-NULL, NULL, NULL},};
-
-int  buildin_message (struct script_state *st); // [MouseJstr]
-
-enum
-{
-    C_NOP, C_POS, C_INT, C_PARAM, C_FUNC, C_STR, C_CONSTSTR, C_ARG,
-    C_NAME, C_EOL, C_RETINFO,
-
-    C_LOR, C_LAND, C_LE, C_LT, C_GE, C_GT, C_EQ, C_NE,  //operator
-    C_XOR, C_OR, C_AND, C_ADD, C_SUB, C_MUL, C_DIV, C_MOD, C_NEG, C_LNOT,
-    C_NOT, C_R_SHIFT, C_L_SHIFT
-};
-
-/*==========================================
- * 文字列のハッシュを計算
- *------------------------------------------
- */
-static int calc_hash (const unsigned char *p)
-{
-    int  h = 0;
-    while (*p)
-    {
-        h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8);
-        h += *p++;
-    }
-    return h & 15;
-}
-
-/*==========================================
- * str_dataの中に名前があるか検索する
- *------------------------------------------
- */
-// 既存のであれば番号、無ければ-1
-static int search_str (const unsigned char *p)
-{
-    int  i;
-    i = str_hash[calc_hash (p)];
-    while (i)
-    {
-        if (strcmp (str_buf + str_data[i].str, p) == 0)
-        {
-            return i;
-        }
-        i = str_data[i].next;
-    }
-    return -1;
-}
-
-/*==========================================
- * str_dataに名前を登録
- *------------------------------------------
- */
-// 既存のであれば番号、無ければ登録して新規番号
-static int add_str (const unsigned char *p)
-{
-    int  i;
-    char *lowcase;
-
-    lowcase = strdup (p);
-    for (i = 0; lowcase[i]; i++)
-        lowcase[i] = tolower (lowcase[i]);
-    if ((i = search_str (lowcase)) >= 0)
-    {
-        free (lowcase);
-        return i;
-    }
-    free (lowcase);
-
-    i = calc_hash (p);
-    if (str_hash[i] == 0)
-    {
-        str_hash[i] = str_num;
-    }
-    else
-    {
-        i = str_hash[i];
-        for (;;)
-        {
-            if (strcmp (str_buf + str_data[i].str, p) == 0)
-            {
-                return i;
-            }
-            if (str_data[i].next == 0)
-                break;
-            i = str_data[i].next;
-        }
-        str_data[i].next = str_num;
-    }
-    if (str_num >= str_data_size)
-    {
-        str_data_size += 128;
-        RECREATE (str_data, struct str_data_t, str_data_size);
-        memset (str_data + (str_data_size - 128), '\0', 128);
-    }
-    while (str_pos + strlen (p) + 1 >= str_size)
-    {
-        str_size += 256;
-        str_buf = (char *) realloc (str_buf, str_size);
-        memset (str_buf + (str_size - 256), '\0', 256);
-    }
-    strcpy (str_buf + str_pos, p);
-    str_data[str_num].type = C_NOP;
-    str_data[str_num].str = str_pos;
-    str_data[str_num].next = 0;
-    str_data[str_num].func = NULL;
-    str_data[str_num].backpatch = -1;
-    str_data[str_num].label = -1;
-    str_pos += strlen (p) + 1;
-    return str_num++;
-}
-
-/*==========================================
- * スクリプトバッファサイズの確認と拡張
- *------------------------------------------
- */
-static void check_script_buf (int size)
-{
-    if (script_pos + size >= script_size)
-    {
-        script_size += SCRIPT_BLOCK_SIZE;
-        script_buf = (char *) realloc (script_buf, script_size);
-        memset (script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0',
-                SCRIPT_BLOCK_SIZE);
-    }
-}
-
-/*==========================================
- * スクリプトバッファに1バイト書き込む
- *------------------------------------------
- */
-static void add_scriptb (int a)
-{
-    check_script_buf (1);
-    script_buf[script_pos++] = a;
-}
-
-/*==========================================
- * スクリプトバッファにデータタイプを書き込む
- *------------------------------------------
- */
-static void add_scriptc (int a)
-{
-    while (a >= 0x40)
-    {
-        add_scriptb ((a & 0x3f) | 0x40);
-        a = (a - 0x40) >> 6;
-    }
-    add_scriptb (a & 0x3f);
-}
-
-/*==========================================
- * スクリプトバッファに整数を書き込む
- *------------------------------------------
- */
-static void add_scripti (unsigned int a)
-{
-    while (a >= 0x40)
-    {
-        add_scriptb (a | 0xc0);
-        a = (a - 0x40) >> 6;
-    }
-    add_scriptb (a | 0x80);
-}
-
-/*==========================================
- * スクリプトバッファにラベル/変数/関数を書き込む
- *------------------------------------------
- */
-// 最大16Mまで
-static void add_scriptl (int l)
-{
-    int  backpatch = str_data[l].backpatch;
-
-    switch (str_data[l].type)
-    {
-        case C_POS:
-            add_scriptc (C_POS);
-            add_scriptb (str_data[l].label);
-            add_scriptb (str_data[l].label >> 8);
-            add_scriptb (str_data[l].label >> 16);
-            break;
-        case C_NOP:
-            // ラベルの可能性があるのでbackpatch用データ埋め込み
-            add_scriptc (C_NAME);
-            str_data[l].backpatch = script_pos;
-            add_scriptb (backpatch);
-            add_scriptb (backpatch >> 8);
-            add_scriptb (backpatch >> 16);
-            break;
-        case C_INT:
-            add_scripti (str_data[l].val);
-            break;
-        default:
-            // もう他の用途と確定してるので数字をそのまま
-            add_scriptc (C_NAME);
-            add_scriptb (l);
-            add_scriptb (l >> 8);
-            add_scriptb (l >> 16);
-            break;
-    }
-}
-
-/*==========================================
- * ラベルを解決する
- *------------------------------------------
- */
-void set_label (int l, int pos)
-{
-    int  i, next;
-
-    str_data[l].type = C_POS;
-    str_data[l].label = pos;
-    for (i = str_data[l].backpatch; i >= 0 && i != 0x00ffffff;)
-    {
-        next = (*(int *) (script_buf + i)) & 0x00ffffff;
-        script_buf[i - 1] = C_POS;
-        script_buf[i] = pos;
-        script_buf[i + 1] = pos >> 8;
-        script_buf[i + 2] = pos >> 16;
-        i = next;
-    }
-}
-
-/*==========================================
- * スペース/コメント読み飛ばし
- *------------------------------------------
- */
-static unsigned char *skip_space (unsigned char *p)
-{
-    while (1)
-    {
-        while (isspace (*p))
-            p++;
-        if (p[0] == '/' && p[1] == '/')
-        {
-            while (*p && *p != '\n')
-                p++;
-        }
-        else if (p[0] == '/' && p[1] == '*')
-        {
-            p++;
-            while (*p && (p[-1] != '*' || p[0] != '/'))
-                p++;
-            if (*p)
-                p++;
-        }
-        else
-            break;
-    }
-    return p;
-}
-
-/*==========================================
- * 1単語スキップ
- *------------------------------------------
- */
-static unsigned char *skip_word (unsigned char *p)
-{
-    // prefix
-    if (*p == '$')
-        p++;                    // MAP鯖内共有変数用
-    if (*p == '@')
-        p++;                    // 一時的変数用(like weiss)
-    if (*p == '#')
-        p++;                    // account変数用
-    if (*p == '#')
-        p++;                    // ワールドaccount変数用
-    if (*p == 'l')
-        p++;                    // 一時的変数用(like weiss)
-
-    while (isalnum (*p) || *p == '_' || *p >= 0x81)
-        if (*p >= 0x81 && p[1])
-        {
-            p += 2;
-        }
-        else
-            p++;
-
-    // postfix
-    if (*p == '$')
-        p++;                    // 文字列変数
-
-    return p;
-}
-
-static unsigned char *startptr;
-static int startline;
-
-/*==========================================
- * エラーメッセージ出力
- *------------------------------------------
- */
-static void disp_error_message (const char *mes, const unsigned char *pos)
-{
-    int  line, c = 0, i;
-    unsigned char *p, *linestart, *lineend;
-
-    for (line = startline, p = startptr; p && *p; line++)
-    {
-        linestart = p;
-        lineend = strchr (p, '\n');
-        if (lineend)
-        {
-            c = *lineend;
-            *lineend = 0;
-        }
-        if (lineend == NULL || pos < lineend)
-        {
-            printf ("%s line %d : ", mes, line);
-            for (i = 0;
-                 (linestart[i] != '\r') && (linestart[i] != '\n')
-                 && linestart[i]; i++)
-            {
-                if (linestart + i != pos)
-                    printf ("%c", linestart[i]);
-                else
-                    printf ("\'%c\'", linestart[i]);
-            }
-            printf ("\a\n");
-            if (lineend)
-                *lineend = c;
-            return;
-        }
-        *lineend = c;
-        p = lineend + 1;
-    }
-}
-
-/*==========================================
- * 項の解析
- *------------------------------------------
- */
-unsigned char *parse_simpleexpr (unsigned char *p)
-{
-    int  i;
-    p = skip_space (p);
-
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_simpleexpr %s\n", p);
-#endif
-    if (*p == ';' || *p == ',')
-    {
-        disp_error_message ("unexpected expr end", p);
-        exit (1);
-    }
-    if (*p == '(')
-    {
-
-        p = parse_subexpr (p + 1, -1);
-        p = skip_space (p);
-        if ((*p++) != ')')
-        {
-            disp_error_message ("unmatch ')'", p);
-            exit (1);
-        }
-    }
-    else if (isdigit (*p) || ((*p == '-' || *p == '+') && isdigit (p[1])))
-    {
-        char *np;
-        i = strtoul (p, &np, 0);
-        add_scripti (i);
-        p = np;
-    }
-    else if (*p == '"')
-    {
-        add_scriptc (C_STR);
-        p++;
-        while (*p && *p != '"')
-        {
-            if (p[-1] <= 0x7e && *p == '\\')
-                p++;
-            else if (*p == '\n')
-            {
-                disp_error_message ("unexpected newline @ string", p);
-                exit (1);
-            }
-            add_scriptb (*p++);
-        }
-        if (!*p)
-        {
-            disp_error_message ("unexpected eof @ string", p);
-            exit (1);
-        }
-        add_scriptb (0);
-        p++;                    //'"'
-    }
-    else
-    {
-        int  c, l;
-        char *p2;
-        // label , register , function etc
-        if (skip_word (p) == p)
-        {
-            disp_error_message ("unexpected character", p);
-            exit (1);
-        }
-        p2 = skip_word (p);
-        c = *p2;
-        *p2 = 0;                // 名前をadd_strする
-        l = add_str (p);
-
-        parse_cmd = l;          // warn_*_mismatch_paramnumのために必要
-        if (l == search_str ("if")) // warn_cmd_no_commaのために必要
-            parse_cmd_if++;
-/*
-		// 廃止予定のl14/l15,およびプレフィックスlの警告
-		if(	strcmp(str_buf+str_data[l].str,"l14")==0 ||
-			strcmp(str_buf+str_data[l].str,"l15")==0 ){
-			disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p);
-		}else if(str_buf[str_data[l].str]=='l'){
-			disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2);
-		}
-*/
-        *p2 = c;
-        p = p2;
-
-        if (str_data[l].type != C_FUNC && c == '[')
-        {
-            // array(name[i] => getelementofarray(name,i) )
-            add_scriptl (search_str ("getelementofarray"));
-            add_scriptc (C_ARG);
-            add_scriptl (l);
-            p = parse_subexpr (p + 1, -1);
-            p = skip_space (p);
-            if ((*p++) != ']')
-            {
-                disp_error_message ("unmatch ']'", p);
-                exit (1);
-            }
-            add_scriptc (C_FUNC);
-        }
-        else
-            add_scriptl (l);
-
-    }
-
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_simpleexpr end %s\n", p);
-#endif
-    return p;
-}
-
-/*==========================================
- * 式の解析
- *------------------------------------------
- */
-unsigned char *parse_subexpr (unsigned char *p, int limit)
-{
-    int  op, opl, len;
-    char *tmpp;
-
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_subexpr %s\n", p);
-#endif
-    p = skip_space (p);
-
-    if (*p == '-')
-    {
-        tmpp = skip_space (p + 1);
-        if (*tmpp == ';' || *tmpp == ',')
-        {
-            add_scriptl (LABEL_NEXTLINE);
-            p++;
-            return p;
-        }
-    }
-    tmpp = p;
-    if ((op = C_NEG, *p == '-') || (op = C_LNOT, *p == '!')
-        || (op = C_NOT, *p == '~'))
-    {
-        p = parse_subexpr (p + 1, 100);
-        add_scriptc (op);
-    }
-    else
-        p = parse_simpleexpr (p);
-    p = skip_space (p);
-    while (((op = C_ADD, opl = 6, len = 1, *p == '+') ||
-            (op = C_SUB, opl = 6, len = 1, *p == '-') ||
-            (op = C_MUL, opl = 7, len = 1, *p == '*') ||
-            (op = C_DIV, opl = 7, len = 1, *p == '/') ||
-            (op = C_MOD, opl = 7, len = 1, *p == '%') ||
-            (op = C_FUNC, opl = 8, len = 1, *p == '(') ||
-            (op = C_LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') ||
-            (op = C_AND, opl = 5, len = 1, *p == '&') ||
-            (op = C_LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') ||
-            (op = C_OR, opl = 4, len = 1, *p == '|') ||
-            (op = C_XOR, opl = 3, len = 1, *p == '^') ||
-            (op = C_EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') ||
-            (op = C_NE, opl = 2, len = 2, *p == '!' && p[1] == '=') ||
-            (op = C_R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') ||
-            (op = C_GE, opl = 2, len = 2, *p == '>' && p[1] == '=') ||
-            (op = C_GT, opl = 2, len = 1, *p == '>') ||
-            (op = C_L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') ||
-            (op = C_LE, opl = 2, len = 2, *p == '<' && p[1] == '=') ||
-            (op = C_LT, opl = 2, len = 1, *p == '<')) && opl > limit)
-    {
-        p += len;
-        if (op == C_FUNC)
-        {
-            int  i = 0, func = parse_cmd;
-            const char *plist[128];
-
-            if (str_data[func].type != C_FUNC)
-            {
-                disp_error_message ("expect function", tmpp);
-                exit (0);
-            }
-
-            add_scriptc (C_ARG);
-            while (*p && *p != ')' && i < 128)
-            {
-                plist[i] = p;
-                p = parse_subexpr (p, -1);
-                p = skip_space (p);
-                if (*p == ',')
-                    p++;
-                else if (*p != ')' && script_config.warn_func_no_comma)
-                {
-                    disp_error_message ("expect ',' or ')' at func params",
-                                        p);
-                }
-                p = skip_space (p);
-                i++;
-            }
-            plist[i] = p;
-            if (*(p++) != ')')
-            {
-                disp_error_message ("func request '(' ')'", p);
-                exit (1);
-            }
-
-            if (str_data[func].type == C_FUNC
-                && script_config.warn_func_mismatch_paramnum)
-            {
-                const char *arg = buildin_func[str_data[func].val].arg;
-                int  j = 0;
-                for (j = 0; arg[j]; j++)
-                    if (arg[j] == '*')
-                        break;
-                if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
-                {
-                    disp_error_message ("illegal number of parameters",
-                                        plist[(i < j) ? i : j]);
-                }
-            }
-        }
-        else // not op == C_FUNC
-        {
-            p = parse_subexpr (p, opl);
-        }
-        add_scriptc (op);
-        p = skip_space (p);
-    }
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_subexpr end %s\n", p);
-#endif
-    return p;                   /* return first untreated operator */
-}
-
-/*==========================================
- * 式の評価
- *------------------------------------------
- */
-unsigned char *parse_expr (unsigned char *p)
-{
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_expr %s\n", p);
-#endif
-    switch (*p)
-    {
-        case ')':
-        case ';':
-        case ':':
-        case '[':
-        case ']':
-        case '}':
-            disp_error_message ("unexpected char", p);
-            exit (1);
-    }
-    p = parse_subexpr (p, -1);
-#ifdef DEBUG_FUNCIN
-    if (battle_config.etc_log)
-        printf ("parse_expr end %s\n", p);
-#endif
-    return p;
-}
-
-/*==========================================
- * 行の解析
- *------------------------------------------
- */
-unsigned char *parse_line (unsigned char *p)
-{
-    int  i = 0, cmd;
-    const char *plist[128];
-    char *p2;
-
-    p = skip_space (p);
-    if (*p == ';')
-        return p;
-
-    parse_cmd_if = 0;           // warn_cmd_no_commaのために必要
-
-    // 最初は関数名
-    p2 = p;
-    p = parse_simpleexpr (p);
-    p = skip_space (p);
-
-    cmd = parse_cmd;
-    if (str_data[cmd].type != C_FUNC)
-    {
-        disp_error_message ("expect command", p2);
-//      exit(0);
-    }
-
-    add_scriptc (C_ARG);
-    while (p && *p && *p != ';' && i < 128)
-    {
-        plist[i] = p;
-
-        p = parse_expr (p);
-        p = skip_space (p);
-        // 引数区切りの,処理
-        if (*p == ',')
-            p++;
-        else if (*p != ';' && script_config.warn_cmd_no_comma
-                 && parse_cmd_if * 2 <= i)
-        {
-            disp_error_message ("expect ',' or ';' at cmd params", p);
-        }
-        p = skip_space (p);
-        i++;
-    }
-    plist[i] = p;
-    if (!p || *(p++) != ';')
-    {
-        disp_error_message ("need ';'", p);
-        exit (1);
-    }
-    add_scriptc (C_FUNC);
-
-    if (str_data[cmd].type == C_FUNC
-        && script_config.warn_cmd_mismatch_paramnum)
-    {
-        const char *arg = buildin_func[str_data[cmd].val].arg;
-        int  j = 0;
-        for (j = 0; arg[j]; j++)
-            if (arg[j] == '*')
-                break;
-        if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
-        {
-            disp_error_message ("illegal number of parameters",
-                                plist[(i < j) ? i : j]);
-        }
-    }
-
-    return p;
-}
-
-/*==========================================
- * 組み込み関数の追加
- *------------------------------------------
- */
-static void add_buildin_func (void)
-{
-    int  i, n;
-    for (i = 0; buildin_func[i].func; i++)
-    {
-        n = add_str (buildin_func[i].name);
-        str_data[n].type = C_FUNC;
-        str_data[n].val = i;
-        str_data[n].func = buildin_func[i].func;
-    }
-}
-
-/*==========================================
- * 定数データベースの読み込み
- *------------------------------------------
- */
-static void read_constdb (void)
-{
-    FILE *fp;
-    char line[1024], name[1024];
-    int  val, n, i, type;
-
-    fp = fopen_ ("db/const.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/const.txt\n");
-        return;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        type = 0;
-        if (sscanf (line, "%[A-Za-z0-9_],%d,%d", name, &val, &type) >= 2 ||
-            sscanf (line, "%[A-Za-z0-9_] %d %d", name, &val, &type) >= 2)
-        {
-            for (i = 0; name[i]; i++)
-                name[i] = tolower (name[i]);
-            n = add_str (name);
-            if (type == 0)
-                str_data[n].type = C_INT;
-            else
-                str_data[n].type = C_PARAM;
-            str_data[n].val = val;
-        }
-    }
-    fclose_ (fp);
-}
-
-/*==========================================
- * スクリプトの解析
- *------------------------------------------
- */
-unsigned char *parse_script (unsigned char *src, int line)
-{
-    unsigned char *p, *tmpp;
-    int  i;
-    static int first = 1;
-
-    if (first)
-    {
-        add_buildin_func ();
-        read_constdb ();
-    }
-    first = 0;
-    script_buf = (unsigned char *) calloc (SCRIPT_BLOCK_SIZE, 1);
-    script_pos = 0;
-    script_size = SCRIPT_BLOCK_SIZE;
-    str_data[LABEL_NEXTLINE].type = C_NOP;
-    str_data[LABEL_NEXTLINE].backpatch = -1;
-    str_data[LABEL_NEXTLINE].label = -1;
-    for (i = LABEL_START; i < str_num; i++)
-    {
-        if (str_data[i].type == C_POS || str_data[i].type == C_NAME)
-        {
-            str_data[i].type = C_NOP;
-            str_data[i].backpatch = -1;
-            str_data[i].label = -1;
-        }
-    }
-
-    // 外部用label dbの初期化
-    if (scriptlabel_db != NULL)
-        strdb_final (scriptlabel_db, NULL);
-    scriptlabel_db = strdb_init (50);
-
-    // for error message
-    startptr = src;
-    startline = line;
-
-    p = src;
-    p = skip_space (p);
-    if (*p != '{')
-    {
-        disp_error_message ("not found '{'", p);
-        return NULL;
-    }
-    for (p++; p && *p && *p != '}';)
-    {
-        p = skip_space (p);
-        // labelだけ特殊処理
-        tmpp = skip_space (skip_word (p));
-        if (*tmpp == ':')
-        {
-            int  l, c;
-
-            c = *skip_word (p);
-            *skip_word (p) = 0;
-            l = add_str (p);
-            if (str_data[l].label != -1)
-            {
-                *skip_word (p) = c;
-                disp_error_message ("dup label ", p);
-                exit (1);
-            }
-            set_label (l, script_pos);
-            strdb_insert (scriptlabel_db, (const char*)p, script_pos);   // 外部用label db登録
-            *skip_word (p) = c;
-            p = tmpp + 1;
-            continue;
-        }
-
-        // 他は全部一緒くた
-        p = parse_line (p);
-        p = skip_space (p);
-        add_scriptc (C_EOL);
-
-        set_label (LABEL_NEXTLINE, script_pos);
-        str_data[LABEL_NEXTLINE].type = C_NOP;
-        str_data[LABEL_NEXTLINE].backpatch = -1;
-        str_data[LABEL_NEXTLINE].label = -1;
-    }
-
-    add_scriptc (C_NOP);
-
-    script_size = script_pos;
-    script_buf = (char *) realloc (script_buf, script_pos + 1);
-
-    // 未解決のラベルを解決
-    for (i = LABEL_START; i < str_num; i++)
-    {
-        if (str_data[i].type == C_NOP)
-        {
-            int  j, next;
-            str_data[i].type = C_NAME;
-            str_data[i].label = i;
-            for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff;)
-            {
-                next = (*(int *) (script_buf + j)) & 0x00ffffff;
-                script_buf[j] = i;
-                script_buf[j + 1] = i >> 8;
-                script_buf[j + 2] = i >> 16;
-                j = next;
-            }
-        }
-    }
-
-#ifdef DEBUG_DISP
-    for (i = 0; i < script_pos; i++)
-    {
-        if ((i & 15) == 0)
-            printf ("%04x : ", i);
-        printf ("%02x ", script_buf[i]);
-        if ((i & 15) == 15)
-            printf ("\n");
-    }
-    printf ("\n");
-#endif
-
-    return script_buf;
-}
-
-//
-// 実行系
-//
-enum
-{ STOP = 1, END, RERUNLINE, GOTO, RETFUNC };
-
-/*==========================================
- * ridからsdへの解決
- *------------------------------------------
- */
-struct map_session_data *script_rid2sd (struct script_state *st)
-{
-    struct map_session_data *sd = map_id2sd (st->rid);
-    if (!sd)
-    {
-        printf ("script_rid2sd: fatal error ! player not attached!\n");
-    }
-    return sd;
-}
-
-/*==========================================
- * 変数の読み取り
- *------------------------------------------
- */
-int get_val (struct script_state *st, struct script_data *data)
-{
-    struct map_session_data *sd = NULL;
-    if (data->type == C_NAME)
-    {
-        char *name = str_buf + str_data[data->u.num & 0x00ffffff].str;
-        char prefix = *name;
-        char postfix = name[strlen (name) - 1];
-
-        if (prefix != '$')
-        {
-            if ((sd = script_rid2sd (st)) == NULL)
-                printf ("get_val error name?:%s\n", name);
-        }
-        if (postfix == '$')
-        {
-
-            data->type = C_CONSTSTR;
-            if (prefix == '@' || prefix == 'l')
-            {
-                if (sd)
-                    data->u.str = pc_readregstr (sd, data->u.num);
-            }
-            else if (prefix == '$')
-            {
-                data->u.str =
-                    (char *) numdb_search (mapregstr_db, data->u.num);
-            }
-            else
-            {
-                printf ("script: get_val: illegal scope string variable.\n");
-                data->u.str = "!!ERROR!!";
-            }
-            if (data->u.str == NULL)
-                data->u.str = "";
-
-        }
-        else
-        {
-
-            data->type = C_INT;
-            if (str_data[data->u.num & 0x00ffffff].type == C_INT)
-            {
-                data->u.num = str_data[data->u.num & 0x00ffffff].val;
-            }
-            else if (str_data[data->u.num & 0x00ffffff].type == C_PARAM)
-            {
-                if (sd)
-                    data->u.num =
-                        pc_readparam (sd,
-                                      str_data[data->u.num & 0x00ffffff].val);
-            }
-            else if (prefix == '@' || prefix == 'l')
-            {
-                if (sd)
-                    data->u.num = pc_readreg (sd, data->u.num);
-            }
-            else if (prefix == '$')
-            {
-                data->u.num = (int) numdb_search (mapreg_db, data->u.num);
-            }
-            else if (prefix == '#')
-            {
-                if (name[1] == '#')
-                {
-                    if (sd)
-                        data->u.num = pc_readaccountreg2 (sd, name);
-                }
-                else
-                {
-                    if (sd)
-                        data->u.num = pc_readaccountreg (sd, name);
-                }
-            }
-            else
-            {
-                if (sd)
-                    data->u.num = pc_readglobalreg (sd, name);
-            }
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * 変数の読み取り2
- *------------------------------------------
- */
-void *get_val2 (struct script_state *st, int num)
-{
-    struct script_data dat;
-    dat.type = C_NAME;
-    dat.u.num = num;
-    get_val (st, &dat);
-    if (dat.type == C_INT)
-        return (void *) dat.u.num;
-    else
-        return (void *) dat.u.str;
-}
-
-/*==========================================
- * 変数設定用
- *------------------------------------------
- */
-static int set_reg (struct map_session_data *sd, int num, char *name, void *v)
-{
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-
-    if (postfix == '$')
-    {
-        char *str = (char *) v;
-        if (prefix == '@' || prefix == 'l')
-        {
-            pc_setregstr (sd, num, str);
-        }
-        else if (prefix == '$')
-        {
-            mapreg_setregstr (num, str);
-        }
-        else
-        {
-            printf ("script: set_reg: illegal scope string variable !");
-        }
-    }
-    else
-    {
-        // 数値
-        int  val = (int) v;
-        if (str_data[num & 0x00ffffff].type == C_PARAM)
-        {
-            pc_setparam (sd, str_data[num & 0x00ffffff].val, val);
-        }
-        else if (prefix == '@' || prefix == 'l')
-        {
-            pc_setreg (sd, num, val);
-        }
-        else if (prefix == '$')
-        {
-            mapreg_setreg (num, val);
-        }
-        else if (prefix == '#')
-        {
-            if (name[1] == '#')
-                pc_setaccountreg2 (sd, name, val);
-            else
-                pc_setaccountreg (sd, name, val);
-        }
-        else
-        {
-            pc_setglobalreg (sd, name, val);
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * 文字列への変換
- *------------------------------------------
- */
-char *conv_str (struct script_state *st, struct script_data *data)
-{
-    get_val (st, data);
-    if (data->type == C_INT)
-    {
-        char *buf;
-        buf = (char *) calloc (16, 1);
-        sprintf (buf, "%d", data->u.num);
-        data->type = C_STR;
-        data->u.str = buf;
-#if 1
-    }
-    else if (data->type == C_NAME)
-    {
-        // テンポラリ。本来無いはず
-        data->type = C_CONSTSTR;
-        data->u.str = str_buf + str_data[data->u.num].str;
-#endif
-    }
-    return data->u.str;
-}
-
-/*==========================================
- * 数値へ変換
- *------------------------------------------
- */
-int conv_num (struct script_state *st, struct script_data *data)
-{
-    char *p;
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        p = data->u.str;
-        data->u.num = atoi (p);
-        if (data->type == C_STR)
-            free (p);
-        data->type = C_INT;
-    }
-    return data->u.num;
-}
-
-/*==========================================
- * スタックへ数値をプッシュ
- *------------------------------------------
- */
-void push_val (struct script_stack *stack, int type, int val)
-{
-    if (stack->sp >= stack->sp_max)
-    {
-        stack->sp_max += 64;
-        stack->stack_data = (struct script_data *)
-            realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
-                                        stack->sp_max);
-        memset (stack->stack_data + (stack->sp_max - 64), 0,
-                64 * sizeof (*(stack->stack_data)));
-    }
-//  if(battle_config.etc_log)
-//      printf("push (%d,%d)-> %d\n",type,val,stack->sp);
-    stack->stack_data[stack->sp].type = type;
-    stack->stack_data[stack->sp].u.num = val;
-    stack->sp++;
-}
-
-/*==========================================
- * スタックへ文字列をプッシュ
- *------------------------------------------
- */
-void push_str (struct script_stack *stack, int type, unsigned char *str)
-{
-    if (stack->sp >= stack->sp_max)
-    {
-        stack->sp_max += 64;
-        stack->stack_data = (struct script_data *)
-            realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
-                                        stack->sp_max);
-        memset (stack->stack_data + (stack->sp_max - 64), '\0',
-                64 * sizeof (*(stack->stack_data)));
-    }
-//  if(battle_config.etc_log)
-//      printf("push (%d,%x)-> %d\n",type,str,stack->sp);
-    stack->stack_data[stack->sp].type = type;
-    stack->stack_data[stack->sp].u.str = str;
-    stack->sp++;
-}
-
-/*==========================================
- * スタックへ複製をプッシュ
- *------------------------------------------
- */
-void push_copy (struct script_stack *stack, int pos)
-{
-    switch (stack->stack_data[pos].type)
-    {
-        case C_CONSTSTR:
-            push_str (stack, C_CONSTSTR, stack->stack_data[pos].u.str);
-            break;
-        case C_STR:
-            push_str (stack, C_STR, strdup (stack->stack_data[pos].u.str));
-            break;
-        default:
-            push_val (stack, stack->stack_data[pos].type,
-                      stack->stack_data[pos].u.num);
-            break;
-    }
-}
-
-/*==========================================
- * スタックからポップ
- *------------------------------------------
- */
-void pop_stack (struct script_stack *stack, int start, int end)
-{
-    int  i;
-    for (i = start; i < end; i++)
-    {
-        if (stack->stack_data[i].type == C_STR)
-        {
-            free (stack->stack_data[i].u.str);
-        }
-    }
-    if (stack->sp > end)
-    {
-        memmove (&stack->stack_data[start], &stack->stack_data[end],
-                 sizeof (stack->stack_data[0]) * (stack->sp - end));
-    }
-    stack->sp -= end - start;
-}
-
-//
-// 埋め込み関数
-//
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_mes (struct script_state *st)
-{
-    conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    clif_scriptmes (script_rid2sd (st), st->oid,
-                    st->stack->stack_data[st->start + 2].u.str);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_goto (struct script_state *st)
-{
-    int  pos;
-
-    if (st->stack->stack_data[st->start + 2].type != C_POS)
-    {
-        printf ("script: goto: not label !\n");
-        st->state = END;
-        return 0;
-    }
-
-    pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    st->pos = pos;
-    st->state = GOTO;
-    return 0;
-}
-
-/*==========================================
- * ユーザー定義関数の呼び出し
- *------------------------------------------
- */
-int buildin_callfunc (struct script_state *st)
-{
-    char *scr;
-    char *str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    if ((scr = (char*)strdb_search (script_get_userfunc_db (), str)))
-    {
-        int  i, j;
-        for (i = st->start + 3, j = 0; i < st->end; i++, j++)
-            push_copy (st->stack, i);
-
-        push_val (st->stack, C_INT, j); // 引数の数をプッシュ
-        push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
-        push_val (st->stack, C_INT, (int) st->script);  // 現在のスクリプトをプッシュ
-        push_val (st->stack, C_RETINFO, st->pos);   // 現在のスクリプト位置をプッシュ
-
-        st->pos = 0;
-        st->script = scr;
-        st->defsp = st->start + 4 + j;
-        st->state = GOTO;
-    }
-    else
-    {
-        printf ("script:callfunc: function not found! [%s]\n", str);
-        st->state = END;
-    }
-    return 0;
-}
-
-/*==========================================
- * サブルーティンの呼び出し
- *------------------------------------------
- */
-int buildin_callsub (struct script_state *st)
-{
-    int  pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  i, j;
-    for (i = st->start + 3, j = 0; i < st->end; i++, j++)
-        push_copy (st->stack, i);
-
-    push_val (st->stack, C_INT, j); // 引数の数をプッシュ
-    push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
-    push_val (st->stack, C_INT, (int) st->script);  // 現在のスクリプトをプッシュ
-    push_val (st->stack, C_RETINFO, st->pos);   // 現在のスクリプト位置をプッシュ
-
-    st->pos = pos;
-    st->defsp = st->start + 4 + j;
-    st->state = GOTO;
-    return 0;
-}
-
-/*==========================================
- * 引数の所得
- *------------------------------------------
- */
-int buildin_getarg (struct script_state *st)
-{
-    int  num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  max, stsp;
-    if (st->defsp < 4
-        || st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
-    {
-        printf ("script:getarg without callfunc or callsub!\n");
-        st->state = END;
-        return 0;
-    }
-    max = conv_num (st, &(st->stack->stack_data[st->defsp - 4]));
-    stsp = st->defsp - max - 4;
-    if (num >= max)
-    {
-        printf ("script:getarg arg1(%d) out of range(%d) !\n", num, max);
-        st->state = END;
-        return 0;
-    }
-    push_copy (st->stack, stsp + num);
-    return 0;
-}
-
-/*==========================================
- * サブルーチン/ユーザー定義関数の終了
- *------------------------------------------
- */
-int buildin_return (struct script_state *st)
-{
-    if (st->end > st->start + 2)
-    {                           // 戻り値有り
-        push_copy (st->stack, st->start + 2);
-    }
-    st->state = RETFUNC;
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_next (struct script_state *st)
-{
-    st->state = STOP;
-    clif_scriptnext (script_rid2sd (st), st->oid);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_close (struct script_state *st)
-{
-    st->state = END;
-    clif_scriptclose (script_rid2sd (st), st->oid);
-    return 0;
-}
-
-int buildin_close2 (struct script_state *st)
-{
-    st->state = STOP;
-    clif_scriptclose (script_rid2sd (st), st->oid);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_menu (struct script_state *st)
-{
-    char *buf;
-    int  i, len = 0;            // [fate] len is the total # of bytes we need to transmit the string choices
-    int  menu_choices = 0;
-    int  finished_menu_items = 0;   // [fate] set to 1 after we hit the first empty string
-
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    // We don't need to do this iteration if the player cancels, strictly speaking.
-    for (i = st->start + 2; i < st->end; i += 2)
-    {
-        int  choice_len;
-        conv_str (st, &(st->stack->stack_data[i]));
-        choice_len = strlen (st->stack->stack_data[i].u.str);
-        len += choice_len + 1;  // count # of bytes we'll need for packet.  Only used if menu_or_input = 0.
-
-        if (choice_len && !finished_menu_items)
-            ++menu_choices;
-        else
-            finished_menu_items = 1;
-    }
-
-    if (sd->state.menu_or_input == 0)
-    {
-        st->state = RERUNLINE;
-        sd->state.menu_or_input = 1;
-
-        buf = (char *) calloc (len + 1, 1);
-        buf[0] = 0;
-        for (i = st->start + 2; menu_choices > 0; i += 2, --menu_choices)
-        {
-            strcat (buf, st->stack->stack_data[i].u.str);
-            strcat (buf, ":");
-        }
-        clif_scriptmenu (script_rid2sd (st), st->oid, buf);
-        free (buf);
-    }
-    else if (sd->npc_menu == 0xff)
-    {                           // cansel
-        sd->state.menu_or_input = 0;
-        st->state = END;
-    }
-    else
-    {                           // goto動作
-        // ragemu互換のため
-        pc_setreg (sd, add_str ("l15"), sd->npc_menu);
-        pc_setreg (sd, add_str ("@menu"), sd->npc_menu);
-        sd->state.menu_or_input = 0;
-        if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices)
-        {
-            int  pos;
-            if (st->stack->
-                stack_data[st->start + sd->npc_menu * 2 + 1].type != C_POS)
-            {
-                st->state = END;
-                return 0;
-            }
-            pos =
-                conv_num (st,
-                          &(st->
-                            stack->stack_data[st->start + sd->npc_menu * 2 +
-                                              1]));
-            st->pos = pos;
-            st->state = GOTO;
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_rand (struct script_state *st)
-{
-    int  range, min, max;
-
-    if (st->end > st->start + 3)
-    {
-        min = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-        max = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-        if (max < min)
-        {
-            int  tmp;
-            tmp = min;
-            min = max;
-            max = tmp;
-        }
-        range = max - min + 1;
-        push_val (st->stack, C_INT, (range <= 0 ? 0 : MRAND (range)) + min);
-    }
-    else
-    {
-        range = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-        push_val (st->stack, C_INT, range <= 0 ? 0 : MRAND (range));
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_pow (struct script_state *st)
-{
-    int  a, b;
-
-    a = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    b = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    push_val (st->stack, C_INT, (int) pow (a * 0.001, b));
-
-    return 0;
-}
-
-/*==========================================
- * Check whether the PC is at the specified location
- *------------------------------------------
- */
-int buildin_isat (struct script_state *st)
-{
-    int  x, y;
-    char *str;
-    struct map_session_data *sd = script_rid2sd (st);
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-
-    if (!sd)
-        return 1;
-
-    push_val (st->stack, C_INT,
-              (x == sd->bl.x)
-              && (y == sd->bl.y) && (!strcmp (str, map[sd->bl.m].name)));
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_warp (struct script_state *st)
-{
-    int  x, y;
-    char *str;
-    struct map_session_data *sd = script_rid2sd (st);
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    if (strcmp (str, "Random") == 0)
-        pc_randomwarp (sd, 3);
-    else if (strcmp (str, "SavePoint") == 0)
-    {
-        if (map[sd->bl.m].flag.noreturn)    // 蝶禁止
-            return 0;
-
-        pc_setpos (sd, sd->status.save_point.map,
-                   sd->status.save_point.x, sd->status.save_point.y, 3);
-    }
-    else if (strcmp (str, "Save") == 0)
-    {
-        if (map[sd->bl.m].flag.noreturn)    // 蝶禁止
-            return 0;
-
-        pc_setpos (sd, sd->status.save_point.map,
-                   sd->status.save_point.x, sd->status.save_point.y, 3);
-    }
-    else
-        pc_setpos (sd, str, x, y, 0);
-    return 0;
-}
-
-/*==========================================
- * エリア指定ワープ
- *------------------------------------------
- */
-int buildin_areawarp_sub (struct block_list *bl, va_list ap)
-{
-    int  x, y;
-    char *map;
-    map = va_arg (ap, char *);
-    x = va_arg (ap, int);
-    y = va_arg (ap, int);
-    if (strcmp (map, "Random") == 0)
-        pc_randomwarp ((struct map_session_data *) bl, 3);
-    else
-        pc_setpos ((struct map_session_data *) bl, map, x, y, 0);
-    return 0;
-}
-
-int buildin_areawarp (struct script_state *st)
-{
-    int  x, y, m;
-    char *str;
-    char *mapname;
-    int  x0, y0, x1, y1;
-
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 8]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 9]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-
-    map_foreachinarea (buildin_areawarp_sub,
-                       m, x0, y0, x1, y1, BL_PC, str, x, y);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_heal (struct script_state *st)
-{
-    int  hp, sp;
-
-    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    pc_heal (script_rid2sd (st), hp, sp);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_itemheal (struct script_state *st)
-{
-    int  hp, sp;
-
-    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    pc_itemheal (script_rid2sd (st), hp, sp);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_percentheal (struct script_state *st)
-{
-    int  hp, sp;
-
-    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    pc_percentheal (script_rid2sd (st), hp, sp);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_jobchange (struct script_state *st)
-{
-    int  job, upper = -1;
-
-    job = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (st->end > st->start + 3)
-        upper = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    if ((job >= 0 && job < MAX_PC_CLASS))
-        pc_jobchange (script_rid2sd (st), job, upper);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_input (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num =
-        (st->end >
-         st->start + 2) ? st->stack->stack_data[st->start + 2].u.num : 0;
-    char *name =
-        (st->end >
-         st->start + 2) ? str_buf + str_data[num & 0x00ffffff].str : "";
-//  char prefix=*name;
-    char postfix = name[strlen (name) - 1];
-
-    sd = script_rid2sd (st);
-    if (sd->state.menu_or_input)
-    {
-        sd->state.menu_or_input = 0;
-        if (postfix == '$')
-        {
-            // 文字列
-            if (st->end > st->start + 2)
-            {                   // 引数1個
-                set_reg (sd, num, name, (void *) sd->npc_str);
-            }
-            else
-            {
-                printf ("buildin_input: string discarded !!\n");
-            }
-        }
-        else
-        {
-
-            //commented by Lupus (check Value Number Input fix in clif.c)
-            //** Fix by fritz :X keeps people from abusing old input bugs
-            if (sd->npc_amount < 0) //** If input amount is less then 0
-            {
-                clif_tradecancelled (sd);   // added "Deal has been cancelled" message by Valaris
-                buildin_close (st); //** close
-            }
-
-            // 数値
-            if (st->end > st->start + 2)
-            {                   // 引数1個
-                set_reg (sd, num, name, (void *) sd->npc_amount);
-            }
-            else
-            {
-                // ragemu互換のため
-                pc_setreg (sd, add_str ("l14"), sd->npc_amount);
-            }
-        }
-    }
-    else
-    {
-        st->state = RERUNLINE;
-        if (postfix == '$')
-            clif_scriptinputstr (sd, st->oid);
-        else
-            clif_scriptinput (sd, st->oid);
-        sd->state.menu_or_input = 1;
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_if (struct script_state *st)
-{
-    int  sel, i;
-
-    sel = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (!sel)
-        return 0;
-
-    // 関数名をコピー
-    push_copy (st->stack, st->start + 3);
-    // 間に引数マーカを入れて
-    push_val (st->stack, C_ARG, 0);
-    // 残りの引数をコピー
-    for (i = st->start + 4; i < st->end; i++)
-    {
-        push_copy (st->stack, i);
-    }
-    run_func (st);
-
-    return 0;
-}
-
-/*==========================================
- * 変数設定
- *------------------------------------------
- */
-int buildin_set (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-
-    if (st->stack->stack_data[st->start + 2].type != C_NAME)
-    {
-        printf ("script: buildin_set: not name\n");
-        return 0;
-    }
-
-    if (prefix != '$')
-        sd = script_rid2sd (st);
-
-    if (postfix == '$')
-    {
-        // 文字列
-        char *str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-        set_reg (sd, num, name, (void *) str);
-    }
-    else
-    {
-        // 数値
-        int  val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-        set_reg (sd, num, name, (void *) val);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 配列変数設定
- *------------------------------------------
- */
-int buildin_setarray (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-    int  i, j;
-
-    if (prefix != '$' && prefix != '@')
-    {
-        printf ("buildin_setarray: illegal scope !\n");
-        return 0;
-    }
-    if (prefix != '$')
-        sd = script_rid2sd (st);
-
-    for (j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++)
-    {
-        void *v;
-        if (postfix == '$')
-            v = (void *) conv_str (st, &(st->stack->stack_data[i]));
-        else
-            v = (void *) conv_num (st, &(st->stack->stack_data[i]));
-        set_reg (sd, num + (j << 24), name, v);
-    }
-    return 0;
-}
-
-/*==========================================
- * 配列変数クリア
- *------------------------------------------
- */
-int buildin_cleararray (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-    int  sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    int  i;
-    void *v;
-
-    if (prefix != '$' && prefix != '@')
-    {
-        printf ("buildin_cleararray: illegal scope !\n");
-        return 0;
-    }
-    if (prefix != '$')
-        sd = script_rid2sd (st);
-
-    if (postfix == '$')
-        v = (void *) conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    else
-        v = (void *) conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    for (i = 0; i < sz; i++)
-        set_reg (sd, num + (i << 24), name, v);
-    return 0;
-}
-
-/*==========================================
- * 配列変数コピー
- *------------------------------------------
- */
-int buildin_copyarray (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-    int  num2 = st->stack->stack_data[st->start + 3].u.num;
-    char *name2 = str_buf + str_data[num2 & 0x00ffffff].str;
-    char prefix2 = *name2;
-    char postfix2 = name2[strlen (name2) - 1];
-    int  sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    int  i;
-
-    if (prefix != '$' && prefix != '@' && prefix2 != '$' && prefix2 != '@')
-    {
-        printf ("buildin_copyarray: illegal scope !\n");
-        return 0;
-    }
-    if ((postfix == '$' || postfix2 == '$') && postfix != postfix2)
-    {
-        printf ("buildin_copyarray: type mismatch !\n");
-        return 0;
-    }
-    if (prefix != '$' || prefix2 != '$')
-        sd = script_rid2sd (st);
-
-    for (i = 0; i < sz; i++)
-        set_reg (sd, num + (i << 24), name, get_val2 (st, num2 + (i << 24)));
-    return 0;
-}
-
-/*==========================================
- * 配列変数のサイズ所得
- *------------------------------------------
- */
-static int getarraysize (struct script_state *st, int num, int postfix)
-{
-    int  i = (num >> 24), c = i;
-    for (; i < 128; i++)
-    {
-        void *v = get_val2 (st, num + (i << 24));
-        if (postfix == '$' && *((char *) v))
-            c = i;
-        if (postfix != '$' && (int) v)
-            c = i;
-    }
-    return c + 1;
-}
-
-int buildin_getarraysize (struct script_state *st)
-{
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-
-    if (prefix != '$' && prefix != '@')
-    {
-        printf ("buildin_copyarray: illegal scope !\n");
-        return 0;
-    }
-
-    push_val (st->stack, C_INT, getarraysize (st, num, postfix));
-    return 0;
-}
-
-/*==========================================
- * 配列変数から要素削除
- *------------------------------------------
- */
-int buildin_deletearray (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  num = st->stack->stack_data[st->start + 2].u.num;
-    char *name = str_buf + str_data[num & 0x00ffffff].str;
-    char prefix = *name;
-    char postfix = name[strlen (name) - 1];
-    int  count = 1;
-    int  i, sz = getarraysize (st, num, postfix) - (num >> 24) - count + 1;
-
-    if ((st->end > st->start + 3))
-        count = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    if (prefix != '$' && prefix != '@')
-    {
-        printf ("buildin_deletearray: illegal scope !\n");
-        return 0;
-    }
-    if (prefix != '$')
-        sd = script_rid2sd (st);
-
-    for (i = 0; i < sz; i++)
-    {
-        set_reg (sd, num + (i << 24), name,
-                 get_val2 (st, num + ((i + count) << 24)));
-    }
-    for (; i < (128 - (num >> 24)); i++)
-    {
-        if (postfix != '$')
-            set_reg (sd, num + (i << 24), name, 0);
-        if (postfix == '$')
-            set_reg (sd, num + (i << 24), name, "");
-    }
-    return 0;
-}
-
-/*==========================================
- * 指定要素を表す値(キー)を所得する
- *------------------------------------------
- */
-int buildin_getelementofarray (struct script_state *st)
-{
-    if (st->stack->stack_data[st->start + 2].type == C_NAME)
-    {
-        int  i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-        if (i > 127 || i < 0)
-        {
-            printf
-                ("script: getelementofarray (operator[]): param2 illegal number %d\n",
-                 i);
-            push_val (st->stack, C_INT, 0);
-        }
-        else
-        {
-            push_val (st->stack, C_NAME,
-                      (i << 24) | st->stack->stack_data[st->start + 2].u.num);
-        }
-    }
-    else
-    {
-        printf
-            ("script: getelementofarray (operator[]): param1 not name !\n");
-        push_val (st->stack, C_INT, 0);
-    }
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_setlook (struct script_state *st)
-{
-    int  type, val;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    pc_changelook (script_rid2sd (st), type, val);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_cutin (struct script_state *st)
-{
-    int  type;
-
-    conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    clif_cutin (script_rid2sd (st),
-                st->stack->stack_data[st->start + 2].u.str, type);
-
-    return 0;
-}
-
-/*==========================================
- * カードのイラストを表示する
- *------------------------------------------
- */
-int buildin_cutincard (struct script_state *st)
-{
-    int  itemid;
-
-    itemid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    clif_cutin (script_rid2sd (st), itemdb_search (itemid)->cardillustname,
-                4);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_viewpoint (struct script_state *st)
-{
-    int  type, x, y, id, color;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    id = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    color = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-
-    clif_viewpoint (script_rid2sd (st), st->oid, type, x, y, id, color);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_countitem (struct script_state *st)
-{
-    int  nameid = 0, count = 0, i;
-    struct map_session_data *sd;
-
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        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 = conv_num (st, data);
-
-    if (nameid >= 500)          //if no such ID then skip this iteration
-        for (i = 0; i < MAX_INVENTORY; i++)
-        {
-            if (sd->status.inventory[i].nameid == nameid)
-                count += sd->status.inventory[i].amount;
-        }
-    else
-    {
-        if (battle_config.error_log)
-            printf ("wrong item ID : countitem(%i)\n", nameid);
-    }
-    push_val (st->stack, C_INT, count);
-
-    return 0;
-}
-
-/*==========================================
- * 重量チェック
- *------------------------------------------
- */
-int buildin_checkweight (struct script_state *st)
-{
-    int  nameid = 0, amount;
-    struct map_session_data *sd;
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        if (item_data)
-            nameid = item_data->nameid;
-    }
-    else
-        nameid = conv_num (st, data);
-
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (amount <= 0 || nameid < 500)
-    {                           //if get wrong item ID or amount<=0, don't count weight of non existing items
-        push_val (st->stack, C_INT, 0);
-    }
-
-    sd = script_rid2sd (st);
-    if (itemdb_weight (nameid) * amount + sd->weight > sd->max_weight)
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_getitem (struct script_state *st)
-{
-    int  nameid, amount, flag = 0;
-    struct item item_tmp;
-    struct map_session_data *sd;
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        nameid = 727;           //Default to iten
-        if (item_data != NULL)
-            nameid = item_data->nameid;
-    }
-    else
-        nameid = conv_num (st, data);
-
-    if ((amount =
-         conv_num (st, &(st->stack->stack_data[st->start + 3]))) <= 0)
-    {
-        return 0;               //return if amount <=0, skip the useles iteration
-    }
-    //Violet Box, Blue Box, etc - random item pick
-    if (nameid < 0)
-    {                           // ランダム
-        nameid = itemdb_searchrandomid (-nameid);
-        flag = 1;
-    }
-
-    if (nameid > 0)
-    {
-        memset (&item_tmp, 0, sizeof (item_tmp));
-        item_tmp.nameid = nameid;
-        if (!flag)
-            item_tmp.identify = 1;
-        else
-            item_tmp.identify = !itemdb_isequip3 (nameid);
-        if (st->end > st->start + 5)    //アイテムを指定したIDに渡す
-            sd = map_id2sd (conv_num
-                            (st, &(st->stack->stack_data[st->start + 5])));
-        if (sd == NULL)         //アイテムを渡す相手がいなかったらお帰り
-            return 0;
-        if ((flag = pc_additem (sd, &item_tmp, amount)))
-        {
-            clif_additem (sd, 0, 0, flag);
-            map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
-                              NULL, NULL, NULL, 0);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_getitem2 (struct script_state *st)
-{
-    int  nameid, amount, flag = 0;
-    int  iden, ref, attr, c1, c2, c3, c4;
-    struct item_data *item_data;
-    struct item item_tmp;
-    struct map_session_data *sd;
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        nameid = 512;           //Apple item ID
-        if (item_data)
-            nameid = item_data->nameid;
-    }
-    else
-        nameid = conv_num (st, data);
-
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    iden = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    ref = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    attr = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    c1 = conv_num (st, &(st->stack->stack_data[st->start + 7]));
-    c2 = conv_num (st, &(st->stack->stack_data[st->start + 8]));
-    c3 = conv_num (st, &(st->stack->stack_data[st->start + 9]));
-    c4 = conv_num (st, &(st->stack->stack_data[st->start + 10]));
-    if (st->end > st->start + 11)   //アイテムを指定したIDに渡す
-        sd = map_id2sd (conv_num
-                        (st, &(st->stack->stack_data[st->start + 11])));
-    if (sd == NULL)             //アイテムを渡す相手がいなかったらお帰り
-        return 0;
-
-    if (nameid < 0)
-    {                           // ランダム
-        nameid = itemdb_searchrandomid (-nameid);
-        flag = 1;
-    }
-
-    if (nameid > 0)
-    {
-        memset (&item_tmp, 0, sizeof (item_tmp));
-        item_data = itemdb_search (nameid);
-        if (item_data->type == 4 || item_data->type == 5)
-        {
-            if (ref > 10)
-                ref = 10;
-        }
-        else if (item_data->type == 7)
-        {
-            iden = 1;
-            ref = 0;
-        }
-        else
-        {
-            iden = 1;
-            ref = attr = 0;
-        }
-
-        item_tmp.nameid = nameid;
-        if (!flag)
-            item_tmp.identify = iden;
-        else if (item_data->type == 4 || item_data->type == 5)
-            item_tmp.identify = 0;
-        item_tmp.refine = ref;
-        item_tmp.attribute = attr;
-        item_tmp.card[0] = c1;
-        item_tmp.card[1] = c2;
-        item_tmp.card[2] = c3;
-        item_tmp.card[3] = c4;
-        if ((flag = pc_additem (sd, &item_tmp, amount)))
-        {
-            clif_additem (sd, 0, 0, flag);
-            map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
-                              NULL, NULL, NULL, 0);
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_makeitem (struct script_state *st)
-{
-    int  nameid, amount, flag = 0;
-    int  x, y, m;
-    char *mapname;
-    struct item item_tmp;
-    struct map_session_data *sd;
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        nameid = 512;           //Apple Item ID
-        if (item_data)
-            nameid = item_data->nameid;
-    }
-    else
-        nameid = conv_num (st, data);
-
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-
-    if (sd && strcmp (mapname, "this") == 0)
-        m = sd->bl.m;
-    else
-        m = map_mapname2mapid (mapname);
-
-    if (nameid < 0)
-    {                           // ランダム
-        nameid = itemdb_searchrandomid (-nameid);
-        flag = 1;
-    }
-
-    if (nameid > 0)
-    {
-        memset (&item_tmp, 0, sizeof (item_tmp));
-        item_tmp.nameid = nameid;
-        if (!flag)
-            item_tmp.identify = 1;
-        else
-            item_tmp.identify = !itemdb_isequip3 (nameid);
-
-//      clif_additem(sd,0,0,flag);
-        map_addflooritem (&item_tmp, amount, m, x, y, NULL, NULL, NULL, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_delitem (struct script_state *st)
-{
-    int  nameid = 0, amount, i;
-    struct map_session_data *sd;
-    struct script_data *data;
-
-    sd = script_rid2sd (st);
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        //nameid=512;
-        if (item_data)
-            nameid = item_data->nameid;
-    }
-    else
-        nameid = conv_num (st, data);
-
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    if (nameid < 500 || amount <= 0)
-    {                           //by Lupus. Don't run FOR if u got wrong item ID or amount<=0
-        //printf("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount);
-        return 0;
-    }
-    sd = script_rid2sd (st);
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid <= 0
-            || sd->inventory_data[i] == NULL
-            || sd->inventory_data[i]->type != 7
-            || sd->status.inventory[i].amount <= 0)
-            continue;
-    }
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid == nameid)
-        {
-            if (sd->status.inventory[i].amount >= amount)
-            {
-                pc_delitem (sd, i, amount, 0);
-                break;
-            }
-            else
-            {
-                amount -= sd->status.inventory[i].amount;
-                if (amount == 0)
-                    amount = sd->status.inventory[i].amount;
-                pc_delitem (sd, i, amount, 0);
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- *キャラ関係のパラメータ取得
- *------------------------------------------
- */
-int buildin_readparam (struct script_state *st)
-{
-    int  type;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (st->end > st->start + 3)
-        sd = map_nick2sd (conv_str
-                          (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        sd = script_rid2sd (st);
-
-    if (sd == NULL)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-
-    push_val (st->stack, C_INT, pc_readparam (sd, type));
-
-    return 0;
-}
-
-/*==========================================
- *キャラ関係のID取得
- *------------------------------------------
- */
-int buildin_getcharid (struct script_state *st)
-{
-    int  num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (st->end > st->start + 3)
-        sd = map_nick2sd (conv_str
-                          (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        sd = script_rid2sd (st);
-    if (sd == NULL)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-    if (num == 0)
-        push_val (st->stack, C_INT, sd->status.char_id);
-    if (num == 1)
-        push_val (st->stack, C_INT, sd->status.party_id);
-    if (num == 2)
-        push_val (st->stack, C_INT, sd->status.guild_id);
-    if (num == 3)
-        push_val (st->stack, C_INT, sd->status.account_id);
-    return 0;
-}
-
-/*==========================================
- *指定IDのPT名取得
- *------------------------------------------
- */
-char *buildin_getpartyname_sub (int party_id)
-{
-    struct party *p;
-
-    p = NULL;
-    p = party_search (party_id);
-
-    if (p != NULL)
-    {
-        char *buf;
-        buf = (char *) calloc (24, 1);
-        strcpy (buf, p->name);
-        return buf;
-    }
-
-    return 0;
-}
-
-int buildin_getpartyname (struct script_state *st)
-{
-    char *name;
-    int  party_id;
-
-    party_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    name = buildin_getpartyname_sub (party_id);
-    if (name != 0)
-        push_str (st->stack, C_STR, name);
-    else
-        push_str (st->stack, C_CONSTSTR, "null");
-
-    return 0;
-}
-
-/*==========================================
- *指定IDのPT人数とメンバーID取得
- *------------------------------------------
- */
-int buildin_getpartymember (struct script_state *st)
-{
-    struct party *p;
-    int  i, j = 0;
-
-    p = NULL;
-    p = party_search (conv_num (st, &(st->stack->stack_data[st->start + 2])));
-
-    if (p != NULL)
-    {
-        for (i = 0; i < MAX_PARTY; i++)
-        {
-            if (p->member[i].account_id)
-            {
-//              printf("name:%s %d\n",p->member[i].name,i);
-                mapreg_setregstr (add_str ("$@partymembername$") + (i << 24),
-                                  p->member[i].name);
-                j++;
-            }
-        }
-    }
-    mapreg_setreg (add_str ("$@partymembercount"), j);
-
-    return 0;
-}
-
-/*==========================================
- *指定IDのギルド名取得
- *------------------------------------------
- */
-char *buildin_getguildname_sub (int guild_id)
-{
-    struct guild *g = NULL;
-    g = guild_search (guild_id);
-
-    if (g != NULL)
-    {
-        char *buf;
-        buf = (char *) calloc (24, 1);
-        strcpy (buf, g->name);
-        return buf;
-    }
-    return 0;
-}
-
-int buildin_getguildname (struct script_state *st)
-{
-    char *name;
-    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    name = buildin_getguildname_sub (guild_id);
-    if (name != 0)
-        push_str (st->stack, C_STR, name);
-    else
-        push_str (st->stack, C_CONSTSTR, "null");
-    return 0;
-}
-
-/*==========================================
- *指定IDのGuildMaster名取得
- *------------------------------------------
- */
-char *buildin_getguildmaster_sub (int guild_id)
-{
-    struct guild *g = NULL;
-    g = guild_search (guild_id);
-
-    if (g != NULL)
-    {
-        char *buf;
-        buf = (char *) calloc (24, 1);
-        strncpy (buf, g->master, 23);
-        return buf;
-    }
-
-    return 0;
-}
-
-int buildin_getguildmaster (struct script_state *st)
-{
-    char *master;
-    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    master = buildin_getguildmaster_sub (guild_id);
-    if (master != 0)
-        push_str (st->stack, C_STR, master);
-    else
-        push_str (st->stack, C_CONSTSTR, "null");
-    return 0;
-}
-
-int buildin_getguildmasterid (struct script_state *st)
-{
-    char *master;
-    struct map_session_data *sd = NULL;
-    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    master = buildin_getguildmaster_sub (guild_id);
-    if (master != 0)
-    {
-        if ((sd = map_nick2sd (master)) == NULL)
-        {
-            push_val (st->stack, C_INT, 0);
-            return 0;
-        }
-        push_val (st->stack, C_INT, sd->status.char_id);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-    return 0;
-}
-
-/*==========================================
- * キャラクタの名前
- *------------------------------------------
- */
-int buildin_strcharinfo (struct script_state *st)
-{
-    struct map_session_data *sd;
-    int  num;
-
-    sd = script_rid2sd (st);
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (num == 0)
-    {
-        char *buf;
-        buf = (char *) calloc (24, 1);
-        strncpy (buf, sd->status.name, 23);
-        push_str (st->stack, C_STR, buf);
-    }
-    if (num == 1)
-    {
-        char *buf;
-        buf = buildin_getpartyname_sub (sd->status.party_id);
-        if (buf != 0)
-            push_str (st->stack, C_STR, buf);
-        else
-            push_str (st->stack, C_CONSTSTR, "");
-    }
-    if (num == 2)
-    {
-        char *buf;
-        buf = buildin_getguildname_sub (sd->status.guild_id);
-        if (buf != 0)
-            push_str (st->stack, C_STR, buf);
-        else
-            push_str (st->stack, C_CONSTSTR, "");
-    }
-
-    return 0;
-}
-
-unsigned int equip[10] =
-    { 0x0100, 0x0010, 0x0020, 0x0002, 0x0004, 0x0040, 0x0008, 0x0080, 0x0200,
-    0x0001
-};
-
-/*==========================================
- * GetEquipID(Pos);     Pos: 1-10
- *------------------------------------------
- */
-int buildin_getequipid (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-    struct item_data *item;
-
-    sd = script_rid2sd (st);
-    if (sd == NULL)
-    {
-        printf ("getequipid: sd == NULL\n");
-        return 0;
-    }
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-    {
-        item = sd->inventory_data[i];
-        if (item)
-            push_val (st->stack, C_INT, item->nameid);
-        else
-            push_val (st->stack, C_INT, 0);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, -1);
-    }
-    return 0;
-}
-
-/*==========================================
- * 装備名文字列(精錬メニュー用)
- *------------------------------------------
- */
-int buildin_getequipname (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-    struct item_data *item;
-    char *buf;
-
-    buf = (char *) calloc (64, 1);
-    sd = script_rid2sd (st);
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-    {
-        item = sd->inventory_data[i];
-        if (item)
-            sprintf (buf, "%s-[%s]", pos[num - 1], item->jname);
-        else
-            sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
-    }
-    else
-    {
-        sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
-    }
-    push_str (st->stack, C_STR, buf);
-
-    return 0;
-}
-
-/*==========================================
- * getbrokenid [Valaris]
- *------------------------------------------
- */
-int buildin_getbrokenid (struct script_state *st)
-{
-    int  i, num, id = 0, brokencounter = 0;
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].broken == 1)
-        {
-            brokencounter++;
-            if (num == brokencounter)
-            {
-                id = sd->status.inventory[i].nameid;
-                break;
-            }
-        }
-    }
-
-    push_val (st->stack, C_INT, id);
-
-    return 0;
-}
-
-/*==========================================
- * repair [Valaris]
- *------------------------------------------
- */
-int buildin_repair (struct script_state *st)
-{
-    int  i, num;
-    int  repaircounter = 0;
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].broken == 1)
-        {
-            repaircounter++;
-            if (num == repaircounter)
-            {
-                sd->status.inventory[i].broken = 0;
-                clif_equiplist (sd);
-                clif_produceeffect (sd, 0, sd->status.inventory[i].nameid);
-                clif_misceffect (&sd->bl, 3);
-                clif_displaymessage (sd->fd, "Item has been repaired.");
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 装備チェック
- *------------------------------------------
- */
-int buildin_getequipisequiped (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 装備品精錬可能チェック
- *------------------------------------------
- */
-int buildin_getequipisenableref (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0 && num < 7 && sd->inventory_data[i]
-        && (num != 1 || sd->inventory_data[i]->def > 1
-            || (sd->inventory_data[i]->def == 1
-                && sd->inventory_data[i]->equip_script == NULL)
-            || (sd->inventory_data[i]->def <= 0
-                && sd->inventory_data[i]->equip_script != NULL)))
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 装備品鑑定チェック
- *------------------------------------------
- */
-int buildin_getequipisidentify (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-        push_val (st->stack, C_INT, sd->status.inventory[i].identify);
-    else
-        push_val (st->stack, C_INT, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品精錬度
- *------------------------------------------
- */
-int buildin_getequiprefinerycnt (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-        push_val (st->stack, C_INT, sd->status.inventory[i].refine);
-    else
-        push_val (st->stack, C_INT, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品武器LV
- *------------------------------------------
- */
-int buildin_getequipweaponlv (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0 && sd->inventory_data[i])
-        push_val (st->stack, C_INT, sd->inventory_data[i]->wlv);
-    else
-        push_val (st->stack, C_INT, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品精錬成功率
- *------------------------------------------
- */
-int buildin_getequippercentrefinery (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-        push_val (st->stack, C_INT,
-                  pc_percentrefinery (sd, &sd->status.inventory[i]));
-    else
-        push_val (st->stack, C_INT, 0);
-
-    return 0;
-}
-
-/*==========================================
- * 精錬成功
- *------------------------------------------
- */
-int buildin_successrefitem (struct script_state *st)
-{
-    int  i, num, ep;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-    {
-        ep = sd->status.inventory[i].equip;
-
-        sd->status.inventory[i].refine++;
-        pc_unequipitem (sd, i, 0);
-        clif_refine (sd->fd, sd, 0, i, sd->status.inventory[i].refine);
-        clif_delitem (sd, i, 1);
-        clif_additem (sd, i, 1, 0);
-        pc_equipitem (sd, i, ep);
-        clif_misceffect (&sd->bl, 3);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 精錬失敗
- *------------------------------------------
- */
-int buildin_failedrefitem (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (i >= 0)
-    {
-        sd->status.inventory[i].refine = 0;
-        pc_unequipitem (sd, i, 0);
-        // 精錬失敗エフェクトのパケット
-        clif_refine (sd->fd, sd, 1, i, sd->status.inventory[i].refine);
-        pc_delitem (sd, i, 1, 0);
-        // 他の人にも失敗を通知
-        clif_misceffect (&sd->bl, 2);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_statusup (struct script_state *st)
-{
-    int  type;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    pc_statusup (sd, type);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_statusup2 (struct script_state *st)
-{
-    int  type, val;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    sd = script_rid2sd (st);
-    pc_statusup2 (sd, type, val);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品による能力値ボーナス
- *------------------------------------------
- */
-int buildin_bonus (struct script_state *st)
-{
-    int  type, val;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    sd = script_rid2sd (st);
-    pc_bonus (sd, type, val);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品による能力値ボーナス
- *------------------------------------------
- */
-int buildin_bonus2 (struct script_state *st)
-{
-    int  type, type2, val;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    val = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    sd = script_rid2sd (st);
-    pc_bonus2 (sd, type, type2, val);
-
-    return 0;
-}
-
-/*==========================================
- * 装備品による能力値ボーナス
- *------------------------------------------
- */
-int buildin_bonus3 (struct script_state *st)
-{
-    int  type, type2, type3, val;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    type3 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    val = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    sd = script_rid2sd (st);
-    pc_bonus3 (sd, type, type2, type3, val);
-
-    return 0;
-}
-
-/*==========================================
- * スキル所得
- *------------------------------------------
- */
-int buildin_skill (struct script_state *st)
-{
-    int  id, level, flag = 1;
-    struct map_session_data *sd;
-
-    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (st->end > st->start + 4)
-        flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    sd = script_rid2sd (st);
-    pc_skill (sd, id, level, flag);
-    clif_skillinfoblock (sd);
-
-    return 0;
-}
-
-/*==========================================
- * [Fate] Sets the skill level permanently
- *------------------------------------------
- */
-int buildin_setskill (struct script_state *st)
-{
-    int  id, level;
-    struct map_session_data *sd;
-
-    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    sd = script_rid2sd (st);
-
-    sd->status.skill[id].id = level ? id : 0;
-    sd->status.skill[id].lv = level;
-    clif_skillinfoblock (sd);
-    return 0;
-}
-
-/*==========================================
- * ギルドスキル取得
- *------------------------------------------
- */
-int buildin_guildskill (struct script_state *st)
-{
-    int  id, level;
-    struct map_session_data *sd;
-    int  i = 0;
-
-    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-//  if( st->end>st->start+4 )
-//      flag=conv_num(st,&(st->stack->stack_data[st->start+4]) );
-    sd = script_rid2sd (st);
-    for (i = 0; i < level; i++)
-        guild_skillup (sd, id);
-
-    return 0;
-}
-
-/*==========================================
- * スキルレベル所得
- *------------------------------------------
- */
-int buildin_getskilllv (struct script_state *st)
-{
-    int  id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    push_val (st->stack, C_INT, pc_checkskill (script_rid2sd (st), id));
-    return 0;
-}
-
-/*==========================================
- * getgdskilllv(Guild_ID, Skill_ID);
- * skill_id = 10000 : GD_APPROVAL
- *            10001 : GD_KAFRACONTACT
- *            10002 : GD_GUARDIANRESEARCH
- *            10003 : GD_CHARISMA
- *            10004 : GD_EXTENSION
- *------------------------------------------
- */
-int buildin_getgdskilllv (struct script_state *st)
-{
-    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    struct guild *g = guild_search (guild_id);
-    push_val (st->stack, C_INT,
-              (g == NULL) ? -1 : guild_checkskill (g, skill_id));
-    return 0;
-/*
-	struct map_session_data *sd=NULL;
-	struct guild *g=NULL;
-	int skill_id;
-
-	skill_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
-	sd=script_rid2sd(st);
-	if(sd && sd->status.guild_id > 0) g=guild_search(sd->status.guild_id);
-	if(sd && g) {
-		push_val(st->stack,C_INT, guild_checkskill(g,skill_id+9999) );
-	} else {
-		push_val(st->stack,C_INT,-1);
-	}
-	return 0;
-*/
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_basicskillcheck (struct script_state *st)
-{
-    push_val (st->stack, C_INT, battle_config.basic_skill_check);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_getgmlevel (struct script_state *st)
-{
-    push_val (st->stack, C_INT, pc_isGM (script_rid2sd (st)));
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_end (struct script_state *st)
-{
-    st->state = END;
-    return 0;
-}
-
-/*==========================================
- * [Freeyorp] Return the current opt2
- *------------------------------------------
- */
-
-int buildin_getopt2 (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    push_val (st->stack, C_INT, sd->opt2);
-
-    return 0;
-}
-
-/*==========================================
- * [Freeyorp] Sets opt2
- *------------------------------------------
- */
-
-int buildin_setopt2 (struct script_state *st)
-{
-    int  new_opt2;
-    struct map_session_data *sd;
-
-    new_opt2 = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    if (new_opt2 == sd->opt2)
-        return 0;
-    sd->opt2 = new_opt2;
-    clif_changeoption (&sd->bl);
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_checkoption (struct script_state *st)
-{
-    int  type;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-
-    if (sd->status.option & type)
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_setoption (struct script_state *st)
-{
-    int  type;
-    struct map_session_data *sd;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    pc_setoption (sd, type);
-
-    return 0;
-}
-
-/*==========================================
- * Checkcart [Valaris]
- *------------------------------------------
- */
-
-int buildin_checkcart (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    if (pc_iscarton (sd))
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-    return 0;
-}
-
-/*==========================================
- * カートを付ける
- *------------------------------------------
- */
-int buildin_setcart (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-    pc_setcart (sd, 1);
-
-    return 0;
-}
-
-/*==========================================
- * checkfalcon [Valaris]
- *------------------------------------------
- */
-
-int buildin_checkfalcon (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    if (pc_isfalcon (sd))
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * 鷹を付ける
- *------------------------------------------
- */
-int buildin_setfalcon (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-    pc_setfalcon (sd);
-
-    return 0;
-}
-
-/*==========================================
- * Checkcart [Valaris]
- *------------------------------------------
- */
-
-int buildin_checkriding (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    if (pc_isriding (sd))
-    {
-        push_val (st->stack, C_INT, 1);
-    }
-    else
-    {
-        push_val (st->stack, C_INT, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * ペコペコ乗り
- *------------------------------------------
- */
-int buildin_setriding (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-    pc_setriding (sd);
-
-    return 0;
-}
-
-/*==========================================
- *	セーブポイントの保存
- *------------------------------------------
- */
-int buildin_savepoint (struct script_state *st)
-{
-    int  x, y;
-    char *str;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    pc_setsavepoint (script_rid2sd (st), str, x, y);
-    return 0;
-}
-
-/*==========================================
- * gettimetick(type)
- *
- * type The type of time measurement.
- *  Specify 0 for the system tick, 1 for
- *  seconds elapsed today, or 2 for seconds
- *  since Unix epoch. Defaults to 0 for any
- *  other value.
- *------------------------------------------
- */
-int buildin_gettimetick (struct script_state *st)   /* Asgard Version */
-{
-    int  type;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    switch (type)
-    {
-        /* Number of seconds elapsed today (0-86399, 00:00:00-23:59:59). */
-        case 1:
-        {
-            time_t timer;
-            struct tm *t;
-
-            time (&timer);
-            t = gmtime (&timer);
-            push_val (st->stack, C_INT,
-                      ((t->tm_hour) * 3600 + (t->tm_min) * 60 + t->tm_sec));
-            break;
-        }
-        /* Seconds since Unix epoch. */
-        case 2:
-            push_val (st->stack, C_INT, (int) time (NULL));
-            break;
-        /* System tick (unsigned int, and yes, it will wrap). */
-        case 0:
-        default:
-            push_val (st->stack, C_INT, gettick ());
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * GetTime(Type);
- * 1: Sec     2: Min     3: Hour
- * 4: WeekDay     5: MonthDay     6: Month
- * 7: Year
- *------------------------------------------
- */
-int buildin_gettime (struct script_state *st)   /* Asgard Version */
-{
-    int  type;
-    time_t timer;
-    struct tm *t;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    time (&timer);
-    t = gmtime (&timer);
-
-    switch (type)
-    {
-        case 1:                //Sec(0~59)
-            push_val (st->stack, C_INT, t->tm_sec);
-            break;
-        case 2:                //Min(0~59)
-            push_val (st->stack, C_INT, t->tm_min);
-            break;
-        case 3:                //Hour(0~23)
-            push_val (st->stack, C_INT, t->tm_hour);
-            break;
-        case 4:                //WeekDay(0~6)
-            push_val (st->stack, C_INT, t->tm_wday);
-            break;
-        case 5:                //MonthDay(01~31)
-            push_val (st->stack, C_INT, t->tm_mday);
-            break;
-        case 6:                //Month(01~12)
-            push_val (st->stack, C_INT, t->tm_mon + 1);
-            break;
-        case 7:                //Year(20xx)
-            push_val (st->stack, C_INT, t->tm_year + 1900);
-            break;
-        default:               //(format error)
-            push_val (st->stack, C_INT, -1);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * GetTimeStr("TimeFMT", Length);
- *------------------------------------------
- */
-int buildin_gettimestr (struct script_state *st)
-{
-    char *tmpstr;
-    char *fmtstr;
-    int  maxlen;
-    time_t now = time (NULL);
-
-    fmtstr = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    maxlen = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    tmpstr = (char *) calloc (maxlen + 1, 1);
-    strftime (tmpstr, maxlen, fmtstr, gmtime (&now));
-    tmpstr[maxlen] = '\0';
-
-    push_str (st->stack, C_STR, tmpstr);
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫を開く
- *------------------------------------------
- */
-int buildin_openstorage (struct script_state *st)
-{
-//  int sync = 0;
-//  if (st->end >= 3) sync = conv_num(st,& (st->stack->stack_data[st->start+2]));
-    struct map_session_data *sd = script_rid2sd (st);
-
-//  if (sync) {
-    st->state = STOP;
-    sd->npc_flags.storage = 1;
-//  } else st->state = END;
-
-    storage_storageopen (sd);
-    return 0;
-}
-
-int buildin_guildopenstorage (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  ret;
-    st->state = STOP;
-    ret = storage_guild_storageopen (sd);
-    push_val (st->stack, C_INT, ret);
-    return 0;
-}
-
-/*==========================================
- * アイテムによるスキル発動
- *------------------------------------------
- */
-int buildin_itemskill (struct script_state *st)
-{
-    int  id, lv;
-    char *str;
-    struct map_session_data *sd = script_rid2sd (st);
-
-    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    lv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-
-    // 詠唱中にスキルアイテムは使用できない
-    if (sd->skilltimer != -1)
-        return 0;
-
-    sd->skillitem = id;
-    sd->skillitemlv = lv;
-    clif_item_skill (sd, id, lv, str);
-    return 0;
-}
-
-/*==========================================
- * NPCで経験値上げる
- *------------------------------------------
- */
-int buildin_getexp (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  base = 0, job = 0;
-
-    base = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    job = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (base < 0 || job < 0)
-        return 0;
-    if (sd)
-        pc_gainexp_reason (sd, base, job, PC_GAINEXP_REASON_SCRIPT);
-
-    return 0;
-}
-
-/*==========================================
- * モンスター発生
- *------------------------------------------
- */
-int buildin_monster (struct script_state *st)
-{
-    int  mob_class, amount, x, y;
-    char *str, *map, *event = "";
-
-    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
-    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
-    if (st->end > st->start + 8)
-        event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
-
-    mob_once_spawn (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
-                    event);
-    return 0;
-}
-
-/*==========================================
- * モンスター発生
- *------------------------------------------
- */
-int buildin_areamonster (struct script_state *st)
-{
-    int  mob_class, amount, x0, y0, x1, y1;
-    char *str, *map, *event = "";
-
-    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
-    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 8]));
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 9]));
-    if (st->end > st->start + 10)
-        event = conv_str (st, &(st->stack->stack_data[st->start + 10]));
-
-    mob_once_spawn_area (map_id2sd (st->rid), map, x0, y0, x1, y1, str, mob_class,
-                         amount, event);
-    return 0;
-}
-
-/*==========================================
- * モンスター削除
- *------------------------------------------
- */
-int buildin_killmonster_sub (struct block_list *bl, va_list ap)
-{
-    char *event = va_arg (ap, char *);
-    int  allflag = va_arg (ap, int);
-
-    if (!allflag)
-    {
-        if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
-            mob_delete ((struct mob_data *) bl);
-        return 0;
-    }
-    else if (allflag)
-    {
-        if (((struct mob_data *) bl)->spawndelay1 == -1
-            && ((struct mob_data *) bl)->spawndelay2 == -1)
-            mob_delete ((struct mob_data *) bl);
-        return 0;
-    }
-    return 0;
-}
-
-int buildin_killmonster (struct script_state *st)
-{
-    char *mapname, *event;
-    int  m, allflag = 0;
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    if (strcmp (event, "All") == 0)
-        allflag = 1;
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-    map_foreachinarea (buildin_killmonster_sub,
-                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, allflag);
-    return 0;
-}
-
-int buildin_killmonsterall_sub (struct block_list *bl, va_list ap)
-{
-    mob_delete ((struct mob_data *) bl);
-    return 0;
-}
-
-int buildin_killmonsterall (struct script_state *st)
-{
-    char *mapname;
-    int  m;
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-    map_foreachinarea (buildin_killmonsterall_sub,
-                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB);
-    return 0;
-}
-
-/*==========================================
- * イベント実行
- *------------------------------------------
- */
-int buildin_doevent (struct script_state *st)
-{
-    char *event;
-    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_event (map_id2sd (st->rid), event, 0);
-    return 0;
-}
-
-/*==========================================
- * NPC主体イベント実行
- *------------------------------------------
- */
-int buildin_donpcevent (struct script_state *st)
-{
-    char *event;
-    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_event_do (event);
-    return 0;
-}
-
-/*==========================================
- * イベントタイマー追加
- *------------------------------------------
- */
-int buildin_addtimer (struct script_state *st)
-{
-    char *event;
-    int  tick;
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    pc_addeventtimer (script_rid2sd (st), tick, event);
-    return 0;
-}
-
-/*==========================================
- * イベントタイマー削除
- *------------------------------------------
- */
-int buildin_deltimer (struct script_state *st)
-{
-    char *event;
-    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    pc_deleventtimer (script_rid2sd (st), event);
-    return 0;
-}
-
-/*==========================================
- * イベントタイマーのカウント値追加
- *------------------------------------------
- */
-int buildin_addtimercount (struct script_state *st)
-{
-    char *event;
-    int  tick;
-    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    pc_addeventtimercount (script_rid2sd (st), event, tick);
-    return 0;
-}
-
-/*==========================================
- * NPCタイマー初期化
- *------------------------------------------
- */
-int buildin_initnpctimer (struct script_state *st)
-{
-    struct npc_data *nd;
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    npc_settimerevent_tick (nd, 0);
-    npc_timerevent_start (nd);
-    return 0;
-}
-
-/*==========================================
- * NPCタイマー開始
- *------------------------------------------
- */
-int buildin_startnpctimer (struct script_state *st)
-{
-    struct npc_data *nd;
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    npc_timerevent_start (nd);
-    return 0;
-}
-
-/*==========================================
- * NPCタイマー停止
- *------------------------------------------
- */
-int buildin_stopnpctimer (struct script_state *st)
-{
-    struct npc_data *nd;
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    npc_timerevent_stop (nd);
-    return 0;
-}
-
-/*==========================================
- * NPCタイマー情報所得
- *------------------------------------------
- */
-int buildin_getnpctimer (struct script_state *st)
-{
-    struct npc_data *nd;
-    int  type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  val = 0;
-    if (st->end > st->start + 3)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    switch (type)
-    {
-        case 0:
-            val = npc_gettimerevent_tick (nd);
-            break;
-        case 1:
-            val = (nd->u.scr.nexttimer >= 0);
-            break;
-        case 2:
-            val = nd->u.scr.timeramount;
-            break;
-    }
-    push_val (st->stack, C_INT, val);
-    return 0;
-}
-
-/*==========================================
- * NPCタイマー値設定
- *------------------------------------------
- */
-int buildin_setnpctimer (struct script_state *st)
-{
-    int  tick;
-    struct npc_data *nd;
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (st->end > st->start + 3)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    npc_settimerevent_tick (nd, tick);
-    return 0;
-}
-
-/*==========================================
- * 天の声アナウンス
- *------------------------------------------
- */
-int buildin_announce (struct script_state *st)
-{
-    char *str;
-    int  flag;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    flag = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    if (flag & 0x0f)
-    {
-        struct block_list *bl = (flag & 0x08) ? map_id2bl (st->oid) :
-            (struct block_list *) script_rid2sd (st);
-        clif_GMmessage (bl, str, strlen (str) + 1, flag);
-    }
-    else
-        intif_GMmessage (str, strlen (str) + 1, flag);
-    return 0;
-}
-
-/*==========================================
- * 天の声アナウンス(特定マップ)
- *------------------------------------------
- */
-int buildin_mapannounce_sub (struct block_list *bl, va_list ap)
-{
-    char *str;
-    int  len, flag;
-    str = va_arg (ap, char *);
-    len = va_arg (ap, int);
-    flag = va_arg (ap, int);
-    clif_GMmessage (bl, str, len, flag | 3);
-    return 0;
-}
-
-int buildin_mapannounce (struct script_state *st)
-{
-    char *mapname, *str;
-    int  flag, m;
-
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-    map_foreachinarea (buildin_mapannounce_sub,
-                       m, 0, 0, map[m].xs, map[m].ys, BL_PC, str,
-                       strlen (str) + 1, flag & 0x10);
-    return 0;
-}
-
-/*==========================================
- * 天の声アナウンス(特定エリア)
- *------------------------------------------
- */
-int buildin_areaannounce (struct script_state *st)
-{
-    char *map, *str;
-    int  flag, m;
-    int  x0, y0, x1, y1;
-
-    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
-    flag = conv_num (st, &(st->stack->stack_data[st->start + 8]));
-
-    if ((m = map_mapname2mapid (map)) < 0)
-        return 0;
-
-    map_foreachinarea (buildin_mapannounce_sub,
-                       m, x0, y0, x1, y1, BL_PC, str, strlen (str) + 1,
-                       flag & 0x10);
-    return 0;
-}
-
-/*==========================================
- * ユーザー数所得
- *------------------------------------------
- */
-int buildin_getusers (struct script_state *st)
-{
-    int  flag = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    struct block_list *bl = map_id2bl ((flag & 0x08) ? st->oid : st->rid);
-    int  val = 0;
-    switch (flag & 0x07)
-    {
-        case 0:
-            val = map[bl->m].users;
-            break;
-        case 1:
-            val = map_getusers ();
-            break;
-    }
-    push_val (st->stack, C_INT, val);
-    return 0;
-}
-
-/*==========================================
- * マップ指定ユーザー数所得
- *------------------------------------------
- */
-int buildin_getmapusers (struct script_state *st)
-{
-    char *str;
-    int  m;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    if ((m = map_mapname2mapid (str)) < 0)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-    push_val (st->stack, C_INT, map[m].users);
-    return 0;
-}
-
-/*==========================================
- * エリア指定ユーザー数所得
- *------------------------------------------
- */
-int buildin_getareausers_sub (struct block_list *bl, va_list ap)
-{
-    int *users = va_arg (ap, int *);
-    (*users)++;
-    return 0;
-}
-int buildin_getareausers_living_sub (struct block_list *bl, va_list ap)
-{
-    int *users = va_arg (ap, int *);
-    if (!pc_isdead((struct map_session_data *)bl))
-        (*users)++;
-    return 0;
-}
-
-int buildin_getareausers (struct script_state *st)
-{
-    char *str;
-    int  m, x0, y0, x1, y1, users = 0;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-
-    int living = 0;
-    if (st->end > st->start + 7)
-    {
-        living = conv_num (st, &(st->stack->stack_data[st->start + 7]));
-    }
-    if ((m = map_mapname2mapid (str)) < 0)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-    map_foreachinarea (living ? buildin_getareausers_living_sub: buildin_getareausers_sub,
-                       m, x0, y0, x1, y1, BL_PC, &users);
-    push_val (st->stack, C_INT, users);
-    return 0;
-}
-
-/*==========================================
- * エリア指定ドロップアイテム数所得
- *------------------------------------------
- */
-int buildin_getareadropitem_sub (struct block_list *bl, va_list ap)
-{
-    int  item = va_arg (ap, int);
-    int *amount = va_arg (ap, int *);
-    struct flooritem_data *drop = (struct flooritem_data *) bl;
-
-    if (drop->item_data.nameid == item)
-        (*amount) += drop->item_data.amount;
-
-    return 0;
-}
-
-int buildin_getareadropitem_sub_anddelete (struct block_list *bl, va_list ap)
-{
-    int  item = va_arg (ap, int);
-    int *amount = va_arg (ap, int *);
-    struct flooritem_data *drop = (struct flooritem_data *) bl;
-
-    if (drop->item_data.nameid == item) {
-        (*amount) += drop->item_data.amount;
-        clif_clearflooritem(drop, 0);
-        map_delobject(drop->bl.id, drop->bl.type);
-    }
-    return 0;
-}
-
-int buildin_getareadropitem (struct script_state *st)
-{
-    char *str;
-    int  m, x0, y0, x1, y1, item, amount = 0, delitems = 0;
-    struct script_data *data;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-
-    data = &(st->stack->stack_data[st->start + 7]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        struct item_data *item_data = itemdb_searchname (name);
-        item = 512;
-        if (item_data)
-            item = item_data->nameid;
-    }
-    else
-        item = conv_num (st, data);
-
-    if (st->end > st->start + 8)
-        delitems = conv_num (st, &(st->stack->stack_data[st->start + 8]));
-
-    if ((m = map_mapname2mapid (str)) < 0)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-    if (delitems)
-        map_foreachinarea (buildin_getareadropitem_sub_anddelete,
-                           m, x0, y0, x1, y1, BL_ITEM, item, &amount);
-    else
-        map_foreachinarea (buildin_getareadropitem_sub,
-                           m, x0, y0, x1, y1, BL_ITEM, item, &amount);
-
-    push_val (st->stack, C_INT, amount);
-    return 0;
-}
-
-/*==========================================
- * NPCの有効化
- *------------------------------------------
- */
-int buildin_enablenpc (struct script_state *st)
-{
-    char *str;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_enable (str, 1);
-    return 0;
-}
-
-/*==========================================
- * NPCの無効化
- *------------------------------------------
- */
-int buildin_disablenpc (struct script_state *st)
-{
-    char *str;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_enable (str, 0);
-    return 0;
-}
-
-int buildin_enablearena (struct script_state *st)   // Added by RoVeRT
-{
-    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
-    struct chat_data *cd;
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-        return 0;
-
-    npc_enable (nd->name, 1);
-    nd->arenaflag = 1;
-
-    if (cd->users >= cd->trigger && cd->npc_event[0])
-        npc_timer_event (cd->npc_event);
-
-    return 0;
-}
-
-int buildin_disablearena (struct script_state *st)  // Added by RoVeRT
-{
-    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
-    nd->arenaflag = 0;
-
-    return 0;
-}
-
-/*==========================================
- * 隠れているNPCの表示
- *------------------------------------------
- */
-int buildin_hideoffnpc (struct script_state *st)
-{
-    char *str;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_enable (str, 2);
-    return 0;
-}
-
-/*==========================================
- * NPCをハイディング
- *------------------------------------------
- */
-int buildin_hideonnpc (struct script_state *st)
-{
-    char *str;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    npc_enable (str, 4);
-    return 0;
-}
-
-/*==========================================
- * 状態異常にかかる
- *------------------------------------------
- */
-int buildin_sc_start (struct script_state *st)
-{
-    struct block_list *bl;
-    int  type, tick, val1;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    if (st->end > st->start + 5)    //指定したキャラを状態異常にする
-        bl = map_id2bl (conv_num
-                        (st, &(st->stack->stack_data[st->start + 5])));
-    else
-        bl = map_id2bl (st->rid);
-    if (bl->type == BL_PC
-        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
-        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
-    skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
-    return 0;
-}
-
-/*==========================================
- * 状態異常にかかる(確率指定)
- *------------------------------------------
- */
-int buildin_sc_start2 (struct script_state *st)
-{
-    struct block_list *bl;
-    int  type, tick, val1, per;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    per = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    if (st->end > st->start + 6)    //指定したキャラを状態異常にする
-        bl = map_id2bl (conv_num
-                        (st, &(st->stack->stack_data[st->start + 6])));
-    else
-        bl = map_id2bl (st->rid);
-    if (bl->type == BL_PC
-        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
-        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
-    if (MRAND (10000) < per)
-        skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
-    return 0;
-}
-
-/*==========================================
- * 状態異常が直る
- *------------------------------------------
- */
-int buildin_sc_end (struct script_state *st)
-{
-    struct block_list *bl;
-    int  type;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    bl = map_id2bl (st->rid);
-    if (bl->type == BL_PC
-        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
-        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
-    skill_status_change_end (bl, type, -1);
-//  if(battle_config.etc_log)
-//      printf("sc_end : %d %d\n",st->rid,type);
-    return 0;
-}
-
-int buildin_sc_check (struct script_state *st)
-{
-    struct block_list *bl;
-    int  type;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    bl = map_id2bl (st->rid);
-    if (bl->type == BL_PC
-        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
-        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
-
-    push_val (st->stack, C_INT, skill_status_change_active (bl, type));
-
-    return 0;
-}
-
-/*==========================================
- * 状態異常耐性を計算した確率を返す
- *------------------------------------------
- */
-int buildin_getscrate (struct script_state *st)
-{
-    struct block_list *bl;
-    int  sc_def = 100, sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2;
-    int  type, rate, luk;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    rate = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (st->end > st->start + 4)    //指定したキャラの耐性を計算する
-        bl = map_id2bl (conv_num
-                        (st, &(st->stack->stack_data[st->start + 6])));
-    else
-        bl = map_id2bl (st->rid);
-
-    luk = battle_get_luk (bl);
-    sc_def_mdef2 = 100 - (3 + battle_get_mdef (bl) + luk / 3);
-    sc_def_vit2 = 100 - (3 + battle_get_vit (bl) + luk / 3);
-    sc_def_int2 = 100 - (3 + battle_get_int (bl) + luk / 3);
-    sc_def_luk2 = 100 - (3 + luk);
-
-    if (type == SC_STONE || type == SC_FREEZE)
-        sc_def = sc_def_mdef2;
-    else if (type == SC_STAN || type == SC_POISON || type == SC_SILENCE)
-        sc_def = sc_def_vit2;
-    else if (type == SC_SLEEP || type == SC_CONFUSION || type == SC_BLIND)
-        sc_def = sc_def_int2;
-    else if (type == SC_CURSE)
-        sc_def = sc_def_luk2;
-
-    rate = rate * sc_def / 100;
-    push_val (st->stack, C_INT, rate);
-
-    return 0;
-
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_debugmes (struct script_state *st)
-{
-    conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    printf ("script debug : %d %d : %s\n", st->rid, st->oid,
-            st->stack->stack_data[st->start + 2].u.str);
-    return 0;
-}
-
-/*==========================================
- * Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes)
- *------------------------------------------
- */
-int buildin_resetlvl (struct script_state *st)
-{
-    struct map_session_data *sd;
-
-    int  type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    sd = script_rid2sd (st);
-    pc_resetlvl (sd, type);
-    return 0;
-}
-
-/*==========================================
- * ステータスリセット
- *------------------------------------------
- */
-int buildin_resetstatus (struct script_state *st)
-{
-    struct map_session_data *sd;
-    sd = script_rid2sd (st);
-    pc_resetstate (sd);
-    return 0;
-}
-
-/*==========================================
- * スキルリセット
- *------------------------------------------
- */
-int buildin_resetskill (struct script_state *st)
-{
-    struct map_session_data *sd;
-    sd = script_rid2sd (st);
-    pc_resetskill (sd);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int buildin_changebase (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    int  vclass;
-
-    if (st->end > st->start + 3)
-        sd = map_id2sd (conv_num
-                        (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        sd = script_rid2sd (st);
-
-    if (sd == NULL)
-        return 0;
-
-    vclass = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (vclass == 22 && !battle_config.wedding_modifydisplay)
-        return 0;
-
-//  if(vclass==22) {
-//      pc_unequipitem(sd,sd->equip_index[9],0);    // 装備外
-//  }
-
-    sd->view_class = vclass;
-
-    return 0;
-}
-
-/*==========================================
- * 性別変換
- *------------------------------------------
- */
-int buildin_changesex (struct script_state *st)
-{
-    struct map_session_data *sd = NULL;
-    sd = script_rid2sd (st);
-
-    if (sd->status.sex == 0)
-    {
-        sd->status.sex = 1;
-        sd->sex = 1;
-        if (sd->status.pc_class == 20 || sd->status.pc_class == 4021)
-            sd->status.pc_class -= 1;
-    }
-    else if (sd->status.sex == 1)
-    {
-        sd->status.sex = 0;
-        sd->sex = 0;
-        if (sd->status.pc_class == 19 || sd->status.pc_class == 4020)
-            sd->status.pc_class += 1;
-    }
-    chrif_char_ask_name (-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
-    chrif_save (sd);
-    return 0;
-}
-
-/*==========================================
- * npcチャット作成
- *------------------------------------------
- */
-int buildin_waitingroom (struct script_state *st)
-{
-    char *name, *ev = "";
-    int  limit, trigger = 0, pub = 1;
-    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    limit = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (limit == 0)
-        pub = 3;
-
-    if ((st->end > st->start + 5))
-    {
-        struct script_data *data = &(st->stack->stack_data[st->start + 5]);
-        get_val (st, data);
-        if (data->type == C_INT)
-        {
-            // 新Athena仕様(旧Athena仕様と互換性あり)
-            ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-            trigger = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-        }
-        else
-        {
-            // eathena仕様
-            trigger = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-            ev = conv_str (st, &(st->stack->stack_data[st->start + 5]));
-        }
-    }
-    else
-    {
-        // 旧Athena仕様
-        if (st->end > st->start + 4)
-            ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-    }
-    chat_createnpcchat ((struct npc_data *) map_id2bl (st->oid),
-                        limit, pub, trigger, name, strlen (name) + 1, ev);
-    return 0;
-}
-
-/*==========================================
- * npcチャット削除
- *------------------------------------------
- */
-int buildin_delwaitingroom (struct script_state *st)
-{
-    struct npc_data *nd;
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-    chat_deletenpcchat (nd);
-    return 0;
-}
-
-/*==========================================
- * npcチャット全員蹴り出す
- *------------------------------------------
- */
-int buildin_waitingroomkickall (struct script_state *st)
-{
-    struct npc_data *nd;
-    struct chat_data *cd;
-
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-        return 0;
-    chat_npckickall (cd);
-    return 0;
-}
-
-/*==========================================
- * npcチャットイベント有効化
- *------------------------------------------
- */
-int buildin_enablewaitingroomevent (struct script_state *st)
-{
-    struct npc_data *nd;
-    struct chat_data *cd;
-
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-        return 0;
-    chat_enableevent (cd);
-    return 0;
-}
-
-/*==========================================
- * npcチャットイベント無効化
- *------------------------------------------
- */
-int buildin_disablewaitingroomevent (struct script_state *st)
-{
-    struct npc_data *nd;
-    struct chat_data *cd;
-
-    if (st->end > st->start + 2)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 2])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-        return 0;
-    chat_disableevent (cd);
-    return 0;
-}
-
-/*==========================================
- * npcチャット状態所得
- *------------------------------------------
- */
-int buildin_getwaitingroomstate (struct script_state *st)
-{
-    struct npc_data *nd;
-    struct chat_data *cd;
-    int  val = 0, type;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (st->end > st->start + 3)
-        nd = npc_name2id (conv_str
-                          (st, &(st->stack->stack_data[st->start + 3])));
-    else
-        nd = (struct npc_data *) map_id2bl (st->oid);
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-
-    switch (type)
-    {
-        case 0:
-            val = cd->users;
-            break;
-        case 1:
-            val = cd->limit;
-            break;
-        case 2:
-            val = cd->trigger & 0x7f;
-            break;
-        case 3:
-            val = ((cd->trigger & 0x80) > 0);
-            break;
-        case 32:
-            val = (cd->users >= cd->limit);
-            break;
-        case 33:
-            val = (cd->users >= cd->trigger);
-            break;
-
-        case 4:
-            push_str (st->stack, C_CONSTSTR, cd->title);
-            return 0;
-        case 5:
-            push_str (st->stack, C_CONSTSTR, cd->pass);
-            return 0;
-        case 16:
-            push_str (st->stack, C_CONSTSTR, cd->npc_event);
-            return 0;
-    }
-    push_val (st->stack, C_INT, val);
-    return 0;
-}
-
-/*==========================================
- * チャットメンバー(規定人数)ワープ
- *------------------------------------------
- */
-int buildin_warpwaitingpc (struct script_state *st)
-{
-    int  x, y, i, n;
-    char *str;
-    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
-    struct chat_data *cd;
-
-    if (nd == NULL
-        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
-        return 0;
-
-    n = cd->trigger & 0x7f;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-
-    if (st->end > st->start + 5)
-        n = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-
-    for (i = 0; i < n; i++)
-    {
-        struct map_session_data *sd = cd->usersd[0];    // リスト先頭のPCを次々に。
-
-        mapreg_setreg (add_str ("$@warpwaitingpc") + (i << 24), sd->bl.id);
-
-        if (strcmp (str, "Random") == 0)
-            pc_randomwarp (sd, 3);
-        else if (strcmp (str, "SavePoint") == 0)
-        {
-            if (map[sd->bl.m].flag.noteleport)  // テレポ禁止
-                return 0;
-
-            pc_setpos (sd, sd->status.save_point.map,
-                       sd->status.save_point.x, sd->status.save_point.y, 3);
-        }
-        else
-            pc_setpos (sd, str, x, y, 0);
-    }
-    mapreg_setreg (add_str ("$@warpwaitingpcnum"), n);
-    return 0;
-}
-
-/*==========================================
- * RIDのアタッチ
- *------------------------------------------
- */
-int buildin_attachrid (struct script_state *st)
-{
-    st->rid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    push_val (st->stack, C_INT, (map_id2sd (st->rid) != NULL));
-    return 0;
-}
-
-/*==========================================
- * RIDのデタッチ
- *------------------------------------------
- */
-int buildin_detachrid (struct script_state *st)
-{
-    st->rid = 0;
-    return 0;
-}
-
-/*==========================================
- * 存在チェック
- *------------------------------------------
- */
-int buildin_isloggedin (struct script_state *st)
-{
-    push_val (st->stack, C_INT,
-              map_id2sd (conv_num
-                         (st,
-                          &(st->stack->stack_data[st->start + 2]))) != NULL);
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-enum
-{ MF_NOMEMO, MF_NOTELEPORT, MF_NOSAVE, MF_NOBRANCH, MF_NOPENALTY,
-    MF_NOZENYPENALTY, MF_PVP, MF_PVP_NOPARTY, MF_PVP_NOGUILD, MF_GVG,
-    MF_GVG_NOPARTY, MF_NOTRADE, MF_NOSKILL, MF_NOWARP, MF_NOPVP,
-    MF_NOICEWALL,
-    MF_SNOW, MF_FOG, MF_SAKURA, MF_LEAVES, MF_RAIN
-};
-
-int buildin_setmapflagnosave (struct script_state *st)
-{
-    int  m, x, y;
-    char *str, *str2;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    str2 = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    m = map_mapname2mapid (str);
-    if (m >= 0)
-    {
-        map[m].flag.nosave = 1;
-        memcpy (map[m].save.map, str2, 16);
-        map[m].save.x = x;
-        map[m].save.y = y;
-    }
-
-    return 0;
-}
-
-int buildin_setmapflag (struct script_state *st)
-{
-    int  m, i;
-    char *str;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    m = map_mapname2mapid (str);
-    if (m >= 0)
-    {
-        switch (i)
-        {
-            case MF_NOMEMO:
-                map[m].flag.nomemo = 1;
-                break;
-            case MF_NOTELEPORT:
-                map[m].flag.noteleport = 1;
-                break;
-            case MF_NOBRANCH:
-                map[m].flag.nobranch = 1;
-                break;
-            case MF_NOPENALTY:
-                map[m].flag.nopenalty = 1;
-                break;
-            case MF_PVP_NOPARTY:
-                map[m].flag.pvp_noparty = 1;
-                break;
-            case MF_PVP_NOGUILD:
-                map[m].flag.pvp_noguild = 1;
-                break;
-            case MF_GVG_NOPARTY:
-                map[m].flag.gvg_noparty = 1;
-                break;
-            case MF_NOZENYPENALTY:
-                map[m].flag.nozenypenalty = 1;
-                break;
-            case MF_NOTRADE:
-                map[m].flag.notrade = 1;
-                break;
-            case MF_NOSKILL:
-                map[m].flag.noskill = 1;
-                break;
-            case MF_NOWARP:
-                map[m].flag.nowarp = 1;
-                break;
-            case MF_NOPVP:
-                map[m].flag.nopvp = 1;
-                break;
-            case MF_NOICEWALL: // [Valaris]
-                map[m].flag.noicewall = 1;
-                break;
-            case MF_SNOW:      // [Valaris]
-                map[m].flag.snow = 1;
-                break;
-            case MF_FOG:       // [Valaris]
-                map[m].flag.fog = 1;
-                break;
-            case MF_SAKURA:    // [Valaris]
-                map[m].flag.sakura = 1;
-                break;
-            case MF_LEAVES:    // [Valaris]
-                map[m].flag.leaves = 1;
-                break;
-            case MF_RAIN:      // [Valaris]
-                map[m].flag.rain = 1;
-                break;
-        }
-    }
-
-    return 0;
-}
-
-int buildin_removemapflag (struct script_state *st)
-{
-    int  m, i;
-    char *str;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    m = map_mapname2mapid (str);
-    if (m >= 0)
-    {
-        switch (i)
-        {
-            case MF_NOMEMO:
-                map[m].flag.nomemo = 0;
-                break;
-            case MF_NOTELEPORT:
-                map[m].flag.noteleport = 0;
-                break;
-            case MF_NOSAVE:
-                map[m].flag.nosave = 0;
-                break;
-            case MF_NOBRANCH:
-                map[m].flag.nobranch = 0;
-                break;
-            case MF_NOPENALTY:
-                map[m].flag.nopenalty = 0;
-                break;
-            case MF_PVP_NOPARTY:
-                map[m].flag.pvp_noparty = 0;
-                break;
-            case MF_PVP_NOGUILD:
-                map[m].flag.pvp_noguild = 0;
-                break;
-            case MF_GVG_NOPARTY:
-                map[m].flag.gvg_noparty = 0;
-                break;
-            case MF_NOZENYPENALTY:
-                map[m].flag.nozenypenalty = 0;
-                break;
-            case MF_NOSKILL:
-                map[m].flag.noskill = 0;
-                break;
-            case MF_NOWARP:
-                map[m].flag.nowarp = 0;
-                break;
-            case MF_NOPVP:
-                map[m].flag.nopvp = 0;
-                break;
-            case MF_NOICEWALL: // [Valaris]
-                map[m].flag.noicewall = 0;
-                break;
-            case MF_SNOW:      // [Valaris]
-                map[m].flag.snow = 0;
-                break;
-            case MF_FOG:       // [Valaris]
-                map[m].flag.fog = 0;
-                break;
-            case MF_SAKURA:    // [Valaris]
-                map[m].flag.sakura = 0;
-                break;
-            case MF_LEAVES:    // [Valaris]
-                map[m].flag.leaves = 0;
-                break;
-            case MF_RAIN:      // [Valaris]
-                map[m].flag.rain = 0;
-                break;
-
-        }
-    }
-
-    return 0;
-}
-
-int buildin_pvpon (struct script_state *st)
-{
-    int  m, i;
-    char *str;
-    struct map_session_data *pl_sd = NULL;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    m = map_mapname2mapid (str);
-    if (m >= 0 && !map[m].flag.pvp && !map[m].flag.nopvp)
-    {
-        map[m].flag.pvp = 1;
-        clif_send0199 (m, 1);
-
-        if (battle_config.pk_mode)  // disable ranking functions if pk_mode is on [Valaris]
-            return 0;
-
-        for (i = 0; i < fd_max; i++)
-        {                       //人数分ループ
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                if (m == pl_sd->bl.m && pl_sd->pvp_timer == -1)
-                {
-                    pl_sd->pvp_timer =
-                        add_timer (gettick () + 200, pc_calc_pvprank_timer,
-                                   pl_sd->bl.id, 0);
-                    pl_sd->pvp_rank = 0;
-                    pl_sd->pvp_lastusers = 0;
-                    pl_sd->pvp_point = 5;
-                }
-            }
-        }
-    }
-
-    return 0;
-}
-
-int buildin_pvpoff (struct script_state *st)
-{
-    int  m, i;
-    char *str;
-    struct map_session_data *pl_sd = NULL;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    m = map_mapname2mapid (str);
-    if (m >= 0 && map[m].flag.pvp && map[m].flag.nopvp)
-    {
-        map[m].flag.pvp = 0;
-        clif_send0199 (m, 0);
-
-        if (battle_config.pk_mode)  // disable ranking options if pk_mode is on [Valaris]
-            return 0;
-
-        for (i = 0; i < fd_max; i++)
-        {                       //人数分ループ
-            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
-                && pl_sd->state.auth)
-            {
-                if (m == pl_sd->bl.m)
-                {
-                    clif_pvpset (pl_sd, 0, 0, 2);
-                    if (pl_sd->pvp_timer != -1)
-                    {
-                        delete_timer (pl_sd->pvp_timer,
-                                      pc_calc_pvprank_timer);
-                        pl_sd->pvp_timer = -1;
-                    }
-                }
-            }
-        }
-    }
-
-    return 0;
-}
-
-int buildin_gvgon (struct script_state *st)
-{
-    int  m;
-    char *str;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    m = map_mapname2mapid (str);
-    if (m >= 0 && !map[m].flag.gvg)
-    {
-        map[m].flag.gvg = 1;
-        clif_send0199 (m, 3);
-    }
-
-    return 0;
-}
-
-int buildin_gvgoff (struct script_state *st)
-{
-    int  m;
-    char *str;
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    m = map_mapname2mapid (str);
-    if (m >= 0 && map[m].flag.gvg)
-    {
-        map[m].flag.gvg = 0;
-        clif_send0199 (m, 0);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *	NPCエモーション
- *------------------------------------------
- */
-
-int buildin_emotion (struct script_state *st)
-{
-    int  type;
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    if (type < 0 || type > 100)
-        return 0;
-    clif_emotion (map_id2bl (st->oid), type);
-    return 0;
-}
-
-int buildin_maprespawnguildid_sub (struct block_list *bl, va_list ap)
-{
-    int  g_id = va_arg (ap, int);
-    int  flag = va_arg (ap, int);
-    struct map_session_data *sd = NULL;
-    struct mob_data *md = NULL;
-
-    if (bl->type == BL_PC)
-        sd = (struct map_session_data *) bl;
-    if (bl->type == BL_MOB)
-        md = (struct mob_data *) bl;
-
-    if (sd)
-    {
-        if ((sd->status.guild_id == g_id) && (flag & 1))
-            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
-                       sd->status.save_point.y, 3);
-        else if ((sd->status.guild_id != g_id) && (flag & 2))
-            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
-                       sd->status.save_point.y, 3);
-        else if (sd->status.guild_id == 0)  // Warp out players not in guild [Valaris]
-            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3); // end addition [Valaris]
-    }
-    if (md && flag & 4)
-    {
-        if (md->mob_class < 1285 || md->mob_class > 1288)
-            mob_delete (md);
-    }
-    return 0;
-}
-
-int buildin_maprespawnguildid (struct script_state *st)
-{
-    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    int  g_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    int  flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-
-    int  m = map_mapname2mapid (mapname);
-
-    if (m)
-        map_foreachinarea (buildin_maprespawnguildid_sub, m, 0, 0,
-                           map[m].xs - 1, map[m].ys - 1, BL_NUL, g_id, flag);
-    return 0;
-}
-
-int buildin_agitstart (struct script_state *st)
-{
-    if (agit_flag == 1)
-        return 1;               // Agit already Start.
-    agit_flag = 1;
-    guild_agit_start ();
-    return 0;
-}
-
-int buildin_agitend (struct script_state *st)
-{
-    if (agit_flag == 0)
-        return 1;               // Agit already End.
-    agit_flag = 0;
-    guild_agit_end ();
-    return 0;
-}
-
-/*==========================================
- * agitcheck 1;    // choice script
- * if(@agit_flag == 1) goto agit;
- * if(agitcheck(0) == 1) goto agit;
- *------------------------------------------
- */
-int buildin_agitcheck (struct script_state *st)
-{
-    struct map_session_data *sd;
-    int  cond;
-
-    sd = script_rid2sd (st);
-    cond = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    if (cond == 0)
-    {
-        if (agit_flag == 1)
-            push_val (st->stack, C_INT, 1);
-        if (agit_flag == 0)
-            push_val (st->stack, C_INT, 0);
-    }
-    else
-    {
-        if (agit_flag == 1)
-            pc_setreg (sd, add_str ("@agit_flag"), 1);
-        if (agit_flag == 0)
-            pc_setreg (sd, add_str ("@agit_flag"), 0);
-    }
-    return 0;
-}
-
-int buildin_flagemblem (struct script_state *st)
-{
-    int  g_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    if (g_id < 0)
-        return 0;
-
-//  printf("Script.c: [FlagEmblem] GuildID=%d, Emblem=%d.\n", g->guild_id, g->emblem_id);
-    ((struct npc_data *) map_id2bl (st->oid))->u.scr.guild_id = g_id;
-    return 1;
-}
-
-int buildin_getcastlename (struct script_state *st)
-{
-    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    struct guild_castle *gc;
-    int  i;
-    char *buf = NULL;
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        if ((gc = guild_castle_search (i)) != NULL)
-        {
-            if (strcmp (mapname, gc->map_name) == 0)
-            {
-                buf = (char *) calloc (24, 1);
-                strncpy (buf, gc->castle_name, 23);
-                break;
-            }
-        }
-    }
-    if (buf)
-        push_str (st->stack, C_STR, buf);
-    else
-        push_str (st->stack, C_CONSTSTR, "");
-    return 0;
-}
-
-int buildin_getcastledata (struct script_state *st)
-{
-    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    int  index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    char *event = NULL;
-    struct guild_castle *gc;
-    int  i, j;
-
-    if (st->end > st->start + 4 && index == 0)
-    {
-        for (i = 0, j = -1; i < MAX_GUILDCASTLE; i++)
-            if ((gc = guild_castle_search (i)) != NULL &&
-                strcmp (mapname, gc->map_name) == 0)
-                j = i;
-        if (j >= 0)
-        {
-            event = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-            guild_addcastleinfoevent (j, 17, event);
-        }
-    }
-
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        if ((gc = guild_castle_search (i)) != NULL)
-        {
-            if (strcmp (mapname, gc->map_name) == 0)
-            {
-                switch (index)
-                {
-                    case 0:
-                        for (j = 1; j < 26; j++)
-                            guild_castledataload (gc->castle_id, j);
-                        break;  // Initialize[AgitInit]
-                    case 1:
-                        push_val (st->stack, C_INT, gc->guild_id);
-                        break;
-                    case 2:
-                        push_val (st->stack, C_INT, gc->economy);
-                        break;
-                    case 3:
-                        push_val (st->stack, C_INT, gc->defense);
-                        break;
-                    case 4:
-                        push_val (st->stack, C_INT, gc->triggerE);
-                        break;
-                    case 5:
-                        push_val (st->stack, C_INT, gc->triggerD);
-                        break;
-                    case 6:
-                        push_val (st->stack, C_INT, gc->nextTime);
-                        break;
-                    case 7:
-                        push_val (st->stack, C_INT, gc->payTime);
-                        break;
-                    case 8:
-                        push_val (st->stack, C_INT, gc->createTime);
-                        break;
-                    case 9:
-                        push_val (st->stack, C_INT, gc->visibleC);
-                        break;
-                    case 10:
-                        push_val (st->stack, C_INT, gc->visibleG0);
-                        break;
-                    case 11:
-                        push_val (st->stack, C_INT, gc->visibleG1);
-                        break;
-                    case 12:
-                        push_val (st->stack, C_INT, gc->visibleG2);
-                        break;
-                    case 13:
-                        push_val (st->stack, C_INT, gc->visibleG3);
-                        break;
-                    case 14:
-                        push_val (st->stack, C_INT, gc->visibleG4);
-                        break;
-                    case 15:
-                        push_val (st->stack, C_INT, gc->visibleG5);
-                        break;
-                    case 16:
-                        push_val (st->stack, C_INT, gc->visibleG6);
-                        break;
-                    case 17:
-                        push_val (st->stack, C_INT, gc->visibleG7);
-                        break;
-                    case 18:
-                        push_val (st->stack, C_INT, gc->Ghp0);
-                        break;
-                    case 19:
-                        push_val (st->stack, C_INT, gc->Ghp1);
-                        break;
-                    case 20:
-                        push_val (st->stack, C_INT, gc->Ghp2);
-                        break;
-                    case 21:
-                        push_val (st->stack, C_INT, gc->Ghp3);
-                        break;
-                    case 22:
-                        push_val (st->stack, C_INT, gc->Ghp4);
-                        break;
-                    case 23:
-                        push_val (st->stack, C_INT, gc->Ghp5);
-                        break;
-                    case 24:
-                        push_val (st->stack, C_INT, gc->Ghp6);
-                        break;
-                    case 25:
-                        push_val (st->stack, C_INT, gc->Ghp7);
-                        break;
-                    default:
-                        push_val (st->stack, C_INT, 0);
-                        break;
-                }
-                return 0;
-            }
-        }
-    }
-    push_val (st->stack, C_INT, 0);
-    return 0;
-}
-
-int buildin_setcastledata (struct script_state *st)
-{
-    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    int  index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    int  value = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    struct guild_castle *gc;
-    int  i;
-
-    for (i = 0; i < MAX_GUILDCASTLE; i++)
-    {
-        if ((gc = guild_castle_search (i)) != NULL)
-        {
-            if (strcmp (mapname, gc->map_name) == 0)
-            {
-                // Save Data byself First
-                switch (index)
-                {
-                    case 1:
-                        gc->guild_id = value;
-                        break;
-                    case 2:
-                        gc->economy = value;
-                        break;
-                    case 3:
-                        gc->defense = value;
-                        break;
-                    case 4:
-                        gc->triggerE = value;
-                        break;
-                    case 5:
-                        gc->triggerD = value;
-                        break;
-                    case 6:
-                        gc->nextTime = value;
-                        break;
-                    case 7:
-                        gc->payTime = value;
-                        break;
-                    case 8:
-                        gc->createTime = value;
-                        break;
-                    case 9:
-                        gc->visibleC = value;
-                        break;
-                    case 10:
-                        gc->visibleG0 = value;
-                        break;
-                    case 11:
-                        gc->visibleG1 = value;
-                        break;
-                    case 12:
-                        gc->visibleG2 = value;
-                        break;
-                    case 13:
-                        gc->visibleG3 = value;
-                        break;
-                    case 14:
-                        gc->visibleG4 = value;
-                        break;
-                    case 15:
-                        gc->visibleG5 = value;
-                        break;
-                    case 16:
-                        gc->visibleG6 = value;
-                        break;
-                    case 17:
-                        gc->visibleG7 = value;
-                        break;
-                    case 18:
-                        gc->Ghp0 = value;
-                        break;
-                    case 19:
-                        gc->Ghp1 = value;
-                        break;
-                    case 20:
-                        gc->Ghp2 = value;
-                        break;
-                    case 21:
-                        gc->Ghp3 = value;
-                        break;
-                    case 22:
-                        gc->Ghp4 = value;
-                        break;
-                    case 23:
-                        gc->Ghp5 = value;
-                        break;
-                    case 24:
-                        gc->Ghp6 = value;
-                        break;
-                    case 25:
-                        gc->Ghp7 = value;
-                        break;
-                    default:
-                        return 0;
-                }
-                guild_castledatasave (gc->castle_id, index, value);
-                return 0;
-            }
-        }
-    }
-    return 0;
-}
-
-/* =====================================================================
- * ギルド情報を要求する
- * ---------------------------------------------------------------------
- */
-int buildin_requestguildinfo (struct script_state *st)
-{
-    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    char *event = NULL;
-
-    if (st->end > st->start + 3)
-        event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-
-    if (guild_id > 0)
-        guild_npc_request_info (guild_id, event);
-    return 0;
-}
-
-/* =====================================================================
- * カードの数を得る
- * ---------------------------------------------------------------------
- */
-int buildin_getequipcardcnt (struct script_state *st)
-{
-    int  i, num;
-    struct map_session_data *sd;
-    int  c = 4;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (sd->status.inventory[i].card[0] == 0x00ff)
-    {                           // 製造武器はカードなし
-        push_val (st->stack, C_INT, 0);
-        return 0;
-    }
-    do
-    {
-        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
-            (sd->status.inventory[i].card[c - 1] < 5000))
-        {
-
-            push_val (st->stack, C_INT, (c));
-            return 0;
-        }
-    }
-    while (c--);
-    push_val (st->stack, C_INT, 0);
-    return 0;
-}
-
-/* ================================================================
- * カード取り外し成功
- * ----------------------------------------------------------------
- */
-int buildin_successremovecards (struct script_state *st)
-{
-    int  i, num, cardflag = 0, flag;
-    struct map_session_data *sd;
-    struct item item_tmp;
-    int  c = 4;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (sd->status.inventory[i].card[0] == 0x00ff)
-    {                           // 製造武器は処理しない
-        return 0;
-    }
-    do
-    {
-        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
-            (sd->status.inventory[i].card[c - 1] < 5000))
-        {
-
-            cardflag = 1;
-            item_tmp.id = 0, item_tmp.nameid =
-                sd->status.inventory[i].card[c - 1];
-            item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine = 0;
-            item_tmp.attribute = 0;
-            item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
-                0, item_tmp.card[3] = 0;
-
-            if ((flag = pc_additem (sd, &item_tmp, 1)))
-            {                   // 持てないならドロップ
-                clif_additem (sd, 0, 0, flag);
-                map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
-                                  NULL, NULL, NULL, 0);
-            }
-        }
-    }
-    while (c--);
-
-    if (cardflag == 1)
-    {                           // カードを取り除いたアイテム所得
-        flag = 0;
-        item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
-        item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
-            sd->status.inventory[i].refine;
-        item_tmp.attribute = sd->status.inventory[i].attribute;
-        item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
-            0, item_tmp.card[3] = 0;
-        pc_delitem (sd, i, 1, 0);
-        if ((flag = pc_additem (sd, &item_tmp, 1)))
-        {                       // もてないならドロップ
-            clif_additem (sd, 0, 0, flag);
-            map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
-                              NULL, NULL, NULL, 0);
-        }
-        clif_misceffect (&sd->bl, 3);
-        return 0;
-    }
-    return 0;
-}
-
-/* ================================================================
- * カード取り外し失敗 slot,type
- * type=0: 両方損失、1:カード損失、2:武具損失、3:損失無し
- * ----------------------------------------------------------------
- */
-int buildin_failedremovecards (struct script_state *st)
-{
-    int  i, num, cardflag = 0, flag, typefail;
-    struct map_session_data *sd;
-    struct item item_tmp;
-    int  c = 4;
-
-    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    typefail = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    sd = script_rid2sd (st);
-    i = pc_checkequip (sd, equip[num - 1]);
-    if (sd->status.inventory[i].card[0] == 0x00ff)
-    {                           // 製造武器は処理しない
-        return 0;
-    }
-    do
-    {
-        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
-            (sd->status.inventory[i].card[c - 1] < 5000))
-        {
-
-            cardflag = 1;
-
-            if (typefail == 2)
-            {                   // 武具のみ損失なら、カードは受け取らせる
-                item_tmp.id = 0, item_tmp.nameid =
-                    sd->status.inventory[i].card[c - 1];
-                item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
-                    0;
-                item_tmp.attribute = 0;
-                item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
-                    0, item_tmp.card[3] = 0;
-                if ((flag = pc_additem (sd, &item_tmp, 1)))
-                {
-                    clif_additem (sd, 0, 0, flag);
-                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
-                                      sd->bl.y, NULL, NULL, NULL, 0);
-                }
-            }
-        }
-    }
-    while (c--);
-
-    if (cardflag == 1)
-    {
-
-        if (typefail == 0 || typefail == 2)
-        {                       // 武具損失
-            pc_delitem (sd, i, 1, 0);
-            clif_misceffect (&sd->bl, 2);
-            return 0;
-        }
-        if (typefail == 1)
-        {                       // カードのみ損失(武具を返す)
-            flag = 0;
-            item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
-            item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
-                sd->status.inventory[i].refine;
-            item_tmp.attribute = sd->status.inventory[i].attribute;
-            item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
-                0, item_tmp.card[3] = 0;
-            pc_delitem (sd, i, 1, 0);
-            if ((flag = pc_additem (sd, &item_tmp, 1)))
-            {
-                clif_additem (sd, 0, 0, flag);
-                map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
-                                  NULL, NULL, NULL, 0);
-            }
-        }
-        clif_misceffect (&sd->bl, 2);
-        return 0;
-    }
-    return 0;
-}
-
-int buildin_mapwarp (struct script_state *st)   // Added by RoVeRT
-{
-    int  x, y, m;
-    char *str;
-    char *mapname;
-    int  x0, y0, x1, y1;
-
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = 0;
-    y0 = 0;
-    x1 = map[map_mapname2mapid (mapname)].xs;
-    y1 = map[map_mapname2mapid (mapname)].ys;
-    str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-
-    map_foreachinarea (buildin_areawarp_sub,
-                       m, x0, y0, x1, y1, BL_PC, str, x, y);
-    return 0;
-}
-
-int buildin_cmdothernpc (struct script_state *st)   // Added by RoVeRT
-{
-    char *npc, *command;
-
-    npc = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    command = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-
-    npc_command (map_id2sd (st->rid), npc, command);
-    return 0;
-}
-
-int buildin_inittimer (struct script_state *st) // Added by RoVeRT
-{
-//  struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
-
-//  nd->lastaction=nd->timer=gettick();
-    npc_do_ontimer (st->oid, map_id2sd (st->rid), 1);
-
-    return 0;
-}
-
-int buildin_stoptimer (struct script_state *st) // Added by RoVeRT
-{
-//  struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
-
-//  nd->lastaction=nd->timer=-1;
-    npc_do_ontimer (st->oid, map_id2sd (st->rid), 0);
-
-    return 0;
-}
-
-int buildin_mobcount_sub (struct block_list *bl, va_list ap)    // Added by RoVeRT
-{
-    char *event = va_arg (ap, char *);
-    int *c = va_arg (ap, int *);
-
-    if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
-        (*c)++;
-    return 0;
-}
-
-int buildin_mobcount (struct script_state *st)  // Added by RoVeRT
-{
-    char *mapname, *event;
-    int  m, c = 0;
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-    {
-        push_val (st->stack, C_INT, -1);
-        return 0;
-    }
-    map_foreachinarea (buildin_mobcount_sub,
-                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, &c);
-
-    push_val (st->stack, C_INT, (c - 1));
-
-    return 0;
-}
-
-int buildin_marriage (struct script_state *st)
-{
-    char *partner = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    struct map_session_data *sd = script_rid2sd (st);
-    struct map_session_data *p_sd = map_nick2sd (partner);
-
-    if (sd == NULL || p_sd == NULL || pc_marriage (sd, p_sd) < 0)
-    {
-        push_val (st->stack, C_INT, 0);
-        return 0;
-    }
-    push_val (st->stack, C_INT, 1);
-    return 0;
-}
-
-int buildin_wedding_effect (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    if (sd == NULL)
-        return 0;
-    clif_wedding_effect (&sd->bl);
-    return 0;
-}
-
-int buildin_divorce (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    st->state = STOP;           // rely on pc_divorce to restart
-
-    sd->npc_flags.divorce = 1;
-
-    if (sd == NULL || pc_divorce (sd) < 0)
-    {
-        push_val (st->stack, C_INT, 0);
-        return 0;
-    }
-
-    push_val (st->stack, C_INT, 1);
-    return 0;
-}
-
-/*================================================
- * Script for Displaying MOB Information [Valaris]
- *------------------------------------------------
- */
-int buildin_strmobinfo (struct script_state *st)
-{
-
-    int  num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  mob_class = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-
-    if (num <= 0 || num >= 8 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)
-        return 0;
-
-    if (num == 1)
-    {
-        char *buf;
-        buf = mob_db[mob_class].name;
-        push_str (st->stack, C_STR, buf);
-        return 0;
-    }
-    else if (num == 2)
-    {
-        char *buf;
-        buf = mob_db[mob_class].jname;
-        push_str (st->stack, C_STR, buf);
-        return 0;
-    }
-    else if (num == 3)
-        push_val (st->stack, C_INT, mob_db[mob_class].lv);
-    else if (num == 4)
-        push_val (st->stack, C_INT, mob_db[mob_class].max_hp);
-    else if (num == 5)
-        push_val (st->stack, C_INT, mob_db[mob_class].max_sp);
-    else if (num == 6)
-        push_val (st->stack, C_INT, mob_db[mob_class].base_exp);
-    else if (num == 7)
-        push_val (st->stack, C_INT, mob_db[mob_class].job_exp);
-    return 0;
-}
-
-/*==========================================
- * Summon guardians [Valaris]
- *------------------------------------------
- */
-int buildin_guardian (struct script_state *st)
-{
-    int  mob_class = 0, amount = 1, x = 0, y = 0, guardian = 0;
-    char *str, *map, *event = "";
-
-    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
-    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
-    event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
-    if (st->end > st->start + 9)
-        guardian = conv_num (st, &(st->stack->stack_data[st->start + 9]));
-
-    mob_spawn_guardian (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
-                        event, guardian);
-
-    return 0;
-}
-
-/*================================================
- * Script for Displaying Guardian Info [Valaris]
- *------------------------------------------------
- */
-int buildin_guardianinfo (struct script_state *st)
-{
-    int  guardian = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    struct map_session_data *sd = script_rid2sd (st);
-    struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
-
-    if (guardian == 0 && gc->visibleG0 == 1)
-        push_val (st->stack, C_INT, gc->Ghp0);
-    if (guardian == 1 && gc->visibleG1 == 1)
-        push_val (st->stack, C_INT, gc->Ghp1);
-    if (guardian == 2 && gc->visibleG2 == 1)
-        push_val (st->stack, C_INT, gc->Ghp2);
-    if (guardian == 3 && gc->visibleG3 == 1)
-        push_val (st->stack, C_INT, gc->Ghp3);
-    if (guardian == 4 && gc->visibleG4 == 1)
-        push_val (st->stack, C_INT, gc->Ghp4);
-    if (guardian == 5 && gc->visibleG5 == 1)
-        push_val (st->stack, C_INT, gc->Ghp5);
-    if (guardian == 6 && gc->visibleG6 == 1)
-        push_val (st->stack, C_INT, gc->Ghp6);
-    if (guardian == 7 && gc->visibleG7 == 1)
-        push_val (st->stack, C_INT, gc->Ghp7);
-    else
-        push_val (st->stack, C_INT, -1);
-
-    return 0;
-}
-
-/*==========================================
- * IDからItem名
- *------------------------------------------
- */
-int buildin_getitemname (struct script_state *st)
-{
-    struct item_data *i_data;
-    char *item_name;
-    struct script_data *data;
-
-    data = &(st->stack->stack_data[st->start + 2]);
-    get_val (st, data);
-    if (data->type == C_STR || data->type == C_CONSTSTR)
-    {
-        const char *name = conv_str (st, data);
-        i_data = itemdb_searchname (name);
-    }
-    else
-    {
-        int  item_id = conv_num (st, data);
-        i_data = itemdb_search (item_id);
-    }
-
-    item_name = (char *) calloc (24, 1);
-    if (i_data)
-        strncpy (item_name, i_data->jname, 23);
-    else
-        strncpy (item_name, "Unknown Item", 23);
-
-    push_str (st->stack, C_STR, item_name);
-
-    return 0;
-}
-
-int buildin_getspellinvocation (struct script_state *st)
-{
-    char *name;
-    char *invocation;
-
-    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    invocation = magic_find_invocation (name);
-    if (!invocation)
-        invocation = "...";
-
-    push_str (st->stack, C_STR, strdup (invocation));
-    return 0;
-}
-
-int buildin_getanchorinvocation (struct script_state *st)
-{
-    char *name;
-    char *invocation;
-
-    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    invocation = magic_find_anchor_invocation (name);
-    if (!invocation)
-        invocation = "...";
-
-    push_str (st->stack, C_STR, strdup (invocation));
-    return 0;
-}
-
-int buildin_getpartnerid (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    push_val (st->stack, C_INT, sd->status.partner_id);
-    return 0;
-}
-
-/*==========================================
- * PCの所持品情報読み取り
- *------------------------------------------
- */
-int buildin_getinventorylist (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i, j = 0;
-    if (!sd)
-        return 0;
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].nameid > 0
-            && sd->status.inventory[i].amount > 0)
-        {
-            pc_setreg (sd, add_str ("@inventorylist_id") + (j << 24),
-                       sd->status.inventory[i].nameid);
-            pc_setreg (sd, add_str ("@inventorylist_amount") + (j << 24),
-                       sd->status.inventory[i].amount);
-            pc_setreg (sd, add_str ("@inventorylist_equip") + (j << 24),
-                       sd->status.inventory[i].equip);
-            pc_setreg (sd, add_str ("@inventorylist_refine") + (j << 24),
-                       sd->status.inventory[i].refine);
-            pc_setreg (sd, add_str ("@inventorylist_identify") + (j << 24),
-                       sd->status.inventory[i].identify);
-            pc_setreg (sd, add_str ("@inventorylist_attribute") + (j << 24),
-                       sd->status.inventory[i].attribute);
-            pc_setreg (sd, add_str ("@inventorylist_card1") + (j << 24),
-                       sd->status.inventory[i].card[0]);
-            pc_setreg (sd, add_str ("@inventorylist_card2") + (j << 24),
-                       sd->status.inventory[i].card[1]);
-            pc_setreg (sd, add_str ("@inventorylist_card3") + (j << 24),
-                       sd->status.inventory[i].card[2]);
-            pc_setreg (sd, add_str ("@inventorylist_card4") + (j << 24),
-                       sd->status.inventory[i].card[3]);
-            j++;
-        }
-    }
-    pc_setreg (sd, add_str ("@inventorylist_count"), j);
-    return 0;
-}
-
-int buildin_getskilllist (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i, j = 0;
-    if (!sd)
-        return 0;
-    for (i = 0; i < MAX_SKILL; i++)
-    {
-        if (sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0)
-        {
-            pc_setreg (sd, add_str ("@skilllist_id") + (j << 24),
-                       sd->status.skill[i].id);
-            pc_setreg (sd, add_str ("@skilllist_lv") + (j << 24),
-                       sd->status.skill[i].lv);
-            pc_setreg (sd, add_str ("@skilllist_flag") + (j << 24),
-                       sd->status.skill[i].flags);
-            j++;
-        }
-    }
-    pc_setreg (sd, add_str ("@skilllist_count"), j);
-    return 0;
-}
-
-int buildin_get_activated_pool_skills (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  pool_skills[MAX_SKILL_POOL];
-    int  skill_pool_size = skill_pool (sd, pool_skills);
-    int  i, count = 0;
-
-    if (!sd)
-        return 0;
-
-    for (i = 0; i < skill_pool_size; i++)
-    {
-        int  skill_id = pool_skills[i];
-
-        if (sd->status.skill[skill_id].id == skill_id)
-        {
-            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
-                       sd->status.skill[skill_id].id);
-            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
-                       sd->status.skill[skill_id].lv);
-            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
-                       sd->status.skill[skill_id].flags);
-            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
-                          skill_name (skill_id));
-            ++count;
-        }
-    }
-    pc_setreg (sd, add_str ("@skilllist_count"), count);
-
-    return 0;
-}
-
-extern int skill_pool_skills[];
-extern int skill_pool_skills_size;
-
-int buildin_get_unactivated_pool_skills (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i, count = 0;
-
-    if (!sd)
-        return 0;
-
-    for (i = 0; i < skill_pool_skills_size; i++)
-    {
-        int  skill_id = skill_pool_skills[i];
-
-        if (sd->status.skill[skill_id].id == skill_id && !(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
-        {
-            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
-                       sd->status.skill[skill_id].id);
-            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
-                       sd->status.skill[skill_id].lv);
-            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
-                       sd->status.skill[skill_id].flags);
-            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
-                          skill_name (skill_id));
-            ++count;
-        }
-    }
-    pc_setreg (sd, add_str ("@skilllist_count"), count);
-
-    return 0;
-}
-
-int buildin_get_pool_skills (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i, count = 0;
-
-    if (!sd)
-        return 0;
-
-    for (i = 0; i < skill_pool_skills_size; i++)
-    {
-        int  skill_id = skill_pool_skills[i];
-
-        if (sd->status.skill[skill_id].id == skill_id)
-        {
-            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
-                       sd->status.skill[skill_id].id);
-            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
-                       sd->status.skill[skill_id].lv);
-            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
-                       sd->status.skill[skill_id].flags);
-            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
-                          skill_name (skill_id));
-            ++count;
-        }
-    }
-    pc_setreg (sd, add_str ("@skilllist_count"), count);
-
-    return 0;
-}
-
-int buildin_activate_pool_skill (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    skill_pool_activate (sd, skill_id);
-    clif_skillinfoblock (sd);
-
-    return 0;
-}
-
-int buildin_deactivate_pool_skill (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    skill_pool_deactivate (sd, skill_id);
-    clif_skillinfoblock (sd);
-
-    return 0;
-}
-
-int buildin_check_pool_skill (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    push_val (st->stack, C_INT, skill_pool_is_activated (sd, skill_id));
-
-    return 0;
-}
-
-int buildin_clearitem (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i;
-    if (sd == NULL)
-        return 0;
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].amount)
-            pc_delitem (sd, i, sd->status.inventory[i].amount, 0);
-    }
-    return 0;
-}
-
-/*==========================================
- * NPCクラスチェンジ
- * classは変わりたいclass
- * typeは通常0なのかな?
- *------------------------------------------
- */
-int buildin_classchange (struct script_state *st)
-{
-    int  npc_class, type;
-    struct block_list *bl = map_id2bl (st->oid);
-
-    if (bl == NULL)
-        return 0;
-
-    npc_class = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    clif_npc_class_change (bl, npc_class, type);
-    return 0;
-}
-
-/*==========================================
- * NPCから発生するエフェクト
- * misceffect(effect, [target])
- *
- * effect The effect type/ID.
- * target The player name or being ID on
- *  which to display the effect. If not
- *  specified, it attempts to default to
- *  the current NPC or invoking PC.
- *------------------------------------------
- */
-int buildin_misceffect (struct script_state *st)
-{
-    int  type;
-    int  id = 0;
-    char *name = NULL;
-    struct block_list *bl = NULL;
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    if (st->end > st->start + 3)
-    {
-        struct script_data *sdata = &(st->stack->stack_data[st->start + 3]);
-
-        get_val (st, sdata);
-
-        if (sdata->type == C_STR || sdata->type == C_CONSTSTR)
-            name = conv_str (st, sdata);
-        else
-            id = conv_num (st, sdata);
-    }
-
-    if (name)
-    {
-        struct map_session_data *sd = map_nick2sd (name);
-        if (sd)
-            bl = &sd->bl;
-    }
-    else if (id)
-        bl = map_id2bl (id);
-    else if (st->oid)
-        bl = map_id2bl (st->oid);
-    else
-    {
-        struct map_session_data *sd = script_rid2sd (st);
-        if (sd)
-            bl = &sd->bl;
-    }
-
-    if (bl)
-        clif_misceffect (bl, type);
-
-    return 0;
-}
-
-/*==========================================
- * サウンドエフェクト
- *------------------------------------------
- */
-int buildin_soundeffect (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    char *name;
-    int  type = 0;
-
-    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    if (sd)
-    {
-        if (st->oid)
-            clif_soundeffect (sd, map_id2bl (st->oid), name, type);
-        else
-        {
-            clif_soundeffect (sd, &sd->bl, name, type);
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * NPC skill effects [Valaris]
- *------------------------------------------
- */
-int buildin_npcskilleffect (struct script_state *st)
-{
-    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
-
-    int  skillid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    int  skilllv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    int  x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    int  y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-
-    clif_skill_poseffect (&nd->bl, skillid, skilllv, x, y, gettick ());
-
-    return 0;
-}
-
-/*==========================================
- * Special effects [Valaris]
- *------------------------------------------
- */
-int buildin_specialeffect (struct script_state *st)
-{
-    struct block_list *bl = map_id2bl (st->oid);
-
-    if (bl == NULL)
-        return 0;
-
-    clif_specialeffect (bl,
-                        conv_num (st,
-                                  &(st->stack->stack_data[st->start + 2])),
-                        0);
-
-    return 0;
-}
-
-int buildin_specialeffect2 (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    if (sd == NULL)
-        return 0;
-
-    clif_specialeffect (&sd->bl,
-                        conv_num (st,
-                                  &(st->stack->stack_data[st->start + 2])),
-                        0);
-
-    return 0;
-}
-
-/*==========================================
- * Nude [Valaris]
- *------------------------------------------
- */
-
-int buildin_nude (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    int  i;
-
-    if (sd == NULL)
-        return 0;
-
-    for (i = 0; i < 11; i++)
-        if (sd->equip_index[i] >= 0)
-            pc_unequipitem (sd, sd->equip_index[i], i);
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * UnequipById [Freeyorp]
- *------------------------------------------
- */
-
-int buildin_unequip_by_id (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    if (sd == NULL)
-        return 0;
-
-    int  slot_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    if (slot_id >= 0 && slot_id < 11 && sd->equip_index[slot_id] >= 0)
-        pc_unequipitem (sd, sd->equip_index[slot_id], slot_id);
-
-    pc_calcstatus (sd, 0);
-
-    return 0;
-}
-
-/*==========================================
- * gmcommand [MouseJstr]
- *
- * suggested on the forums...
- *------------------------------------------
- */
-
-int buildin_gmcommand (struct script_state *st)
-{
-    struct map_session_data *sd;
-    char *cmd;
-
-    sd = script_rid2sd (st);
-    cmd = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    is_atcommand (sd->fd, sd, cmd, 99);
-
-    return 0;
-}
-
-/*==========================================
- * movenpc [MouseJstr]
- *------------------------------------------
- */
-
-int buildin_movenpc (struct script_state *st)
-{
-    struct map_session_data *sd;
-    char *map, *npc;
-    int  x, y;
-
-    sd = script_rid2sd (st);
-
-    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    npc = conv_str (st, &(st->stack->stack_data[st->start + 5]));
-
-    return 0;
-}
-
-/*==========================================
- * npcwarp [remoitnane]
- * Move NPC to a new position on the same map.
- *------------------------------------------
- */
-int buildin_npcwarp (struct script_state *st)
-{
-    int  x, y;
-    char *npc;
-    struct npc_data *nd = NULL;
-
-    x = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    y = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    npc = conv_str (st, &(st->stack->stack_data[st->start + 4]));
-    nd = npc_name2id (npc);
-
-    if (!nd)
-        return -1;
-
-    short m = nd->bl.m;
-
-    /* Crude sanity checks. */
-    if (m < 0 || !nd->bl.prev
-            || x < 0 || x > map[m].xs -1
-            || y < 0 || y > map[m].ys - 1)
-        return -1;
-
-    npc_enable (npc, 0);
-    map_delblock(&nd->bl); /* [Freeyorp] */
-    nd->bl.x = x;
-    nd->bl.y = y;
-    map_addblock(&nd->bl);
-    npc_enable (npc, 1);
-
-    return 0;
-}
-
-/*==========================================
- * message [MouseJstr]
- *------------------------------------------
- */
-
-int buildin_message (struct script_state *st)
-{
-    char *msg, *player;
-    struct map_session_data *pl_sd = NULL;
-
-    player = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    msg = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-
-    if ((pl_sd = map_nick2sd ((char *) player)) == NULL)
-        return 1;
-    clif_displaymessage (pl_sd->fd, msg);
-
-    return 0;
-}
-
-/*==========================================
- * npctalk (sends message to surrounding
- * area) [Valaris]
- *------------------------------------------
- */
-
-int buildin_npctalk (struct script_state *st)
-{
-    char *str;
-    char message[255];
-
-    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-
-    if (nd)
-    {
-        memcpy (message, nd->name, 24);
-        strcat (message, " : ");
-        strcat (message, str);
-        clif_message (&(nd->bl), message);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * hasitems (checks to see if player has any
- * items on them, if so will return a 1)
- * [Valaris]
- *------------------------------------------
- */
-
-int buildin_hasitems (struct script_state *st)
-{
-    int  i;
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    for (i = 0; i < MAX_INVENTORY; i++)
-    {
-        if (sd->status.inventory[i].amount)
-        {
-            push_val (st->stack, C_INT, 1);
-            return 0;
-        }
-    }
-
-    push_val (st->stack, C_INT, 0);
-
-    return 0;
-}
-
-/*==========================================
-  * getlook char info. getlook(arg)
-  *------------------------------------------
-  */
-int buildin_getlook (struct script_state *st)
-{
-    int  type, val;
-    struct map_session_data *sd;
-    sd = script_rid2sd (st);
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-    val = -1;
-    switch (type)
-    {
-        case LOOK_HAIR:        //1
-            val = sd->status.hair;
-            break;
-        case LOOK_WEAPON:      //2
-            val = sd->status.weapon;
-            break;
-        case LOOK_HEAD_BOTTOM: //3
-            val = sd->status.head_bottom;
-            break;
-        case LOOK_HEAD_TOP:    //4
-            val = sd->status.head_top;
-            break;
-        case LOOK_HEAD_MID:    //5
-            val = sd->status.head_mid;
-            break;
-        case LOOK_HAIR_COLOR:  //6
-            val = sd->status.hair_color;
-            break;
-        case LOOK_CLOTHES_COLOR:   //7
-            val = sd->status.clothes_color;
-            break;
-        case LOOK_SHIELD:      //8
-            val = sd->status.shield;
-            break;
-        case LOOK_SHOES:       //9
-            break;
-    }
-
-    push_val (st->stack, C_INT, val);
-    return 0;
-}
-
-/*==========================================
-  *     get char save point. argument: 0- map name, 1- x, 2- y
-  *------------------------------------------
-*/
-int buildin_getsavepoint (struct script_state *st)
-{
-    int  x, y, type;
-    char *mapname;
-    struct map_session_data *sd;
-
-    sd = script_rid2sd (st);
-
-    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
-
-    x = sd->status.save_point.x;
-    y = sd->status.save_point.y;
-    switch (type)
-    {
-        case 0:
-            mapname = (char*)calloc (24, 1);
-            strncpy (mapname, sd->status.save_point.map, 23);
-            push_str (st->stack, C_STR, mapname);
-            break;
-        case 1:
-            push_val (st->stack, C_INT, x);
-            break;
-        case 2:
-            push_val (st->stack, C_INT, y);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- *     areatimer
- *------------------------------------------
- */
-int buildin_areatimer_sub (struct block_list *bl, va_list ap)
-{
-    int  tick;
-    char *event;
-    tick = va_arg (ap, int);
-    event = va_arg (ap, char *);
-    pc_addeventtimer ((struct map_session_data *) bl, tick, event);
-    return 0;
-}
-
-int buildin_areatimer (struct script_state *st)
-{
-    int  tick, m;
-    char *event;
-    char *mapname;
-    int  x0, y0, x1, y1;
-
-    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-    tick = conv_num (st, &(st->stack->stack_data[st->start + 7]));
-    event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
-
-    if ((m = map_mapname2mapid (mapname)) < 0)
-        return 0;
-
-    map_foreachinarea (buildin_areatimer_sub,
-                       m, x0, y0, x1, y1, BL_PC, tick, event);
-    return 0;
-}
-
-/*==========================================
- * Check whether the PC is in the specified rectangle
- *------------------------------------------
- */
-int buildin_isin (struct script_state *st)
-{
-    int  x1, y1, x2, y2;
-    char *str;
-    struct map_session_data *sd = script_rid2sd (st);
-
-    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    x1 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
-    y1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    x2 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
-    y2 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
-
-    if (!sd)
-        return 1;
-
-    push_val (st->stack, C_INT,
-              (sd->bl.x >= x1 && sd->bl.x <= x2)
-              && (sd->bl.y >= y1 && sd->bl.y <= y2)
-              && (!strcmp (str, map[sd->bl.m].name)));
-
-    return 0;
-}
-
-// Trigger the shop on a (hopefully) nearby shop NPC
-int buildin_shop (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-    struct npc_data *nd;
-
-    if (!sd)
-        return 1;
-
-    nd = npc_name2id (conv_str (st, &(st->stack->stack_data[st->start + 2])));
-    if (!nd)
-        return 1;
-
-    buildin_close (st);
-    clif_npcbuysell (sd, nd->bl.id);
-    return 0;
-}
-
-/*==========================================
- * Check whether the PC is dead
- *------------------------------------------
- */
-int buildin_isdead (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    push_val (st->stack, C_INT, pc_isdead (sd));
-    return 0;
-}
-
-/*========================================
- * Changes a NPC name, and sprite
- *----------------------------------------
- */
-int buildin_fakenpcname (struct script_state *st)
-{
-    char *name, *newname;
-    int  newsprite;
-    struct npc_data *nd;
-
-    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
-    newname = conv_str (st, &(st->stack->stack_data[st->start + 3]));
-    newsprite = conv_num (st, &(st->stack->stack_data[st->start + 4]));
-    nd = npc_name2id (name);
-    if (!nd)
-        return 1;
-    strncpy (nd->name, newname, sizeof(nd->name)-1);
-    nd->name[sizeof(nd->name)-1] = '\0';
-    nd->npc_class = newsprite;
-
-    // Refresh this npc
-    npc_enable (name, 0);
-    npc_enable (name, 1);
-
-    return 0;
-}
-
-/*============================
- * Gets the PC's x pos
- *----------------------------
- */
-
-int buildin_getx (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    push_val (st->stack, C_INT, sd->bl.x);
-    return 0;
-}
-
-/*============================
- * Gets the PC's y pos
- *----------------------------
- */
-int buildin_gety (struct script_state *st)
-{
-    struct map_session_data *sd = script_rid2sd (st);
-
-    push_val (st->stack, C_INT, sd->bl.y);
-    return 0;
-}
-
-//
-// 実行部main
-//
-/*==========================================
- * コマンドの読み取り
- *------------------------------------------
- */
-static int unget_com_data = -1;
-int get_com (unsigned char *script, int *pos)
-{
-    int  i, j;
-    if (unget_com_data >= 0)
-    {
-        i = unget_com_data;
-        unget_com_data = -1;
-        return i;
-    }
-    if (script[*pos] >= 0x80)
-    {
-        return C_INT;
-    }
-    i = 0;
-    j = 0;
-    while (script[*pos] >= 0x40)
-    {
-        i = script[(*pos)++] << j;
-        j += 6;
-    }
-    return i + (script[(*pos)++] << j);
-}
-
-/*==========================================
- * コマンドのプッシュバック
- *------------------------------------------
- */
-void unget_com (int c)
-{
-    if (unget_com_data != -1)
-    {
-        if (battle_config.error_log)
-            printf ("unget_com can back only 1 data\n");
-    }
-    unget_com_data = c;
-}
-
-/*==========================================
- * 数値の所得
- *------------------------------------------
- */
-int get_num (unsigned char *script, int *pos)
-{
-    int  i, j;
-    i = 0;
-    j = 0;
-    while (script[*pos] >= 0xc0)
-    {
-        i += (script[(*pos)++] & 0x7f) << j;
-        j += 6;
-    }
-    return i + ((script[(*pos)++] & 0x7f) << j);
-}
-
-/*==========================================
- * スタックから値を取り出す
- *------------------------------------------
- */
-int pop_val (struct script_state *st)
-{
-    if (st->stack->sp <= 0)
-        return 0;
-    st->stack->sp--;
-    get_val (st, &(st->stack->stack_data[st->stack->sp]));
-    if (st->stack->stack_data[st->stack->sp].type == C_INT)
-        return st->stack->stack_data[st->stack->sp].u.num;
-    return 0;
-}
-
-#define isstr(c) ((c).type==C_STR || (c).type==C_CONSTSTR)
-
-/*==========================================
- * 加算演算子
- *------------------------------------------
- */
-void op_add (struct script_state *st)
-{
-    st->stack->sp--;
-    get_val (st, &(st->stack->stack_data[st->stack->sp]));
-    get_val (st, &(st->stack->stack_data[st->stack->sp - 1]));
-
-    if (isstr (st->stack->stack_data[st->stack->sp])
-        || isstr (st->stack->stack_data[st->stack->sp - 1]))
-    {
-        conv_str (st, &(st->stack->stack_data[st->stack->sp]));
-        conv_str (st, &(st->stack->stack_data[st->stack->sp - 1]));
-    }
-    if (st->stack->stack_data[st->stack->sp].type == C_INT)
-    {                           // ii
-        st->stack->stack_data[st->stack->sp - 1].u.num +=
-            st->stack->stack_data[st->stack->sp].u.num;
-    }
-    else
-    {                           // ssの予定
-        char *buf;
-        buf = (char *)
-            calloc (strlen (st->stack->stack_data[st->stack->sp - 1].u.str) +
-                    strlen (st->stack->stack_data[st->stack->sp].u.str) + 1,
-                    1);
-        strcpy (buf, st->stack->stack_data[st->stack->sp - 1].u.str);
-        strcat (buf, st->stack->stack_data[st->stack->sp].u.str);
-        if (st->stack->stack_data[st->stack->sp - 1].type == C_STR)
-            free (st->stack->stack_data[st->stack->sp - 1].u.str);
-        if (st->stack->stack_data[st->stack->sp].type == C_STR)
-            free (st->stack->stack_data[st->stack->sp].u.str);
-        st->stack->stack_data[st->stack->sp - 1].type = C_STR;
-        st->stack->stack_data[st->stack->sp - 1].u.str = buf;
-    }
-}
-
-/*==========================================
- * 二項演算子(文字列)
- *------------------------------------------
- */
-void op_2str (struct script_state *st, int op, int sp1, int sp2)
-{
-    char *s1 = st->stack->stack_data[sp1].u.str,
-        *s2 = st->stack->stack_data[sp2].u.str;
-    int  a = 0;
-
-    switch (op)
-    {
-        case C_EQ:
-            a = (strcmp (s1, s2) == 0);
-            break;
-        case C_NE:
-            a = (strcmp (s1, s2) != 0);
-            break;
-        case C_GT:
-            a = (strcmp (s1, s2) > 0);
-            break;
-        case C_GE:
-            a = (strcmp (s1, s2) >= 0);
-            break;
-        case C_LT:
-            a = (strcmp (s1, s2) < 0);
-            break;
-        case C_LE:
-            a = (strcmp (s1, s2) <= 0);
-            break;
-        default:
-            printf ("illegal string operater\n");
-            break;
-    }
-
-    push_val (st->stack, C_INT, a);
-
-    if (st->stack->stack_data[sp1].type == C_STR)
-        free (s1);
-    if (st->stack->stack_data[sp2].type == C_STR)
-        free (s2);
-}
-
-/*==========================================
- * 二項演算子(数値)
- *------------------------------------------
- */
-void op_2num (struct script_state *st, int op, int i1, int i2)
-{
-    switch (op)
-    {
-        case C_SUB:
-            i1 -= i2;
-            break;
-        case C_MUL:
-            i1 *= i2;
-            break;
-        case C_DIV:
-            i1 /= i2;
-            break;
-        case C_MOD:
-            i1 %= i2;
-            break;
-        case C_AND:
-            i1 &= i2;
-            break;
-        case C_OR:
-            i1 |= i2;
-            break;
-        case C_XOR:
-            i1 ^= i2;
-            break;
-        case C_LAND:
-            i1 = i1 && i2;
-            break;
-        case C_LOR:
-            i1 = i1 || i2;
-            break;
-        case C_EQ:
-            i1 = i1 == i2;
-            break;
-        case C_NE:
-            i1 = i1 != i2;
-            break;
-        case C_GT:
-            i1 = i1 > i2;
-            break;
-        case C_GE:
-            i1 = i1 >= i2;
-            break;
-        case C_LT:
-            i1 = i1 < i2;
-            break;
-        case C_LE:
-            i1 = i1 <= i2;
-            break;
-        case C_R_SHIFT:
-            i1 = i1 >> i2;
-            break;
-        case C_L_SHIFT:
-            i1 = i1 << i2;
-            break;
-    }
-    push_val (st->stack, C_INT, i1);
-}
-
-/*==========================================
- * 二項演算子
- *------------------------------------------
- */
-void op_2 (struct script_state *st, int op)
-{
-    int  i1, i2;
-    char *s1 = NULL, *s2 = NULL;
-
-    i2 = pop_val (st);
-    if (isstr (st->stack->stack_data[st->stack->sp]))
-        s2 = st->stack->stack_data[st->stack->sp].u.str;
-
-    i1 = pop_val (st);
-    if (isstr (st->stack->stack_data[st->stack->sp]))
-        s1 = st->stack->stack_data[st->stack->sp].u.str;
-
-    if (s1 != NULL && s2 != NULL)
-    {
-        // ss => op_2str
-        op_2str (st, op, st->stack->sp, st->stack->sp + 1);
-    }
-    else if (s1 == NULL && s2 == NULL)
-    {
-        // ii => op_2num
-        op_2num (st, op, i1, i2);
-    }
-    else
-    {
-        // si,is => error
-        printf ("script: op_2: int&str, str&int not allow.");
-        push_val (st->stack, C_INT, 0);
-    }
-}
-
-/*==========================================
- * 単項演算子
- *------------------------------------------
- */
-void op_1num (struct script_state *st, int op)
-{
-    int  i1;
-    i1 = pop_val (st);
-    switch (op)
-    {
-        case C_NEG:
-            i1 = -i1;
-            break;
-        case C_NOT:
-            i1 = ~i1;
-            break;
-        case C_LNOT:
-            i1 = !i1;
-            break;
-    }
-    push_val (st->stack, C_INT, i1);
-}
-
-/*==========================================
- * 関数の実行
- *------------------------------------------
- */
-int run_func (struct script_state *st)
-{
-    int  i, start_sp, end_sp, func;
-
-    end_sp = st->stack->sp;
-    for (i = end_sp - 1; i >= 0 && st->stack->stack_data[i].type != C_ARG;
-         i--);
-    if (i == 0)
-    {
-        if (battle_config.error_log)
-            printf ("function not found\n");
-//      st->stack->sp=0;
-        st->state = END;
-        return 0;
-    }
-    start_sp = i - 1;
-    st->start = i - 1;
-    st->end = end_sp;
-
-    func = st->stack->stack_data[st->start].u.num;
-    if (st->stack->stack_data[st->start].type != C_NAME
-        || str_data[func].type != C_FUNC)
-    {
-        printf ("run_func: not function and command! \n");
-//      st->stack->sp=0;
-        st->state = END;
-        return 0;
-    }
-#ifdef DEBUG_RUN
-    if (battle_config.etc_log)
-    {
-        printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
-                func, str_data[func].type);
-        printf ("stack dump :");
-        for (i = 0; i < end_sp; i++)
-        {
-            switch (st->stack->stack_data[i].type)
-            {
-                case C_INT:
-                    printf (" int(%d)", st->stack->stack_data[i].u.num);
-                    break;
-                case C_NAME:
-                    printf (" name(%s)",
-                            str_buf +
-                            str_data[st->stack->stack_data[i].u.num].str);
-                    break;
-                case C_ARG:
-                    printf (" arg");
-                    break;
-                case C_POS:
-                    printf (" pos(%d)", st->stack->stack_data[i].u.num);
-                    break;
-                default:
-                    printf (" %d,%d", st->stack->stack_data[i].type,
-                            st->stack->stack_data[i].u.num);
-            }
-        }
-        printf ("\n");
-    }
-#endif
-    if (str_data[func].func)
-    {
-        str_data[func].func (st);
-    }
-    else
-    {
-        if (battle_config.error_log)
-            printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
-                    func, str_data[func].type);
-        push_val (st->stack, C_INT, 0);
-    }
-
-    pop_stack (st->stack, start_sp, end_sp);
-
-    if (st->state == RETFUNC)
-    {
-        // ユーザー定義関数からの復帰
-        int  olddefsp = st->defsp;
-        int  i;
-
-        pop_stack (st->stack, st->defsp, start_sp); // 復帰に邪魔なスタック削除
-        if (st->defsp < 4
-            || st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
-        {
-            printf
-                ("script:run_func(return) return without callfunc or callsub!\n");
-            st->state = END;
-            return 0;
-        }
-        i = conv_num (st, &(st->stack->stack_data[st->defsp - 4])); // 引数の数所得
-        st->pos = conv_num (st, &(st->stack->stack_data[st->defsp - 1]));   // スクリプト位置の復元
-        st->script = (char *) conv_num (st, &(st->stack->stack_data[st->defsp - 2]));   // スクリプトを復元
-        st->defsp = conv_num (st, &(st->stack->stack_data[st->defsp - 3])); // 基準スタックポインタを復元
-
-        pop_stack (st->stack, olddefsp - 4 - i, olddefsp);  // 要らなくなったスタック(引数と復帰用データ)削除
-
-        st->state = GOTO;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スクリプトの実行メイン部分
- *------------------------------------------
- */
-int run_script_main (unsigned char *script, int pos, int rid, int oid,
-                     struct script_state *st, unsigned char *rootscript)
-{
-    int  c, rerun_pos;
-    int  cmdcount = script_config.check_cmdcount;
-    int  gotocount = script_config.check_gotocount;
-    struct script_stack *stack = st->stack;
-
-    st->defsp = stack->sp;
-    st->script = script;
-
-    rerun_pos = st->pos;
-    for (st->state = 0; st->state == 0;)
-    {
-        switch (c = get_com (script, &st->pos))
-        {
-            case C_EOL:
-                if (stack->sp != st->defsp)
-                {
-                    if (battle_config.error_log)
-                        printf ("stack.sp(%d) != default(%d)\n", stack->sp,
-                                st->defsp);
-                    stack->sp = st->defsp;
-                }
-                rerun_pos = st->pos;
-                break;
-            case C_INT:
-                push_val (stack, C_INT, get_num (script, &st->pos));
-                break;
-            case C_POS:
-            case C_NAME:
-                push_val (stack, c, (*(int *) (script + st->pos)) & 0xffffff);
-                st->pos += 3;
-                break;
-            case C_ARG:
-                push_val (stack, c, 0);
-                break;
-            case C_STR:
-                push_str (stack, C_CONSTSTR, script + st->pos);
-                while (script[st->pos++]);
-                break;
-            case C_FUNC:
-                run_func (st);
-                if (st->state == GOTO)
-                {
-                    rerun_pos = st->pos;
-                    script = st->script;
-                    st->state = 0;
-                    if (gotocount > 0 && (--gotocount) <= 0)
-                    {
-                        printf ("run_script: infinity loop !\n");
-                        st->state = END;
-                    }
-                }
-                break;
-
-            case C_ADD:
-                op_add (st);
-                break;
-
-            case C_SUB:
-            case C_MUL:
-            case C_DIV:
-            case C_MOD:
-            case C_EQ:
-            case C_NE:
-            case C_GT:
-            case C_GE:
-            case C_LT:
-            case C_LE:
-            case C_AND:
-            case C_OR:
-            case C_XOR:
-            case C_LAND:
-            case C_LOR:
-            case C_R_SHIFT:
-            case C_L_SHIFT:
-                op_2 (st, c);
-                break;
-
-            case C_NEG:
-            case C_NOT:
-            case C_LNOT:
-                op_1num (st, c);
-                break;
-
-            case C_NOP:
-                st->state = END;
-                break;
-
-            default:
-                if (battle_config.error_log)
-                    printf ("unknown command : %d @ %d\n", c, pos);
-                st->state = END;
-                break;
-        }
-        if (cmdcount > 0 && (--cmdcount) <= 0)
-        {
-            printf ("run_script: infinity loop !\n");
-            st->state = END;
-        }
-    }
-    switch (st->state)
-    {
-        case STOP:
-            break;
-        case END:
-        {
-            struct map_session_data *sd = map_id2sd (st->rid);
-            st->pos = -1;
-            if (sd && sd->npc_id == st->oid)
-                npc_event_dequeue (sd);
-        }
-            break;
-        case RERUNLINE:
-        {
-            st->pos = rerun_pos;
-        }
-            break;
-    }
-
-    if (st->state != END)
-    {
-        // 再開するためにスタック情報を保存
-        struct map_session_data *sd = map_id2sd (st->rid);
-        if (sd /* && sd->npc_stackbuf==NULL */ )
-        {
-            if (sd->npc_stackbuf)
-                free (sd->npc_stackbuf);
-            sd->npc_stackbuf = (char *)
-                calloc (sizeof (stack->stack_data[0]) * stack->sp_max, 1);
-            memcpy (sd->npc_stackbuf, stack->stack_data,
-                    sizeof (stack->stack_data[0]) * stack->sp_max);
-            sd->npc_stack = stack->sp;
-            sd->npc_stackmax = stack->sp_max;
-            sd->npc_script = script;
-            sd->npc_scriptroot = rootscript;
-        }
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スクリプトの実行
- *------------------------------------------
- */
-int run_script (unsigned char *script, int pos, int rid, int oid)
-{
-    return run_script_l (script, pos, rid, oid, 0, NULL);
-}
-
-int run_script_l (unsigned char *script, int pos, int rid, int oid,
-                  int args_nr, argrec_t * args)
-{
-    struct script_stack stack;
-    struct script_state st;
-    struct map_session_data *sd = map_id2sd (rid);
-    unsigned char *rootscript = script;
-    int  i;
-    if (script == NULL || pos < 0)
-        return -1;
-
-    if (sd && sd->npc_stackbuf && sd->npc_scriptroot == (char *) rootscript)
-    {
-        // 前回のスタックを復帰
-        script = sd->npc_script;
-        stack.sp = sd->npc_stack;
-        stack.sp_max = sd->npc_stackmax;
-        stack.stack_data = (struct script_data *)
-            calloc (stack.sp_max, sizeof (stack.stack_data[0]));
-        memcpy (stack.stack_data, sd->npc_stackbuf,
-                sizeof (stack.stack_data[0]) * stack.sp_max);
-        free (sd->npc_stackbuf);
-        sd->npc_stackbuf = NULL;
-    }
-    else
-    {
-        // スタック初期化
-        stack.sp = 0;
-        stack.sp_max = 64;
-        stack.stack_data = (struct script_data *)
-            calloc (stack.sp_max, sizeof (stack.stack_data[0]));
-    }
-    st.stack = &stack;
-    st.pos = pos;
-    st.rid = rid;
-    st.oid = oid;
-    for (i = 0; i < args_nr; i++)
-    {
-        if (args[i].name[strlen (args[i].name) - 1] == '$')
-            pc_setregstr (sd, add_str (args[i].name), args[i].v.s);
-        else
-            pc_setreg (sd, add_str (args[i].name), args[i].v.i);
-    }
-    run_script_main (script, pos, rid, oid, &st, rootscript);
-
-    free (stack.stack_data);
-    stack.stack_data = NULL;
-    return st.pos;
-}
-
-/*==========================================
- * マップ変数の変更
- *------------------------------------------
- */
-int mapreg_setreg (int num, int val)
-{
-    if (val != 0)
-        numdb_insert (mapreg_db, num, val);
-    else
-        numdb_erase (mapreg_db, num);
-
-    mapreg_dirty = 1;
-    return 0;
-}
-
-/*==========================================
- * 文字列型マップ変数の変更
- *------------------------------------------
- */
-int mapreg_setregstr (int num, const char *str)
-{
-    char *p;
-
-    if ((p = (char *)numdb_search (mapregstr_db, num)) != NULL)
-        free (p);
-
-    if (str == NULL || *str == 0)
-    {
-        numdb_erase (mapregstr_db, num);
-        mapreg_dirty = 1;
-        return 0;
-    }
-    p = (char *) calloc (strlen (str) + 1, 1);
-    strcpy (p, str);
-    numdb_insert (mapregstr_db, num, p);
-    mapreg_dirty = 1;
-    return 0;
-}
-
-/*==========================================
- * 永続的マップ変数の読み込み
- *------------------------------------------
- */
-static int script_load_mapreg (void)
-{
-    FILE *fp;
-    char line[1024];
-
-    if ((fp = fopen_ (mapreg_txt, "rt")) == NULL)
-        return -1;
-
-    while (fgets (line, sizeof (line), fp))
-    {
-        char buf1[256], buf2[1024], *p;
-        int  n, v, s, i;
-        if (sscanf (line, "%255[^,],%d\t%n", buf1, &i, &n) != 2 &&
-            (i = 0, sscanf (line, "%[^\t]\t%n", buf1, &n) != 1))
-            continue;
-        if (buf1[strlen (buf1) - 1] == '$')
-        {
-            if (sscanf (line + n, "%[^\n\r]", buf2) != 1)
-            {
-                printf ("%s: %s broken data !\n", mapreg_txt, buf1);
-                continue;
-            }
-            p = (char *) calloc (strlen (buf2) + 1, 1);
-            strcpy (p, buf2);
-            s = add_str (buf1);
-            numdb_insert (mapregstr_db, (i << 24) | s, p);
-        }
-        else
-        {
-            if (sscanf (line + n, "%d", &v) != 1)
-            {
-                printf ("%s: %s broken data !\n", mapreg_txt, buf1);
-                continue;
-            }
-            s = add_str (buf1);
-            numdb_insert (mapreg_db, (i << 24) | s, v);
-        }
-    }
-    fclose_ (fp);
-    mapreg_dirty = 0;
-    return 0;
-}
-
-/*==========================================
- * 永続的マップ変数の書き込み
- *------------------------------------------
- */
-static void script_save_mapreg_intsub (db_key_t key, db_val_t data, va_list ap)
-{
-    FILE *fp = va_arg (ap, FILE *);
-    int  num = key.i & 0x00ffffff, i = key.i >> 24;
-    char *name = str_buf + str_data[num].str;
-    if (name[1] != '@')
-    {
-        if (i == 0)
-            fprintf (fp, "%s\t%d\n", name, (int) data);
-        else
-            fprintf (fp, "%s,%d\t%d\n", name, i, (int) data);
-    }
-}
-
-static void script_save_mapreg_strsub (db_key_t key, db_val_t data, va_list ap)
-{
-    FILE *fp = va_arg (ap, FILE *);
-    int  num = key.i & 0x00ffffff, i = key.i >> 24;
-    char *name = str_buf + str_data[num].str;
-    if (name[1] != '@')
-    {
-        if (i == 0)
-            fprintf (fp, "%s\t%s\n", name, (char *) data);
-        else
-            fprintf (fp, "%s,%d\t%s\n", name, i, (char *) data);
-    }
-}
-
-static int script_save_mapreg (void)
-{
-    FILE *fp;
-    int  lock;
-
-    if ((fp = lock_fopen (mapreg_txt, &lock)) == NULL)
-        return -1;
-    numdb_foreach (mapreg_db, script_save_mapreg_intsub, fp);
-    numdb_foreach (mapregstr_db, script_save_mapreg_strsub, fp);
-    lock_fclose (fp, mapreg_txt, &lock);
-    mapreg_dirty = 0;
-    return 0;
-}
-
-static void script_autosave_mapreg (timer_id tid, tick_t tick, custom_id_t id,
-                                    custom_data_t data)
-{
-    if (mapreg_dirty)
-        script_save_mapreg ();
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static int set_posword (char *p)
-{
-    char *np, *str[15];
-    int  i = 0;
-    for (i = 0; i < 11; i++)
-    {
-        if ((np = strchr (p, ',')) != NULL)
-        {
-            str[i] = p;
-            *np = 0;
-            p = np + 1;
-        }
-        else
-        {
-            str[i] = p;
-            p += strlen (p);
-        }
-        if (str[i])
-            strcpy (pos[i], str[i]);
-    }
-    return 0;
-}
-
-int script_config_read (char *cfgName)
-{
-    int  i;
-    char line[1024], w1[1024], w2[1024];
-    FILE *fp;
-
-    script_config.warn_func_no_comma = 1;
-    script_config.warn_cmd_no_comma = 1;
-    script_config.warn_func_mismatch_paramnum = 1;
-    script_config.warn_cmd_mismatch_paramnum = 1;
-    script_config.check_cmdcount = 8192;
-    script_config.check_gotocount = 512;
-
-    fp = fopen_ (cfgName, "r");
-    if (fp == NULL)
-    {
-        printf ("file not found: %s\n", cfgName);
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        i = sscanf (line, "%[^:]: %[^\r\n]", w1, w2);
-        if (i != 2)
-            continue;
-        if (strcasecmp (w1, "refine_posword") == 0)
-        {
-            set_posword (w2);
-        }
-        if (strcasecmp (w1, "import") == 0)
-        {
-            script_config_read (w2);
-        }
-    }
-    fclose_ (fp);
-
-    return 0;
-}
-
-/*==========================================
- * 終了
- *------------------------------------------
- */
-
-static void mapregstr_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free (data);
-}
-
-static void userfunc_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    free ((char*)key.s);
-    free (data);
-}
-
-int do_final_script (void)
-{
-    if (mapreg_dirty >= 0)
-        script_save_mapreg ();
-    if (script_buf)
-        free (script_buf);
-
-    if (mapreg_db)
-        numdb_final (mapreg_db, NULL);
-    if (mapregstr_db)
-        strdb_final (mapregstr_db, mapregstr_db_final);
-    if (scriptlabel_db)
-        strdb_final (scriptlabel_db, NULL);
-    if (userfunc_db)
-        strdb_final (userfunc_db, userfunc_db_final);
-
-    if (str_data)
-        free (str_data);
-    if (str_buf)
-        free (str_buf);
-
-    return 0;
-}
-
-/*==========================================
- * 初期化
- *------------------------------------------
- */
-int do_init_script (void)
-{
-    mapreg_db = numdb_init ();
-    mapregstr_db = numdb_init ();
-    script_load_mapreg ();
-
-    add_timer_interval (gettick () + MAPREG_AUTOSAVE_INTERVAL,
-                        script_autosave_mapreg, 0, 0,
-                        MAPREG_AUTOSAVE_INTERVAL);
-
-    scriptlabel_db = strdb_init (50);
-    return 0;
-}
diff --git a/src/map/script.cpp b/src/map/script.cpp
new file mode 100644
index 0000000..9e851bb
--- /dev/null
+++ b/src/map/script.cpp
@@ -0,0 +1,8145 @@
+// $Id: script.c 148 2004-09-30 14:05:37Z MouseJstr $
+//#define DEBUG_FUNCIN
+//#define DEBUG_DISP
+//#define DEBUG_RUN
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef LCCWIN32
+#include <sys/time.h>
+#endif
+
+#include <time.h>
+#include <math.h>
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/lock.hpp"
+#include "../common/mt_rand.hpp"
+
+#include "atcommand.hpp"
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "../common/db.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "../common/lock.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define SCRIPT_BLOCK_SIZE 256
+enum
+{ LABEL_NEXTLINE = 1, LABEL_START };
+static unsigned char *script_buf;
+static int script_pos, script_size;
+
+char *str_buf;
+int  str_pos, str_size;
+static struct str_data_t
+{
+    int  type;
+    int  str;
+    int  backpatch;
+    int  label;
+    int  (*func) (struct script_state *);
+    int  val;
+    int  next;
+}   *str_data;
+int  str_num = LABEL_START, str_data_size;
+int  str_hash[16];
+
+static struct dbt *mapreg_db = NULL;
+static struct dbt *mapregstr_db = NULL;
+static int mapreg_dirty = -1;
+char mapreg_txt[256] = "save/mapreg.txt";
+#define MAPREG_AUTOSAVE_INTERVAL	(10*1000)
+
+static struct dbt *scriptlabel_db = NULL;
+static struct dbt *userfunc_db = NULL;
+
+struct dbt *script_get_label_db (void)
+{
+    return scriptlabel_db;
+}
+
+struct dbt *script_get_userfunc_db (void)
+{
+    if (!userfunc_db)
+        userfunc_db = strdb_init (50);
+    return userfunc_db;
+}
+
+static char pos[11][100] =
+    { "頭", "体", "左手", "右手", "ローブ", "靴", "アクセサリー1",
+    "アクセサリー2", "頭2", "頭3", "装着していない"
+};
+
+static struct Script_Config
+{
+    int  warn_func_no_comma;
+    int  warn_cmd_no_comma;
+    int  warn_func_mismatch_paramnum;
+    int  warn_cmd_mismatch_paramnum;
+    int  check_cmdcount;
+    int  check_gotocount;
+} script_config;
+static int parse_cmd_if = 0;
+static int parse_cmd;
+
+/*==========================================
+ * ローカルプロトタイプ宣言 (必要な物のみ)
+ *------------------------------------------
+ */
+unsigned char *parse_subexpr (unsigned char *, int);
+int  buildin_mes (struct script_state *st);
+int  buildin_goto (struct script_state *st);
+int  buildin_callsub (struct script_state *st);
+int  buildin_callfunc (struct script_state *st);
+int  buildin_return (struct script_state *st);
+int  buildin_getarg (struct script_state *st);
+int  buildin_next (struct script_state *st);
+int  buildin_close (struct script_state *st);
+int  buildin_close2 (struct script_state *st);
+int  buildin_menu (struct script_state *st);
+int  buildin_rand (struct script_state *st);
+int  buildin_pow (struct script_state *st);
+int  buildin_warp (struct script_state *st);
+int  buildin_isat (struct script_state *st);
+int  buildin_areawarp (struct script_state *st);
+int  buildin_heal (struct script_state *st);
+int  buildin_itemheal (struct script_state *st);
+int  buildin_percentheal (struct script_state *st);
+int  buildin_jobchange (struct script_state *st);
+int  buildin_input (struct script_state *st);
+int  buildin_setlook (struct script_state *st);
+int  buildin_set (struct script_state *st);
+int  buildin_setarray (struct script_state *st);
+int  buildin_cleararray (struct script_state *st);
+int  buildin_copyarray (struct script_state *st);
+int  buildin_getarraysize (struct script_state *st);
+int  buildin_deletearray (struct script_state *st);
+int  buildin_getelementofarray (struct script_state *st);
+int  buildin_if (struct script_state *st);
+int  buildin_getitem (struct script_state *st);
+int  buildin_getitem2 (struct script_state *st);
+int  buildin_makeitem (struct script_state *st);
+int  buildin_delitem (struct script_state *st);
+int  buildin_viewpoint (struct script_state *st);
+int  buildin_countitem (struct script_state *st);
+int  buildin_checkweight (struct script_state *st);
+int  buildin_readparam (struct script_state *st);
+int  buildin_getcharid (struct script_state *st);
+int  buildin_getpartyname (struct script_state *st);
+int  buildin_getpartymember (struct script_state *st);
+int  buildin_getguildname (struct script_state *st);
+int  buildin_getguildmaster (struct script_state *st);
+int  buildin_getguildmasterid (struct script_state *st);
+int  buildin_strcharinfo (struct script_state *st);
+int  buildin_getequipid (struct script_state *st);
+int  buildin_getequipname (struct script_state *st);
+int  buildin_getbrokenid (struct script_state *st); // [Valaris]
+int  buildin_repair (struct script_state *st);  // [Valaris]
+int  buildin_getequipisequiped (struct script_state *st);
+int  buildin_getequipisenableref (struct script_state *st);
+int  buildin_getequipisidentify (struct script_state *st);
+int  buildin_getequiprefinerycnt (struct script_state *st);
+int  buildin_getequipweaponlv (struct script_state *st);
+int  buildin_getequippercentrefinery (struct script_state *st);
+int  buildin_successrefitem (struct script_state *st);
+int  buildin_failedrefitem (struct script_state *st);
+int  buildin_cutin (struct script_state *st);
+int  buildin_cutincard (struct script_state *st);
+int  buildin_statusup (struct script_state *st);
+int  buildin_statusup2 (struct script_state *st);
+int  buildin_bonus (struct script_state *st);
+int  buildin_bonus2 (struct script_state *st);
+int  buildin_bonus3 (struct script_state *st);
+int  buildin_skill (struct script_state *st);
+int  buildin_setskill (struct script_state *st);
+int  buildin_guildskill (struct script_state *st);
+int  buildin_getskilllv (struct script_state *st);
+int  buildin_getgdskilllv (struct script_state *st);
+int  buildin_basicskillcheck (struct script_state *st);
+int  buildin_getgmlevel (struct script_state *st);
+int  buildin_end (struct script_state *st);
+int  buildin_getopt2 (struct script_state *st);
+int  buildin_setopt2 (struct script_state *st);
+int  buildin_checkoption (struct script_state *st);
+int  buildin_setoption (struct script_state *st);
+int  buildin_setcart (struct script_state *st);
+int  buildin_checkcart (struct script_state *st);   // check cart [Valaris]
+int  buildin_setfalcon (struct script_state *st);
+int  buildin_checkfalcon (struct script_state *st); // check falcon [Valaris]
+int  buildin_setriding (struct script_state *st);
+int  buildin_checkriding (struct script_state *st); // check for pecopeco [Valaris]
+int  buildin_savepoint (struct script_state *st);
+int  buildin_gettimetick (struct script_state *st);
+int  buildin_gettime (struct script_state *st);
+int  buildin_gettimestr (struct script_state *st);
+int  buildin_openstorage (struct script_state *st);
+int  buildin_guildopenstorage (struct script_state *st);
+int  buildin_itemskill (struct script_state *st);
+int  buildin_monster (struct script_state *st);
+int  buildin_areamonster (struct script_state *st);
+int  buildin_killmonster (struct script_state *st);
+int  buildin_killmonsterall (struct script_state *st);
+int  buildin_doevent (struct script_state *st);
+int  buildin_donpcevent (struct script_state *st);
+int  buildin_addtimer (struct script_state *st);
+int  buildin_deltimer (struct script_state *st);
+int  buildin_addtimercount (struct script_state *st);
+int  buildin_initnpctimer (struct script_state *st);
+int  buildin_stopnpctimer (struct script_state *st);
+int  buildin_startnpctimer (struct script_state *st);
+int  buildin_setnpctimer (struct script_state *st);
+int  buildin_getnpctimer (struct script_state *st);
+int  buildin_announce (struct script_state *st);
+int  buildin_mapannounce (struct script_state *st);
+int  buildin_areaannounce (struct script_state *st);
+int  buildin_getusers (struct script_state *st);
+int  buildin_getmapusers (struct script_state *st);
+int  buildin_getareausers (struct script_state *st);
+int  buildin_getareadropitem (struct script_state *st);
+int  buildin_enablenpc (struct script_state *st);
+int  buildin_disablenpc (struct script_state *st);
+int  buildin_enablearena (struct script_state *st); // Added by RoVeRT
+int  buildin_disablearena (struct script_state *st);    // Added by RoVeRT
+int  buildin_hideoffnpc (struct script_state *st);
+int  buildin_hideonnpc (struct script_state *st);
+int  buildin_sc_start (struct script_state *st);
+int  buildin_sc_start2 (struct script_state *st);
+int  buildin_sc_end (struct script_state *st);
+int  buildin_sc_check (struct script_state *st);    // [Fate]
+int  buildin_getscrate (struct script_state *st);
+int  buildin_debugmes (struct script_state *st);
+int  buildin_resetlvl (struct script_state *st);
+int  buildin_resetstatus (struct script_state *st);
+int  buildin_resetskill (struct script_state *st);
+int  buildin_changebase (struct script_state *st);
+int  buildin_changesex (struct script_state *st);
+int  buildin_waitingroom (struct script_state *st);
+int  buildin_delwaitingroom (struct script_state *st);
+int  buildin_enablewaitingroomevent (struct script_state *st);
+int  buildin_disablewaitingroomevent (struct script_state *st);
+int  buildin_getwaitingroomstate (struct script_state *st);
+int  buildin_warpwaitingpc (struct script_state *st);
+int  buildin_attachrid (struct script_state *st);
+int  buildin_detachrid (struct script_state *st);
+int  buildin_isloggedin (struct script_state *st);
+int  buildin_setmapflagnosave (struct script_state *st);
+int  buildin_setmapflag (struct script_state *st);
+int  buildin_removemapflag (struct script_state *st);
+int  buildin_pvpon (struct script_state *st);
+int  buildin_pvpoff (struct script_state *st);
+int  buildin_gvgon (struct script_state *st);
+int  buildin_gvgoff (struct script_state *st);
+int  buildin_emotion (struct script_state *st);
+int  buildin_maprespawnguildid (struct script_state *st);
+int  buildin_agitstart (struct script_state *st);   // <Agit>
+int  buildin_agitend (struct script_state *st);
+int  buildin_agitcheck (struct script_state *st);   // <Agitcheck>
+int  buildin_flagemblem (struct script_state *st);  // Flag Emblem
+int  buildin_getcastlename (struct script_state *st);
+int  buildin_getcastledata (struct script_state *st);
+int  buildin_setcastledata (struct script_state *st);
+int  buildin_requestguildinfo (struct script_state *st);
+int  buildin_getequipcardcnt (struct script_state *st);
+int  buildin_successremovecards (struct script_state *st);
+int  buildin_failedremovecards (struct script_state *st);
+int  buildin_marriage (struct script_state *st);
+int  buildin_wedding_effect (struct script_state *st);
+int  buildin_divorce (struct script_state *st);
+int  buildin_getitemname (struct script_state *st);
+int  buildin_getspellinvocation (struct script_state *st);  // [Fate]
+int  buildin_getanchorinvocation (struct script_state *st); // [Fate]
+int  buildin_getexp (struct script_state *st);
+int  buildin_getinventorylist (struct script_state *st);
+int  buildin_getskilllist (struct script_state *st);
+int  buildin_get_pool_skills (struct script_state *st); // [fate]
+int  buildin_get_activated_pool_skills (struct script_state *st);   // [fate]
+int  buildin_get_unactivated_pool_skills (struct script_state *st);   // [PO]
+int  buildin_activate_pool_skill (struct script_state *st); // [fate]
+int  buildin_deactivate_pool_skill (struct script_state *st);   // [fate]
+int  buildin_check_pool_skill (struct script_state *st);    // [fate]
+int  buildin_getskilllist (struct script_state *st);
+int  buildin_getskilllist (struct script_state *st);
+int  buildin_clearitem (struct script_state *st);
+int  buildin_classchange (struct script_state *st);
+int  buildin_misceffect (struct script_state *st);
+int  buildin_soundeffect (struct script_state *st);
+int  buildin_setcastledata (struct script_state *st);
+int  buildin_mapwarp (struct script_state *st);
+int  buildin_inittimer (struct script_state *st);
+int  buildin_stoptimer (struct script_state *st);
+int  buildin_cmdothernpc (struct script_state *st);
+int  buildin_mobcount (struct script_state *st);
+int  buildin_strmobinfo (struct script_state *st);  // Script for displaying mob info [Valaris]
+int  buildin_guardian (struct script_state *st);    // Script for displaying mob info [Valaris]
+int  buildin_guardianinfo (struct script_state *st);    // Script for displaying mob info [Valaris]
+int  buildin_npcskilleffect (struct script_state *st);  // skill effects for npcs [Valaris]
+int  buildin_specialeffect (struct script_state *st);   // special effect script [Valaris]
+int  buildin_specialeffect2 (struct script_state *st);  // special effect script [Valaris]
+int  buildin_nude (struct script_state *st);    // nude [Valaris]
+int  buildin_gmcommand (struct script_state *st);   // [MouseJstr]
+int  buildin_movenpc (struct script_state *st); // [MouseJstr]
+int  buildin_npcwarp (struct script_state *st); // [remoitnane]
+int  buildin_message (struct script_state *st); // [MouseJstr]
+int  buildin_npctalk (struct script_state *st); // [Valaris]
+int  buildin_hasitems (struct script_state *st);    // [Valaris]
+int  buildin_getlook (struct script_state *st); //Lorky [Lupus]
+int  buildin_getsavepoint (struct script_state *st);    //Lorky [Lupus]
+int  buildin_getpartnerid (struct script_state *st);    // [Fate]
+int  buildin_areatimer (struct script_state *st);   // [Jaxad0127]
+int  buildin_isin (struct script_state *st);    // [Jaxad0127]
+int  buildin_shop (struct script_state *st);    // [MadCamel]
+int  buildin_isdead (struct script_state *st);  // [Jaxad0127]
+int  buildin_fakenpcname (struct script_state *st); //[Kage]
+int  buildin_unequip_by_id (struct script_state *st);   // [Freeyorp]
+int  buildin_getx (struct script_state *st);  // [Kage]
+int  buildin_gety (struct script_state *st);  // [Kage]
+
+
+void push_val (struct script_stack *stack, int type, int val);
+int  run_func (struct script_state *st);
+
+int  mapreg_setreg (int num, int val);
+int  mapreg_setregstr (int num, const char *str);
+
+struct
+{
+    int  (*func) (struct script_state *);
+    char *name;
+    char *arg;
+} buildin_func[] =
+{
+    {
+    buildin_mes, "mes", "s"},
+    {
+    buildin_next, "next", ""},
+    {
+    buildin_close, "close", ""},
+    {
+    buildin_close2, "close2", ""},
+    {
+    buildin_menu, "menu", "sL*"},
+    {
+    buildin_goto, "goto", "L"},
+    {
+    buildin_callsub, "callsub", "L*"},
+    {
+    buildin_callfunc, "callfunc", "F*"},
+    {
+    buildin_return, "return", "*"},
+    {
+    buildin_getarg, "getarg", "i"},
+    {
+    buildin_jobchange, "jobchange", "i*"},
+    {
+    buildin_input, "input", "N"},
+    {
+    buildin_warp, "warp", "Mxy"},
+    {
+    buildin_isat, "isat", "Mxy"},
+    {
+    buildin_areawarp, "areawarp", "MxyxyMxy"},
+    {
+    buildin_setlook, "setlook", "ii"},
+    {
+    buildin_set, "set", "Ne"},
+    {
+    buildin_setarray, "setarray", "Ne*"},
+    {
+    buildin_cleararray, "cleararray", "Nei"},
+    {
+    buildin_copyarray, "copyarray", "NNi"},
+    {
+    buildin_getarraysize, "getarraysize", "N"},
+    {
+    buildin_deletearray, "deletearray", "N*"},
+    {
+    buildin_getelementofarray, "getelementofarray", "Ni"},
+    {
+    buildin_if, "if", "iF*"},
+    {
+    buildin_getitem, "getitem", "Ii**"},
+    {
+    buildin_getitem2, "getitem2", "iiiiiiiii*"},
+    {
+    buildin_makeitem, "makeitem", "IiMxy"},
+    {
+    buildin_delitem, "delitem", "Ii"},
+    {
+    buildin_cutin, "cutin", "si"},
+    {
+    buildin_cutincard, "cutincard", "i"},
+    {
+    buildin_viewpoint, "viewpoint", "iiiii"},
+    {
+    buildin_heal, "heal", "ii"},
+    {
+    buildin_itemheal, "itemheal", "ii"},
+    {
+    buildin_percentheal, "percentheal", "ii"},
+    {
+    buildin_rand, "rand", "i*"},
+    {
+    buildin_pow, "pow", "ii"},
+    {
+    buildin_countitem, "countitem", "I"},
+    {
+    buildin_checkweight, "checkweight", "Ii"},
+    {
+    buildin_readparam, "readparam", "i*"},
+    {
+    buildin_getcharid, "getcharid", "i*"},
+    {
+    buildin_getpartyname, "getpartyname", "i"},
+    {
+    buildin_getpartymember, "getpartymember", "i"},
+    {
+    buildin_getguildname, "getguildname", "i"},
+    {
+    buildin_getguildmaster, "getguildmaster", "i"},
+    {
+    buildin_getguildmasterid, "getguildmasterid", "i"},
+    {
+    buildin_strcharinfo, "strcharinfo", "i"},
+    {
+    buildin_getequipid, "getequipid", "i"},
+    {
+    buildin_getequipname, "getequipname", "i"},
+    {
+    buildin_getbrokenid, "getbrokenid", "i"},   // [Valaris]
+    {
+    buildin_repair, "repair", "i"}, // [Valaris]
+    {
+    buildin_getequipisequiped, "getequipisequiped", "i"},
+    {
+    buildin_getequipisenableref, "getequipisenableref", "i"},
+    {
+    buildin_getequipisidentify, "getequipisidentify", "i"},
+    {
+    buildin_getequiprefinerycnt, "getequiprefinerycnt", "i"},
+    {
+    buildin_getequipweaponlv, "getequipweaponlv", "i"},
+    {
+    buildin_getequippercentrefinery, "getequippercentrefinery", "i"},
+    {
+    buildin_successrefitem, "successrefitem", "i"},
+    {
+    buildin_failedrefitem, "failedrefitem", "i"},
+    {
+    buildin_statusup, "statusup", "i"},
+    {
+    buildin_statusup2, "statusup2", "ii"},
+    {
+    buildin_bonus, "bonus", "ii"},
+    {
+    buildin_bonus2, "bonus2", "iii"},
+    {
+    buildin_bonus3, "bonus3", "iiii"},
+    {
+    buildin_skill, "skill", "ii*"},
+    {
+    buildin_setskill, "setskill", "ii"},    // [Fate]
+    {
+    buildin_guildskill, "guildskill", "ii"},
+    {
+    buildin_getskilllv, "getskilllv", "i"},
+    {
+    buildin_getgdskilllv, "getgdskilllv", "ii"},
+    {
+    buildin_basicskillcheck, "basicskillcheck", "*"},
+    {
+    buildin_getgmlevel, "getgmlevel", ""},
+    {
+    buildin_end, "end", ""},
+    {
+    buildin_getopt2, "getopt2", ""},
+    {
+    buildin_setopt2, "setopt2", "i"},
+    {
+    buildin_end, "break", ""},
+    {
+    buildin_checkoption, "checkoption", "i"},
+    {
+    buildin_setoption, "setoption", "i"},
+    {
+    buildin_setcart, "setcart", ""},
+    {
+    buildin_checkcart, "checkcart", "*"},   //fixed by Lupus (added '*')
+    {
+    buildin_setfalcon, "setfalcon", ""},
+    {
+    buildin_checkfalcon, "checkfalcon", "*"},   //fixed by Lupus (fixed wrong pointer, added '*')
+    {
+    buildin_setriding, "setriding", ""},
+    {
+    buildin_checkriding, "checkriding", "*"},   //fixed by Lupus (fixed wrong pointer, added '*')
+    {
+    buildin_savepoint, "save", "sii"},
+    {
+    buildin_savepoint, "savepoint", "Mxy"},
+    {
+    buildin_gettimetick, "gettimetick", "i"},
+    {
+    buildin_gettime, "gettime", "i"},
+    {
+    buildin_gettimestr, "gettimestr", "si"},
+    {
+    buildin_openstorage, "openstorage", "*"},
+    {
+    buildin_guildopenstorage, "guildopenstorage", "*"},
+    {
+    buildin_itemskill, "itemskill", "iis"},
+    {
+    buildin_monster, "monster", "Mxysmi*"},
+    {
+    buildin_areamonster, "areamonster", "Mxyxysmi*"},
+    {
+    buildin_killmonster, "killmonster", "ME"},
+    {
+    buildin_killmonsterall, "killmonsterall", "M"},
+    {
+    buildin_doevent, "doevent", "E"},
+    {
+    buildin_donpcevent, "donpcevent", "E"},
+    {
+    buildin_addtimer, "addtimer", "tE"},
+    {
+    buildin_deltimer, "deltimer", "E"},
+    {
+    buildin_addtimercount, "addtimercount", "si"},
+    {
+    buildin_initnpctimer, "initnpctimer", ""},
+    {
+    buildin_stopnpctimer, "stopnpctimer", ""},
+    {
+    buildin_startnpctimer, "startnpctimer", "*"},
+    {
+    buildin_setnpctimer, "setnpctimer", "i"},
+    {
+    buildin_getnpctimer, "getnpctimer", "i"},
+    {
+    buildin_announce, "announce", "si"},
+    {
+    buildin_mapannounce, "mapannounce", "Msi"},
+    {
+    buildin_areaannounce, "areaannounce", "Mxyxysi"},
+    {
+    buildin_getusers, "getusers", "i"},
+    {
+    buildin_getmapusers, "getmapusers", "M"},
+    {
+    buildin_getareausers, "getareausers", "Mxyxy*"},
+    {
+    buildin_getareadropitem, "getareadropitem", "Mxyxyi*"},
+    {
+    buildin_enablenpc, "enablenpc", "s"},
+    {
+    buildin_disablenpc, "disablenpc", "s"},
+    {
+    buildin_enablearena, "enablearena", ""},    // Added by RoVeRT
+    {
+    buildin_disablearena, "disablearena", ""},  // Added by RoVeRT
+    {
+    buildin_hideoffnpc, "hideoffnpc", "s"},
+    {
+    buildin_hideonnpc, "hideonnpc", "s"},
+    {
+    buildin_sc_start, "sc_start", "iTi*"},
+    {
+    buildin_sc_start2, "sc_start2", "iTii*"},
+    {
+    buildin_sc_end, "sc_end", "i"},
+    {
+    buildin_sc_check, "sc_check", "i"},
+    {
+    buildin_getscrate, "getscrate", "ii*"},
+    {
+    buildin_debugmes, "debugmes", "s"},
+    {
+    buildin_resetlvl, "resetlvl", "i"},
+    {
+    buildin_resetstatus, "resetstatus", ""},
+    {
+    buildin_resetskill, "resetskill", ""},
+    {
+    buildin_changebase, "changebase", "i"},
+    {
+    buildin_changesex, "changesex", ""},
+    {
+    buildin_waitingroom, "waitingroom", "si*"},
+    {
+    buildin_warpwaitingpc, "warpwaitingpc", "sii"},
+    {
+    buildin_delwaitingroom, "delwaitingroom", "*"},
+    {
+    buildin_enablewaitingroomevent, "enablewaitingroomevent", "*"},
+    {
+    buildin_disablewaitingroomevent, "disablewaitingroomevent", "*"},
+    {
+    buildin_getwaitingroomstate, "getwaitingroomstate", "i*"},
+    {
+    buildin_warpwaitingpc, "warpwaitingpc", "sii*"},
+    {
+    buildin_attachrid, "attachrid", "i"},
+    {
+    buildin_detachrid, "detachrid", ""},
+    {
+    buildin_isloggedin, "isloggedin", "i"},
+    {
+    buildin_setmapflagnosave, "setmapflagnosave", "MMxy"},
+    {
+    buildin_setmapflag, "setmapflag", "Mi"},
+    {
+    buildin_removemapflag, "removemapflag", "Mi"},
+    {
+    buildin_pvpon, "pvpon", "M"},
+    {
+    buildin_pvpoff, "pvpoff", "M"},
+    {
+    buildin_gvgon, "gvgon", "s"},
+    {
+    buildin_gvgoff, "gvgoff", "s"},
+    {
+    buildin_emotion, "emotion", "i"},
+    {
+    buildin_maprespawnguildid, "maprespawnguildid", "sii"},
+    {
+    buildin_agitstart, "agitstart", ""},    // <Agit>
+    {
+    buildin_agitend, "agitend", ""},
+    {
+    buildin_agitcheck, "agitcheck", "i"},   // <Agitcheck>
+    {
+    buildin_flagemblem, "flagemblem", "i"}, // Flag Emblem
+    {
+    buildin_getcastlename, "getcastlename", "s"},
+    {
+    buildin_getcastledata, "getcastledata", "si*"},
+    {
+    buildin_setcastledata, "setcastledata", "sii"},
+    {
+    buildin_requestguildinfo, "requestguildinfo", "i*"},
+    {
+    buildin_getequipcardcnt, "getequipcardcnt", "i"},
+    {
+    buildin_successremovecards, "successremovecards", "i"},
+    {
+    buildin_failedremovecards, "failedremovecards", "ii"},
+    {
+    buildin_marriage, "marriage", "P"},
+    {
+    buildin_wedding_effect, "wedding", ""},
+    {
+    buildin_divorce, "divorce", ""},
+    {
+    buildin_getitemname, "getitemname", "I"},
+    {
+    buildin_getspellinvocation, "getspellinvocation", "s"},
+    {
+    buildin_getanchorinvocation, "getanchorinvocation", "s"},
+    {
+    buildin_getpartnerid, "getpartnerid2", ""},
+    {
+    buildin_getexp, "getexp", "ii"},
+    {
+    buildin_getinventorylist, "getinventorylist", ""},
+    {
+    buildin_getskilllist, "getskilllist", ""},
+    {
+    buildin_get_pool_skills, "getpoolskilllist", ""},
+    {
+    buildin_get_activated_pool_skills, "getactivatedpoolskilllist", ""},
+    {
+    buildin_get_unactivated_pool_skills, "getunactivatedpoolskilllist", ""},
+    {
+    buildin_activate_pool_skill, "poolskill", "i"},
+    {
+    buildin_deactivate_pool_skill, "unpoolskill", "i"},
+    {
+    buildin_check_pool_skill, "checkpoolskill", "i"},
+    {
+    buildin_clearitem, "clearitem", ""},
+    {
+    buildin_classchange, "classchange", "ii"},
+    {
+    buildin_misceffect, "misceffect", "i*"},
+    {
+    buildin_soundeffect, "soundeffect", "si"},
+    {
+    buildin_strmobinfo, "strmobinfo", "im"},    // display mob data [Valaris]
+    {
+    buildin_guardian, "guardian", "siisii*i"},  // summon guardians
+    {
+    buildin_guardianinfo, "guardianinfo", "i"}, // display guardian data [Valaris]
+    {
+    buildin_npcskilleffect, "npcskilleffect", "iiii"},  // npc skill effect [Valaris]
+    {
+    buildin_specialeffect, "specialeffect", "i"},   // npc skill effect [Valaris]
+    {
+    buildin_specialeffect2, "specialeffect2", "i"}, // skill effect on players[Valaris]
+    {
+    buildin_nude, "nude", ""},  // nude command [Valaris]
+    {
+    buildin_mapwarp, "mapwarp", "MMxy"},    // Added by RoVeRT
+    {
+    buildin_inittimer, "inittimer", ""},
+    {
+    buildin_stoptimer, "stoptimer", ""},
+    {
+    buildin_cmdothernpc, "cmdothernpc", "ss"},
+    {
+    buildin_gmcommand, "gmcommand", "s"},   // [MouseJstr]
+//  {buildin_movenpc,"movenpc","siis"}, // [MouseJstr]
+    {
+    buildin_npcwarp, "npcwarp", "xys"}, // [remoitnane]
+    {
+    buildin_message, "message", "Ps"},  // [MouseJstr]
+    {
+    buildin_npctalk, "npctalk", "s"},   // [Valaris]
+    {
+    buildin_hasitems, "hasitems", ""}, // [Valaris]
+    {
+    buildin_mobcount, "mobcount", "ME"},
+    {
+    buildin_getlook, "getlook", "i"},
+    {
+    buildin_getsavepoint, "getsavepoint", "i"},
+    {
+    buildin_areatimer, "areatimer", "MxyxytE"},
+    {
+    buildin_isin, "isin", "Mxyxy"},
+    {
+    buildin_shop, "shop", "s"},
+    {
+    buildin_isdead, "isdead", ""},
+    {
+    buildin_fakenpcname, "fakenpcname", "ssi"},
+    {
+    buildin_unequip_by_id, "unequipbyid", "i"}, // [Freeyorp]
+    {
+    buildin_getx, "getx", ""}, // [Kage]
+    {
+    buildin_gety, "gety", ""}, // [Kage]
+        // End Additions
+    {
+NULL, NULL, NULL},};
+
+int  buildin_message (struct script_state *st); // [MouseJstr]
+
+enum
+{
+    C_NOP, C_POS, C_INT, C_PARAM, C_FUNC, C_STR, C_CONSTSTR, C_ARG,
+    C_NAME, C_EOL, C_RETINFO,
+
+    C_LOR, C_LAND, C_LE, C_LT, C_GE, C_GT, C_EQ, C_NE,  //operator
+    C_XOR, C_OR, C_AND, C_ADD, C_SUB, C_MUL, C_DIV, C_MOD, C_NEG, C_LNOT,
+    C_NOT, C_R_SHIFT, C_L_SHIFT
+};
+
+/*==========================================
+ * 文字列のハッシュを計算
+ *------------------------------------------
+ */
+static int calc_hash (const unsigned char *p)
+{
+    int  h = 0;
+    while (*p)
+    {
+        h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8);
+        h += *p++;
+    }
+    return h & 15;
+}
+
+/*==========================================
+ * str_dataの中に名前があるか検索する
+ *------------------------------------------
+ */
+// 既存のであれば番号、無ければ-1
+static int search_str (const unsigned char *p)
+{
+    int  i;
+    i = str_hash[calc_hash (p)];
+    while (i)
+    {
+        if (strcmp (str_buf + str_data[i].str, p) == 0)
+        {
+            return i;
+        }
+        i = str_data[i].next;
+    }
+    return -1;
+}
+
+/*==========================================
+ * str_dataに名前を登録
+ *------------------------------------------
+ */
+// 既存のであれば番号、無ければ登録して新規番号
+static int add_str (const unsigned char *p)
+{
+    int  i;
+    char *lowcase;
+
+    lowcase = strdup (p);
+    for (i = 0; lowcase[i]; i++)
+        lowcase[i] = tolower (lowcase[i]);
+    if ((i = search_str (lowcase)) >= 0)
+    {
+        free (lowcase);
+        return i;
+    }
+    free (lowcase);
+
+    i = calc_hash (p);
+    if (str_hash[i] == 0)
+    {
+        str_hash[i] = str_num;
+    }
+    else
+    {
+        i = str_hash[i];
+        for (;;)
+        {
+            if (strcmp (str_buf + str_data[i].str, p) == 0)
+            {
+                return i;
+            }
+            if (str_data[i].next == 0)
+                break;
+            i = str_data[i].next;
+        }
+        str_data[i].next = str_num;
+    }
+    if (str_num >= str_data_size)
+    {
+        str_data_size += 128;
+        RECREATE (str_data, struct str_data_t, str_data_size);
+        memset (str_data + (str_data_size - 128), '\0', 128);
+    }
+    while (str_pos + strlen (p) + 1 >= str_size)
+    {
+        str_size += 256;
+        str_buf = (char *) realloc (str_buf, str_size);
+        memset (str_buf + (str_size - 256), '\0', 256);
+    }
+    strcpy (str_buf + str_pos, p);
+    str_data[str_num].type = C_NOP;
+    str_data[str_num].str = str_pos;
+    str_data[str_num].next = 0;
+    str_data[str_num].func = NULL;
+    str_data[str_num].backpatch = -1;
+    str_data[str_num].label = -1;
+    str_pos += strlen (p) + 1;
+    return str_num++;
+}
+
+/*==========================================
+ * スクリプトバッファサイズの確認と拡張
+ *------------------------------------------
+ */
+static void check_script_buf (int size)
+{
+    if (script_pos + size >= script_size)
+    {
+        script_size += SCRIPT_BLOCK_SIZE;
+        script_buf = (char *) realloc (script_buf, script_size);
+        memset (script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0',
+                SCRIPT_BLOCK_SIZE);
+    }
+}
+
+/*==========================================
+ * スクリプトバッファに1バイト書き込む
+ *------------------------------------------
+ */
+static void add_scriptb (int a)
+{
+    check_script_buf (1);
+    script_buf[script_pos++] = a;
+}
+
+/*==========================================
+ * スクリプトバッファにデータタイプを書き込む
+ *------------------------------------------
+ */
+static void add_scriptc (int a)
+{
+    while (a >= 0x40)
+    {
+        add_scriptb ((a & 0x3f) | 0x40);
+        a = (a - 0x40) >> 6;
+    }
+    add_scriptb (a & 0x3f);
+}
+
+/*==========================================
+ * スクリプトバッファに整数を書き込む
+ *------------------------------------------
+ */
+static void add_scripti (unsigned int a)
+{
+    while (a >= 0x40)
+    {
+        add_scriptb (a | 0xc0);
+        a = (a - 0x40) >> 6;
+    }
+    add_scriptb (a | 0x80);
+}
+
+/*==========================================
+ * スクリプトバッファにラベル/変数/関数を書き込む
+ *------------------------------------------
+ */
+// 最大16Mまで
+static void add_scriptl (int l)
+{
+    int  backpatch = str_data[l].backpatch;
+
+    switch (str_data[l].type)
+    {
+        case C_POS:
+            add_scriptc (C_POS);
+            add_scriptb (str_data[l].label);
+            add_scriptb (str_data[l].label >> 8);
+            add_scriptb (str_data[l].label >> 16);
+            break;
+        case C_NOP:
+            // ラベルの可能性があるのでbackpatch用データ埋め込み
+            add_scriptc (C_NAME);
+            str_data[l].backpatch = script_pos;
+            add_scriptb (backpatch);
+            add_scriptb (backpatch >> 8);
+            add_scriptb (backpatch >> 16);
+            break;
+        case C_INT:
+            add_scripti (str_data[l].val);
+            break;
+        default:
+            // もう他の用途と確定してるので数字をそのまま
+            add_scriptc (C_NAME);
+            add_scriptb (l);
+            add_scriptb (l >> 8);
+            add_scriptb (l >> 16);
+            break;
+    }
+}
+
+/*==========================================
+ * ラベルを解決する
+ *------------------------------------------
+ */
+void set_label (int l, int pos)
+{
+    int  i, next;
+
+    str_data[l].type = C_POS;
+    str_data[l].label = pos;
+    for (i = str_data[l].backpatch; i >= 0 && i != 0x00ffffff;)
+    {
+        next = (*(int *) (script_buf + i)) & 0x00ffffff;
+        script_buf[i - 1] = C_POS;
+        script_buf[i] = pos;
+        script_buf[i + 1] = pos >> 8;
+        script_buf[i + 2] = pos >> 16;
+        i = next;
+    }
+}
+
+/*==========================================
+ * スペース/コメント読み飛ばし
+ *------------------------------------------
+ */
+static unsigned char *skip_space (unsigned char *p)
+{
+    while (1)
+    {
+        while (isspace (*p))
+            p++;
+        if (p[0] == '/' && p[1] == '/')
+        {
+            while (*p && *p != '\n')
+                p++;
+        }
+        else if (p[0] == '/' && p[1] == '*')
+        {
+            p++;
+            while (*p && (p[-1] != '*' || p[0] != '/'))
+                p++;
+            if (*p)
+                p++;
+        }
+        else
+            break;
+    }
+    return p;
+}
+
+/*==========================================
+ * 1単語スキップ
+ *------------------------------------------
+ */
+static unsigned char *skip_word (unsigned char *p)
+{
+    // prefix
+    if (*p == '$')
+        p++;                    // MAP鯖内共有変数用
+    if (*p == '@')
+        p++;                    // 一時的変数用(like weiss)
+    if (*p == '#')
+        p++;                    // account変数用
+    if (*p == '#')
+        p++;                    // ワールドaccount変数用
+    if (*p == 'l')
+        p++;                    // 一時的変数用(like weiss)
+
+    while (isalnum (*p) || *p == '_' || *p >= 0x81)
+        if (*p >= 0x81 && p[1])
+        {
+            p += 2;
+        }
+        else
+            p++;
+
+    // postfix
+    if (*p == '$')
+        p++;                    // 文字列変数
+
+    return p;
+}
+
+static unsigned char *startptr;
+static int startline;
+
+/*==========================================
+ * エラーメッセージ出力
+ *------------------------------------------
+ */
+static void disp_error_message (const char *mes, const unsigned char *pos)
+{
+    int  line, c = 0, i;
+    unsigned char *p, *linestart, *lineend;
+
+    for (line = startline, p = startptr; p && *p; line++)
+    {
+        linestart = p;
+        lineend = strchr (p, '\n');
+        if (lineend)
+        {
+            c = *lineend;
+            *lineend = 0;
+        }
+        if (lineend == NULL || pos < lineend)
+        {
+            printf ("%s line %d : ", mes, line);
+            for (i = 0;
+                 (linestart[i] != '\r') && (linestart[i] != '\n')
+                 && linestart[i]; i++)
+            {
+                if (linestart + i != pos)
+                    printf ("%c", linestart[i]);
+                else
+                    printf ("\'%c\'", linestart[i]);
+            }
+            printf ("\a\n");
+            if (lineend)
+                *lineend = c;
+            return;
+        }
+        *lineend = c;
+        p = lineend + 1;
+    }
+}
+
+/*==========================================
+ * 項の解析
+ *------------------------------------------
+ */
+unsigned char *parse_simpleexpr (unsigned char *p)
+{
+    int  i;
+    p = skip_space (p);
+
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_simpleexpr %s\n", p);
+#endif
+    if (*p == ';' || *p == ',')
+    {
+        disp_error_message ("unexpected expr end", p);
+        exit (1);
+    }
+    if (*p == '(')
+    {
+
+        p = parse_subexpr (p + 1, -1);
+        p = skip_space (p);
+        if ((*p++) != ')')
+        {
+            disp_error_message ("unmatch ')'", p);
+            exit (1);
+        }
+    }
+    else if (isdigit (*p) || ((*p == '-' || *p == '+') && isdigit (p[1])))
+    {
+        char *np;
+        i = strtoul (p, &np, 0);
+        add_scripti (i);
+        p = np;
+    }
+    else if (*p == '"')
+    {
+        add_scriptc (C_STR);
+        p++;
+        while (*p && *p != '"')
+        {
+            if (p[-1] <= 0x7e && *p == '\\')
+                p++;
+            else if (*p == '\n')
+            {
+                disp_error_message ("unexpected newline @ string", p);
+                exit (1);
+            }
+            add_scriptb (*p++);
+        }
+        if (!*p)
+        {
+            disp_error_message ("unexpected eof @ string", p);
+            exit (1);
+        }
+        add_scriptb (0);
+        p++;                    //'"'
+    }
+    else
+    {
+        int  c, l;
+        char *p2;
+        // label , register , function etc
+        if (skip_word (p) == p)
+        {
+            disp_error_message ("unexpected character", p);
+            exit (1);
+        }
+        p2 = skip_word (p);
+        c = *p2;
+        *p2 = 0;                // 名前をadd_strする
+        l = add_str (p);
+
+        parse_cmd = l;          // warn_*_mismatch_paramnumのために必要
+        if (l == search_str ("if")) // warn_cmd_no_commaのために必要
+            parse_cmd_if++;
+/*
+		// 廃止予定のl14/l15,およびプレフィックスlの警告
+		if(	strcmp(str_buf+str_data[l].str,"l14")==0 ||
+			strcmp(str_buf+str_data[l].str,"l15")==0 ){
+			disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p);
+		}else if(str_buf[str_data[l].str]=='l'){
+			disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2);
+		}
+*/
+        *p2 = c;
+        p = p2;
+
+        if (str_data[l].type != C_FUNC && c == '[')
+        {
+            // array(name[i] => getelementofarray(name,i) )
+            add_scriptl (search_str ("getelementofarray"));
+            add_scriptc (C_ARG);
+            add_scriptl (l);
+            p = parse_subexpr (p + 1, -1);
+            p = skip_space (p);
+            if ((*p++) != ']')
+            {
+                disp_error_message ("unmatch ']'", p);
+                exit (1);
+            }
+            add_scriptc (C_FUNC);
+        }
+        else
+            add_scriptl (l);
+
+    }
+
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_simpleexpr end %s\n", p);
+#endif
+    return p;
+}
+
+/*==========================================
+ * 式の解析
+ *------------------------------------------
+ */
+unsigned char *parse_subexpr (unsigned char *p, int limit)
+{
+    int  op, opl, len;
+    char *tmpp;
+
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_subexpr %s\n", p);
+#endif
+    p = skip_space (p);
+
+    if (*p == '-')
+    {
+        tmpp = skip_space (p + 1);
+        if (*tmpp == ';' || *tmpp == ',')
+        {
+            add_scriptl (LABEL_NEXTLINE);
+            p++;
+            return p;
+        }
+    }
+    tmpp = p;
+    if ((op = C_NEG, *p == '-') || (op = C_LNOT, *p == '!')
+        || (op = C_NOT, *p == '~'))
+    {
+        p = parse_subexpr (p + 1, 100);
+        add_scriptc (op);
+    }
+    else
+        p = parse_simpleexpr (p);
+    p = skip_space (p);
+    while (((op = C_ADD, opl = 6, len = 1, *p == '+') ||
+            (op = C_SUB, opl = 6, len = 1, *p == '-') ||
+            (op = C_MUL, opl = 7, len = 1, *p == '*') ||
+            (op = C_DIV, opl = 7, len = 1, *p == '/') ||
+            (op = C_MOD, opl = 7, len = 1, *p == '%') ||
+            (op = C_FUNC, opl = 8, len = 1, *p == '(') ||
+            (op = C_LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') ||
+            (op = C_AND, opl = 5, len = 1, *p == '&') ||
+            (op = C_LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') ||
+            (op = C_OR, opl = 4, len = 1, *p == '|') ||
+            (op = C_XOR, opl = 3, len = 1, *p == '^') ||
+            (op = C_EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') ||
+            (op = C_NE, opl = 2, len = 2, *p == '!' && p[1] == '=') ||
+            (op = C_R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') ||
+            (op = C_GE, opl = 2, len = 2, *p == '>' && p[1] == '=') ||
+            (op = C_GT, opl = 2, len = 1, *p == '>') ||
+            (op = C_L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') ||
+            (op = C_LE, opl = 2, len = 2, *p == '<' && p[1] == '=') ||
+            (op = C_LT, opl = 2, len = 1, *p == '<')) && opl > limit)
+    {
+        p += len;
+        if (op == C_FUNC)
+        {
+            int  i = 0, func = parse_cmd;
+            const char *plist[128];
+
+            if (str_data[func].type != C_FUNC)
+            {
+                disp_error_message ("expect function", tmpp);
+                exit (0);
+            }
+
+            add_scriptc (C_ARG);
+            while (*p && *p != ')' && i < 128)
+            {
+                plist[i] = p;
+                p = parse_subexpr (p, -1);
+                p = skip_space (p);
+                if (*p == ',')
+                    p++;
+                else if (*p != ')' && script_config.warn_func_no_comma)
+                {
+                    disp_error_message ("expect ',' or ')' at func params",
+                                        p);
+                }
+                p = skip_space (p);
+                i++;
+            }
+            plist[i] = p;
+            if (*(p++) != ')')
+            {
+                disp_error_message ("func request '(' ')'", p);
+                exit (1);
+            }
+
+            if (str_data[func].type == C_FUNC
+                && script_config.warn_func_mismatch_paramnum)
+            {
+                const char *arg = buildin_func[str_data[func].val].arg;
+                int  j = 0;
+                for (j = 0; arg[j]; j++)
+                    if (arg[j] == '*')
+                        break;
+                if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
+                {
+                    disp_error_message ("illegal number of parameters",
+                                        plist[(i < j) ? i : j]);
+                }
+            }
+        }
+        else // not op == C_FUNC
+        {
+            p = parse_subexpr (p, opl);
+        }
+        add_scriptc (op);
+        p = skip_space (p);
+    }
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_subexpr end %s\n", p);
+#endif
+    return p;                   /* return first untreated operator */
+}
+
+/*==========================================
+ * 式の評価
+ *------------------------------------------
+ */
+unsigned char *parse_expr (unsigned char *p)
+{
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_expr %s\n", p);
+#endif
+    switch (*p)
+    {
+        case ')':
+        case ';':
+        case ':':
+        case '[':
+        case ']':
+        case '}':
+            disp_error_message ("unexpected char", p);
+            exit (1);
+    }
+    p = parse_subexpr (p, -1);
+#ifdef DEBUG_FUNCIN
+    if (battle_config.etc_log)
+        printf ("parse_expr end %s\n", p);
+#endif
+    return p;
+}
+
+/*==========================================
+ * 行の解析
+ *------------------------------------------
+ */
+unsigned char *parse_line (unsigned char *p)
+{
+    int  i = 0, cmd;
+    const char *plist[128];
+    char *p2;
+
+    p = skip_space (p);
+    if (*p == ';')
+        return p;
+
+    parse_cmd_if = 0;           // warn_cmd_no_commaのために必要
+
+    // 最初は関数名
+    p2 = p;
+    p = parse_simpleexpr (p);
+    p = skip_space (p);
+
+    cmd = parse_cmd;
+    if (str_data[cmd].type != C_FUNC)
+    {
+        disp_error_message ("expect command", p2);
+//      exit(0);
+    }
+
+    add_scriptc (C_ARG);
+    while (p && *p && *p != ';' && i < 128)
+    {
+        plist[i] = p;
+
+        p = parse_expr (p);
+        p = skip_space (p);
+        // 引数区切りの,処理
+        if (*p == ',')
+            p++;
+        else if (*p != ';' && script_config.warn_cmd_no_comma
+                 && parse_cmd_if * 2 <= i)
+        {
+            disp_error_message ("expect ',' or ';' at cmd params", p);
+        }
+        p = skip_space (p);
+        i++;
+    }
+    plist[i] = p;
+    if (!p || *(p++) != ';')
+    {
+        disp_error_message ("need ';'", p);
+        exit (1);
+    }
+    add_scriptc (C_FUNC);
+
+    if (str_data[cmd].type == C_FUNC
+        && script_config.warn_cmd_mismatch_paramnum)
+    {
+        const char *arg = buildin_func[str_data[cmd].val].arg;
+        int  j = 0;
+        for (j = 0; arg[j]; j++)
+            if (arg[j] == '*')
+                break;
+        if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
+        {
+            disp_error_message ("illegal number of parameters",
+                                plist[(i < j) ? i : j]);
+        }
+    }
+
+    return p;
+}
+
+/*==========================================
+ * 組み込み関数の追加
+ *------------------------------------------
+ */
+static void add_buildin_func (void)
+{
+    int  i, n;
+    for (i = 0; buildin_func[i].func; i++)
+    {
+        n = add_str (buildin_func[i].name);
+        str_data[n].type = C_FUNC;
+        str_data[n].val = i;
+        str_data[n].func = buildin_func[i].func;
+    }
+}
+
+/*==========================================
+ * 定数データベースの読み込み
+ *------------------------------------------
+ */
+static void read_constdb (void)
+{
+    FILE *fp;
+    char line[1024], name[1024];
+    int  val, n, i, type;
+
+    fp = fopen_ ("db/const.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/const.txt\n");
+        return;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        type = 0;
+        if (sscanf (line, "%[A-Za-z0-9_],%d,%d", name, &val, &type) >= 2 ||
+            sscanf (line, "%[A-Za-z0-9_] %d %d", name, &val, &type) >= 2)
+        {
+            for (i = 0; name[i]; i++)
+                name[i] = tolower (name[i]);
+            n = add_str (name);
+            if (type == 0)
+                str_data[n].type = C_INT;
+            else
+                str_data[n].type = C_PARAM;
+            str_data[n].val = val;
+        }
+    }
+    fclose_ (fp);
+}
+
+/*==========================================
+ * スクリプトの解析
+ *------------------------------------------
+ */
+unsigned char *parse_script (unsigned char *src, int line)
+{
+    unsigned char *p, *tmpp;
+    int  i;
+    static int first = 1;
+
+    if (first)
+    {
+        add_buildin_func ();
+        read_constdb ();
+    }
+    first = 0;
+    script_buf = (unsigned char *) calloc (SCRIPT_BLOCK_SIZE, 1);
+    script_pos = 0;
+    script_size = SCRIPT_BLOCK_SIZE;
+    str_data[LABEL_NEXTLINE].type = C_NOP;
+    str_data[LABEL_NEXTLINE].backpatch = -1;
+    str_data[LABEL_NEXTLINE].label = -1;
+    for (i = LABEL_START; i < str_num; i++)
+    {
+        if (str_data[i].type == C_POS || str_data[i].type == C_NAME)
+        {
+            str_data[i].type = C_NOP;
+            str_data[i].backpatch = -1;
+            str_data[i].label = -1;
+        }
+    }
+
+    // 外部用label dbの初期化
+    if (scriptlabel_db != NULL)
+        strdb_final (scriptlabel_db, NULL);
+    scriptlabel_db = strdb_init (50);
+
+    // for error message
+    startptr = src;
+    startline = line;
+
+    p = src;
+    p = skip_space (p);
+    if (*p != '{')
+    {
+        disp_error_message ("not found '{'", p);
+        return NULL;
+    }
+    for (p++; p && *p && *p != '}';)
+    {
+        p = skip_space (p);
+        // labelだけ特殊処理
+        tmpp = skip_space (skip_word (p));
+        if (*tmpp == ':')
+        {
+            int  l, c;
+
+            c = *skip_word (p);
+            *skip_word (p) = 0;
+            l = add_str (p);
+            if (str_data[l].label != -1)
+            {
+                *skip_word (p) = c;
+                disp_error_message ("dup label ", p);
+                exit (1);
+            }
+            set_label (l, script_pos);
+            strdb_insert (scriptlabel_db, (const char*)p, script_pos);   // 外部用label db登録
+            *skip_word (p) = c;
+            p = tmpp + 1;
+            continue;
+        }
+
+        // 他は全部一緒くた
+        p = parse_line (p);
+        p = skip_space (p);
+        add_scriptc (C_EOL);
+
+        set_label (LABEL_NEXTLINE, script_pos);
+        str_data[LABEL_NEXTLINE].type = C_NOP;
+        str_data[LABEL_NEXTLINE].backpatch = -1;
+        str_data[LABEL_NEXTLINE].label = -1;
+    }
+
+    add_scriptc (C_NOP);
+
+    script_size = script_pos;
+    script_buf = (char *) realloc (script_buf, script_pos + 1);
+
+    // 未解決のラベルを解決
+    for (i = LABEL_START; i < str_num; i++)
+    {
+        if (str_data[i].type == C_NOP)
+        {
+            int  j, next;
+            str_data[i].type = C_NAME;
+            str_data[i].label = i;
+            for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff;)
+            {
+                next = (*(int *) (script_buf + j)) & 0x00ffffff;
+                script_buf[j] = i;
+                script_buf[j + 1] = i >> 8;
+                script_buf[j + 2] = i >> 16;
+                j = next;
+            }
+        }
+    }
+
+#ifdef DEBUG_DISP
+    for (i = 0; i < script_pos; i++)
+    {
+        if ((i & 15) == 0)
+            printf ("%04x : ", i);
+        printf ("%02x ", script_buf[i]);
+        if ((i & 15) == 15)
+            printf ("\n");
+    }
+    printf ("\n");
+#endif
+
+    return script_buf;
+}
+
+//
+// 実行系
+//
+enum
+{ STOP = 1, END, RERUNLINE, GOTO, RETFUNC };
+
+/*==========================================
+ * ridからsdへの解決
+ *------------------------------------------
+ */
+struct map_session_data *script_rid2sd (struct script_state *st)
+{
+    struct map_session_data *sd = map_id2sd (st->rid);
+    if (!sd)
+    {
+        printf ("script_rid2sd: fatal error ! player not attached!\n");
+    }
+    return sd;
+}
+
+/*==========================================
+ * 変数の読み取り
+ *------------------------------------------
+ */
+int get_val (struct script_state *st, struct script_data *data)
+{
+    struct map_session_data *sd = NULL;
+    if (data->type == C_NAME)
+    {
+        char *name = str_buf + str_data[data->u.num & 0x00ffffff].str;
+        char prefix = *name;
+        char postfix = name[strlen (name) - 1];
+
+        if (prefix != '$')
+        {
+            if ((sd = script_rid2sd (st)) == NULL)
+                printf ("get_val error name?:%s\n", name);
+        }
+        if (postfix == '$')
+        {
+
+            data->type = C_CONSTSTR;
+            if (prefix == '@' || prefix == 'l')
+            {
+                if (sd)
+                    data->u.str = pc_readregstr (sd, data->u.num);
+            }
+            else if (prefix == '$')
+            {
+                data->u.str =
+                    (char *) numdb_search (mapregstr_db, data->u.num);
+            }
+            else
+            {
+                printf ("script: get_val: illegal scope string variable.\n");
+                data->u.str = "!!ERROR!!";
+            }
+            if (data->u.str == NULL)
+                data->u.str = "";
+
+        }
+        else
+        {
+
+            data->type = C_INT;
+            if (str_data[data->u.num & 0x00ffffff].type == C_INT)
+            {
+                data->u.num = str_data[data->u.num & 0x00ffffff].val;
+            }
+            else if (str_data[data->u.num & 0x00ffffff].type == C_PARAM)
+            {
+                if (sd)
+                    data->u.num =
+                        pc_readparam (sd,
+                                      str_data[data->u.num & 0x00ffffff].val);
+            }
+            else if (prefix == '@' || prefix == 'l')
+            {
+                if (sd)
+                    data->u.num = pc_readreg (sd, data->u.num);
+            }
+            else if (prefix == '$')
+            {
+                data->u.num = (int) numdb_search (mapreg_db, data->u.num);
+            }
+            else if (prefix == '#')
+            {
+                if (name[1] == '#')
+                {
+                    if (sd)
+                        data->u.num = pc_readaccountreg2 (sd, name);
+                }
+                else
+                {
+                    if (sd)
+                        data->u.num = pc_readaccountreg (sd, name);
+                }
+            }
+            else
+            {
+                if (sd)
+                    data->u.num = pc_readglobalreg (sd, name);
+            }
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * 変数の読み取り2
+ *------------------------------------------
+ */
+void *get_val2 (struct script_state *st, int num)
+{
+    struct script_data dat;
+    dat.type = C_NAME;
+    dat.u.num = num;
+    get_val (st, &dat);
+    if (dat.type == C_INT)
+        return (void *) dat.u.num;
+    else
+        return (void *) dat.u.str;
+}
+
+/*==========================================
+ * 変数設定用
+ *------------------------------------------
+ */
+static int set_reg (struct map_session_data *sd, int num, char *name, void *v)
+{
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+
+    if (postfix == '$')
+    {
+        char *str = (char *) v;
+        if (prefix == '@' || prefix == 'l')
+        {
+            pc_setregstr (sd, num, str);
+        }
+        else if (prefix == '$')
+        {
+            mapreg_setregstr (num, str);
+        }
+        else
+        {
+            printf ("script: set_reg: illegal scope string variable !");
+        }
+    }
+    else
+    {
+        // 数値
+        int  val = (int) v;
+        if (str_data[num & 0x00ffffff].type == C_PARAM)
+        {
+            pc_setparam (sd, str_data[num & 0x00ffffff].val, val);
+        }
+        else if (prefix == '@' || prefix == 'l')
+        {
+            pc_setreg (sd, num, val);
+        }
+        else if (prefix == '$')
+        {
+            mapreg_setreg (num, val);
+        }
+        else if (prefix == '#')
+        {
+            if (name[1] == '#')
+                pc_setaccountreg2 (sd, name, val);
+            else
+                pc_setaccountreg (sd, name, val);
+        }
+        else
+        {
+            pc_setglobalreg (sd, name, val);
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * 文字列への変換
+ *------------------------------------------
+ */
+char *conv_str (struct script_state *st, struct script_data *data)
+{
+    get_val (st, data);
+    if (data->type == C_INT)
+    {
+        char *buf;
+        buf = (char *) calloc (16, 1);
+        sprintf (buf, "%d", data->u.num);
+        data->type = C_STR;
+        data->u.str = buf;
+#if 1
+    }
+    else if (data->type == C_NAME)
+    {
+        // テンポラリ。本来無いはず
+        data->type = C_CONSTSTR;
+        data->u.str = str_buf + str_data[data->u.num].str;
+#endif
+    }
+    return data->u.str;
+}
+
+/*==========================================
+ * 数値へ変換
+ *------------------------------------------
+ */
+int conv_num (struct script_state *st, struct script_data *data)
+{
+    char *p;
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        p = data->u.str;
+        data->u.num = atoi (p);
+        if (data->type == C_STR)
+            free (p);
+        data->type = C_INT;
+    }
+    return data->u.num;
+}
+
+/*==========================================
+ * スタックへ数値をプッシュ
+ *------------------------------------------
+ */
+void push_val (struct script_stack *stack, int type, int val)
+{
+    if (stack->sp >= stack->sp_max)
+    {
+        stack->sp_max += 64;
+        stack->stack_data = (struct script_data *)
+            realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
+                                        stack->sp_max);
+        memset (stack->stack_data + (stack->sp_max - 64), 0,
+                64 * sizeof (*(stack->stack_data)));
+    }
+//  if(battle_config.etc_log)
+//      printf("push (%d,%d)-> %d\n",type,val,stack->sp);
+    stack->stack_data[stack->sp].type = type;
+    stack->stack_data[stack->sp].u.num = val;
+    stack->sp++;
+}
+
+/*==========================================
+ * スタックへ文字列をプッシュ
+ *------------------------------------------
+ */
+void push_str (struct script_stack *stack, int type, unsigned char *str)
+{
+    if (stack->sp >= stack->sp_max)
+    {
+        stack->sp_max += 64;
+        stack->stack_data = (struct script_data *)
+            realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
+                                        stack->sp_max);
+        memset (stack->stack_data + (stack->sp_max - 64), '\0',
+                64 * sizeof (*(stack->stack_data)));
+    }
+//  if(battle_config.etc_log)
+//      printf("push (%d,%x)-> %d\n",type,str,stack->sp);
+    stack->stack_data[stack->sp].type = type;
+    stack->stack_data[stack->sp].u.str = str;
+    stack->sp++;
+}
+
+/*==========================================
+ * スタックへ複製をプッシュ
+ *------------------------------------------
+ */
+void push_copy (struct script_stack *stack, int pos)
+{
+    switch (stack->stack_data[pos].type)
+    {
+        case C_CONSTSTR:
+            push_str (stack, C_CONSTSTR, stack->stack_data[pos].u.str);
+            break;
+        case C_STR:
+            push_str (stack, C_STR, strdup (stack->stack_data[pos].u.str));
+            break;
+        default:
+            push_val (stack, stack->stack_data[pos].type,
+                      stack->stack_data[pos].u.num);
+            break;
+    }
+}
+
+/*==========================================
+ * スタックからポップ
+ *------------------------------------------
+ */
+void pop_stack (struct script_stack *stack, int start, int end)
+{
+    int  i;
+    for (i = start; i < end; i++)
+    {
+        if (stack->stack_data[i].type == C_STR)
+        {
+            free (stack->stack_data[i].u.str);
+        }
+    }
+    if (stack->sp > end)
+    {
+        memmove (&stack->stack_data[start], &stack->stack_data[end],
+                 sizeof (stack->stack_data[0]) * (stack->sp - end));
+    }
+    stack->sp -= end - start;
+}
+
+//
+// 埋め込み関数
+//
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_mes (struct script_state *st)
+{
+    conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    clif_scriptmes (script_rid2sd (st), st->oid,
+                    st->stack->stack_data[st->start + 2].u.str);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_goto (struct script_state *st)
+{
+    int  pos;
+
+    if (st->stack->stack_data[st->start + 2].type != C_POS)
+    {
+        printf ("script: goto: not label !\n");
+        st->state = END;
+        return 0;
+    }
+
+    pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    st->pos = pos;
+    st->state = GOTO;
+    return 0;
+}
+
+/*==========================================
+ * ユーザー定義関数の呼び出し
+ *------------------------------------------
+ */
+int buildin_callfunc (struct script_state *st)
+{
+    char *scr;
+    char *str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    if ((scr = (char*)strdb_search (script_get_userfunc_db (), str)))
+    {
+        int  i, j;
+        for (i = st->start + 3, j = 0; i < st->end; i++, j++)
+            push_copy (st->stack, i);
+
+        push_val (st->stack, C_INT, j); // 引数の数をプッシュ
+        push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
+        push_val (st->stack, C_INT, (int) st->script);  // 現在のスクリプトをプッシュ
+        push_val (st->stack, C_RETINFO, st->pos);   // 現在のスクリプト位置をプッシュ
+
+        st->pos = 0;
+        st->script = scr;
+        st->defsp = st->start + 4 + j;
+        st->state = GOTO;
+    }
+    else
+    {
+        printf ("script:callfunc: function not found! [%s]\n", str);
+        st->state = END;
+    }
+    return 0;
+}
+
+/*==========================================
+ * サブルーティンの呼び出し
+ *------------------------------------------
+ */
+int buildin_callsub (struct script_state *st)
+{
+    int  pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  i, j;
+    for (i = st->start + 3, j = 0; i < st->end; i++, j++)
+        push_copy (st->stack, i);
+
+    push_val (st->stack, C_INT, j); // 引数の数をプッシュ
+    push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
+    push_val (st->stack, C_INT, (int) st->script);  // 現在のスクリプトをプッシュ
+    push_val (st->stack, C_RETINFO, st->pos);   // 現在のスクリプト位置をプッシュ
+
+    st->pos = pos;
+    st->defsp = st->start + 4 + j;
+    st->state = GOTO;
+    return 0;
+}
+
+/*==========================================
+ * 引数の所得
+ *------------------------------------------
+ */
+int buildin_getarg (struct script_state *st)
+{
+    int  num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  max, stsp;
+    if (st->defsp < 4
+        || st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
+    {
+        printf ("script:getarg without callfunc or callsub!\n");
+        st->state = END;
+        return 0;
+    }
+    max = conv_num (st, &(st->stack->stack_data[st->defsp - 4]));
+    stsp = st->defsp - max - 4;
+    if (num >= max)
+    {
+        printf ("script:getarg arg1(%d) out of range(%d) !\n", num, max);
+        st->state = END;
+        return 0;
+    }
+    push_copy (st->stack, stsp + num);
+    return 0;
+}
+
+/*==========================================
+ * サブルーチン/ユーザー定義関数の終了
+ *------------------------------------------
+ */
+int buildin_return (struct script_state *st)
+{
+    if (st->end > st->start + 2)
+    {                           // 戻り値有り
+        push_copy (st->stack, st->start + 2);
+    }
+    st->state = RETFUNC;
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_next (struct script_state *st)
+{
+    st->state = STOP;
+    clif_scriptnext (script_rid2sd (st), st->oid);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_close (struct script_state *st)
+{
+    st->state = END;
+    clif_scriptclose (script_rid2sd (st), st->oid);
+    return 0;
+}
+
+int buildin_close2 (struct script_state *st)
+{
+    st->state = STOP;
+    clif_scriptclose (script_rid2sd (st), st->oid);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_menu (struct script_state *st)
+{
+    char *buf;
+    int  i, len = 0;            // [fate] len is the total # of bytes we need to transmit the string choices
+    int  menu_choices = 0;
+    int  finished_menu_items = 0;   // [fate] set to 1 after we hit the first empty string
+
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    // We don't need to do this iteration if the player cancels, strictly speaking.
+    for (i = st->start + 2; i < st->end; i += 2)
+    {
+        int  choice_len;
+        conv_str (st, &(st->stack->stack_data[i]));
+        choice_len = strlen (st->stack->stack_data[i].u.str);
+        len += choice_len + 1;  // count # of bytes we'll need for packet.  Only used if menu_or_input = 0.
+
+        if (choice_len && !finished_menu_items)
+            ++menu_choices;
+        else
+            finished_menu_items = 1;
+    }
+
+    if (sd->state.menu_or_input == 0)
+    {
+        st->state = RERUNLINE;
+        sd->state.menu_or_input = 1;
+
+        buf = (char *) calloc (len + 1, 1);
+        buf[0] = 0;
+        for (i = st->start + 2; menu_choices > 0; i += 2, --menu_choices)
+        {
+            strcat (buf, st->stack->stack_data[i].u.str);
+            strcat (buf, ":");
+        }
+        clif_scriptmenu (script_rid2sd (st), st->oid, buf);
+        free (buf);
+    }
+    else if (sd->npc_menu == 0xff)
+    {                           // cansel
+        sd->state.menu_or_input = 0;
+        st->state = END;
+    }
+    else
+    {                           // goto動作
+        // ragemu互換のため
+        pc_setreg (sd, add_str ("l15"), sd->npc_menu);
+        pc_setreg (sd, add_str ("@menu"), sd->npc_menu);
+        sd->state.menu_or_input = 0;
+        if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices)
+        {
+            int  pos;
+            if (st->stack->
+                stack_data[st->start + sd->npc_menu * 2 + 1].type != C_POS)
+            {
+                st->state = END;
+                return 0;
+            }
+            pos =
+                conv_num (st,
+                          &(st->
+                            stack->stack_data[st->start + sd->npc_menu * 2 +
+                                              1]));
+            st->pos = pos;
+            st->state = GOTO;
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_rand (struct script_state *st)
+{
+    int  range, min, max;
+
+    if (st->end > st->start + 3)
+    {
+        min = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+        max = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+        if (max < min)
+        {
+            int  tmp;
+            tmp = min;
+            min = max;
+            max = tmp;
+        }
+        range = max - min + 1;
+        push_val (st->stack, C_INT, (range <= 0 ? 0 : MRAND (range)) + min);
+    }
+    else
+    {
+        range = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+        push_val (st->stack, C_INT, range <= 0 ? 0 : MRAND (range));
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_pow (struct script_state *st)
+{
+    int  a, b;
+
+    a = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    b = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    push_val (st->stack, C_INT, (int) pow (a * 0.001, b));
+
+    return 0;
+}
+
+/*==========================================
+ * Check whether the PC is at the specified location
+ *------------------------------------------
+ */
+int buildin_isat (struct script_state *st)
+{
+    int  x, y;
+    char *str;
+    struct map_session_data *sd = script_rid2sd (st);
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+
+    if (!sd)
+        return 1;
+
+    push_val (st->stack, C_INT,
+              (x == sd->bl.x)
+              && (y == sd->bl.y) && (!strcmp (str, map[sd->bl.m].name)));
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_warp (struct script_state *st)
+{
+    int  x, y;
+    char *str;
+    struct map_session_data *sd = script_rid2sd (st);
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    if (strcmp (str, "Random") == 0)
+        pc_randomwarp (sd, 3);
+    else if (strcmp (str, "SavePoint") == 0)
+    {
+        if (map[sd->bl.m].flag.noreturn)    // 蝶禁止
+            return 0;
+
+        pc_setpos (sd, sd->status.save_point.map,
+                   sd->status.save_point.x, sd->status.save_point.y, 3);
+    }
+    else if (strcmp (str, "Save") == 0)
+    {
+        if (map[sd->bl.m].flag.noreturn)    // 蝶禁止
+            return 0;
+
+        pc_setpos (sd, sd->status.save_point.map,
+                   sd->status.save_point.x, sd->status.save_point.y, 3);
+    }
+    else
+        pc_setpos (sd, str, x, y, 0);
+    return 0;
+}
+
+/*==========================================
+ * エリア指定ワープ
+ *------------------------------------------
+ */
+int buildin_areawarp_sub (struct block_list *bl, va_list ap)
+{
+    int  x, y;
+    char *map;
+    map = va_arg (ap, char *);
+    x = va_arg (ap, int);
+    y = va_arg (ap, int);
+    if (strcmp (map, "Random") == 0)
+        pc_randomwarp ((struct map_session_data *) bl, 3);
+    else
+        pc_setpos ((struct map_session_data *) bl, map, x, y, 0);
+    return 0;
+}
+
+int buildin_areawarp (struct script_state *st)
+{
+    int  x, y, m;
+    char *str;
+    char *mapname;
+    int  x0, y0, x1, y1;
+
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 8]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 9]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+
+    map_foreachinarea (buildin_areawarp_sub,
+                       m, x0, y0, x1, y1, BL_PC, str, x, y);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_heal (struct script_state *st)
+{
+    int  hp, sp;
+
+    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    pc_heal (script_rid2sd (st), hp, sp);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_itemheal (struct script_state *st)
+{
+    int  hp, sp;
+
+    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    pc_itemheal (script_rid2sd (st), hp, sp);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_percentheal (struct script_state *st)
+{
+    int  hp, sp;
+
+    hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    pc_percentheal (script_rid2sd (st), hp, sp);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_jobchange (struct script_state *st)
+{
+    int  job, upper = -1;
+
+    job = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (st->end > st->start + 3)
+        upper = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    if ((job >= 0 && job < MAX_PC_CLASS))
+        pc_jobchange (script_rid2sd (st), job, upper);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_input (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num =
+        (st->end >
+         st->start + 2) ? st->stack->stack_data[st->start + 2].u.num : 0;
+    char *name =
+        (st->end >
+         st->start + 2) ? str_buf + str_data[num & 0x00ffffff].str : "";
+//  char prefix=*name;
+    char postfix = name[strlen (name) - 1];
+
+    sd = script_rid2sd (st);
+    if (sd->state.menu_or_input)
+    {
+        sd->state.menu_or_input = 0;
+        if (postfix == '$')
+        {
+            // 文字列
+            if (st->end > st->start + 2)
+            {                   // 引数1個
+                set_reg (sd, num, name, (void *) sd->npc_str);
+            }
+            else
+            {
+                printf ("buildin_input: string discarded !!\n");
+            }
+        }
+        else
+        {
+
+            //commented by Lupus (check Value Number Input fix in clif.c)
+            //** Fix by fritz :X keeps people from abusing old input bugs
+            if (sd->npc_amount < 0) //** If input amount is less then 0
+            {
+                clif_tradecancelled (sd);   // added "Deal has been cancelled" message by Valaris
+                buildin_close (st); //** close
+            }
+
+            // 数値
+            if (st->end > st->start + 2)
+            {                   // 引数1個
+                set_reg (sd, num, name, (void *) sd->npc_amount);
+            }
+            else
+            {
+                // ragemu互換のため
+                pc_setreg (sd, add_str ("l14"), sd->npc_amount);
+            }
+        }
+    }
+    else
+    {
+        st->state = RERUNLINE;
+        if (postfix == '$')
+            clif_scriptinputstr (sd, st->oid);
+        else
+            clif_scriptinput (sd, st->oid);
+        sd->state.menu_or_input = 1;
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_if (struct script_state *st)
+{
+    int  sel, i;
+
+    sel = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (!sel)
+        return 0;
+
+    // 関数名をコピー
+    push_copy (st->stack, st->start + 3);
+    // 間に引数マーカを入れて
+    push_val (st->stack, C_ARG, 0);
+    // 残りの引数をコピー
+    for (i = st->start + 4; i < st->end; i++)
+    {
+        push_copy (st->stack, i);
+    }
+    run_func (st);
+
+    return 0;
+}
+
+/*==========================================
+ * 変数設定
+ *------------------------------------------
+ */
+int buildin_set (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+
+    if (st->stack->stack_data[st->start + 2].type != C_NAME)
+    {
+        printf ("script: buildin_set: not name\n");
+        return 0;
+    }
+
+    if (prefix != '$')
+        sd = script_rid2sd (st);
+
+    if (postfix == '$')
+    {
+        // 文字列
+        char *str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+        set_reg (sd, num, name, (void *) str);
+    }
+    else
+    {
+        // 数値
+        int  val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+        set_reg (sd, num, name, (void *) val);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 配列変数設定
+ *------------------------------------------
+ */
+int buildin_setarray (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+    int  i, j;
+
+    if (prefix != '$' && prefix != '@')
+    {
+        printf ("buildin_setarray: illegal scope !\n");
+        return 0;
+    }
+    if (prefix != '$')
+        sd = script_rid2sd (st);
+
+    for (j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++)
+    {
+        void *v;
+        if (postfix == '$')
+            v = (void *) conv_str (st, &(st->stack->stack_data[i]));
+        else
+            v = (void *) conv_num (st, &(st->stack->stack_data[i]));
+        set_reg (sd, num + (j << 24), name, v);
+    }
+    return 0;
+}
+
+/*==========================================
+ * 配列変数クリア
+ *------------------------------------------
+ */
+int buildin_cleararray (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+    int  sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    int  i;
+    void *v;
+
+    if (prefix != '$' && prefix != '@')
+    {
+        printf ("buildin_cleararray: illegal scope !\n");
+        return 0;
+    }
+    if (prefix != '$')
+        sd = script_rid2sd (st);
+
+    if (postfix == '$')
+        v = (void *) conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    else
+        v = (void *) conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    for (i = 0; i < sz; i++)
+        set_reg (sd, num + (i << 24), name, v);
+    return 0;
+}
+
+/*==========================================
+ * 配列変数コピー
+ *------------------------------------------
+ */
+int buildin_copyarray (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+    int  num2 = st->stack->stack_data[st->start + 3].u.num;
+    char *name2 = str_buf + str_data[num2 & 0x00ffffff].str;
+    char prefix2 = *name2;
+    char postfix2 = name2[strlen (name2) - 1];
+    int  sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    int  i;
+
+    if (prefix != '$' && prefix != '@' && prefix2 != '$' && prefix2 != '@')
+    {
+        printf ("buildin_copyarray: illegal scope !\n");
+        return 0;
+    }
+    if ((postfix == '$' || postfix2 == '$') && postfix != postfix2)
+    {
+        printf ("buildin_copyarray: type mismatch !\n");
+        return 0;
+    }
+    if (prefix != '$' || prefix2 != '$')
+        sd = script_rid2sd (st);
+
+    for (i = 0; i < sz; i++)
+        set_reg (sd, num + (i << 24), name, get_val2 (st, num2 + (i << 24)));
+    return 0;
+}
+
+/*==========================================
+ * 配列変数のサイズ所得
+ *------------------------------------------
+ */
+static int getarraysize (struct script_state *st, int num, int postfix)
+{
+    int  i = (num >> 24), c = i;
+    for (; i < 128; i++)
+    {
+        void *v = get_val2 (st, num + (i << 24));
+        if (postfix == '$' && *((char *) v))
+            c = i;
+        if (postfix != '$' && (int) v)
+            c = i;
+    }
+    return c + 1;
+}
+
+int buildin_getarraysize (struct script_state *st)
+{
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+
+    if (prefix != '$' && prefix != '@')
+    {
+        printf ("buildin_copyarray: illegal scope !\n");
+        return 0;
+    }
+
+    push_val (st->stack, C_INT, getarraysize (st, num, postfix));
+    return 0;
+}
+
+/*==========================================
+ * 配列変数から要素削除
+ *------------------------------------------
+ */
+int buildin_deletearray (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  num = st->stack->stack_data[st->start + 2].u.num;
+    char *name = str_buf + str_data[num & 0x00ffffff].str;
+    char prefix = *name;
+    char postfix = name[strlen (name) - 1];
+    int  count = 1;
+    int  i, sz = getarraysize (st, num, postfix) - (num >> 24) - count + 1;
+
+    if ((st->end > st->start + 3))
+        count = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    if (prefix != '$' && prefix != '@')
+    {
+        printf ("buildin_deletearray: illegal scope !\n");
+        return 0;
+    }
+    if (prefix != '$')
+        sd = script_rid2sd (st);
+
+    for (i = 0; i < sz; i++)
+    {
+        set_reg (sd, num + (i << 24), name,
+                 get_val2 (st, num + ((i + count) << 24)));
+    }
+    for (; i < (128 - (num >> 24)); i++)
+    {
+        if (postfix != '$')
+            set_reg (sd, num + (i << 24), name, 0);
+        if (postfix == '$')
+            set_reg (sd, num + (i << 24), name, "");
+    }
+    return 0;
+}
+
+/*==========================================
+ * 指定要素を表す値(キー)を所得する
+ *------------------------------------------
+ */
+int buildin_getelementofarray (struct script_state *st)
+{
+    if (st->stack->stack_data[st->start + 2].type == C_NAME)
+    {
+        int  i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+        if (i > 127 || i < 0)
+        {
+            printf
+                ("script: getelementofarray (operator[]): param2 illegal number %d\n",
+                 i);
+            push_val (st->stack, C_INT, 0);
+        }
+        else
+        {
+            push_val (st->stack, C_NAME,
+                      (i << 24) | st->stack->stack_data[st->start + 2].u.num);
+        }
+    }
+    else
+    {
+        printf
+            ("script: getelementofarray (operator[]): param1 not name !\n");
+        push_val (st->stack, C_INT, 0);
+    }
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_setlook (struct script_state *st)
+{
+    int  type, val;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    pc_changelook (script_rid2sd (st), type, val);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_cutin (struct script_state *st)
+{
+    int  type;
+
+    conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    clif_cutin (script_rid2sd (st),
+                st->stack->stack_data[st->start + 2].u.str, type);
+
+    return 0;
+}
+
+/*==========================================
+ * カードのイラストを表示する
+ *------------------------------------------
+ */
+int buildin_cutincard (struct script_state *st)
+{
+    int  itemid;
+
+    itemid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    clif_cutin (script_rid2sd (st), itemdb_search (itemid)->cardillustname,
+                4);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_viewpoint (struct script_state *st)
+{
+    int  type, x, y, id, color;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    id = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    color = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+
+    clif_viewpoint (script_rid2sd (st), st->oid, type, x, y, id, color);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_countitem (struct script_state *st)
+{
+    int  nameid = 0, count = 0, i;
+    struct map_session_data *sd;
+
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        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 = conv_num (st, data);
+
+    if (nameid >= 500)          //if no such ID then skip this iteration
+        for (i = 0; i < MAX_INVENTORY; i++)
+        {
+            if (sd->status.inventory[i].nameid == nameid)
+                count += sd->status.inventory[i].amount;
+        }
+    else
+    {
+        if (battle_config.error_log)
+            printf ("wrong item ID : countitem(%i)\n", nameid);
+    }
+    push_val (st->stack, C_INT, count);
+
+    return 0;
+}
+
+/*==========================================
+ * 重量チェック
+ *------------------------------------------
+ */
+int buildin_checkweight (struct script_state *st)
+{
+    int  nameid = 0, amount;
+    struct map_session_data *sd;
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        if (item_data)
+            nameid = item_data->nameid;
+    }
+    else
+        nameid = conv_num (st, data);
+
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (amount <= 0 || nameid < 500)
+    {                           //if get wrong item ID or amount<=0, don't count weight of non existing items
+        push_val (st->stack, C_INT, 0);
+    }
+
+    sd = script_rid2sd (st);
+    if (itemdb_weight (nameid) * amount + sd->weight > sd->max_weight)
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_getitem (struct script_state *st)
+{
+    int  nameid, amount, flag = 0;
+    struct item item_tmp;
+    struct map_session_data *sd;
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        nameid = 727;           //Default to iten
+        if (item_data != NULL)
+            nameid = item_data->nameid;
+    }
+    else
+        nameid = conv_num (st, data);
+
+    if ((amount =
+         conv_num (st, &(st->stack->stack_data[st->start + 3]))) <= 0)
+    {
+        return 0;               //return if amount <=0, skip the useles iteration
+    }
+    //Violet Box, Blue Box, etc - random item pick
+    if (nameid < 0)
+    {                           // ランダム
+        nameid = itemdb_searchrandomid (-nameid);
+        flag = 1;
+    }
+
+    if (nameid > 0)
+    {
+        memset (&item_tmp, 0, sizeof (item_tmp));
+        item_tmp.nameid = nameid;
+        if (!flag)
+            item_tmp.identify = 1;
+        else
+            item_tmp.identify = !itemdb_isequip3 (nameid);
+        if (st->end > st->start + 5)    //アイテムを指定したIDに渡す
+            sd = map_id2sd (conv_num
+                            (st, &(st->stack->stack_data[st->start + 5])));
+        if (sd == NULL)         //アイテムを渡す相手がいなかったらお帰り
+            return 0;
+        if ((flag = pc_additem (sd, &item_tmp, amount)))
+        {
+            clif_additem (sd, 0, 0, flag);
+            map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
+                              NULL, NULL, NULL, 0);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_getitem2 (struct script_state *st)
+{
+    int  nameid, amount, flag = 0;
+    int  iden, ref, attr, c1, c2, c3, c4;
+    struct item_data *item_data;
+    struct item item_tmp;
+    struct map_session_data *sd;
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        nameid = 512;           //Apple item ID
+        if (item_data)
+            nameid = item_data->nameid;
+    }
+    else
+        nameid = conv_num (st, data);
+
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    iden = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    ref = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    attr = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    c1 = conv_num (st, &(st->stack->stack_data[st->start + 7]));
+    c2 = conv_num (st, &(st->stack->stack_data[st->start + 8]));
+    c3 = conv_num (st, &(st->stack->stack_data[st->start + 9]));
+    c4 = conv_num (st, &(st->stack->stack_data[st->start + 10]));
+    if (st->end > st->start + 11)   //アイテムを指定したIDに渡す
+        sd = map_id2sd (conv_num
+                        (st, &(st->stack->stack_data[st->start + 11])));
+    if (sd == NULL)             //アイテムを渡す相手がいなかったらお帰り
+        return 0;
+
+    if (nameid < 0)
+    {                           // ランダム
+        nameid = itemdb_searchrandomid (-nameid);
+        flag = 1;
+    }
+
+    if (nameid > 0)
+    {
+        memset (&item_tmp, 0, sizeof (item_tmp));
+        item_data = itemdb_search (nameid);
+        if (item_data->type == 4 || item_data->type == 5)
+        {
+            if (ref > 10)
+                ref = 10;
+        }
+        else if (item_data->type == 7)
+        {
+            iden = 1;
+            ref = 0;
+        }
+        else
+        {
+            iden = 1;
+            ref = attr = 0;
+        }
+
+        item_tmp.nameid = nameid;
+        if (!flag)
+            item_tmp.identify = iden;
+        else if (item_data->type == 4 || item_data->type == 5)
+            item_tmp.identify = 0;
+        item_tmp.refine = ref;
+        item_tmp.attribute = attr;
+        item_tmp.card[0] = c1;
+        item_tmp.card[1] = c2;
+        item_tmp.card[2] = c3;
+        item_tmp.card[3] = c4;
+        if ((flag = pc_additem (sd, &item_tmp, amount)))
+        {
+            clif_additem (sd, 0, 0, flag);
+            map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
+                              NULL, NULL, NULL, 0);
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_makeitem (struct script_state *st)
+{
+    int  nameid, amount, flag = 0;
+    int  x, y, m;
+    char *mapname;
+    struct item item_tmp;
+    struct map_session_data *sd;
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        nameid = 512;           //Apple Item ID
+        if (item_data)
+            nameid = item_data->nameid;
+    }
+    else
+        nameid = conv_num (st, data);
+
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+
+    if (sd && strcmp (mapname, "this") == 0)
+        m = sd->bl.m;
+    else
+        m = map_mapname2mapid (mapname);
+
+    if (nameid < 0)
+    {                           // ランダム
+        nameid = itemdb_searchrandomid (-nameid);
+        flag = 1;
+    }
+
+    if (nameid > 0)
+    {
+        memset (&item_tmp, 0, sizeof (item_tmp));
+        item_tmp.nameid = nameid;
+        if (!flag)
+            item_tmp.identify = 1;
+        else
+            item_tmp.identify = !itemdb_isequip3 (nameid);
+
+//      clif_additem(sd,0,0,flag);
+        map_addflooritem (&item_tmp, amount, m, x, y, NULL, NULL, NULL, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_delitem (struct script_state *st)
+{
+    int  nameid = 0, amount, i;
+    struct map_session_data *sd;
+    struct script_data *data;
+
+    sd = script_rid2sd (st);
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        //nameid=512;
+        if (item_data)
+            nameid = item_data->nameid;
+    }
+    else
+        nameid = conv_num (st, data);
+
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    if (nameid < 500 || amount <= 0)
+    {                           //by Lupus. Don't run FOR if u got wrong item ID or amount<=0
+        //printf("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount);
+        return 0;
+    }
+    sd = script_rid2sd (st);
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid <= 0
+            || sd->inventory_data[i] == NULL
+            || sd->inventory_data[i]->type != 7
+            || sd->status.inventory[i].amount <= 0)
+            continue;
+    }
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid == nameid)
+        {
+            if (sd->status.inventory[i].amount >= amount)
+            {
+                pc_delitem (sd, i, amount, 0);
+                break;
+            }
+            else
+            {
+                amount -= sd->status.inventory[i].amount;
+                if (amount == 0)
+                    amount = sd->status.inventory[i].amount;
+                pc_delitem (sd, i, amount, 0);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *キャラ関係のパラメータ取得
+ *------------------------------------------
+ */
+int buildin_readparam (struct script_state *st)
+{
+    int  type;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (st->end > st->start + 3)
+        sd = map_nick2sd (conv_str
+                          (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        sd = script_rid2sd (st);
+
+    if (sd == NULL)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+
+    push_val (st->stack, C_INT, pc_readparam (sd, type));
+
+    return 0;
+}
+
+/*==========================================
+ *キャラ関係のID取得
+ *------------------------------------------
+ */
+int buildin_getcharid (struct script_state *st)
+{
+    int  num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (st->end > st->start + 3)
+        sd = map_nick2sd (conv_str
+                          (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        sd = script_rid2sd (st);
+    if (sd == NULL)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+    if (num == 0)
+        push_val (st->stack, C_INT, sd->status.char_id);
+    if (num == 1)
+        push_val (st->stack, C_INT, sd->status.party_id);
+    if (num == 2)
+        push_val (st->stack, C_INT, sd->status.guild_id);
+    if (num == 3)
+        push_val (st->stack, C_INT, sd->status.account_id);
+    return 0;
+}
+
+/*==========================================
+ *指定IDのPT名取得
+ *------------------------------------------
+ */
+char *buildin_getpartyname_sub (int party_id)
+{
+    struct party *p;
+
+    p = NULL;
+    p = party_search (party_id);
+
+    if (p != NULL)
+    {
+        char *buf;
+        buf = (char *) calloc (24, 1);
+        strcpy (buf, p->name);
+        return buf;
+    }
+
+    return 0;
+}
+
+int buildin_getpartyname (struct script_state *st)
+{
+    char *name;
+    int  party_id;
+
+    party_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    name = buildin_getpartyname_sub (party_id);
+    if (name != 0)
+        push_str (st->stack, C_STR, name);
+    else
+        push_str (st->stack, C_CONSTSTR, "null");
+
+    return 0;
+}
+
+/*==========================================
+ *指定IDのPT人数とメンバーID取得
+ *------------------------------------------
+ */
+int buildin_getpartymember (struct script_state *st)
+{
+    struct party *p;
+    int  i, j = 0;
+
+    p = NULL;
+    p = party_search (conv_num (st, &(st->stack->stack_data[st->start + 2])));
+
+    if (p != NULL)
+    {
+        for (i = 0; i < MAX_PARTY; i++)
+        {
+            if (p->member[i].account_id)
+            {
+//              printf("name:%s %d\n",p->member[i].name,i);
+                mapreg_setregstr (add_str ("$@partymembername$") + (i << 24),
+                                  p->member[i].name);
+                j++;
+            }
+        }
+    }
+    mapreg_setreg (add_str ("$@partymembercount"), j);
+
+    return 0;
+}
+
+/*==========================================
+ *指定IDのギルド名取得
+ *------------------------------------------
+ */
+char *buildin_getguildname_sub (int guild_id)
+{
+    struct guild *g = NULL;
+    g = guild_search (guild_id);
+
+    if (g != NULL)
+    {
+        char *buf;
+        buf = (char *) calloc (24, 1);
+        strcpy (buf, g->name);
+        return buf;
+    }
+    return 0;
+}
+
+int buildin_getguildname (struct script_state *st)
+{
+    char *name;
+    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    name = buildin_getguildname_sub (guild_id);
+    if (name != 0)
+        push_str (st->stack, C_STR, name);
+    else
+        push_str (st->stack, C_CONSTSTR, "null");
+    return 0;
+}
+
+/*==========================================
+ *指定IDのGuildMaster名取得
+ *------------------------------------------
+ */
+char *buildin_getguildmaster_sub (int guild_id)
+{
+    struct guild *g = NULL;
+    g = guild_search (guild_id);
+
+    if (g != NULL)
+    {
+        char *buf;
+        buf = (char *) calloc (24, 1);
+        strncpy (buf, g->master, 23);
+        return buf;
+    }
+
+    return 0;
+}
+
+int buildin_getguildmaster (struct script_state *st)
+{
+    char *master;
+    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    master = buildin_getguildmaster_sub (guild_id);
+    if (master != 0)
+        push_str (st->stack, C_STR, master);
+    else
+        push_str (st->stack, C_CONSTSTR, "null");
+    return 0;
+}
+
+int buildin_getguildmasterid (struct script_state *st)
+{
+    char *master;
+    struct map_session_data *sd = NULL;
+    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    master = buildin_getguildmaster_sub (guild_id);
+    if (master != 0)
+    {
+        if ((sd = map_nick2sd (master)) == NULL)
+        {
+            push_val (st->stack, C_INT, 0);
+            return 0;
+        }
+        push_val (st->stack, C_INT, sd->status.char_id);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+    return 0;
+}
+
+/*==========================================
+ * キャラクタの名前
+ *------------------------------------------
+ */
+int buildin_strcharinfo (struct script_state *st)
+{
+    struct map_session_data *sd;
+    int  num;
+
+    sd = script_rid2sd (st);
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (num == 0)
+    {
+        char *buf;
+        buf = (char *) calloc (24, 1);
+        strncpy (buf, sd->status.name, 23);
+        push_str (st->stack, C_STR, buf);
+    }
+    if (num == 1)
+    {
+        char *buf;
+        buf = buildin_getpartyname_sub (sd->status.party_id);
+        if (buf != 0)
+            push_str (st->stack, C_STR, buf);
+        else
+            push_str (st->stack, C_CONSTSTR, "");
+    }
+    if (num == 2)
+    {
+        char *buf;
+        buf = buildin_getguildname_sub (sd->status.guild_id);
+        if (buf != 0)
+            push_str (st->stack, C_STR, buf);
+        else
+            push_str (st->stack, C_CONSTSTR, "");
+    }
+
+    return 0;
+}
+
+unsigned int equip[10] =
+    { 0x0100, 0x0010, 0x0020, 0x0002, 0x0004, 0x0040, 0x0008, 0x0080, 0x0200,
+    0x0001
+};
+
+/*==========================================
+ * GetEquipID(Pos);     Pos: 1-10
+ *------------------------------------------
+ */
+int buildin_getequipid (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+    struct item_data *item;
+
+    sd = script_rid2sd (st);
+    if (sd == NULL)
+    {
+        printf ("getequipid: sd == NULL\n");
+        return 0;
+    }
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+    {
+        item = sd->inventory_data[i];
+        if (item)
+            push_val (st->stack, C_INT, item->nameid);
+        else
+            push_val (st->stack, C_INT, 0);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, -1);
+    }
+    return 0;
+}
+
+/*==========================================
+ * 装備名文字列(精錬メニュー用)
+ *------------------------------------------
+ */
+int buildin_getequipname (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+    struct item_data *item;
+    char *buf;
+
+    buf = (char *) calloc (64, 1);
+    sd = script_rid2sd (st);
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+    {
+        item = sd->inventory_data[i];
+        if (item)
+            sprintf (buf, "%s-[%s]", pos[num - 1], item->jname);
+        else
+            sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
+    }
+    else
+    {
+        sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
+    }
+    push_str (st->stack, C_STR, buf);
+
+    return 0;
+}
+
+/*==========================================
+ * getbrokenid [Valaris]
+ *------------------------------------------
+ */
+int buildin_getbrokenid (struct script_state *st)
+{
+    int  i, num, id = 0, brokencounter = 0;
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].broken == 1)
+        {
+            brokencounter++;
+            if (num == brokencounter)
+            {
+                id = sd->status.inventory[i].nameid;
+                break;
+            }
+        }
+    }
+
+    push_val (st->stack, C_INT, id);
+
+    return 0;
+}
+
+/*==========================================
+ * repair [Valaris]
+ *------------------------------------------
+ */
+int buildin_repair (struct script_state *st)
+{
+    int  i, num;
+    int  repaircounter = 0;
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].broken == 1)
+        {
+            repaircounter++;
+            if (num == repaircounter)
+            {
+                sd->status.inventory[i].broken = 0;
+                clif_equiplist (sd);
+                clif_produceeffect (sd, 0, sd->status.inventory[i].nameid);
+                clif_misceffect (&sd->bl, 3);
+                clif_displaymessage (sd->fd, "Item has been repaired.");
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 装備チェック
+ *------------------------------------------
+ */
+int buildin_getequipisequiped (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品精錬可能チェック
+ *------------------------------------------
+ */
+int buildin_getequipisenableref (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0 && num < 7 && sd->inventory_data[i]
+        && (num != 1 || sd->inventory_data[i]->def > 1
+            || (sd->inventory_data[i]->def == 1
+                && sd->inventory_data[i]->equip_script == NULL)
+            || (sd->inventory_data[i]->def <= 0
+                && sd->inventory_data[i]->equip_script != NULL)))
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品鑑定チェック
+ *------------------------------------------
+ */
+int buildin_getequipisidentify (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+        push_val (st->stack, C_INT, sd->status.inventory[i].identify);
+    else
+        push_val (st->stack, C_INT, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品精錬度
+ *------------------------------------------
+ */
+int buildin_getequiprefinerycnt (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+        push_val (st->stack, C_INT, sd->status.inventory[i].refine);
+    else
+        push_val (st->stack, C_INT, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品武器LV
+ *------------------------------------------
+ */
+int buildin_getequipweaponlv (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0 && sd->inventory_data[i])
+        push_val (st->stack, C_INT, sd->inventory_data[i]->wlv);
+    else
+        push_val (st->stack, C_INT, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品精錬成功率
+ *------------------------------------------
+ */
+int buildin_getequippercentrefinery (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+        push_val (st->stack, C_INT,
+                  pc_percentrefinery (sd, &sd->status.inventory[i]));
+    else
+        push_val (st->stack, C_INT, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * 精錬成功
+ *------------------------------------------
+ */
+int buildin_successrefitem (struct script_state *st)
+{
+    int  i, num, ep;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+    {
+        ep = sd->status.inventory[i].equip;
+
+        sd->status.inventory[i].refine++;
+        pc_unequipitem (sd, i, 0);
+        clif_refine (sd->fd, sd, 0, i, sd->status.inventory[i].refine);
+        clif_delitem (sd, i, 1);
+        clif_additem (sd, i, 1, 0);
+        pc_equipitem (sd, i, ep);
+        clif_misceffect (&sd->bl, 3);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 精錬失敗
+ *------------------------------------------
+ */
+int buildin_failedrefitem (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (i >= 0)
+    {
+        sd->status.inventory[i].refine = 0;
+        pc_unequipitem (sd, i, 0);
+        // 精錬失敗エフェクトのパケット
+        clif_refine (sd->fd, sd, 1, i, sd->status.inventory[i].refine);
+        pc_delitem (sd, i, 1, 0);
+        // 他の人にも失敗を通知
+        clif_misceffect (&sd->bl, 2);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_statusup (struct script_state *st)
+{
+    int  type;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    pc_statusup (sd, type);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_statusup2 (struct script_state *st)
+{
+    int  type, val;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    sd = script_rid2sd (st);
+    pc_statusup2 (sd, type, val);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品による能力値ボーナス
+ *------------------------------------------
+ */
+int buildin_bonus (struct script_state *st)
+{
+    int  type, val;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    sd = script_rid2sd (st);
+    pc_bonus (sd, type, val);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品による能力値ボーナス
+ *------------------------------------------
+ */
+int buildin_bonus2 (struct script_state *st)
+{
+    int  type, type2, val;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    val = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    sd = script_rid2sd (st);
+    pc_bonus2 (sd, type, type2, val);
+
+    return 0;
+}
+
+/*==========================================
+ * 装備品による能力値ボーナス
+ *------------------------------------------
+ */
+int buildin_bonus3 (struct script_state *st)
+{
+    int  type, type2, type3, val;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    type3 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    val = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    sd = script_rid2sd (st);
+    pc_bonus3 (sd, type, type2, type3, val);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル所得
+ *------------------------------------------
+ */
+int buildin_skill (struct script_state *st)
+{
+    int  id, level, flag = 1;
+    struct map_session_data *sd;
+
+    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (st->end > st->start + 4)
+        flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    sd = script_rid2sd (st);
+    pc_skill (sd, id, level, flag);
+    clif_skillinfoblock (sd);
+
+    return 0;
+}
+
+/*==========================================
+ * [Fate] Sets the skill level permanently
+ *------------------------------------------
+ */
+int buildin_setskill (struct script_state *st)
+{
+    int  id, level;
+    struct map_session_data *sd;
+
+    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    sd = script_rid2sd (st);
+
+    sd->status.skill[id].id = level ? id : 0;
+    sd->status.skill[id].lv = level;
+    clif_skillinfoblock (sd);
+    return 0;
+}
+
+/*==========================================
+ * ギルドスキル取得
+ *------------------------------------------
+ */
+int buildin_guildskill (struct script_state *st)
+{
+    int  id, level;
+    struct map_session_data *sd;
+    int  i = 0;
+
+    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+//  if( st->end>st->start+4 )
+//      flag=conv_num(st,&(st->stack->stack_data[st->start+4]) );
+    sd = script_rid2sd (st);
+    for (i = 0; i < level; i++)
+        guild_skillup (sd, id);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルレベル所得
+ *------------------------------------------
+ */
+int buildin_getskilllv (struct script_state *st)
+{
+    int  id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    push_val (st->stack, C_INT, pc_checkskill (script_rid2sd (st), id));
+    return 0;
+}
+
+/*==========================================
+ * getgdskilllv(Guild_ID, Skill_ID);
+ * skill_id = 10000 : GD_APPROVAL
+ *            10001 : GD_KAFRACONTACT
+ *            10002 : GD_GUARDIANRESEARCH
+ *            10003 : GD_CHARISMA
+ *            10004 : GD_EXTENSION
+ *------------------------------------------
+ */
+int buildin_getgdskilllv (struct script_state *st)
+{
+    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    struct guild *g = guild_search (guild_id);
+    push_val (st->stack, C_INT,
+              (g == NULL) ? -1 : guild_checkskill (g, skill_id));
+    return 0;
+/*
+	struct map_session_data *sd=NULL;
+	struct guild *g=NULL;
+	int skill_id;
+
+	skill_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
+	sd=script_rid2sd(st);
+	if(sd && sd->status.guild_id > 0) g=guild_search(sd->status.guild_id);
+	if(sd && g) {
+		push_val(st->stack,C_INT, guild_checkskill(g,skill_id+9999) );
+	} else {
+		push_val(st->stack,C_INT,-1);
+	}
+	return 0;
+*/
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_basicskillcheck (struct script_state *st)
+{
+    push_val (st->stack, C_INT, battle_config.basic_skill_check);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_getgmlevel (struct script_state *st)
+{
+    push_val (st->stack, C_INT, pc_isGM (script_rid2sd (st)));
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_end (struct script_state *st)
+{
+    st->state = END;
+    return 0;
+}
+
+/*==========================================
+ * [Freeyorp] Return the current opt2
+ *------------------------------------------
+ */
+
+int buildin_getopt2 (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    push_val (st->stack, C_INT, sd->opt2);
+
+    return 0;
+}
+
+/*==========================================
+ * [Freeyorp] Sets opt2
+ *------------------------------------------
+ */
+
+int buildin_setopt2 (struct script_state *st)
+{
+    int  new_opt2;
+    struct map_session_data *sd;
+
+    new_opt2 = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    if (new_opt2 == sd->opt2)
+        return 0;
+    sd->opt2 = new_opt2;
+    clif_changeoption (&sd->bl);
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_checkoption (struct script_state *st)
+{
+    int  type;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+
+    if (sd->status.option & type)
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_setoption (struct script_state *st)
+{
+    int  type;
+    struct map_session_data *sd;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    pc_setoption (sd, type);
+
+    return 0;
+}
+
+/*==========================================
+ * Checkcart [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_checkcart (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    if (pc_iscarton (sd))
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+    return 0;
+}
+
+/*==========================================
+ * カートを付ける
+ *------------------------------------------
+ */
+int buildin_setcart (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+    pc_setcart (sd, 1);
+
+    return 0;
+}
+
+/*==========================================
+ * checkfalcon [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_checkfalcon (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    if (pc_isfalcon (sd))
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * 鷹を付ける
+ *------------------------------------------
+ */
+int buildin_setfalcon (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+    pc_setfalcon (sd);
+
+    return 0;
+}
+
+/*==========================================
+ * Checkcart [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_checkriding (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    if (pc_isriding (sd))
+    {
+        push_val (st->stack, C_INT, 1);
+    }
+    else
+    {
+        push_val (st->stack, C_INT, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * ペコペコ乗り
+ *------------------------------------------
+ */
+int buildin_setriding (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+    pc_setriding (sd);
+
+    return 0;
+}
+
+/*==========================================
+ *	セーブポイントの保存
+ *------------------------------------------
+ */
+int buildin_savepoint (struct script_state *st)
+{
+    int  x, y;
+    char *str;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    pc_setsavepoint (script_rid2sd (st), str, x, y);
+    return 0;
+}
+
+/*==========================================
+ * gettimetick(type)
+ *
+ * type The type of time measurement.
+ *  Specify 0 for the system tick, 1 for
+ *  seconds elapsed today, or 2 for seconds
+ *  since Unix epoch. Defaults to 0 for any
+ *  other value.
+ *------------------------------------------
+ */
+int buildin_gettimetick (struct script_state *st)   /* Asgard Version */
+{
+    int  type;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    switch (type)
+    {
+        /* Number of seconds elapsed today (0-86399, 00:00:00-23:59:59). */
+        case 1:
+        {
+            time_t timer;
+            struct tm *t;
+
+            time (&timer);
+            t = gmtime (&timer);
+            push_val (st->stack, C_INT,
+                      ((t->tm_hour) * 3600 + (t->tm_min) * 60 + t->tm_sec));
+            break;
+        }
+        /* Seconds since Unix epoch. */
+        case 2:
+            push_val (st->stack, C_INT, (int) time (NULL));
+            break;
+        /* System tick (unsigned int, and yes, it will wrap). */
+        case 0:
+        default:
+            push_val (st->stack, C_INT, gettick ());
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * GetTime(Type);
+ * 1: Sec     2: Min     3: Hour
+ * 4: WeekDay     5: MonthDay     6: Month
+ * 7: Year
+ *------------------------------------------
+ */
+int buildin_gettime (struct script_state *st)   /* Asgard Version */
+{
+    int  type;
+    time_t timer;
+    struct tm *t;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    time (&timer);
+    t = gmtime (&timer);
+
+    switch (type)
+    {
+        case 1:                //Sec(0~59)
+            push_val (st->stack, C_INT, t->tm_sec);
+            break;
+        case 2:                //Min(0~59)
+            push_val (st->stack, C_INT, t->tm_min);
+            break;
+        case 3:                //Hour(0~23)
+            push_val (st->stack, C_INT, t->tm_hour);
+            break;
+        case 4:                //WeekDay(0~6)
+            push_val (st->stack, C_INT, t->tm_wday);
+            break;
+        case 5:                //MonthDay(01~31)
+            push_val (st->stack, C_INT, t->tm_mday);
+            break;
+        case 6:                //Month(01~12)
+            push_val (st->stack, C_INT, t->tm_mon + 1);
+            break;
+        case 7:                //Year(20xx)
+            push_val (st->stack, C_INT, t->tm_year + 1900);
+            break;
+        default:               //(format error)
+            push_val (st->stack, C_INT, -1);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * GetTimeStr("TimeFMT", Length);
+ *------------------------------------------
+ */
+int buildin_gettimestr (struct script_state *st)
+{
+    char *tmpstr;
+    char *fmtstr;
+    int  maxlen;
+    time_t now = time (NULL);
+
+    fmtstr = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    maxlen = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    tmpstr = (char *) calloc (maxlen + 1, 1);
+    strftime (tmpstr, maxlen, fmtstr, gmtime (&now));
+    tmpstr[maxlen] = '\0';
+
+    push_str (st->stack, C_STR, tmpstr);
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫を開く
+ *------------------------------------------
+ */
+int buildin_openstorage (struct script_state *st)
+{
+//  int sync = 0;
+//  if (st->end >= 3) sync = conv_num(st,& (st->stack->stack_data[st->start+2]));
+    struct map_session_data *sd = script_rid2sd (st);
+
+//  if (sync) {
+    st->state = STOP;
+    sd->npc_flags.storage = 1;
+//  } else st->state = END;
+
+    storage_storageopen (sd);
+    return 0;
+}
+
+int buildin_guildopenstorage (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  ret;
+    st->state = STOP;
+    ret = storage_guild_storageopen (sd);
+    push_val (st->stack, C_INT, ret);
+    return 0;
+}
+
+/*==========================================
+ * アイテムによるスキル発動
+ *------------------------------------------
+ */
+int buildin_itemskill (struct script_state *st)
+{
+    int  id, lv;
+    char *str;
+    struct map_session_data *sd = script_rid2sd (st);
+
+    id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    lv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+
+    // 詠唱中にスキルアイテムは使用できない
+    if (sd->skilltimer != -1)
+        return 0;
+
+    sd->skillitem = id;
+    sd->skillitemlv = lv;
+    clif_item_skill (sd, id, lv, str);
+    return 0;
+}
+
+/*==========================================
+ * NPCで経験値上げる
+ *------------------------------------------
+ */
+int buildin_getexp (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  base = 0, job = 0;
+
+    base = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    job = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (base < 0 || job < 0)
+        return 0;
+    if (sd)
+        pc_gainexp_reason (sd, base, job, PC_GAINEXP_REASON_SCRIPT);
+
+    return 0;
+}
+
+/*==========================================
+ * モンスター発生
+ *------------------------------------------
+ */
+int buildin_monster (struct script_state *st)
+{
+    int  mob_class, amount, x, y;
+    char *str, *map, *event = "";
+
+    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
+    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
+    if (st->end > st->start + 8)
+        event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
+
+    mob_once_spawn (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
+                    event);
+    return 0;
+}
+
+/*==========================================
+ * モンスター発生
+ *------------------------------------------
+ */
+int buildin_areamonster (struct script_state *st)
+{
+    int  mob_class, amount, x0, y0, x1, y1;
+    char *str, *map, *event = "";
+
+    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
+    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 8]));
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 9]));
+    if (st->end > st->start + 10)
+        event = conv_str (st, &(st->stack->stack_data[st->start + 10]));
+
+    mob_once_spawn_area (map_id2sd (st->rid), map, x0, y0, x1, y1, str, mob_class,
+                         amount, event);
+    return 0;
+}
+
+/*==========================================
+ * モンスター削除
+ *------------------------------------------
+ */
+int buildin_killmonster_sub (struct block_list *bl, va_list ap)
+{
+    char *event = va_arg (ap, char *);
+    int  allflag = va_arg (ap, int);
+
+    if (!allflag)
+    {
+        if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
+            mob_delete ((struct mob_data *) bl);
+        return 0;
+    }
+    else if (allflag)
+    {
+        if (((struct mob_data *) bl)->spawndelay1 == -1
+            && ((struct mob_data *) bl)->spawndelay2 == -1)
+            mob_delete ((struct mob_data *) bl);
+        return 0;
+    }
+    return 0;
+}
+
+int buildin_killmonster (struct script_state *st)
+{
+    char *mapname, *event;
+    int  m, allflag = 0;
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    if (strcmp (event, "All") == 0)
+        allflag = 1;
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+    map_foreachinarea (buildin_killmonster_sub,
+                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, allflag);
+    return 0;
+}
+
+int buildin_killmonsterall_sub (struct block_list *bl, va_list ap)
+{
+    mob_delete ((struct mob_data *) bl);
+    return 0;
+}
+
+int buildin_killmonsterall (struct script_state *st)
+{
+    char *mapname;
+    int  m;
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+    map_foreachinarea (buildin_killmonsterall_sub,
+                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB);
+    return 0;
+}
+
+/*==========================================
+ * イベント実行
+ *------------------------------------------
+ */
+int buildin_doevent (struct script_state *st)
+{
+    char *event;
+    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_event (map_id2sd (st->rid), event, 0);
+    return 0;
+}
+
+/*==========================================
+ * NPC主体イベント実行
+ *------------------------------------------
+ */
+int buildin_donpcevent (struct script_state *st)
+{
+    char *event;
+    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_event_do (event);
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマー追加
+ *------------------------------------------
+ */
+int buildin_addtimer (struct script_state *st)
+{
+    char *event;
+    int  tick;
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    pc_addeventtimer (script_rid2sd (st), tick, event);
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマー削除
+ *------------------------------------------
+ */
+int buildin_deltimer (struct script_state *st)
+{
+    char *event;
+    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    pc_deleventtimer (script_rid2sd (st), event);
+    return 0;
+}
+
+/*==========================================
+ * イベントタイマーのカウント値追加
+ *------------------------------------------
+ */
+int buildin_addtimercount (struct script_state *st)
+{
+    char *event;
+    int  tick;
+    event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    pc_addeventtimercount (script_rid2sd (st), event, tick);
+    return 0;
+}
+
+/*==========================================
+ * NPCタイマー初期化
+ *------------------------------------------
+ */
+int buildin_initnpctimer (struct script_state *st)
+{
+    struct npc_data *nd;
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    npc_settimerevent_tick (nd, 0);
+    npc_timerevent_start (nd);
+    return 0;
+}
+
+/*==========================================
+ * NPCタイマー開始
+ *------------------------------------------
+ */
+int buildin_startnpctimer (struct script_state *st)
+{
+    struct npc_data *nd;
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    npc_timerevent_start (nd);
+    return 0;
+}
+
+/*==========================================
+ * NPCタイマー停止
+ *------------------------------------------
+ */
+int buildin_stopnpctimer (struct script_state *st)
+{
+    struct npc_data *nd;
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    npc_timerevent_stop (nd);
+    return 0;
+}
+
+/*==========================================
+ * NPCタイマー情報所得
+ *------------------------------------------
+ */
+int buildin_getnpctimer (struct script_state *st)
+{
+    struct npc_data *nd;
+    int  type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  val = 0;
+    if (st->end > st->start + 3)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    switch (type)
+    {
+        case 0:
+            val = npc_gettimerevent_tick (nd);
+            break;
+        case 1:
+            val = (nd->u.scr.nexttimer >= 0);
+            break;
+        case 2:
+            val = nd->u.scr.timeramount;
+            break;
+    }
+    push_val (st->stack, C_INT, val);
+    return 0;
+}
+
+/*==========================================
+ * NPCタイマー値設定
+ *------------------------------------------
+ */
+int buildin_setnpctimer (struct script_state *st)
+{
+    int  tick;
+    struct npc_data *nd;
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (st->end > st->start + 3)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    npc_settimerevent_tick (nd, tick);
+    return 0;
+}
+
+/*==========================================
+ * 天の声アナウンス
+ *------------------------------------------
+ */
+int buildin_announce (struct script_state *st)
+{
+    char *str;
+    int  flag;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    flag = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    if (flag & 0x0f)
+    {
+        struct block_list *bl = (flag & 0x08) ? map_id2bl (st->oid) :
+            (struct block_list *) script_rid2sd (st);
+        clif_GMmessage (bl, str, strlen (str) + 1, flag);
+    }
+    else
+        intif_GMmessage (str, strlen (str) + 1, flag);
+    return 0;
+}
+
+/*==========================================
+ * 天の声アナウンス(特定マップ)
+ *------------------------------------------
+ */
+int buildin_mapannounce_sub (struct block_list *bl, va_list ap)
+{
+    char *str;
+    int  len, flag;
+    str = va_arg (ap, char *);
+    len = va_arg (ap, int);
+    flag = va_arg (ap, int);
+    clif_GMmessage (bl, str, len, flag | 3);
+    return 0;
+}
+
+int buildin_mapannounce (struct script_state *st)
+{
+    char *mapname, *str;
+    int  flag, m;
+
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+    map_foreachinarea (buildin_mapannounce_sub,
+                       m, 0, 0, map[m].xs, map[m].ys, BL_PC, str,
+                       strlen (str) + 1, flag & 0x10);
+    return 0;
+}
+
+/*==========================================
+ * 天の声アナウンス(特定エリア)
+ *------------------------------------------
+ */
+int buildin_areaannounce (struct script_state *st)
+{
+    char *map, *str;
+    int  flag, m;
+    int  x0, y0, x1, y1;
+
+    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
+    flag = conv_num (st, &(st->stack->stack_data[st->start + 8]));
+
+    if ((m = map_mapname2mapid (map)) < 0)
+        return 0;
+
+    map_foreachinarea (buildin_mapannounce_sub,
+                       m, x0, y0, x1, y1, BL_PC, str, strlen (str) + 1,
+                       flag & 0x10);
+    return 0;
+}
+
+/*==========================================
+ * ユーザー数所得
+ *------------------------------------------
+ */
+int buildin_getusers (struct script_state *st)
+{
+    int  flag = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    struct block_list *bl = map_id2bl ((flag & 0x08) ? st->oid : st->rid);
+    int  val = 0;
+    switch (flag & 0x07)
+    {
+        case 0:
+            val = map[bl->m].users;
+            break;
+        case 1:
+            val = map_getusers ();
+            break;
+    }
+    push_val (st->stack, C_INT, val);
+    return 0;
+}
+
+/*==========================================
+ * マップ指定ユーザー数所得
+ *------------------------------------------
+ */
+int buildin_getmapusers (struct script_state *st)
+{
+    char *str;
+    int  m;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    if ((m = map_mapname2mapid (str)) < 0)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+    push_val (st->stack, C_INT, map[m].users);
+    return 0;
+}
+
+/*==========================================
+ * エリア指定ユーザー数所得
+ *------------------------------------------
+ */
+int buildin_getareausers_sub (struct block_list *bl, va_list ap)
+{
+    int *users = va_arg (ap, int *);
+    (*users)++;
+    return 0;
+}
+int buildin_getareausers_living_sub (struct block_list *bl, va_list ap)
+{
+    int *users = va_arg (ap, int *);
+    if (!pc_isdead((struct map_session_data *)bl))
+        (*users)++;
+    return 0;
+}
+
+int buildin_getareausers (struct script_state *st)
+{
+    char *str;
+    int  m, x0, y0, x1, y1, users = 0;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+
+    int living = 0;
+    if (st->end > st->start + 7)
+    {
+        living = conv_num (st, &(st->stack->stack_data[st->start + 7]));
+    }
+    if ((m = map_mapname2mapid (str)) < 0)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+    map_foreachinarea (living ? buildin_getareausers_living_sub: buildin_getareausers_sub,
+                       m, x0, y0, x1, y1, BL_PC, &users);
+    push_val (st->stack, C_INT, users);
+    return 0;
+}
+
+/*==========================================
+ * エリア指定ドロップアイテム数所得
+ *------------------------------------------
+ */
+int buildin_getareadropitem_sub (struct block_list *bl, va_list ap)
+{
+    int  item = va_arg (ap, int);
+    int *amount = va_arg (ap, int *);
+    struct flooritem_data *drop = (struct flooritem_data *) bl;
+
+    if (drop->item_data.nameid == item)
+        (*amount) += drop->item_data.amount;
+
+    return 0;
+}
+
+int buildin_getareadropitem_sub_anddelete (struct block_list *bl, va_list ap)
+{
+    int  item = va_arg (ap, int);
+    int *amount = va_arg (ap, int *);
+    struct flooritem_data *drop = (struct flooritem_data *) bl;
+
+    if (drop->item_data.nameid == item) {
+        (*amount) += drop->item_data.amount;
+        clif_clearflooritem(drop, 0);
+        map_delobject(drop->bl.id, drop->bl.type);
+    }
+    return 0;
+}
+
+int buildin_getareadropitem (struct script_state *st)
+{
+    char *str;
+    int  m, x0, y0, x1, y1, item, amount = 0, delitems = 0;
+    struct script_data *data;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+
+    data = &(st->stack->stack_data[st->start + 7]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        struct item_data *item_data = itemdb_searchname (name);
+        item = 512;
+        if (item_data)
+            item = item_data->nameid;
+    }
+    else
+        item = conv_num (st, data);
+
+    if (st->end > st->start + 8)
+        delitems = conv_num (st, &(st->stack->stack_data[st->start + 8]));
+
+    if ((m = map_mapname2mapid (str)) < 0)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+    if (delitems)
+        map_foreachinarea (buildin_getareadropitem_sub_anddelete,
+                           m, x0, y0, x1, y1, BL_ITEM, item, &amount);
+    else
+        map_foreachinarea (buildin_getareadropitem_sub,
+                           m, x0, y0, x1, y1, BL_ITEM, item, &amount);
+
+    push_val (st->stack, C_INT, amount);
+    return 0;
+}
+
+/*==========================================
+ * NPCの有効化
+ *------------------------------------------
+ */
+int buildin_enablenpc (struct script_state *st)
+{
+    char *str;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_enable (str, 1);
+    return 0;
+}
+
+/*==========================================
+ * NPCの無効化
+ *------------------------------------------
+ */
+int buildin_disablenpc (struct script_state *st)
+{
+    char *str;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_enable (str, 0);
+    return 0;
+}
+
+int buildin_enablearena (struct script_state *st)   // Added by RoVeRT
+{
+    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
+    struct chat_data *cd;
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+        return 0;
+
+    npc_enable (nd->name, 1);
+    nd->arenaflag = 1;
+
+    if (cd->users >= cd->trigger && cd->npc_event[0])
+        npc_timer_event (cd->npc_event);
+
+    return 0;
+}
+
+int buildin_disablearena (struct script_state *st)  // Added by RoVeRT
+{
+    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
+    nd->arenaflag = 0;
+
+    return 0;
+}
+
+/*==========================================
+ * 隠れているNPCの表示
+ *------------------------------------------
+ */
+int buildin_hideoffnpc (struct script_state *st)
+{
+    char *str;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_enable (str, 2);
+    return 0;
+}
+
+/*==========================================
+ * NPCをハイディング
+ *------------------------------------------
+ */
+int buildin_hideonnpc (struct script_state *st)
+{
+    char *str;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    npc_enable (str, 4);
+    return 0;
+}
+
+/*==========================================
+ * 状態異常にかかる
+ *------------------------------------------
+ */
+int buildin_sc_start (struct script_state *st)
+{
+    struct block_list *bl;
+    int  type, tick, val1;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    if (st->end > st->start + 5)    //指定したキャラを状態異常にする
+        bl = map_id2bl (conv_num
+                        (st, &(st->stack->stack_data[st->start + 5])));
+    else
+        bl = map_id2bl (st->rid);
+    if (bl->type == BL_PC
+        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
+        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
+    skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
+    return 0;
+}
+
+/*==========================================
+ * 状態異常にかかる(確率指定)
+ *------------------------------------------
+ */
+int buildin_sc_start2 (struct script_state *st)
+{
+    struct block_list *bl;
+    int  type, tick, val1, per;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    per = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    if (st->end > st->start + 6)    //指定したキャラを状態異常にする
+        bl = map_id2bl (conv_num
+                        (st, &(st->stack->stack_data[st->start + 6])));
+    else
+        bl = map_id2bl (st->rid);
+    if (bl->type == BL_PC
+        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
+        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
+    if (MRAND (10000) < per)
+        skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
+    return 0;
+}
+
+/*==========================================
+ * 状態異常が直る
+ *------------------------------------------
+ */
+int buildin_sc_end (struct script_state *st)
+{
+    struct block_list *bl;
+    int  type;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    bl = map_id2bl (st->rid);
+    if (bl->type == BL_PC
+        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
+        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
+    skill_status_change_end (bl, type, -1);
+//  if(battle_config.etc_log)
+//      printf("sc_end : %d %d\n",st->rid,type);
+    return 0;
+}
+
+int buildin_sc_check (struct script_state *st)
+{
+    struct block_list *bl;
+    int  type;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    bl = map_id2bl (st->rid);
+    if (bl->type == BL_PC
+        && ((struct map_session_data *) bl)->state.potionpitcher_flag)
+        bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
+
+    push_val (st->stack, C_INT, skill_status_change_active (bl, type));
+
+    return 0;
+}
+
+/*==========================================
+ * 状態異常耐性を計算した確率を返す
+ *------------------------------------------
+ */
+int buildin_getscrate (struct script_state *st)
+{
+    struct block_list *bl;
+    int  sc_def = 100, sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2;
+    int  type, rate, luk;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    rate = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (st->end > st->start + 4)    //指定したキャラの耐性を計算する
+        bl = map_id2bl (conv_num
+                        (st, &(st->stack->stack_data[st->start + 6])));
+    else
+        bl = map_id2bl (st->rid);
+
+    luk = battle_get_luk (bl);
+    sc_def_mdef2 = 100 - (3 + battle_get_mdef (bl) + luk / 3);
+    sc_def_vit2 = 100 - (3 + battle_get_vit (bl) + luk / 3);
+    sc_def_int2 = 100 - (3 + battle_get_int (bl) + luk / 3);
+    sc_def_luk2 = 100 - (3 + luk);
+
+    if (type == SC_STONE || type == SC_FREEZE)
+        sc_def = sc_def_mdef2;
+    else if (type == SC_STAN || type == SC_POISON || type == SC_SILENCE)
+        sc_def = sc_def_vit2;
+    else if (type == SC_SLEEP || type == SC_CONFUSION || type == SC_BLIND)
+        sc_def = sc_def_int2;
+    else if (type == SC_CURSE)
+        sc_def = sc_def_luk2;
+
+    rate = rate * sc_def / 100;
+    push_val (st->stack, C_INT, rate);
+
+    return 0;
+
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_debugmes (struct script_state *st)
+{
+    conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    printf ("script debug : %d %d : %s\n", st->rid, st->oid,
+            st->stack->stack_data[st->start + 2].u.str);
+    return 0;
+}
+
+/*==========================================
+ * Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes)
+ *------------------------------------------
+ */
+int buildin_resetlvl (struct script_state *st)
+{
+    struct map_session_data *sd;
+
+    int  type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    sd = script_rid2sd (st);
+    pc_resetlvl (sd, type);
+    return 0;
+}
+
+/*==========================================
+ * ステータスリセット
+ *------------------------------------------
+ */
+int buildin_resetstatus (struct script_state *st)
+{
+    struct map_session_data *sd;
+    sd = script_rid2sd (st);
+    pc_resetstate (sd);
+    return 0;
+}
+
+/*==========================================
+ * スキルリセット
+ *------------------------------------------
+ */
+int buildin_resetskill (struct script_state *st)
+{
+    struct map_session_data *sd;
+    sd = script_rid2sd (st);
+    pc_resetskill (sd);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int buildin_changebase (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    int  vclass;
+
+    if (st->end > st->start + 3)
+        sd = map_id2sd (conv_num
+                        (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        sd = script_rid2sd (st);
+
+    if (sd == NULL)
+        return 0;
+
+    vclass = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (vclass == 22 && !battle_config.wedding_modifydisplay)
+        return 0;
+
+//  if(vclass==22) {
+//      pc_unequipitem(sd,sd->equip_index[9],0);    // 装備外
+//  }
+
+    sd->view_class = vclass;
+
+    return 0;
+}
+
+/*==========================================
+ * 性別変換
+ *------------------------------------------
+ */
+int buildin_changesex (struct script_state *st)
+{
+    struct map_session_data *sd = NULL;
+    sd = script_rid2sd (st);
+
+    if (sd->status.sex == 0)
+    {
+        sd->status.sex = 1;
+        sd->sex = 1;
+        if (sd->status.pc_class == 20 || sd->status.pc_class == 4021)
+            sd->status.pc_class -= 1;
+    }
+    else if (sd->status.sex == 1)
+    {
+        sd->status.sex = 0;
+        sd->sex = 0;
+        if (sd->status.pc_class == 19 || sd->status.pc_class == 4020)
+            sd->status.pc_class += 1;
+    }
+    chrif_char_ask_name (-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
+    chrif_save (sd);
+    return 0;
+}
+
+/*==========================================
+ * npcチャット作成
+ *------------------------------------------
+ */
+int buildin_waitingroom (struct script_state *st)
+{
+    char *name, *ev = "";
+    int  limit, trigger = 0, pub = 1;
+    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    limit = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (limit == 0)
+        pub = 3;
+
+    if ((st->end > st->start + 5))
+    {
+        struct script_data *data = &(st->stack->stack_data[st->start + 5]);
+        get_val (st, data);
+        if (data->type == C_INT)
+        {
+            // 新Athena仕様(旧Athena仕様と互換性あり)
+            ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+            trigger = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+        }
+        else
+        {
+            // eathena仕様
+            trigger = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+            ev = conv_str (st, &(st->stack->stack_data[st->start + 5]));
+        }
+    }
+    else
+    {
+        // 旧Athena仕様
+        if (st->end > st->start + 4)
+            ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+    }
+    chat_createnpcchat ((struct npc_data *) map_id2bl (st->oid),
+                        limit, pub, trigger, name, strlen (name) + 1, ev);
+    return 0;
+}
+
+/*==========================================
+ * npcチャット削除
+ *------------------------------------------
+ */
+int buildin_delwaitingroom (struct script_state *st)
+{
+    struct npc_data *nd;
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+    chat_deletenpcchat (nd);
+    return 0;
+}
+
+/*==========================================
+ * npcチャット全員蹴り出す
+ *------------------------------------------
+ */
+int buildin_waitingroomkickall (struct script_state *st)
+{
+    struct npc_data *nd;
+    struct chat_data *cd;
+
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+        return 0;
+    chat_npckickall (cd);
+    return 0;
+}
+
+/*==========================================
+ * npcチャットイベント有効化
+ *------------------------------------------
+ */
+int buildin_enablewaitingroomevent (struct script_state *st)
+{
+    struct npc_data *nd;
+    struct chat_data *cd;
+
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+        return 0;
+    chat_enableevent (cd);
+    return 0;
+}
+
+/*==========================================
+ * npcチャットイベント無効化
+ *------------------------------------------
+ */
+int buildin_disablewaitingroomevent (struct script_state *st)
+{
+    struct npc_data *nd;
+    struct chat_data *cd;
+
+    if (st->end > st->start + 2)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 2])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+        return 0;
+    chat_disableevent (cd);
+    return 0;
+}
+
+/*==========================================
+ * npcチャット状態所得
+ *------------------------------------------
+ */
+int buildin_getwaitingroomstate (struct script_state *st)
+{
+    struct npc_data *nd;
+    struct chat_data *cd;
+    int  val = 0, type;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (st->end > st->start + 3)
+        nd = npc_name2id (conv_str
+                          (st, &(st->stack->stack_data[st->start + 3])));
+    else
+        nd = (struct npc_data *) map_id2bl (st->oid);
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+
+    switch (type)
+    {
+        case 0:
+            val = cd->users;
+            break;
+        case 1:
+            val = cd->limit;
+            break;
+        case 2:
+            val = cd->trigger & 0x7f;
+            break;
+        case 3:
+            val = ((cd->trigger & 0x80) > 0);
+            break;
+        case 32:
+            val = (cd->users >= cd->limit);
+            break;
+        case 33:
+            val = (cd->users >= cd->trigger);
+            break;
+
+        case 4:
+            push_str (st->stack, C_CONSTSTR, cd->title);
+            return 0;
+        case 5:
+            push_str (st->stack, C_CONSTSTR, cd->pass);
+            return 0;
+        case 16:
+            push_str (st->stack, C_CONSTSTR, cd->npc_event);
+            return 0;
+    }
+    push_val (st->stack, C_INT, val);
+    return 0;
+}
+
+/*==========================================
+ * チャットメンバー(規定人数)ワープ
+ *------------------------------------------
+ */
+int buildin_warpwaitingpc (struct script_state *st)
+{
+    int  x, y, i, n;
+    char *str;
+    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
+    struct chat_data *cd;
+
+    if (nd == NULL
+        || (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
+        return 0;
+
+    n = cd->trigger & 0x7f;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+
+    if (st->end > st->start + 5)
+        n = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+
+    for (i = 0; i < n; i++)
+    {
+        struct map_session_data *sd = cd->usersd[0];    // リスト先頭のPCを次々に。
+
+        mapreg_setreg (add_str ("$@warpwaitingpc") + (i << 24), sd->bl.id);
+
+        if (strcmp (str, "Random") == 0)
+            pc_randomwarp (sd, 3);
+        else if (strcmp (str, "SavePoint") == 0)
+        {
+            if (map[sd->bl.m].flag.noteleport)  // テレポ禁止
+                return 0;
+
+            pc_setpos (sd, sd->status.save_point.map,
+                       sd->status.save_point.x, sd->status.save_point.y, 3);
+        }
+        else
+            pc_setpos (sd, str, x, y, 0);
+    }
+    mapreg_setreg (add_str ("$@warpwaitingpcnum"), n);
+    return 0;
+}
+
+/*==========================================
+ * RIDのアタッチ
+ *------------------------------------------
+ */
+int buildin_attachrid (struct script_state *st)
+{
+    st->rid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    push_val (st->stack, C_INT, (map_id2sd (st->rid) != NULL));
+    return 0;
+}
+
+/*==========================================
+ * RIDのデタッチ
+ *------------------------------------------
+ */
+int buildin_detachrid (struct script_state *st)
+{
+    st->rid = 0;
+    return 0;
+}
+
+/*==========================================
+ * 存在チェック
+ *------------------------------------------
+ */
+int buildin_isloggedin (struct script_state *st)
+{
+    push_val (st->stack, C_INT,
+              map_id2sd (conv_num
+                         (st,
+                          &(st->stack->stack_data[st->start + 2]))) != NULL);
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+enum
+{ MF_NOMEMO, MF_NOTELEPORT, MF_NOSAVE, MF_NOBRANCH, MF_NOPENALTY,
+    MF_NOZENYPENALTY, MF_PVP, MF_PVP_NOPARTY, MF_PVP_NOGUILD, MF_GVG,
+    MF_GVG_NOPARTY, MF_NOTRADE, MF_NOSKILL, MF_NOWARP, MF_NOPVP,
+    MF_NOICEWALL,
+    MF_SNOW, MF_FOG, MF_SAKURA, MF_LEAVES, MF_RAIN
+};
+
+int buildin_setmapflagnosave (struct script_state *st)
+{
+    int  m, x, y;
+    char *str, *str2;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    str2 = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    m = map_mapname2mapid (str);
+    if (m >= 0)
+    {
+        map[m].flag.nosave = 1;
+        memcpy (map[m].save.map, str2, 16);
+        map[m].save.x = x;
+        map[m].save.y = y;
+    }
+
+    return 0;
+}
+
+int buildin_setmapflag (struct script_state *st)
+{
+    int  m, i;
+    char *str;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    m = map_mapname2mapid (str);
+    if (m >= 0)
+    {
+        switch (i)
+        {
+            case MF_NOMEMO:
+                map[m].flag.nomemo = 1;
+                break;
+            case MF_NOTELEPORT:
+                map[m].flag.noteleport = 1;
+                break;
+            case MF_NOBRANCH:
+                map[m].flag.nobranch = 1;
+                break;
+            case MF_NOPENALTY:
+                map[m].flag.nopenalty = 1;
+                break;
+            case MF_PVP_NOPARTY:
+                map[m].flag.pvp_noparty = 1;
+                break;
+            case MF_PVP_NOGUILD:
+                map[m].flag.pvp_noguild = 1;
+                break;
+            case MF_GVG_NOPARTY:
+                map[m].flag.gvg_noparty = 1;
+                break;
+            case MF_NOZENYPENALTY:
+                map[m].flag.nozenypenalty = 1;
+                break;
+            case MF_NOTRADE:
+                map[m].flag.notrade = 1;
+                break;
+            case MF_NOSKILL:
+                map[m].flag.noskill = 1;
+                break;
+            case MF_NOWARP:
+                map[m].flag.nowarp = 1;
+                break;
+            case MF_NOPVP:
+                map[m].flag.nopvp = 1;
+                break;
+            case MF_NOICEWALL: // [Valaris]
+                map[m].flag.noicewall = 1;
+                break;
+            case MF_SNOW:      // [Valaris]
+                map[m].flag.snow = 1;
+                break;
+            case MF_FOG:       // [Valaris]
+                map[m].flag.fog = 1;
+                break;
+            case MF_SAKURA:    // [Valaris]
+                map[m].flag.sakura = 1;
+                break;
+            case MF_LEAVES:    // [Valaris]
+                map[m].flag.leaves = 1;
+                break;
+            case MF_RAIN:      // [Valaris]
+                map[m].flag.rain = 1;
+                break;
+        }
+    }
+
+    return 0;
+}
+
+int buildin_removemapflag (struct script_state *st)
+{
+    int  m, i;
+    char *str;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    m = map_mapname2mapid (str);
+    if (m >= 0)
+    {
+        switch (i)
+        {
+            case MF_NOMEMO:
+                map[m].flag.nomemo = 0;
+                break;
+            case MF_NOTELEPORT:
+                map[m].flag.noteleport = 0;
+                break;
+            case MF_NOSAVE:
+                map[m].flag.nosave = 0;
+                break;
+            case MF_NOBRANCH:
+                map[m].flag.nobranch = 0;
+                break;
+            case MF_NOPENALTY:
+                map[m].flag.nopenalty = 0;
+                break;
+            case MF_PVP_NOPARTY:
+                map[m].flag.pvp_noparty = 0;
+                break;
+            case MF_PVP_NOGUILD:
+                map[m].flag.pvp_noguild = 0;
+                break;
+            case MF_GVG_NOPARTY:
+                map[m].flag.gvg_noparty = 0;
+                break;
+            case MF_NOZENYPENALTY:
+                map[m].flag.nozenypenalty = 0;
+                break;
+            case MF_NOSKILL:
+                map[m].flag.noskill = 0;
+                break;
+            case MF_NOWARP:
+                map[m].flag.nowarp = 0;
+                break;
+            case MF_NOPVP:
+                map[m].flag.nopvp = 0;
+                break;
+            case MF_NOICEWALL: // [Valaris]
+                map[m].flag.noicewall = 0;
+                break;
+            case MF_SNOW:      // [Valaris]
+                map[m].flag.snow = 0;
+                break;
+            case MF_FOG:       // [Valaris]
+                map[m].flag.fog = 0;
+                break;
+            case MF_SAKURA:    // [Valaris]
+                map[m].flag.sakura = 0;
+                break;
+            case MF_LEAVES:    // [Valaris]
+                map[m].flag.leaves = 0;
+                break;
+            case MF_RAIN:      // [Valaris]
+                map[m].flag.rain = 0;
+                break;
+
+        }
+    }
+
+    return 0;
+}
+
+int buildin_pvpon (struct script_state *st)
+{
+    int  m, i;
+    char *str;
+    struct map_session_data *pl_sd = NULL;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    m = map_mapname2mapid (str);
+    if (m >= 0 && !map[m].flag.pvp && !map[m].flag.nopvp)
+    {
+        map[m].flag.pvp = 1;
+        clif_send0199 (m, 1);
+
+        if (battle_config.pk_mode)  // disable ranking functions if pk_mode is on [Valaris]
+            return 0;
+
+        for (i = 0; i < fd_max; i++)
+        {                       //人数分ループ
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                if (m == pl_sd->bl.m && pl_sd->pvp_timer == -1)
+                {
+                    pl_sd->pvp_timer =
+                        add_timer (gettick () + 200, pc_calc_pvprank_timer,
+                                   pl_sd->bl.id, 0);
+                    pl_sd->pvp_rank = 0;
+                    pl_sd->pvp_lastusers = 0;
+                    pl_sd->pvp_point = 5;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+int buildin_pvpoff (struct script_state *st)
+{
+    int  m, i;
+    char *str;
+    struct map_session_data *pl_sd = NULL;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    m = map_mapname2mapid (str);
+    if (m >= 0 && map[m].flag.pvp && map[m].flag.nopvp)
+    {
+        map[m].flag.pvp = 0;
+        clif_send0199 (m, 0);
+
+        if (battle_config.pk_mode)  // disable ranking options if pk_mode is on [Valaris]
+            return 0;
+
+        for (i = 0; i < fd_max; i++)
+        {                       //人数分ループ
+            if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
+                && pl_sd->state.auth)
+            {
+                if (m == pl_sd->bl.m)
+                {
+                    clif_pvpset (pl_sd, 0, 0, 2);
+                    if (pl_sd->pvp_timer != -1)
+                    {
+                        delete_timer (pl_sd->pvp_timer,
+                                      pc_calc_pvprank_timer);
+                        pl_sd->pvp_timer = -1;
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+int buildin_gvgon (struct script_state *st)
+{
+    int  m;
+    char *str;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    m = map_mapname2mapid (str);
+    if (m >= 0 && !map[m].flag.gvg)
+    {
+        map[m].flag.gvg = 1;
+        clif_send0199 (m, 3);
+    }
+
+    return 0;
+}
+
+int buildin_gvgoff (struct script_state *st)
+{
+    int  m;
+    char *str;
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    m = map_mapname2mapid (str);
+    if (m >= 0 && map[m].flag.gvg)
+    {
+        map[m].flag.gvg = 0;
+        clif_send0199 (m, 0);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *	NPCエモーション
+ *------------------------------------------
+ */
+
+int buildin_emotion (struct script_state *st)
+{
+    int  type;
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    if (type < 0 || type > 100)
+        return 0;
+    clif_emotion (map_id2bl (st->oid), type);
+    return 0;
+}
+
+int buildin_maprespawnguildid_sub (struct block_list *bl, va_list ap)
+{
+    int  g_id = va_arg (ap, int);
+    int  flag = va_arg (ap, int);
+    struct map_session_data *sd = NULL;
+    struct mob_data *md = NULL;
+
+    if (bl->type == BL_PC)
+        sd = (struct map_session_data *) bl;
+    if (bl->type == BL_MOB)
+        md = (struct mob_data *) bl;
+
+    if (sd)
+    {
+        if ((sd->status.guild_id == g_id) && (flag & 1))
+            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
+                       sd->status.save_point.y, 3);
+        else if ((sd->status.guild_id != g_id) && (flag & 2))
+            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
+                       sd->status.save_point.y, 3);
+        else if (sd->status.guild_id == 0)  // Warp out players not in guild [Valaris]
+            pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3); // end addition [Valaris]
+    }
+    if (md && flag & 4)
+    {
+        if (md->mob_class < 1285 || md->mob_class > 1288)
+            mob_delete (md);
+    }
+    return 0;
+}
+
+int buildin_maprespawnguildid (struct script_state *st)
+{
+    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    int  g_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    int  flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+
+    int  m = map_mapname2mapid (mapname);
+
+    if (m)
+        map_foreachinarea (buildin_maprespawnguildid_sub, m, 0, 0,
+                           map[m].xs - 1, map[m].ys - 1, BL_NUL, g_id, flag);
+    return 0;
+}
+
+int buildin_agitstart (struct script_state *st)
+{
+    if (agit_flag == 1)
+        return 1;               // Agit already Start.
+    agit_flag = 1;
+    guild_agit_start ();
+    return 0;
+}
+
+int buildin_agitend (struct script_state *st)
+{
+    if (agit_flag == 0)
+        return 1;               // Agit already End.
+    agit_flag = 0;
+    guild_agit_end ();
+    return 0;
+}
+
+/*==========================================
+ * agitcheck 1;    // choice script
+ * if(@agit_flag == 1) goto agit;
+ * if(agitcheck(0) == 1) goto agit;
+ *------------------------------------------
+ */
+int buildin_agitcheck (struct script_state *st)
+{
+    struct map_session_data *sd;
+    int  cond;
+
+    sd = script_rid2sd (st);
+    cond = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    if (cond == 0)
+    {
+        if (agit_flag == 1)
+            push_val (st->stack, C_INT, 1);
+        if (agit_flag == 0)
+            push_val (st->stack, C_INT, 0);
+    }
+    else
+    {
+        if (agit_flag == 1)
+            pc_setreg (sd, add_str ("@agit_flag"), 1);
+        if (agit_flag == 0)
+            pc_setreg (sd, add_str ("@agit_flag"), 0);
+    }
+    return 0;
+}
+
+int buildin_flagemblem (struct script_state *st)
+{
+    int  g_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    if (g_id < 0)
+        return 0;
+
+//  printf("Script.c: [FlagEmblem] GuildID=%d, Emblem=%d.\n", g->guild_id, g->emblem_id);
+    ((struct npc_data *) map_id2bl (st->oid))->u.scr.guild_id = g_id;
+    return 1;
+}
+
+int buildin_getcastlename (struct script_state *st)
+{
+    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    struct guild_castle *gc;
+    int  i;
+    char *buf = NULL;
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        if ((gc = guild_castle_search (i)) != NULL)
+        {
+            if (strcmp (mapname, gc->map_name) == 0)
+            {
+                buf = (char *) calloc (24, 1);
+                strncpy (buf, gc->castle_name, 23);
+                break;
+            }
+        }
+    }
+    if (buf)
+        push_str (st->stack, C_STR, buf);
+    else
+        push_str (st->stack, C_CONSTSTR, "");
+    return 0;
+}
+
+int buildin_getcastledata (struct script_state *st)
+{
+    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    int  index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    char *event = NULL;
+    struct guild_castle *gc;
+    int  i, j;
+
+    if (st->end > st->start + 4 && index == 0)
+    {
+        for (i = 0, j = -1; i < MAX_GUILDCASTLE; i++)
+            if ((gc = guild_castle_search (i)) != NULL &&
+                strcmp (mapname, gc->map_name) == 0)
+                j = i;
+        if (j >= 0)
+        {
+            event = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+            guild_addcastleinfoevent (j, 17, event);
+        }
+    }
+
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        if ((gc = guild_castle_search (i)) != NULL)
+        {
+            if (strcmp (mapname, gc->map_name) == 0)
+            {
+                switch (index)
+                {
+                    case 0:
+                        for (j = 1; j < 26; j++)
+                            guild_castledataload (gc->castle_id, j);
+                        break;  // Initialize[AgitInit]
+                    case 1:
+                        push_val (st->stack, C_INT, gc->guild_id);
+                        break;
+                    case 2:
+                        push_val (st->stack, C_INT, gc->economy);
+                        break;
+                    case 3:
+                        push_val (st->stack, C_INT, gc->defense);
+                        break;
+                    case 4:
+                        push_val (st->stack, C_INT, gc->triggerE);
+                        break;
+                    case 5:
+                        push_val (st->stack, C_INT, gc->triggerD);
+                        break;
+                    case 6:
+                        push_val (st->stack, C_INT, gc->nextTime);
+                        break;
+                    case 7:
+                        push_val (st->stack, C_INT, gc->payTime);
+                        break;
+                    case 8:
+                        push_val (st->stack, C_INT, gc->createTime);
+                        break;
+                    case 9:
+                        push_val (st->stack, C_INT, gc->visibleC);
+                        break;
+                    case 10:
+                        push_val (st->stack, C_INT, gc->visibleG0);
+                        break;
+                    case 11:
+                        push_val (st->stack, C_INT, gc->visibleG1);
+                        break;
+                    case 12:
+                        push_val (st->stack, C_INT, gc->visibleG2);
+                        break;
+                    case 13:
+                        push_val (st->stack, C_INT, gc->visibleG3);
+                        break;
+                    case 14:
+                        push_val (st->stack, C_INT, gc->visibleG4);
+                        break;
+                    case 15:
+                        push_val (st->stack, C_INT, gc->visibleG5);
+                        break;
+                    case 16:
+                        push_val (st->stack, C_INT, gc->visibleG6);
+                        break;
+                    case 17:
+                        push_val (st->stack, C_INT, gc->visibleG7);
+                        break;
+                    case 18:
+                        push_val (st->stack, C_INT, gc->Ghp0);
+                        break;
+                    case 19:
+                        push_val (st->stack, C_INT, gc->Ghp1);
+                        break;
+                    case 20:
+                        push_val (st->stack, C_INT, gc->Ghp2);
+                        break;
+                    case 21:
+                        push_val (st->stack, C_INT, gc->Ghp3);
+                        break;
+                    case 22:
+                        push_val (st->stack, C_INT, gc->Ghp4);
+                        break;
+                    case 23:
+                        push_val (st->stack, C_INT, gc->Ghp5);
+                        break;
+                    case 24:
+                        push_val (st->stack, C_INT, gc->Ghp6);
+                        break;
+                    case 25:
+                        push_val (st->stack, C_INT, gc->Ghp7);
+                        break;
+                    default:
+                        push_val (st->stack, C_INT, 0);
+                        break;
+                }
+                return 0;
+            }
+        }
+    }
+    push_val (st->stack, C_INT, 0);
+    return 0;
+}
+
+int buildin_setcastledata (struct script_state *st)
+{
+    char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    int  index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    int  value = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    struct guild_castle *gc;
+    int  i;
+
+    for (i = 0; i < MAX_GUILDCASTLE; i++)
+    {
+        if ((gc = guild_castle_search (i)) != NULL)
+        {
+            if (strcmp (mapname, gc->map_name) == 0)
+            {
+                // Save Data byself First
+                switch (index)
+                {
+                    case 1:
+                        gc->guild_id = value;
+                        break;
+                    case 2:
+                        gc->economy = value;
+                        break;
+                    case 3:
+                        gc->defense = value;
+                        break;
+                    case 4:
+                        gc->triggerE = value;
+                        break;
+                    case 5:
+                        gc->triggerD = value;
+                        break;
+                    case 6:
+                        gc->nextTime = value;
+                        break;
+                    case 7:
+                        gc->payTime = value;
+                        break;
+                    case 8:
+                        gc->createTime = value;
+                        break;
+                    case 9:
+                        gc->visibleC = value;
+                        break;
+                    case 10:
+                        gc->visibleG0 = value;
+                        break;
+                    case 11:
+                        gc->visibleG1 = value;
+                        break;
+                    case 12:
+                        gc->visibleG2 = value;
+                        break;
+                    case 13:
+                        gc->visibleG3 = value;
+                        break;
+                    case 14:
+                        gc->visibleG4 = value;
+                        break;
+                    case 15:
+                        gc->visibleG5 = value;
+                        break;
+                    case 16:
+                        gc->visibleG6 = value;
+                        break;
+                    case 17:
+                        gc->visibleG7 = value;
+                        break;
+                    case 18:
+                        gc->Ghp0 = value;
+                        break;
+                    case 19:
+                        gc->Ghp1 = value;
+                        break;
+                    case 20:
+                        gc->Ghp2 = value;
+                        break;
+                    case 21:
+                        gc->Ghp3 = value;
+                        break;
+                    case 22:
+                        gc->Ghp4 = value;
+                        break;
+                    case 23:
+                        gc->Ghp5 = value;
+                        break;
+                    case 24:
+                        gc->Ghp6 = value;
+                        break;
+                    case 25:
+                        gc->Ghp7 = value;
+                        break;
+                    default:
+                        return 0;
+                }
+                guild_castledatasave (gc->castle_id, index, value);
+                return 0;
+            }
+        }
+    }
+    return 0;
+}
+
+/* =====================================================================
+ * ギルド情報を要求する
+ * ---------------------------------------------------------------------
+ */
+int buildin_requestguildinfo (struct script_state *st)
+{
+    int  guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    char *event = NULL;
+
+    if (st->end > st->start + 3)
+        event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+
+    if (guild_id > 0)
+        guild_npc_request_info (guild_id, event);
+    return 0;
+}
+
+/* =====================================================================
+ * カードの数を得る
+ * ---------------------------------------------------------------------
+ */
+int buildin_getequipcardcnt (struct script_state *st)
+{
+    int  i, num;
+    struct map_session_data *sd;
+    int  c = 4;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (sd->status.inventory[i].card[0] == 0x00ff)
+    {                           // 製造武器はカードなし
+        push_val (st->stack, C_INT, 0);
+        return 0;
+    }
+    do
+    {
+        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
+            (sd->status.inventory[i].card[c - 1] < 5000))
+        {
+
+            push_val (st->stack, C_INT, (c));
+            return 0;
+        }
+    }
+    while (c--);
+    push_val (st->stack, C_INT, 0);
+    return 0;
+}
+
+/* ================================================================
+ * カード取り外し成功
+ * ----------------------------------------------------------------
+ */
+int buildin_successremovecards (struct script_state *st)
+{
+    int  i, num, cardflag = 0, flag;
+    struct map_session_data *sd;
+    struct item item_tmp;
+    int  c = 4;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (sd->status.inventory[i].card[0] == 0x00ff)
+    {                           // 製造武器は処理しない
+        return 0;
+    }
+    do
+    {
+        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
+            (sd->status.inventory[i].card[c - 1] < 5000))
+        {
+
+            cardflag = 1;
+            item_tmp.id = 0, item_tmp.nameid =
+                sd->status.inventory[i].card[c - 1];
+            item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine = 0;
+            item_tmp.attribute = 0;
+            item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
+                0, item_tmp.card[3] = 0;
+
+            if ((flag = pc_additem (sd, &item_tmp, 1)))
+            {                   // 持てないならドロップ
+                clif_additem (sd, 0, 0, flag);
+                map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
+                                  NULL, NULL, NULL, 0);
+            }
+        }
+    }
+    while (c--);
+
+    if (cardflag == 1)
+    {                           // カードを取り除いたアイテム所得
+        flag = 0;
+        item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
+        item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
+            sd->status.inventory[i].refine;
+        item_tmp.attribute = sd->status.inventory[i].attribute;
+        item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
+            0, item_tmp.card[3] = 0;
+        pc_delitem (sd, i, 1, 0);
+        if ((flag = pc_additem (sd, &item_tmp, 1)))
+        {                       // もてないならドロップ
+            clif_additem (sd, 0, 0, flag);
+            map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
+                              NULL, NULL, NULL, 0);
+        }
+        clif_misceffect (&sd->bl, 3);
+        return 0;
+    }
+    return 0;
+}
+
+/* ================================================================
+ * カード取り外し失敗 slot,type
+ * type=0: 両方損失、1:カード損失、2:武具損失、3:損失無し
+ * ----------------------------------------------------------------
+ */
+int buildin_failedremovecards (struct script_state *st)
+{
+    int  i, num, cardflag = 0, flag, typefail;
+    struct map_session_data *sd;
+    struct item item_tmp;
+    int  c = 4;
+
+    num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    typefail = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    sd = script_rid2sd (st);
+    i = pc_checkequip (sd, equip[num - 1]);
+    if (sd->status.inventory[i].card[0] == 0x00ff)
+    {                           // 製造武器は処理しない
+        return 0;
+    }
+    do
+    {
+        if ((sd->status.inventory[i].card[c - 1] > 4000) &&
+            (sd->status.inventory[i].card[c - 1] < 5000))
+        {
+
+            cardflag = 1;
+
+            if (typefail == 2)
+            {                   // 武具のみ損失なら、カードは受け取らせる
+                item_tmp.id = 0, item_tmp.nameid =
+                    sd->status.inventory[i].card[c - 1];
+                item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
+                    0;
+                item_tmp.attribute = 0;
+                item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
+                    0, item_tmp.card[3] = 0;
+                if ((flag = pc_additem (sd, &item_tmp, 1)))
+                {
+                    clif_additem (sd, 0, 0, flag);
+                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
+                                      sd->bl.y, NULL, NULL, NULL, 0);
+                }
+            }
+        }
+    }
+    while (c--);
+
+    if (cardflag == 1)
+    {
+
+        if (typefail == 0 || typefail == 2)
+        {                       // 武具損失
+            pc_delitem (sd, i, 1, 0);
+            clif_misceffect (&sd->bl, 2);
+            return 0;
+        }
+        if (typefail == 1)
+        {                       // カードのみ損失(武具を返す)
+            flag = 0;
+            item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
+            item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
+                sd->status.inventory[i].refine;
+            item_tmp.attribute = sd->status.inventory[i].attribute;
+            item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
+                0, item_tmp.card[3] = 0;
+            pc_delitem (sd, i, 1, 0);
+            if ((flag = pc_additem (sd, &item_tmp, 1)))
+            {
+                clif_additem (sd, 0, 0, flag);
+                map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
+                                  NULL, NULL, NULL, 0);
+            }
+        }
+        clif_misceffect (&sd->bl, 2);
+        return 0;
+    }
+    return 0;
+}
+
+int buildin_mapwarp (struct script_state *st)   // Added by RoVeRT
+{
+    int  x, y, m;
+    char *str;
+    char *mapname;
+    int  x0, y0, x1, y1;
+
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = 0;
+    y0 = 0;
+    x1 = map[map_mapname2mapid (mapname)].xs;
+    y1 = map[map_mapname2mapid (mapname)].ys;
+    str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+
+    map_foreachinarea (buildin_areawarp_sub,
+                       m, x0, y0, x1, y1, BL_PC, str, x, y);
+    return 0;
+}
+
+int buildin_cmdothernpc (struct script_state *st)   // Added by RoVeRT
+{
+    char *npc, *command;
+
+    npc = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    command = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+
+    npc_command (map_id2sd (st->rid), npc, command);
+    return 0;
+}
+
+int buildin_inittimer (struct script_state *st) // Added by RoVeRT
+{
+//  struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
+
+//  nd->lastaction=nd->timer=gettick();
+    npc_do_ontimer (st->oid, map_id2sd (st->rid), 1);
+
+    return 0;
+}
+
+int buildin_stoptimer (struct script_state *st) // Added by RoVeRT
+{
+//  struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
+
+//  nd->lastaction=nd->timer=-1;
+    npc_do_ontimer (st->oid, map_id2sd (st->rid), 0);
+
+    return 0;
+}
+
+int buildin_mobcount_sub (struct block_list *bl, va_list ap)    // Added by RoVeRT
+{
+    char *event = va_arg (ap, char *);
+    int *c = va_arg (ap, int *);
+
+    if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
+        (*c)++;
+    return 0;
+}
+
+int buildin_mobcount (struct script_state *st)  // Added by RoVeRT
+{
+    char *mapname, *event;
+    int  m, c = 0;
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+    {
+        push_val (st->stack, C_INT, -1);
+        return 0;
+    }
+    map_foreachinarea (buildin_mobcount_sub,
+                       m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, &c);
+
+    push_val (st->stack, C_INT, (c - 1));
+
+    return 0;
+}
+
+int buildin_marriage (struct script_state *st)
+{
+    char *partner = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    struct map_session_data *sd = script_rid2sd (st);
+    struct map_session_data *p_sd = map_nick2sd (partner);
+
+    if (sd == NULL || p_sd == NULL || pc_marriage (sd, p_sd) < 0)
+    {
+        push_val (st->stack, C_INT, 0);
+        return 0;
+    }
+    push_val (st->stack, C_INT, 1);
+    return 0;
+}
+
+int buildin_wedding_effect (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    if (sd == NULL)
+        return 0;
+    clif_wedding_effect (&sd->bl);
+    return 0;
+}
+
+int buildin_divorce (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    st->state = STOP;           // rely on pc_divorce to restart
+
+    sd->npc_flags.divorce = 1;
+
+    if (sd == NULL || pc_divorce (sd) < 0)
+    {
+        push_val (st->stack, C_INT, 0);
+        return 0;
+    }
+
+    push_val (st->stack, C_INT, 1);
+    return 0;
+}
+
+/*================================================
+ * Script for Displaying MOB Information [Valaris]
+ *------------------------------------------------
+ */
+int buildin_strmobinfo (struct script_state *st)
+{
+
+    int  num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  mob_class = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+
+    if (num <= 0 || num >= 8 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)
+        return 0;
+
+    if (num == 1)
+    {
+        char *buf;
+        buf = mob_db[mob_class].name;
+        push_str (st->stack, C_STR, buf);
+        return 0;
+    }
+    else if (num == 2)
+    {
+        char *buf;
+        buf = mob_db[mob_class].jname;
+        push_str (st->stack, C_STR, buf);
+        return 0;
+    }
+    else if (num == 3)
+        push_val (st->stack, C_INT, mob_db[mob_class].lv);
+    else if (num == 4)
+        push_val (st->stack, C_INT, mob_db[mob_class].max_hp);
+    else if (num == 5)
+        push_val (st->stack, C_INT, mob_db[mob_class].max_sp);
+    else if (num == 6)
+        push_val (st->stack, C_INT, mob_db[mob_class].base_exp);
+    else if (num == 7)
+        push_val (st->stack, C_INT, mob_db[mob_class].job_exp);
+    return 0;
+}
+
+/*==========================================
+ * Summon guardians [Valaris]
+ *------------------------------------------
+ */
+int buildin_guardian (struct script_state *st)
+{
+    int  mob_class = 0, amount = 1, x = 0, y = 0, guardian = 0;
+    char *str, *map, *event = "";
+
+    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
+    mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
+    event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
+    if (st->end > st->start + 9)
+        guardian = conv_num (st, &(st->stack->stack_data[st->start + 9]));
+
+    mob_spawn_guardian (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
+                        event, guardian);
+
+    return 0;
+}
+
+/*================================================
+ * Script for Displaying Guardian Info [Valaris]
+ *------------------------------------------------
+ */
+int buildin_guardianinfo (struct script_state *st)
+{
+    int  guardian = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    struct map_session_data *sd = script_rid2sd (st);
+    struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
+
+    if (guardian == 0 && gc->visibleG0 == 1)
+        push_val (st->stack, C_INT, gc->Ghp0);
+    if (guardian == 1 && gc->visibleG1 == 1)
+        push_val (st->stack, C_INT, gc->Ghp1);
+    if (guardian == 2 && gc->visibleG2 == 1)
+        push_val (st->stack, C_INT, gc->Ghp2);
+    if (guardian == 3 && gc->visibleG3 == 1)
+        push_val (st->stack, C_INT, gc->Ghp3);
+    if (guardian == 4 && gc->visibleG4 == 1)
+        push_val (st->stack, C_INT, gc->Ghp4);
+    if (guardian == 5 && gc->visibleG5 == 1)
+        push_val (st->stack, C_INT, gc->Ghp5);
+    if (guardian == 6 && gc->visibleG6 == 1)
+        push_val (st->stack, C_INT, gc->Ghp6);
+    if (guardian == 7 && gc->visibleG7 == 1)
+        push_val (st->stack, C_INT, gc->Ghp7);
+    else
+        push_val (st->stack, C_INT, -1);
+
+    return 0;
+}
+
+/*==========================================
+ * IDからItem名
+ *------------------------------------------
+ */
+int buildin_getitemname (struct script_state *st)
+{
+    struct item_data *i_data;
+    char *item_name;
+    struct script_data *data;
+
+    data = &(st->stack->stack_data[st->start + 2]);
+    get_val (st, data);
+    if (data->type == C_STR || data->type == C_CONSTSTR)
+    {
+        const char *name = conv_str (st, data);
+        i_data = itemdb_searchname (name);
+    }
+    else
+    {
+        int  item_id = conv_num (st, data);
+        i_data = itemdb_search (item_id);
+    }
+
+    item_name = (char *) calloc (24, 1);
+    if (i_data)
+        strncpy (item_name, i_data->jname, 23);
+    else
+        strncpy (item_name, "Unknown Item", 23);
+
+    push_str (st->stack, C_STR, item_name);
+
+    return 0;
+}
+
+int buildin_getspellinvocation (struct script_state *st)
+{
+    char *name;
+    char *invocation;
+
+    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    invocation = magic_find_invocation (name);
+    if (!invocation)
+        invocation = "...";
+
+    push_str (st->stack, C_STR, strdup (invocation));
+    return 0;
+}
+
+int buildin_getanchorinvocation (struct script_state *st)
+{
+    char *name;
+    char *invocation;
+
+    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    invocation = magic_find_anchor_invocation (name);
+    if (!invocation)
+        invocation = "...";
+
+    push_str (st->stack, C_STR, strdup (invocation));
+    return 0;
+}
+
+int buildin_getpartnerid (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    push_val (st->stack, C_INT, sd->status.partner_id);
+    return 0;
+}
+
+/*==========================================
+ * PCの所持品情報読み取り
+ *------------------------------------------
+ */
+int buildin_getinventorylist (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i, j = 0;
+    if (!sd)
+        return 0;
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].nameid > 0
+            && sd->status.inventory[i].amount > 0)
+        {
+            pc_setreg (sd, add_str ("@inventorylist_id") + (j << 24),
+                       sd->status.inventory[i].nameid);
+            pc_setreg (sd, add_str ("@inventorylist_amount") + (j << 24),
+                       sd->status.inventory[i].amount);
+            pc_setreg (sd, add_str ("@inventorylist_equip") + (j << 24),
+                       sd->status.inventory[i].equip);
+            pc_setreg (sd, add_str ("@inventorylist_refine") + (j << 24),
+                       sd->status.inventory[i].refine);
+            pc_setreg (sd, add_str ("@inventorylist_identify") + (j << 24),
+                       sd->status.inventory[i].identify);
+            pc_setreg (sd, add_str ("@inventorylist_attribute") + (j << 24),
+                       sd->status.inventory[i].attribute);
+            pc_setreg (sd, add_str ("@inventorylist_card1") + (j << 24),
+                       sd->status.inventory[i].card[0]);
+            pc_setreg (sd, add_str ("@inventorylist_card2") + (j << 24),
+                       sd->status.inventory[i].card[1]);
+            pc_setreg (sd, add_str ("@inventorylist_card3") + (j << 24),
+                       sd->status.inventory[i].card[2]);
+            pc_setreg (sd, add_str ("@inventorylist_card4") + (j << 24),
+                       sd->status.inventory[i].card[3]);
+            j++;
+        }
+    }
+    pc_setreg (sd, add_str ("@inventorylist_count"), j);
+    return 0;
+}
+
+int buildin_getskilllist (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i, j = 0;
+    if (!sd)
+        return 0;
+    for (i = 0; i < MAX_SKILL; i++)
+    {
+        if (sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0)
+        {
+            pc_setreg (sd, add_str ("@skilllist_id") + (j << 24),
+                       sd->status.skill[i].id);
+            pc_setreg (sd, add_str ("@skilllist_lv") + (j << 24),
+                       sd->status.skill[i].lv);
+            pc_setreg (sd, add_str ("@skilllist_flag") + (j << 24),
+                       sd->status.skill[i].flags);
+            j++;
+        }
+    }
+    pc_setreg (sd, add_str ("@skilllist_count"), j);
+    return 0;
+}
+
+int buildin_get_activated_pool_skills (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  pool_skills[MAX_SKILL_POOL];
+    int  skill_pool_size = skill_pool (sd, pool_skills);
+    int  i, count = 0;
+
+    if (!sd)
+        return 0;
+
+    for (i = 0; i < skill_pool_size; i++)
+    {
+        int  skill_id = pool_skills[i];
+
+        if (sd->status.skill[skill_id].id == skill_id)
+        {
+            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
+                       sd->status.skill[skill_id].id);
+            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
+                       sd->status.skill[skill_id].lv);
+            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
+                       sd->status.skill[skill_id].flags);
+            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
+                          skill_name (skill_id));
+            ++count;
+        }
+    }
+    pc_setreg (sd, add_str ("@skilllist_count"), count);
+
+    return 0;
+}
+
+extern int skill_pool_skills[];
+extern int skill_pool_skills_size;
+
+int buildin_get_unactivated_pool_skills (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i, count = 0;
+
+    if (!sd)
+        return 0;
+
+    for (i = 0; i < skill_pool_skills_size; i++)
+    {
+        int  skill_id = skill_pool_skills[i];
+
+        if (sd->status.skill[skill_id].id == skill_id && !(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
+        {
+            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
+                       sd->status.skill[skill_id].id);
+            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
+                       sd->status.skill[skill_id].lv);
+            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
+                       sd->status.skill[skill_id].flags);
+            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
+                          skill_name (skill_id));
+            ++count;
+        }
+    }
+    pc_setreg (sd, add_str ("@skilllist_count"), count);
+
+    return 0;
+}
+
+int buildin_get_pool_skills (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i, count = 0;
+
+    if (!sd)
+        return 0;
+
+    for (i = 0; i < skill_pool_skills_size; i++)
+    {
+        int  skill_id = skill_pool_skills[i];
+
+        if (sd->status.skill[skill_id].id == skill_id)
+        {
+            pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
+                       sd->status.skill[skill_id].id);
+            pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
+                       sd->status.skill[skill_id].lv);
+            pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
+                       sd->status.skill[skill_id].flags);
+            pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
+                          skill_name (skill_id));
+            ++count;
+        }
+    }
+    pc_setreg (sd, add_str ("@skilllist_count"), count);
+
+    return 0;
+}
+
+int buildin_activate_pool_skill (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    skill_pool_activate (sd, skill_id);
+    clif_skillinfoblock (sd);
+
+    return 0;
+}
+
+int buildin_deactivate_pool_skill (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    skill_pool_deactivate (sd, skill_id);
+    clif_skillinfoblock (sd);
+
+    return 0;
+}
+
+int buildin_check_pool_skill (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    push_val (st->stack, C_INT, skill_pool_is_activated (sd, skill_id));
+
+    return 0;
+}
+
+int buildin_clearitem (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i;
+    if (sd == NULL)
+        return 0;
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].amount)
+            pc_delitem (sd, i, sd->status.inventory[i].amount, 0);
+    }
+    return 0;
+}
+
+/*==========================================
+ * NPCクラスチェンジ
+ * classは変わりたいclass
+ * typeは通常0なのかな?
+ *------------------------------------------
+ */
+int buildin_classchange (struct script_state *st)
+{
+    int  npc_class, type;
+    struct block_list *bl = map_id2bl (st->oid);
+
+    if (bl == NULL)
+        return 0;
+
+    npc_class = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    clif_npc_class_change (bl, npc_class, type);
+    return 0;
+}
+
+/*==========================================
+ * NPCから発生するエフェクト
+ * misceffect(effect, [target])
+ *
+ * effect The effect type/ID.
+ * target The player name or being ID on
+ *  which to display the effect. If not
+ *  specified, it attempts to default to
+ *  the current NPC or invoking PC.
+ *------------------------------------------
+ */
+int buildin_misceffect (struct script_state *st)
+{
+    int  type;
+    int  id = 0;
+    char *name = NULL;
+    struct block_list *bl = NULL;
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    if (st->end > st->start + 3)
+    {
+        struct script_data *sdata = &(st->stack->stack_data[st->start + 3]);
+
+        get_val (st, sdata);
+
+        if (sdata->type == C_STR || sdata->type == C_CONSTSTR)
+            name = conv_str (st, sdata);
+        else
+            id = conv_num (st, sdata);
+    }
+
+    if (name)
+    {
+        struct map_session_data *sd = map_nick2sd (name);
+        if (sd)
+            bl = &sd->bl;
+    }
+    else if (id)
+        bl = map_id2bl (id);
+    else if (st->oid)
+        bl = map_id2bl (st->oid);
+    else
+    {
+        struct map_session_data *sd = script_rid2sd (st);
+        if (sd)
+            bl = &sd->bl;
+    }
+
+    if (bl)
+        clif_misceffect (bl, type);
+
+    return 0;
+}
+
+/*==========================================
+ * サウンドエフェクト
+ *------------------------------------------
+ */
+int buildin_soundeffect (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    char *name;
+    int  type = 0;
+
+    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    if (sd)
+    {
+        if (st->oid)
+            clif_soundeffect (sd, map_id2bl (st->oid), name, type);
+        else
+        {
+            clif_soundeffect (sd, &sd->bl, name, type);
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * NPC skill effects [Valaris]
+ *------------------------------------------
+ */
+int buildin_npcskilleffect (struct script_state *st)
+{
+    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
+
+    int  skillid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    int  skilllv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    int  x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    int  y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+
+    clif_skill_poseffect (&nd->bl, skillid, skilllv, x, y, gettick ());
+
+    return 0;
+}
+
+/*==========================================
+ * Special effects [Valaris]
+ *------------------------------------------
+ */
+int buildin_specialeffect (struct script_state *st)
+{
+    struct block_list *bl = map_id2bl (st->oid);
+
+    if (bl == NULL)
+        return 0;
+
+    clif_specialeffect (bl,
+                        conv_num (st,
+                                  &(st->stack->stack_data[st->start + 2])),
+                        0);
+
+    return 0;
+}
+
+int buildin_specialeffect2 (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    if (sd == NULL)
+        return 0;
+
+    clif_specialeffect (&sd->bl,
+                        conv_num (st,
+                                  &(st->stack->stack_data[st->start + 2])),
+                        0);
+
+    return 0;
+}
+
+/*==========================================
+ * Nude [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_nude (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    int  i;
+
+    if (sd == NULL)
+        return 0;
+
+    for (i = 0; i < 11; i++)
+        if (sd->equip_index[i] >= 0)
+            pc_unequipitem (sd, sd->equip_index[i], i);
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * UnequipById [Freeyorp]
+ *------------------------------------------
+ */
+
+int buildin_unequip_by_id (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    if (sd == NULL)
+        return 0;
+
+    int  slot_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    if (slot_id >= 0 && slot_id < 11 && sd->equip_index[slot_id] >= 0)
+        pc_unequipitem (sd, sd->equip_index[slot_id], slot_id);
+
+    pc_calcstatus (sd, 0);
+
+    return 0;
+}
+
+/*==========================================
+ * gmcommand [MouseJstr]
+ *
+ * suggested on the forums...
+ *------------------------------------------
+ */
+
+int buildin_gmcommand (struct script_state *st)
+{
+    struct map_session_data *sd;
+    char *cmd;
+
+    sd = script_rid2sd (st);
+    cmd = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    is_atcommand (sd->fd, sd, cmd, 99);
+
+    return 0;
+}
+
+/*==========================================
+ * movenpc [MouseJstr]
+ *------------------------------------------
+ */
+
+int buildin_movenpc (struct script_state *st)
+{
+    struct map_session_data *sd;
+    char *map, *npc;
+    int  x, y;
+
+    sd = script_rid2sd (st);
+
+    map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    npc = conv_str (st, &(st->stack->stack_data[st->start + 5]));
+
+    return 0;
+}
+
+/*==========================================
+ * npcwarp [remoitnane]
+ * Move NPC to a new position on the same map.
+ *------------------------------------------
+ */
+int buildin_npcwarp (struct script_state *st)
+{
+    int  x, y;
+    char *npc;
+    struct npc_data *nd = NULL;
+
+    x = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    y = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    npc = conv_str (st, &(st->stack->stack_data[st->start + 4]));
+    nd = npc_name2id (npc);
+
+    if (!nd)
+        return -1;
+
+    short m = nd->bl.m;
+
+    /* Crude sanity checks. */
+    if (m < 0 || !nd->bl.prev
+            || x < 0 || x > map[m].xs -1
+            || y < 0 || y > map[m].ys - 1)
+        return -1;
+
+    npc_enable (npc, 0);
+    map_delblock(&nd->bl); /* [Freeyorp] */
+    nd->bl.x = x;
+    nd->bl.y = y;
+    map_addblock(&nd->bl);
+    npc_enable (npc, 1);
+
+    return 0;
+}
+
+/*==========================================
+ * message [MouseJstr]
+ *------------------------------------------
+ */
+
+int buildin_message (struct script_state *st)
+{
+    char *msg, *player;
+    struct map_session_data *pl_sd = NULL;
+
+    player = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    msg = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+
+    if ((pl_sd = map_nick2sd ((char *) player)) == NULL)
+        return 1;
+    clif_displaymessage (pl_sd->fd, msg);
+
+    return 0;
+}
+
+/*==========================================
+ * npctalk (sends message to surrounding
+ * area) [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_npctalk (struct script_state *st)
+{
+    char *str;
+    char message[255];
+
+    struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+
+    if (nd)
+    {
+        memcpy (message, nd->name, 24);
+        strcat (message, " : ");
+        strcat (message, str);
+        clif_message (&(nd->bl), message);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * hasitems (checks to see if player has any
+ * items on them, if so will return a 1)
+ * [Valaris]
+ *------------------------------------------
+ */
+
+int buildin_hasitems (struct script_state *st)
+{
+    int  i;
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    for (i = 0; i < MAX_INVENTORY; i++)
+    {
+        if (sd->status.inventory[i].amount)
+        {
+            push_val (st->stack, C_INT, 1);
+            return 0;
+        }
+    }
+
+    push_val (st->stack, C_INT, 0);
+
+    return 0;
+}
+
+/*==========================================
+  * getlook char info. getlook(arg)
+  *------------------------------------------
+  */
+int buildin_getlook (struct script_state *st)
+{
+    int  type, val;
+    struct map_session_data *sd;
+    sd = script_rid2sd (st);
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+    val = -1;
+    switch (type)
+    {
+        case LOOK_HAIR:        //1
+            val = sd->status.hair;
+            break;
+        case LOOK_WEAPON:      //2
+            val = sd->status.weapon;
+            break;
+        case LOOK_HEAD_BOTTOM: //3
+            val = sd->status.head_bottom;
+            break;
+        case LOOK_HEAD_TOP:    //4
+            val = sd->status.head_top;
+            break;
+        case LOOK_HEAD_MID:    //5
+            val = sd->status.head_mid;
+            break;
+        case LOOK_HAIR_COLOR:  //6
+            val = sd->status.hair_color;
+            break;
+        case LOOK_CLOTHES_COLOR:   //7
+            val = sd->status.clothes_color;
+            break;
+        case LOOK_SHIELD:      //8
+            val = sd->status.shield;
+            break;
+        case LOOK_SHOES:       //9
+            break;
+    }
+
+    push_val (st->stack, C_INT, val);
+    return 0;
+}
+
+/*==========================================
+  *     get char save point. argument: 0- map name, 1- x, 2- y
+  *------------------------------------------
+*/
+int buildin_getsavepoint (struct script_state *st)
+{
+    int  x, y, type;
+    char *mapname;
+    struct map_session_data *sd;
+
+    sd = script_rid2sd (st);
+
+    type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
+
+    x = sd->status.save_point.x;
+    y = sd->status.save_point.y;
+    switch (type)
+    {
+        case 0:
+            mapname = (char*)calloc (24, 1);
+            strncpy (mapname, sd->status.save_point.map, 23);
+            push_str (st->stack, C_STR, mapname);
+            break;
+        case 1:
+            push_val (st->stack, C_INT, x);
+            break;
+        case 2:
+            push_val (st->stack, C_INT, y);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ *     areatimer
+ *------------------------------------------
+ */
+int buildin_areatimer_sub (struct block_list *bl, va_list ap)
+{
+    int  tick;
+    char *event;
+    tick = va_arg (ap, int);
+    event = va_arg (ap, char *);
+    pc_addeventtimer ((struct map_session_data *) bl, tick, event);
+    return 0;
+}
+
+int buildin_areatimer (struct script_state *st)
+{
+    int  tick, m;
+    char *event;
+    char *mapname;
+    int  x0, y0, x1, y1;
+
+    mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+    tick = conv_num (st, &(st->stack->stack_data[st->start + 7]));
+    event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
+
+    if ((m = map_mapname2mapid (mapname)) < 0)
+        return 0;
+
+    map_foreachinarea (buildin_areatimer_sub,
+                       m, x0, y0, x1, y1, BL_PC, tick, event);
+    return 0;
+}
+
+/*==========================================
+ * Check whether the PC is in the specified rectangle
+ *------------------------------------------
+ */
+int buildin_isin (struct script_state *st)
+{
+    int  x1, y1, x2, y2;
+    char *str;
+    struct map_session_data *sd = script_rid2sd (st);
+
+    str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    x1 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
+    y1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    x2 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
+    y2 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
+
+    if (!sd)
+        return 1;
+
+    push_val (st->stack, C_INT,
+              (sd->bl.x >= x1 && sd->bl.x <= x2)
+              && (sd->bl.y >= y1 && sd->bl.y <= y2)
+              && (!strcmp (str, map[sd->bl.m].name)));
+
+    return 0;
+}
+
+// Trigger the shop on a (hopefully) nearby shop NPC
+int buildin_shop (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+    struct npc_data *nd;
+
+    if (!sd)
+        return 1;
+
+    nd = npc_name2id (conv_str (st, &(st->stack->stack_data[st->start + 2])));
+    if (!nd)
+        return 1;
+
+    buildin_close (st);
+    clif_npcbuysell (sd, nd->bl.id);
+    return 0;
+}
+
+/*==========================================
+ * Check whether the PC is dead
+ *------------------------------------------
+ */
+int buildin_isdead (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    push_val (st->stack, C_INT, pc_isdead (sd));
+    return 0;
+}
+
+/*========================================
+ * Changes a NPC name, and sprite
+ *----------------------------------------
+ */
+int buildin_fakenpcname (struct script_state *st)
+{
+    char *name, *newname;
+    int  newsprite;
+    struct npc_data *nd;
+
+    name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
+    newname = conv_str (st, &(st->stack->stack_data[st->start + 3]));
+    newsprite = conv_num (st, &(st->stack->stack_data[st->start + 4]));
+    nd = npc_name2id (name);
+    if (!nd)
+        return 1;
+    strncpy (nd->name, newname, sizeof(nd->name)-1);
+    nd->name[sizeof(nd->name)-1] = '\0';
+    nd->npc_class = newsprite;
+
+    // Refresh this npc
+    npc_enable (name, 0);
+    npc_enable (name, 1);
+
+    return 0;
+}
+
+/*============================
+ * Gets the PC's x pos
+ *----------------------------
+ */
+
+int buildin_getx (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    push_val (st->stack, C_INT, sd->bl.x);
+    return 0;
+}
+
+/*============================
+ * Gets the PC's y pos
+ *----------------------------
+ */
+int buildin_gety (struct script_state *st)
+{
+    struct map_session_data *sd = script_rid2sd (st);
+
+    push_val (st->stack, C_INT, sd->bl.y);
+    return 0;
+}
+
+//
+// 実行部main
+//
+/*==========================================
+ * コマンドの読み取り
+ *------------------------------------------
+ */
+static int unget_com_data = -1;
+int get_com (unsigned char *script, int *pos)
+{
+    int  i, j;
+    if (unget_com_data >= 0)
+    {
+        i = unget_com_data;
+        unget_com_data = -1;
+        return i;
+    }
+    if (script[*pos] >= 0x80)
+    {
+        return C_INT;
+    }
+    i = 0;
+    j = 0;
+    while (script[*pos] >= 0x40)
+    {
+        i = script[(*pos)++] << j;
+        j += 6;
+    }
+    return i + (script[(*pos)++] << j);
+}
+
+/*==========================================
+ * コマンドのプッシュバック
+ *------------------------------------------
+ */
+void unget_com (int c)
+{
+    if (unget_com_data != -1)
+    {
+        if (battle_config.error_log)
+            printf ("unget_com can back only 1 data\n");
+    }
+    unget_com_data = c;
+}
+
+/*==========================================
+ * 数値の所得
+ *------------------------------------------
+ */
+int get_num (unsigned char *script, int *pos)
+{
+    int  i, j;
+    i = 0;
+    j = 0;
+    while (script[*pos] >= 0xc0)
+    {
+        i += (script[(*pos)++] & 0x7f) << j;
+        j += 6;
+    }
+    return i + ((script[(*pos)++] & 0x7f) << j);
+}
+
+/*==========================================
+ * スタックから値を取り出す
+ *------------------------------------------
+ */
+int pop_val (struct script_state *st)
+{
+    if (st->stack->sp <= 0)
+        return 0;
+    st->stack->sp--;
+    get_val (st, &(st->stack->stack_data[st->stack->sp]));
+    if (st->stack->stack_data[st->stack->sp].type == C_INT)
+        return st->stack->stack_data[st->stack->sp].u.num;
+    return 0;
+}
+
+#define isstr(c) ((c).type==C_STR || (c).type==C_CONSTSTR)
+
+/*==========================================
+ * 加算演算子
+ *------------------------------------------
+ */
+void op_add (struct script_state *st)
+{
+    st->stack->sp--;
+    get_val (st, &(st->stack->stack_data[st->stack->sp]));
+    get_val (st, &(st->stack->stack_data[st->stack->sp - 1]));
+
+    if (isstr (st->stack->stack_data[st->stack->sp])
+        || isstr (st->stack->stack_data[st->stack->sp - 1]))
+    {
+        conv_str (st, &(st->stack->stack_data[st->stack->sp]));
+        conv_str (st, &(st->stack->stack_data[st->stack->sp - 1]));
+    }
+    if (st->stack->stack_data[st->stack->sp].type == C_INT)
+    {                           // ii
+        st->stack->stack_data[st->stack->sp - 1].u.num +=
+            st->stack->stack_data[st->stack->sp].u.num;
+    }
+    else
+    {                           // ssの予定
+        char *buf;
+        buf = (char *)
+            calloc (strlen (st->stack->stack_data[st->stack->sp - 1].u.str) +
+                    strlen (st->stack->stack_data[st->stack->sp].u.str) + 1,
+                    1);
+        strcpy (buf, st->stack->stack_data[st->stack->sp - 1].u.str);
+        strcat (buf, st->stack->stack_data[st->stack->sp].u.str);
+        if (st->stack->stack_data[st->stack->sp - 1].type == C_STR)
+            free (st->stack->stack_data[st->stack->sp - 1].u.str);
+        if (st->stack->stack_data[st->stack->sp].type == C_STR)
+            free (st->stack->stack_data[st->stack->sp].u.str);
+        st->stack->stack_data[st->stack->sp - 1].type = C_STR;
+        st->stack->stack_data[st->stack->sp - 1].u.str = buf;
+    }
+}
+
+/*==========================================
+ * 二項演算子(文字列)
+ *------------------------------------------
+ */
+void op_2str (struct script_state *st, int op, int sp1, int sp2)
+{
+    char *s1 = st->stack->stack_data[sp1].u.str,
+        *s2 = st->stack->stack_data[sp2].u.str;
+    int  a = 0;
+
+    switch (op)
+    {
+        case C_EQ:
+            a = (strcmp (s1, s2) == 0);
+            break;
+        case C_NE:
+            a = (strcmp (s1, s2) != 0);
+            break;
+        case C_GT:
+            a = (strcmp (s1, s2) > 0);
+            break;
+        case C_GE:
+            a = (strcmp (s1, s2) >= 0);
+            break;
+        case C_LT:
+            a = (strcmp (s1, s2) < 0);
+            break;
+        case C_LE:
+            a = (strcmp (s1, s2) <= 0);
+            break;
+        default:
+            printf ("illegal string operater\n");
+            break;
+    }
+
+    push_val (st->stack, C_INT, a);
+
+    if (st->stack->stack_data[sp1].type == C_STR)
+        free (s1);
+    if (st->stack->stack_data[sp2].type == C_STR)
+        free (s2);
+}
+
+/*==========================================
+ * 二項演算子(数値)
+ *------------------------------------------
+ */
+void op_2num (struct script_state *st, int op, int i1, int i2)
+{
+    switch (op)
+    {
+        case C_SUB:
+            i1 -= i2;
+            break;
+        case C_MUL:
+            i1 *= i2;
+            break;
+        case C_DIV:
+            i1 /= i2;
+            break;
+        case C_MOD:
+            i1 %= i2;
+            break;
+        case C_AND:
+            i1 &= i2;
+            break;
+        case C_OR:
+            i1 |= i2;
+            break;
+        case C_XOR:
+            i1 ^= i2;
+            break;
+        case C_LAND:
+            i1 = i1 && i2;
+            break;
+        case C_LOR:
+            i1 = i1 || i2;
+            break;
+        case C_EQ:
+            i1 = i1 == i2;
+            break;
+        case C_NE:
+            i1 = i1 != i2;
+            break;
+        case C_GT:
+            i1 = i1 > i2;
+            break;
+        case C_GE:
+            i1 = i1 >= i2;
+            break;
+        case C_LT:
+            i1 = i1 < i2;
+            break;
+        case C_LE:
+            i1 = i1 <= i2;
+            break;
+        case C_R_SHIFT:
+            i1 = i1 >> i2;
+            break;
+        case C_L_SHIFT:
+            i1 = i1 << i2;
+            break;
+    }
+    push_val (st->stack, C_INT, i1);
+}
+
+/*==========================================
+ * 二項演算子
+ *------------------------------------------
+ */
+void op_2 (struct script_state *st, int op)
+{
+    int  i1, i2;
+    char *s1 = NULL, *s2 = NULL;
+
+    i2 = pop_val (st);
+    if (isstr (st->stack->stack_data[st->stack->sp]))
+        s2 = st->stack->stack_data[st->stack->sp].u.str;
+
+    i1 = pop_val (st);
+    if (isstr (st->stack->stack_data[st->stack->sp]))
+        s1 = st->stack->stack_data[st->stack->sp].u.str;
+
+    if (s1 != NULL && s2 != NULL)
+    {
+        // ss => op_2str
+        op_2str (st, op, st->stack->sp, st->stack->sp + 1);
+    }
+    else if (s1 == NULL && s2 == NULL)
+    {
+        // ii => op_2num
+        op_2num (st, op, i1, i2);
+    }
+    else
+    {
+        // si,is => error
+        printf ("script: op_2: int&str, str&int not allow.");
+        push_val (st->stack, C_INT, 0);
+    }
+}
+
+/*==========================================
+ * 単項演算子
+ *------------------------------------------
+ */
+void op_1num (struct script_state *st, int op)
+{
+    int  i1;
+    i1 = pop_val (st);
+    switch (op)
+    {
+        case C_NEG:
+            i1 = -i1;
+            break;
+        case C_NOT:
+            i1 = ~i1;
+            break;
+        case C_LNOT:
+            i1 = !i1;
+            break;
+    }
+    push_val (st->stack, C_INT, i1);
+}
+
+/*==========================================
+ * 関数の実行
+ *------------------------------------------
+ */
+int run_func (struct script_state *st)
+{
+    int  i, start_sp, end_sp, func;
+
+    end_sp = st->stack->sp;
+    for (i = end_sp - 1; i >= 0 && st->stack->stack_data[i].type != C_ARG;
+         i--);
+    if (i == 0)
+    {
+        if (battle_config.error_log)
+            printf ("function not found\n");
+//      st->stack->sp=0;
+        st->state = END;
+        return 0;
+    }
+    start_sp = i - 1;
+    st->start = i - 1;
+    st->end = end_sp;
+
+    func = st->stack->stack_data[st->start].u.num;
+    if (st->stack->stack_data[st->start].type != C_NAME
+        || str_data[func].type != C_FUNC)
+    {
+        printf ("run_func: not function and command! \n");
+//      st->stack->sp=0;
+        st->state = END;
+        return 0;
+    }
+#ifdef DEBUG_RUN
+    if (battle_config.etc_log)
+    {
+        printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
+                func, str_data[func].type);
+        printf ("stack dump :");
+        for (i = 0; i < end_sp; i++)
+        {
+            switch (st->stack->stack_data[i].type)
+            {
+                case C_INT:
+                    printf (" int(%d)", st->stack->stack_data[i].u.num);
+                    break;
+                case C_NAME:
+                    printf (" name(%s)",
+                            str_buf +
+                            str_data[st->stack->stack_data[i].u.num].str);
+                    break;
+                case C_ARG:
+                    printf (" arg");
+                    break;
+                case C_POS:
+                    printf (" pos(%d)", st->stack->stack_data[i].u.num);
+                    break;
+                default:
+                    printf (" %d,%d", st->stack->stack_data[i].type,
+                            st->stack->stack_data[i].u.num);
+            }
+        }
+        printf ("\n");
+    }
+#endif
+    if (str_data[func].func)
+    {
+        str_data[func].func (st);
+    }
+    else
+    {
+        if (battle_config.error_log)
+            printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
+                    func, str_data[func].type);
+        push_val (st->stack, C_INT, 0);
+    }
+
+    pop_stack (st->stack, start_sp, end_sp);
+
+    if (st->state == RETFUNC)
+    {
+        // ユーザー定義関数からの復帰
+        int  olddefsp = st->defsp;
+        int  i;
+
+        pop_stack (st->stack, st->defsp, start_sp); // 復帰に邪魔なスタック削除
+        if (st->defsp < 4
+            || st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
+        {
+            printf
+                ("script:run_func(return) return without callfunc or callsub!\n");
+            st->state = END;
+            return 0;
+        }
+        i = conv_num (st, &(st->stack->stack_data[st->defsp - 4])); // 引数の数所得
+        st->pos = conv_num (st, &(st->stack->stack_data[st->defsp - 1]));   // スクリプト位置の復元
+        st->script = (char *) conv_num (st, &(st->stack->stack_data[st->defsp - 2]));   // スクリプトを復元
+        st->defsp = conv_num (st, &(st->stack->stack_data[st->defsp - 3])); // 基準スタックポインタを復元
+
+        pop_stack (st->stack, olddefsp - 4 - i, olddefsp);  // 要らなくなったスタック(引数と復帰用データ)削除
+
+        st->state = GOTO;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スクリプトの実行メイン部分
+ *------------------------------------------
+ */
+int run_script_main (unsigned char *script, int pos, int rid, int oid,
+                     struct script_state *st, unsigned char *rootscript)
+{
+    int  c, rerun_pos;
+    int  cmdcount = script_config.check_cmdcount;
+    int  gotocount = script_config.check_gotocount;
+    struct script_stack *stack = st->stack;
+
+    st->defsp = stack->sp;
+    st->script = script;
+
+    rerun_pos = st->pos;
+    for (st->state = 0; st->state == 0;)
+    {
+        switch (c = get_com (script, &st->pos))
+        {
+            case C_EOL:
+                if (stack->sp != st->defsp)
+                {
+                    if (battle_config.error_log)
+                        printf ("stack.sp(%d) != default(%d)\n", stack->sp,
+                                st->defsp);
+                    stack->sp = st->defsp;
+                }
+                rerun_pos = st->pos;
+                break;
+            case C_INT:
+                push_val (stack, C_INT, get_num (script, &st->pos));
+                break;
+            case C_POS:
+            case C_NAME:
+                push_val (stack, c, (*(int *) (script + st->pos)) & 0xffffff);
+                st->pos += 3;
+                break;
+            case C_ARG:
+                push_val (stack, c, 0);
+                break;
+            case C_STR:
+                push_str (stack, C_CONSTSTR, script + st->pos);
+                while (script[st->pos++]);
+                break;
+            case C_FUNC:
+                run_func (st);
+                if (st->state == GOTO)
+                {
+                    rerun_pos = st->pos;
+                    script = st->script;
+                    st->state = 0;
+                    if (gotocount > 0 && (--gotocount) <= 0)
+                    {
+                        printf ("run_script: infinity loop !\n");
+                        st->state = END;
+                    }
+                }
+                break;
+
+            case C_ADD:
+                op_add (st);
+                break;
+
+            case C_SUB:
+            case C_MUL:
+            case C_DIV:
+            case C_MOD:
+            case C_EQ:
+            case C_NE:
+            case C_GT:
+            case C_GE:
+            case C_LT:
+            case C_LE:
+            case C_AND:
+            case C_OR:
+            case C_XOR:
+            case C_LAND:
+            case C_LOR:
+            case C_R_SHIFT:
+            case C_L_SHIFT:
+                op_2 (st, c);
+                break;
+
+            case C_NEG:
+            case C_NOT:
+            case C_LNOT:
+                op_1num (st, c);
+                break;
+
+            case C_NOP:
+                st->state = END;
+                break;
+
+            default:
+                if (battle_config.error_log)
+                    printf ("unknown command : %d @ %d\n", c, pos);
+                st->state = END;
+                break;
+        }
+        if (cmdcount > 0 && (--cmdcount) <= 0)
+        {
+            printf ("run_script: infinity loop !\n");
+            st->state = END;
+        }
+    }
+    switch (st->state)
+    {
+        case STOP:
+            break;
+        case END:
+        {
+            struct map_session_data *sd = map_id2sd (st->rid);
+            st->pos = -1;
+            if (sd && sd->npc_id == st->oid)
+                npc_event_dequeue (sd);
+        }
+            break;
+        case RERUNLINE:
+        {
+            st->pos = rerun_pos;
+        }
+            break;
+    }
+
+    if (st->state != END)
+    {
+        // 再開するためにスタック情報を保存
+        struct map_session_data *sd = map_id2sd (st->rid);
+        if (sd /* && sd->npc_stackbuf==NULL */ )
+        {
+            if (sd->npc_stackbuf)
+                free (sd->npc_stackbuf);
+            sd->npc_stackbuf = (char *)
+                calloc (sizeof (stack->stack_data[0]) * stack->sp_max, 1);
+            memcpy (sd->npc_stackbuf, stack->stack_data,
+                    sizeof (stack->stack_data[0]) * stack->sp_max);
+            sd->npc_stack = stack->sp;
+            sd->npc_stackmax = stack->sp_max;
+            sd->npc_script = script;
+            sd->npc_scriptroot = rootscript;
+        }
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スクリプトの実行
+ *------------------------------------------
+ */
+int run_script (unsigned char *script, int pos, int rid, int oid)
+{
+    return run_script_l (script, pos, rid, oid, 0, NULL);
+}
+
+int run_script_l (unsigned char *script, int pos, int rid, int oid,
+                  int args_nr, argrec_t * args)
+{
+    struct script_stack stack;
+    struct script_state st;
+    struct map_session_data *sd = map_id2sd (rid);
+    unsigned char *rootscript = script;
+    int  i;
+    if (script == NULL || pos < 0)
+        return -1;
+
+    if (sd && sd->npc_stackbuf && sd->npc_scriptroot == (char *) rootscript)
+    {
+        // 前回のスタックを復帰
+        script = sd->npc_script;
+        stack.sp = sd->npc_stack;
+        stack.sp_max = sd->npc_stackmax;
+        stack.stack_data = (struct script_data *)
+            calloc (stack.sp_max, sizeof (stack.stack_data[0]));
+        memcpy (stack.stack_data, sd->npc_stackbuf,
+                sizeof (stack.stack_data[0]) * stack.sp_max);
+        free (sd->npc_stackbuf);
+        sd->npc_stackbuf = NULL;
+    }
+    else
+    {
+        // スタック初期化
+        stack.sp = 0;
+        stack.sp_max = 64;
+        stack.stack_data = (struct script_data *)
+            calloc (stack.sp_max, sizeof (stack.stack_data[0]));
+    }
+    st.stack = &stack;
+    st.pos = pos;
+    st.rid = rid;
+    st.oid = oid;
+    for (i = 0; i < args_nr; i++)
+    {
+        if (args[i].name[strlen (args[i].name) - 1] == '$')
+            pc_setregstr (sd, add_str (args[i].name), args[i].v.s);
+        else
+            pc_setreg (sd, add_str (args[i].name), args[i].v.i);
+    }
+    run_script_main (script, pos, rid, oid, &st, rootscript);
+
+    free (stack.stack_data);
+    stack.stack_data = NULL;
+    return st.pos;
+}
+
+/*==========================================
+ * マップ変数の変更
+ *------------------------------------------
+ */
+int mapreg_setreg (int num, int val)
+{
+    if (val != 0)
+        numdb_insert (mapreg_db, num, val);
+    else
+        numdb_erase (mapreg_db, num);
+
+    mapreg_dirty = 1;
+    return 0;
+}
+
+/*==========================================
+ * 文字列型マップ変数の変更
+ *------------------------------------------
+ */
+int mapreg_setregstr (int num, const char *str)
+{
+    char *p;
+
+    if ((p = (char *)numdb_search (mapregstr_db, num)) != NULL)
+        free (p);
+
+    if (str == NULL || *str == 0)
+    {
+        numdb_erase (mapregstr_db, num);
+        mapreg_dirty = 1;
+        return 0;
+    }
+    p = (char *) calloc (strlen (str) + 1, 1);
+    strcpy (p, str);
+    numdb_insert (mapregstr_db, num, p);
+    mapreg_dirty = 1;
+    return 0;
+}
+
+/*==========================================
+ * 永続的マップ変数の読み込み
+ *------------------------------------------
+ */
+static int script_load_mapreg (void)
+{
+    FILE *fp;
+    char line[1024];
+
+    if ((fp = fopen_ (mapreg_txt, "rt")) == NULL)
+        return -1;
+
+    while (fgets (line, sizeof (line), fp))
+    {
+        char buf1[256], buf2[1024], *p;
+        int  n, v, s, i;
+        if (sscanf (line, "%255[^,],%d\t%n", buf1, &i, &n) != 2 &&
+            (i = 0, sscanf (line, "%[^\t]\t%n", buf1, &n) != 1))
+            continue;
+        if (buf1[strlen (buf1) - 1] == '$')
+        {
+            if (sscanf (line + n, "%[^\n\r]", buf2) != 1)
+            {
+                printf ("%s: %s broken data !\n", mapreg_txt, buf1);
+                continue;
+            }
+            p = (char *) calloc (strlen (buf2) + 1, 1);
+            strcpy (p, buf2);
+            s = add_str (buf1);
+            numdb_insert (mapregstr_db, (i << 24) | s, p);
+        }
+        else
+        {
+            if (sscanf (line + n, "%d", &v) != 1)
+            {
+                printf ("%s: %s broken data !\n", mapreg_txt, buf1);
+                continue;
+            }
+            s = add_str (buf1);
+            numdb_insert (mapreg_db, (i << 24) | s, v);
+        }
+    }
+    fclose_ (fp);
+    mapreg_dirty = 0;
+    return 0;
+}
+
+/*==========================================
+ * 永続的マップ変数の書き込み
+ *------------------------------------------
+ */
+static void script_save_mapreg_intsub (db_key_t key, db_val_t data, va_list ap)
+{
+    FILE *fp = va_arg (ap, FILE *);
+    int  num = key.i & 0x00ffffff, i = key.i >> 24;
+    char *name = str_buf + str_data[num].str;
+    if (name[1] != '@')
+    {
+        if (i == 0)
+            fprintf (fp, "%s\t%d\n", name, (int) data);
+        else
+            fprintf (fp, "%s,%d\t%d\n", name, i, (int) data);
+    }
+}
+
+static void script_save_mapreg_strsub (db_key_t key, db_val_t data, va_list ap)
+{
+    FILE *fp = va_arg (ap, FILE *);
+    int  num = key.i & 0x00ffffff, i = key.i >> 24;
+    char *name = str_buf + str_data[num].str;
+    if (name[1] != '@')
+    {
+        if (i == 0)
+            fprintf (fp, "%s\t%s\n", name, (char *) data);
+        else
+            fprintf (fp, "%s,%d\t%s\n", name, i, (char *) data);
+    }
+}
+
+static int script_save_mapreg (void)
+{
+    FILE *fp;
+    int  lock;
+
+    if ((fp = lock_fopen (mapreg_txt, &lock)) == NULL)
+        return -1;
+    numdb_foreach (mapreg_db, script_save_mapreg_intsub, fp);
+    numdb_foreach (mapregstr_db, script_save_mapreg_strsub, fp);
+    lock_fclose (fp, mapreg_txt, &lock);
+    mapreg_dirty = 0;
+    return 0;
+}
+
+static void script_autosave_mapreg (timer_id tid, tick_t tick, custom_id_t id,
+                                    custom_data_t data)
+{
+    if (mapreg_dirty)
+        script_save_mapreg ();
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int set_posword (char *p)
+{
+    char *np, *str[15];
+    int  i = 0;
+    for (i = 0; i < 11; i++)
+    {
+        if ((np = strchr (p, ',')) != NULL)
+        {
+            str[i] = p;
+            *np = 0;
+            p = np + 1;
+        }
+        else
+        {
+            str[i] = p;
+            p += strlen (p);
+        }
+        if (str[i])
+            strcpy (pos[i], str[i]);
+    }
+    return 0;
+}
+
+int script_config_read (char *cfgName)
+{
+    int  i;
+    char line[1024], w1[1024], w2[1024];
+    FILE *fp;
+
+    script_config.warn_func_no_comma = 1;
+    script_config.warn_cmd_no_comma = 1;
+    script_config.warn_func_mismatch_paramnum = 1;
+    script_config.warn_cmd_mismatch_paramnum = 1;
+    script_config.check_cmdcount = 8192;
+    script_config.check_gotocount = 512;
+
+    fp = fopen_ (cfgName, "r");
+    if (fp == NULL)
+    {
+        printf ("file not found: %s\n", cfgName);
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        i = sscanf (line, "%[^:]: %[^\r\n]", w1, w2);
+        if (i != 2)
+            continue;
+        if (strcasecmp (w1, "refine_posword") == 0)
+        {
+            set_posword (w2);
+        }
+        if (strcasecmp (w1, "import") == 0)
+        {
+            script_config_read (w2);
+        }
+    }
+    fclose_ (fp);
+
+    return 0;
+}
+
+/*==========================================
+ * 終了
+ *------------------------------------------
+ */
+
+static void mapregstr_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free (data);
+}
+
+static void userfunc_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    free ((char*)key.s);
+    free (data);
+}
+
+int do_final_script (void)
+{
+    if (mapreg_dirty >= 0)
+        script_save_mapreg ();
+    if (script_buf)
+        free (script_buf);
+
+    if (mapreg_db)
+        numdb_final (mapreg_db, NULL);
+    if (mapregstr_db)
+        strdb_final (mapregstr_db, mapregstr_db_final);
+    if (scriptlabel_db)
+        strdb_final (scriptlabel_db, NULL);
+    if (userfunc_db)
+        strdb_final (userfunc_db, userfunc_db_final);
+
+    if (str_data)
+        free (str_data);
+    if (str_buf)
+        free (str_buf);
+
+    return 0;
+}
+
+/*==========================================
+ * 初期化
+ *------------------------------------------
+ */
+int do_init_script (void)
+{
+    mapreg_db = numdb_init ();
+    mapregstr_db = numdb_init ();
+    script_load_mapreg ();
+
+    add_timer_interval (gettick () + MAPREG_AUTOSAVE_INTERVAL,
+                        script_autosave_mapreg, 0, 0,
+                        MAPREG_AUTOSAVE_INTERVAL);
+
+    scriptlabel_db = strdb_init (50);
+    return 0;
+}
diff --git a/src/map/script.h b/src/map/script.h
deleted file mode 100644
index 62d3ee1..0000000
--- a/src/map/script.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// $Id: script.h,v 1.2 2004/09/25 05:32:19 MouseJstr Exp $
-#ifndef _SCRIPT_H_
-#define _SCRIPT_H_
-
-struct script_data
-{
-    int  type;
-    union
-    {
-        int  num;
-        char *str;
-    } u;
-};
-
-struct script_stack
-{
-    int  sp, sp_max;
-    struct script_data *stack_data;
-};
-struct script_state
-{
-    struct script_stack *stack;
-    int  start, end;
-    int  pos, state;
-    int  rid, oid;
-    char *script, *new_script;
-    int  defsp, new_pos, new_defsp;
-};
-
-unsigned char *parse_script (unsigned char *, int);
-typedef struct argrec
-{
-    char *name;
-    union
-    {
-        int  i;
-        char *s;
-    } v;
-} argrec_t;
-int  run_script_l (unsigned char *, int, int, int, int, argrec_t * args);
-int  run_script (unsigned char *, int, int, int);
-
-struct dbt *script_get_label_db (void);
-struct dbt *script_get_userfunc_db (void);
-
-int  script_config_read (char *cfgName);
-int  do_init_script (void);
-int  do_final_script (void);
-
-extern char mapreg_txt[];
-
-#endif
diff --git a/src/map/script.hpp b/src/map/script.hpp
new file mode 100644
index 0000000..a96bc5a
--- /dev/null
+++ b/src/map/script.hpp
@@ -0,0 +1,52 @@
+// $Id: script.h,v 1.2 2004/09/25 05:32:19 MouseJstr Exp $
+#ifndef SCRIPT_HPP
+#define SCRIPT_HPP
+
+struct script_data
+{
+    int  type;
+    union
+    {
+        int  num;
+        char *str;
+    } u;
+};
+
+struct script_stack
+{
+    int  sp, sp_max;
+    struct script_data *stack_data;
+};
+struct script_state
+{
+    struct script_stack *stack;
+    int  start, end;
+    int  pos, state;
+    int  rid, oid;
+    char *script, *new_script;
+    int  defsp, new_pos, new_defsp;
+};
+
+unsigned char *parse_script (unsigned char *, int);
+typedef struct argrec
+{
+    char *name;
+    union
+    {
+        int  i;
+        char *s;
+    } v;
+} argrec_t;
+int  run_script_l (unsigned char *, int, int, int, int, argrec_t * args);
+int  run_script (unsigned char *, int, int, int);
+
+struct dbt *script_get_label_db (void);
+struct dbt *script_get_userfunc_db (void);
+
+int  script_config_read (char *cfgName);
+int  do_init_script (void);
+int  do_final_script (void);
+
+extern char mapreg_txt[];
+
+#endif
diff --git a/src/map/skill-pools.c b/src/map/skill-pools.c
deleted file mode 100644
index 0c91360..0000000
--- a/src/map/skill-pools.c
+++ /dev/null
@@ -1,158 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mt_rand.h"
-#include "magic.h"
-
-#include "battle.h"
-#include "clif.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "../common/socket.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-int  skill_pool_skills[MAX_POOL_SKILLS];
-int  skill_pool_skills_size = 0;
-
-extern void skill_pool_register (int id)
-{
-    if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS)
-    {
-        fprintf (stderr,
-                 "Too many pool skills! Increase MAX_POOL_SKILLS and recompile.");
-        return;
-    }
-
-    skill_pool_skills[skill_pool_skills_size++] = id;
-}
-
-char *skill_name (int skill)
-{
-    if (skill > 0 && skill < MAX_SKILL_DB)
-        return skill_names[skill].desc;
-    else
-        return NULL;
-}
-
-int skill_pool (struct map_session_data *sd, int *skills)
-{
-    int  i, count = 0;
-
-    for (i = 0; count < MAX_SKILL_POOL && i < skill_pool_skills_size; i++)
-    {
-        int  skill_id = skill_pool_skills[i];
-        if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
-        {
-            if (skills)
-                skills[count] = skill_id;
-            ++count;
-        }
-    }
-
-    return count;
-}
-
-void skill_pool_empty (struct map_session_data *sd)
-{
-    int  i;
-
-    for (i = 0; i < skill_pool_skills_size; i++)
-    {
-        int  skill_id = skill_pool_skills[i];
-        sd->status.skill[skill_id].flags = 0;
-    }
-}
-
-int skill_pool_size (struct map_session_data *sd)
-{
-    return skill_pool (sd, NULL);
-}
-
-int skill_pool_max (struct map_session_data *sd)
-{
-    return sd->status.skill[TMW_SKILLPOOL].lv;
-}
-
-int skill_pool_activate (struct map_session_data *sd, int skill_id)
-{
-    if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
-        return 0;               // Already there
-    else if (sd->status.skill[skill_id].id == skill_id  // knows the skill
-             && (skill_pool_size (sd) < skill_pool_max (sd)))
-    {
-        sd->status.skill[skill_id].flags |= SKILL_POOL_ACTIVATED;
-        pc_calcstatus (sd, 0);
-        MAP_LOG_PC (sd, "SKILL-ACTIVATE %d %d %d", skill_id,
-                    sd->status.skill[skill_id].lv, skill_power (sd,
-                                                                skill_id));
-        return 0;
-    }
-
-    return 1;                   // failed
-}
-
-int skill_pool_is_activated (struct map_session_data *sd, int skill_id)
-{
-    return sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED;
-}
-
-int skill_pool_deactivate (struct map_session_data *sd, int skill_id)
-{
-    if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
-    {
-        sd->status.skill[skill_id].flags &= ~SKILL_POOL_ACTIVATED;
-        MAP_LOG_PC (sd, "SKILL-DEACTIVATE %d", skill_id);
-        pc_calcstatus (sd, 0);
-        return 0;
-    }
-
-    return 1;
-}
-
-int skill_stat (int skill_id)
-{
-    return skill_db[skill_id].stat;
-}
-
-int skill_power (struct map_session_data *sd, int skill_id)
-{
-    int  stat = skill_stat (skill_id);
-    int  stat_value, skill_value;
-    int  result;
-
-    if (stat == 0 || !skill_pool_is_activated (sd, skill_id))
-        return 0;
-
-    stat_value = battle_get_stat (stat, &(sd->bl));
-    skill_value = sd->status.skill[skill_id].lv;
-
-    if ((skill_value * 10) - 1 > stat_value)
-        skill_value += (stat_value / 10);
-    else
-        skill_value *= 2;
-
-    result = (skill_value * stat_value) / 10;
-
-    return result;
-}
-
-int skill_power_bl (struct block_list *bl, int skill)
-{
-    if (bl->type == BL_PC)
-        return skill_power ((struct map_session_data *) bl, skill);
-    else
-        return 0;
-}
diff --git a/src/map/skill-pools.cpp b/src/map/skill-pools.cpp
new file mode 100644
index 0000000..6ab6ea5
--- /dev/null
+++ b/src/map/skill-pools.cpp
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/timer.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/mt_rand.hpp"
+#include "magic.hpp"
+
+#include "battle.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "../common/socket.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+int  skill_pool_skills[MAX_POOL_SKILLS];
+int  skill_pool_skills_size = 0;
+
+extern void skill_pool_register (int id)
+{
+    if (skill_pool_skills_size + 1 >= MAX_POOL_SKILLS)
+    {
+        fprintf (stderr,
+                 "Too many pool skills! Increase MAX_POOL_SKILLS and recompile.");
+        return;
+    }
+
+    skill_pool_skills[skill_pool_skills_size++] = id;
+}
+
+char *skill_name (int skill)
+{
+    if (skill > 0 && skill < MAX_SKILL_DB)
+        return skill_names[skill].desc;
+    else
+        return NULL;
+}
+
+int skill_pool (struct map_session_data *sd, int *skills)
+{
+    int  i, count = 0;
+
+    for (i = 0; count < MAX_SKILL_POOL && i < skill_pool_skills_size; i++)
+    {
+        int  skill_id = skill_pool_skills[i];
+        if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
+        {
+            if (skills)
+                skills[count] = skill_id;
+            ++count;
+        }
+    }
+
+    return count;
+}
+
+void skill_pool_empty (struct map_session_data *sd)
+{
+    int  i;
+
+    for (i = 0; i < skill_pool_skills_size; i++)
+    {
+        int  skill_id = skill_pool_skills[i];
+        sd->status.skill[skill_id].flags = 0;
+    }
+}
+
+int skill_pool_size (struct map_session_data *sd)
+{
+    return skill_pool (sd, NULL);
+}
+
+int skill_pool_max (struct map_session_data *sd)
+{
+    return sd->status.skill[TMW_SKILLPOOL].lv;
+}
+
+int skill_pool_activate (struct map_session_data *sd, int skill_id)
+{
+    if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
+        return 0;               // Already there
+    else if (sd->status.skill[skill_id].id == skill_id  // knows the skill
+             && (skill_pool_size (sd) < skill_pool_max (sd)))
+    {
+        sd->status.skill[skill_id].flags |= SKILL_POOL_ACTIVATED;
+        pc_calcstatus (sd, 0);
+        MAP_LOG_PC (sd, "SKILL-ACTIVATE %d %d %d", skill_id,
+                    sd->status.skill[skill_id].lv, skill_power (sd,
+                                                                skill_id));
+        return 0;
+    }
+
+    return 1;                   // failed
+}
+
+int skill_pool_is_activated (struct map_session_data *sd, int skill_id)
+{
+    return sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED;
+}
+
+int skill_pool_deactivate (struct map_session_data *sd, int skill_id)
+{
+    if (sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED)
+    {
+        sd->status.skill[skill_id].flags &= ~SKILL_POOL_ACTIVATED;
+        MAP_LOG_PC (sd, "SKILL-DEACTIVATE %d", skill_id);
+        pc_calcstatus (sd, 0);
+        return 0;
+    }
+
+    return 1;
+}
+
+int skill_stat (int skill_id)
+{
+    return skill_db[skill_id].stat;
+}
+
+int skill_power (struct map_session_data *sd, int skill_id)
+{
+    int  stat = skill_stat (skill_id);
+    int  stat_value, skill_value;
+    int  result;
+
+    if (stat == 0 || !skill_pool_is_activated (sd, skill_id))
+        return 0;
+
+    stat_value = battle_get_stat (stat, &(sd->bl));
+    skill_value = sd->status.skill[skill_id].lv;
+
+    if ((skill_value * 10) - 1 > stat_value)
+        skill_value += (stat_value / 10);
+    else
+        skill_value *= 2;
+
+    result = (skill_value * stat_value) / 10;
+
+    return result;
+}
+
+int skill_power_bl (struct block_list *bl, int skill)
+{
+    if (bl->type == BL_PC)
+        return skill_power ((struct map_session_data *) bl, skill);
+    else
+        return 0;
+}
diff --git a/src/map/skill.c b/src/map/skill.c
deleted file mode 100644
index e232820..0000000
--- a/src/map/skill.c
+++ /dev/null
@@ -1,12279 +0,0 @@
-// $Id: skill.c,v 1.8 2004/09/25 05:32:19 MouseJstr Exp $
-/* スキル関係 */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/mt_rand.h"
-#include "magic.h"
-
-#include "battle.h"
-#include "clif.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "mob.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "../common/socket.h"
-
-#ifdef MEMWATCH
-#include "memwatch.h"
-#endif
-
-#define SKILLUNITTIMER_INVERVAL	100
-
-#define STATE_BLIND 0x10
-
-/* スキル番号=>ステータス異常番号変換テーブル */
-int  SkillStatusChangeTable[] = {   /* skill.hのenumのSC_***とあわせること */
-/* 0- */
-    -1, -1, -1, -1, -1, -1,
-    SC_PROVOKE,                 /* プロボック */
-    -1, 1, -1,
-/* 10- */
-    SC_SIGHT,                   /* サイト */
-    -1, -1, -1, -1,
-    SC_FREEZE,                  /* フロストダイバー */
-    SC_STONE,                   /* ストーンカース */
-    -1, -1, -1,
-/* 20- */
-    -1, -1, -1, -1,
-    SC_RUWACH,                  /* ルアフ */
-    -1, -1, -1, -1,
-    SC_INCREASEAGI,             /* 速度増加 */
-/* 30- */
-    SC_DECREASEAGI,             /* 速度減少 */
-    -1,
-    SC_SIGNUMCRUCIS,            /* シグナムクルシス */
-    SC_ANGELUS,                 /* エンジェラス */
-    SC_BLESSING,                /* ブレッシング */
-    -1, -1, -1, -1, -1,
-/* 40- */
-    -1, -1, -1, -1, -1,
-    SC_CONCENTRATE,             /* 集中力向上 */
-    -1, -1, -1, -1,
-/* 50- */
-    -1,
-    SC_HIDING,                  /* ハイディング */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-/* 60- */
-    SC_TWOHANDQUICKEN,          /* 2HQ */
-    SC_AUTOCOUNTER,
-    -1, -1, -1, -1,
-    SC_IMPOSITIO,               /* インポシティオマヌス */
-    SC_SUFFRAGIUM,              /* サフラギウム */
-    SC_ASPERSIO,                /* アスペルシオ */
-    SC_BENEDICTIO,              /* 聖体降福 */
-/* 70- */
-    -1,
-    SC_SLOWPOISON,
-    -1,
-    SC_KYRIE,                   /* キリエエレイソン */
-    SC_MAGNIFICAT,              /* マグニフィカート */
-    SC_GLORIA,                  /* グロリア */
-    SC_DIVINA,                  /* レックスディビーナ */
-    -1,
-    SC_AETERNA,                 /* レックスエーテルナ */
-    -1,
-/* 80- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 90- */
-    -1, -1,
-    SC_QUAGMIRE,                /* クァグマイア */
-    -1, -1, -1, -1, -1, -1, -1,
-/* 100- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 110- */
-    -1,
-    SC_ADRENALINE,              /* アドレナリンラッシュ */
-    SC_WEAPONPERFECTION,        /* ウェポンパーフェクション */
-    SC_OVERTHRUST,              /* オーバートラスト */
-    SC_MAXIMIZEPOWER,           /* マキシマイズパワー */
-    -1, -1, -1, -1, -1,
-/* 120- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 130- */
-    -1, -1, -1, -1, -1,
-    SC_CLOAKING,                /* クローキング */
-    SC_STAN,                    /* ソニックブロー */
-    -1,
-    SC_ENCPOISON,               /* エンチャントポイズン */
-    SC_POISONREACT,             /* ポイズンリアクト */
-/* 140- */
-    SC_POISON,                  /* ベノムダスト */
-    SC_SPLASHER,                /* ベナムスプラッシャー */
-    -1,
-    SC_TRICKDEAD,               /* 死んだふり */
-    -1, -1, -1, -1, -1, -1,
-/* 150- */
-    -1, -1, -1, -1, -1,
-    SC_LOUD,                    /* ラウドボイス */
-    -1,
-    SC_ENERGYCOAT,              /* エナジーコート */
-    -1, -1,
-/* 160- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1,
-    SC_SELFDESTRUCTION,
-    -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1,
-    SC_KEEPING,
-    -1, -1,
-    SC_BARRIER,
-    -1, -1,
-    SC_HALLUCINATION,
-    -1, -1,
-/* 210- */
-    -1, -1, -1, -1, -1,
-    SC_STRIPWEAPON,
-    SC_STRIPSHIELD,
-    SC_STRIPARMOR,
-    SC_STRIPHELM,
-    -1,
-/* 220- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 230- */
-    -1, -1, -1, -1,
-    SC_CP_WEAPON,
-    SC_CP_SHIELD,
-    SC_CP_ARMOR,
-    SC_CP_HELM,
-    -1, -1,
-/* 240- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    SC_AUTOGUARD,
-/* 250- */
-    -1, -1,
-    SC_REFLECTSHIELD,
-    -1, -1,
-    SC_DEVOTION,
-    SC_PROVIDENCE,
-    SC_DEFENDER,
-    SC_SPEARSQUICKEN,
-    -1,
-/* 260- */
-    -1, -1, -1, -1, -1, -1, -1, -1,
-    SC_STEELBODY,
-    SC_BLADESTOP_WAIT,
-/* 270- */
-    SC_EXPLOSIONSPIRITS,
-    SC_EXTREMITYFIST,
-    -1, -1, -1, -1,
-    SC_MAGICROD,
-    -1, -1, -1,
-/* 280- */
-    SC_FLAMELAUNCHER,
-    SC_FROSTWEAPON,
-    SC_LIGHTNINGLOADER,
-    SC_SEISMICWEAPON,
-    -1,
-    SC_VOLCANO,
-    SC_DELUGE,
-    SC_VIOLENTGALE,
-    SC_LANDPROTECTOR,
-    -1,
-/* 290- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 300- */
-    -1, -1, -1, -1, -1, -1,
-    SC_LULLABY,
-    SC_RICHMANKIM,
-    SC_ETERNALCHAOS,
-    SC_DRUMBATTLE,
-/* 310- */
-    SC_NIBELUNGEN,
-    SC_ROKISWEIL,
-    SC_INTOABYSS,
-    SC_SIEGFRIED,
-    -1, -1, -1,
-    SC_DISSONANCE,
-    -1,
-    SC_WHISTLE,
-/* 320- */
-    SC_ASSNCROS,
-    SC_POEMBRAGI,
-    SC_APPLEIDUN,
-    -1, -1,
-    SC_UGLYDANCE,
-    -1,
-    SC_HUMMING,
-    SC_DONTFORGETME,
-    SC_FORTUNE,
-/* 330- */
-    SC_SERVICE4U,
-    SC_SELFDESTRUCTION,
-    -1, -1, -1, -1, -1, -1, -1, -1,
-/* 340- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 350- */
-    -1, -1, -1, -1, -1,
-    SC_AURABLADE,
-    SC_PARRYING,
-    SC_CONCENTRATION,
-    SC_TENSIONRELAX,
-    SC_BERSERK,
-/* 360- */
-    SC_BERSERK,
-    SC_ASSUMPTIO,
-    SC_BASILICA,
-    -1, -1, -1,
-    SC_MAGICPOWER,
-    -1, -1,
-    SC_GOSPEL,
-/* 370- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-/* 380- */
-    SC_TRUESIGHT,
-    -1, -1,
-    SC_WINDWALK,
-    SC_MELTDOWN,
-    -1, -1,
-    SC_CARTBOOST,
-    -1,
-    SC_CHASEWALK,
-/* 390- */
-    SC_REJECTSWORD,
-    -1, -1, -1, -1, -1,
-    SC_MARIONETTE,
-    -1,
-    SC_HEADCRUSH,
-    SC_JOINTBEAT,
-/* 400 */
-    -1, -1,
-    SC_MINDBREAKER,
-    SC_MEMORIZE,
-    SC_FOGWALL,
-    SC_SPIDERWEB,
-    -1, -1, -1, -1,
-/* 410- */
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-};
-
-struct skill_name_db skill_names[] = {
-    {AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow"},
-    {AC_CONCENTRATION, "CONCENTRATION", "Improve_Concentration"},
-    {AC_DOUBLE, "DOUBLE", "Double_Strafe"},
-    {AC_MAKINGARROW, "MAKINGARROW", "Arrow_Creation"},
-    {AC_OWL, "OWL", "Owl's_Eye"},
-    {AC_SHOWER, "SHOWER", "Arrow_Shower"},
-    {AC_VULTURE, "VULTURE", "Vulture's_Eye"},
-    {ALL_RESURRECTION, "RESURRECTION", "Resurrection"},
-    {AL_ANGELUS, "ANGELUS", "Angelus"},
-    {AL_BLESSING, "BLESSING", "Blessing"},
-    {AL_CRUCIS, "CRUCIS", "Signum_Crusis"},
-    {AL_CURE, "CURE", "Cure"},
-    {AL_DECAGI, "DECAGI", "Decrease_AGI"},
-    {AL_DEMONBANE, "DEMONBANE", "Demon_Bane"},
-    {AL_DP, "DP", "Divine_Protection"},
-    {AL_HEAL, "HEAL", "Heal"},
-    {AL_HOLYLIGHT, "HOLYLIGHT", "Holy_Light"},
-    {AL_HOLYWATER, "HOLYWATER", "Aqua_Benedicta"},
-    {AL_INCAGI, "INCAGI", "Increase_AGI"},
-    {AL_PNEUMA, "PNEUMA", "Pneuma"},
-    {AL_RUWACH, "RUWACH", "Ruwach"},
-    {AL_TELEPORT, "TELEPORT", "Teleport"},
-    {AL_WARP, "WARP", "Warp_Portal"},
-    {AM_ACIDTERROR, "ACIDTERROR", "Acid_Terror"},
-    {AM_AXEMASTERY, "AXEMASTERY", "Axe_Mastery"},
-    {AM_BERSERKPITCHER, "BERSERKPITCHER", "Berserk Pitcher"},
-    {AM_BIOETHICS, "BIOETHICS", "Bioethics"},
-    {AM_BIOTECHNOLOGY, "BIOTECHNOLOGY", "Biotechnology"},
-    {AM_CALLHOMUN, "CALLHOMUN", "Call_Homunculus"},
-    {AM_CANNIBALIZE, "CANNIBALIZE", "Bio_Cannibalize"},
-    {AM_CP_ARMOR, "ARMOR", "Chemical_Protection_Armor"},
-    {AM_CP_HELM, "HELM", "Chemical_Protection_Helm"},
-    {AM_CP_SHIELD, "SHIELD", "Chemical_Protection_Shield"},
-    {AM_CP_WEAPON, "WEAPON", "Chemical_Protection_Weapon"},
-    {AM_CREATECREATURE, "CREATECREATURE", "Life_Creation"},
-    {AM_CULTIVATION, "CULTIVATION", "Cultivation"},
-    {AM_DEMONSTRATION, "DEMONSTRATION", "Demonstration"},
-    {AM_DRILLMASTER, "DRILLMASTER", "Drillmaster"},
-    {AM_FLAMECONTROL, "FLAMECONTROL", "Flame_Control"},
-    {AM_HEALHOMUN, "HEALHOMUN", "Heal_Homunculus"},
-    {AM_LEARNINGPOTION, "LEARNINGPOTION", "AM_LEARNINGPOTION"},
-    {AM_PHARMACY, "PHARMACY", "Pharmacy"},
-    {AM_POTIONPITCHER, "POTIONPITCHER", "Potion_Pitcher"},
-    {AM_REST, "REST", "Sabbath"},
-    {AM_RESURRECTHOMUN, "RESURRECTHOMUN", "Ressurect_Homunculus"},
-    {AM_SPHEREMINE, "SPHEREMINE", "Sphere_Mine"},
-    {ASC_BREAKER, "BREAKER", "Breaker"},
-    {ASC_CDP, "CDP", "Create_Deadly_Poison"},
-    {ASC_EDP, "EDP", "Deadly_Poison_Enchantment"},
-    {ASC_HALLUCINATION, "HALLUCINATION", "Hallucination_Walk"},
-    {ASC_KATAR, "KATAR", "Advanced_Katar_Mastery"},
-    {ASC_METEORASSAULT, "METEORASSAULT", "Meteor_Assault"},
-    {AS_CLOAKING, "CLOAKING", "Cloaking"},
-    {AS_ENCHANTPOISON, "ENCHANTPOISON", "Enchant_Poison"},
-    {AS_GRIMTOOTH, "GRIMTOOTH", "Grimtooth"},
-    {AS_KATAR, "KATAR", "Katar_Mastery"},
-    {AS_LEFT, "LEFT", "Lefthand_Mastery"},
-    {AS_POISONREACT, "POISONREACT", "Poison_React"},
-    {AS_RIGHT, "RIGHT", "Righthand_Mastery"},
-    {AS_SONICBLOW, "SONICBLOW", "Sonic_Blow"},
-    {AS_SPLASHER, "SPLASHER", "Venom_Splasher"},
-    {AS_VENOMDUST, "VENOMDUST", "Venom_Dust"},
-    {BA_APPLEIDUN, "APPLEIDUN", "Apple_of_Idun"},
-    {BA_ASSASSINCROSS, "ASSASSINCROSS", "Assassin_Cross"},
-    {BA_DISSONANCE, "DISSONANCE", "Dissonance"},
-    {BA_FROSTJOKE, "FROSTJOKE", "Dumb_Joke"},
-    {BA_MUSICALLESSON, "MUSICALLESSON", "Musical_Lesson"},
-    {BA_MUSICALSTRIKE, "MUSICALSTRIKE", "Musical_Strike"},
-    {BA_POEMBRAGI, "POEMBRAGI", "Poem_of_Bragi"},
-    {BA_WHISTLE, "WHISTLE", "Whistle"},
-    {BD_ADAPTATION, "ADAPTATION", "Adaption"},
-    {BD_DRUMBATTLEFIELD, "DRUMBATTLEFIELD", "Drumb_BattleField"},
-    {BD_ENCORE, "ENCORE", "Encore"},
-    {BD_ETERNALCHAOS, "ETERNALCHAOS", "Eternal_Chaos"},
-    {BD_INTOABYSS, "INTOABYSS", "Into_the_Abyss"},
-    {BD_LULLABY, "LULLABY", "Lullaby"},
-    {BD_RAGNAROK, "RAGNAROK", "Ragnarok"},
-    {BD_RICHMANKIM, "RICHMANKIM", "Rich_Mankim"},
-    {BD_RINGNIBELUNGEN, "RINGNIBELUNGEN", "Ring_of_Nibelugen"},
-    {BD_ROKISWEIL, "ROKISWEIL", "Loki's_Wail"},
-    {BD_SIEGFRIED, "SIEGFRIED", "Invulnerable_Siegfried"},
-    {BS_ADRENALINE, "ADRENALINE", "Adrenaline_Rush"},
-    {BS_ADRENALINE2, "ADRENALINE2", "Adrenaline Rush 2"},
-    {BS_AXE, "AXE", "Smith_Axe"},
-    {BS_DAGGER, "DAGGER", "Smith_Dagger"},
-    {BS_ENCHANTEDSTONE, "ENCHANTEDSTONE", "Enchantedstone_Craft"},
-    {BS_FINDINGORE, "FINDINGORE", "Ore_Discovery"},
-    {BS_HAMMERFALL, "HAMMERFALL", "Hammer_Fall"},
-    {BS_HILTBINDING, "HILTBINDING", "Hilt_Binding"},
-    {BS_IRON, "IRON", "Iron_Tempering"},
-    {BS_KNUCKLE, "KNUCKLE", "Smith_Knucklebrace"},
-    {BS_MACE, "MACE", "Smith_Mace"},
-    {BS_MAXIMIZE, "MAXIMIZE", "Power_Maximize"},
-    {BS_ORIDEOCON, "ORIDEOCON", "Orideocon_Research"},
-    {BS_OVERTHRUST, "OVERTHRUST", "Power-Thrust"},
-    {BS_REPAIRWEAPON, "REPAIRWEAPON", "Weapon_Repair"},
-    {BS_SKINTEMPER, "SKINTEMPER", "Skin_Tempering"},
-    {BS_SPEAR, "SPEAR", "Smith_Spear"},
-    {BS_STEEL, "STEEL", "Steel_Tempering"},
-    {BS_SWORD, "SWORD", "Smith_Sword"},
-    {BS_TWOHANDSWORD, "TWOHANDSWORD", "Smith_Two-handed_Sword"},
-    {BS_WEAPONPERFECT, "WEAPONPERFECT", "Weapon_Perfection"},
-    {BS_WEAPONRESEARCH, "WEAPONRESEARCH", "Weaponry_Research"},
-    {CG_ARROWVULCAN, "ARROWVULCAN", "Vulcan_Arrow"},
-    {CG_MARIONETTE, "MARIONETTE", "Marionette_Control"},
-    {CG_MOONLIT, "MOONLIT", "Moonlight_Petals"},
-    {CH_CHAINCRUSH, "CHAINCRUSH", "Chain_Crush_Combo"},
-    {CH_PALMSTRIKE, "PALMSTRIKE", "Palm_Push_Strike"},
-    {CH_SOULCOLLECT, "SOULCOLLECT", "Collect_Soul"},
-    {CH_TIGERFIST, "TIGERFIST", "Tiger_Knuckle_Fist"},
-    {CR_ALCHEMY, "ALCHEMY", "Alchemy"},
-    {CR_AUTOGUARD, "AUTOGUARD", "Guard"},
-    {CR_DEFENDER, "DEFENDER", "Defender"},
-    {CR_DEVOTION, "DEVOTION", "Sacrifice"},
-    {CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross"},
-    {CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross"},
-    {CR_PROVIDENCE, "PROVIDENCE", "Providence"},
-    {CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect"},
-    {CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang"},
-    {CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge"},
-    {CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken"},
-    {CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis"},
-    {CR_TRUST, "TRUST", "Faith"},
-    {DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson"},
-    {DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me"},
-    {DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss"},
-    {DC_HUMMING, "HUMMING", "Humming"},
-    {DC_SCREAM, "SCREAM", "Scream"},
-    {DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute"},
-    {DC_THROWARROW, "THROWARROW", "Throw_Arrow"},
-    {DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance"},
-    {HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio"},
-    {HP_BASILICA, "BASILICA", "Basilica"},
-    {HP_MEDITATIO, "MEDITATIO", "Meditation"},
-    {HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare"},
-    {HT_BEASTBANE, "BEASTBANE", "Beast_Bane"},
-    {HT_BLASTMINE, "BLASTMINE", "Blast_Mine"},
-    {HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat"},
-    {HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap"},
-    {HT_DETECTING, "DETECTING", "Detect"},
-    {HT_FALCON, "FALCON", "Falconry_Mastery"},
-    {HT_FLASHER, "FLASHER", "Flasher"},
-    {HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap"},
-    {HT_LANDMINE, "LANDMINE", "Land_Mine"},
-    {HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap"},
-    {HT_SANDMAN, "SANDMAN", "Sandman"},
-    {HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap"},
-    {HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap"},
-    {HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap"},
-    {HT_STEELCROW, "STEELCROW", "Steel_Crow"},
-    {HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box"},
-    {HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher"},
-    {HW_MAGICPOWER, "MAGICPOWER", "Magic_Power"},
-    {HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan"},
-    {HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain"},
-    {KN_AUTOCOUNTER, "AUTOCOUNTER", "Counter_Attack"},
-    {KN_BOWLINGBASH, "BOWLINGBASH", "Bowling_Bash"},
-    {KN_BRANDISHSPEAR, "BRANDISHSPEAR", "Brandish_Spear"},
-    {KN_CAVALIERMASTERY, "CAVALIERMASTERY", "Cavalier_Mastery"},
-    {KN_PIERCE, "PIERCE", "Pierce"},
-    {KN_RIDING, "RIDING", "Peco_Peco_Ride"},
-    {KN_SPEARBOOMERANG, "SPEARBOOMERANG", "Spear_Boomerang"},
-    {KN_SPEARMASTERY, "SPEARMASTERY", "Spear_Mastery"},
-    {KN_SPEARSTAB, "SPEARSTAB", "Spear_Stab"},
-    {KN_TWOHANDQUICKEN, "TWOHANDQUICKEN", "Twohand_Quicken"},
-    {LK_AURABLADE, "AURABLADE", "Aura_Blade"},
-    {LK_BERSERK, "BERSERK", "Berserk"},
-    {LK_CONCENTRATION, "CONCENTRATION", "Concentration"},
-    {LK_FURY, "FURY", "LK_FURY"},
-    {LK_HEADCRUSH, "HEADCRUSH", "Head_Crusher"},
-    {LK_JOINTBEAT, "JOINTBEAT", "Joint_Beat"},
-    {LK_PARRYING, "PARRYING", "Parrying"},
-    {LK_SPIRALPIERCE, "SPIRALPIERCE", "Spiral_Pierce"},
-    {LK_TENSIONRELAX, "TENSIONRELAX", "Tension_Relax"},
-    {MC_CARTREVOLUTION, "CARTREVOLUTION", "Cart_Revolution"},
-    {MC_CHANGECART, "CHANGECART", "Change_Cart"},
-    {MC_DISCOUNT, "DISCOUNT", "Discount"},
-    {MC_IDENTIFY, "IDENTIFY", "Item_Appraisal"},
-    {MC_INCCARRY, "INCCARRY", "Enlarge_Weight_Limit"},
-    {MC_LOUD, "LOUD", "Lord_Exclamation"},
-    {MC_MAMMONITE, "MAMMONITE", "Mammonite"},
-    {MC_OVERCHARGE, "OVERCHARGE", "Overcharge"},
-    {MC_PUSHCART, "PUSHCART", "Pushcart"},
-    {MG_COLDBOLT, "COLDBOLT", "Cold_Bolt"},
-    {MG_ENERGYCOAT, "ENERGYCOAT", "Energy_Coat"},
-    {MG_FIREBALL, "FIREBALL", "Fire_Ball"},
-    {MG_FIREBOLT, "FIREBOLT", "Fire_Bolt"},
-    {MG_FIREWALL, "FIREWALL", "Fire_Wall"},
-    {MG_FROSTDIVER, "FROSTDIVER", "Frost_Diver"},
-    {MG_LIGHTNINGBOLT, "LIGHTNINGBOLT", "Lightening_Bolt"},
-    {MG_NAPALMBEAT, "NAPALMBEAT", "Napalm_Beat"},
-    {MG_SAFETYWALL, "SAFETYWALL", "Safety_Wall"},
-    {MG_SIGHT, "SIGHT", "Sight"},
-    {MG_SOULSTRIKE, "SOULSTRIKE", "Soul_Strike"},
-    {MG_SRECOVERY, "SRECOVERY", "Increase_SP_Recovery"},
-    {MG_STONECURSE, "STONECURSE", "Stone_Curse"},
-    {MG_THUNDERSTORM, "THUNDERSTORM", "Thunderstorm"},
-    {MO_ABSORBSPIRITS, "ABSORBSPIRITS", "Absorb_Spirits"},
-    {MO_BLADESTOP, "BLADESTOP", "Blade_Stop"},
-    {MO_BODYRELOCATION, "BODYRELOCATION", "Body_Relocation"},
-    {MO_CALLSPIRITS, "CALLSPIRITS", "Call_Spirits"},
-    {MO_CHAINCOMBO, "CHAINCOMBO", "Chain_Combo"},
-    {MO_COMBOFINISH, "COMBOFINISH", "Combo_Finish"},
-    {MO_DODGE, "DODGE", "Dodge"},
-    {MO_EXPLOSIONSPIRITS, "EXPLOSIONSPIRITS", "Explosion_Spirits"},
-    {MO_EXTREMITYFIST, "EXTREMITYFIST", "Extremity_Fist"},
-    {MO_FINGEROFFENSIVE, "FINGEROFFENSIVE", "Finger_Offensive"},
-    {MO_INVESTIGATE, "INVESTIGATE", "Investigate"},
-    {MO_IRONHAND, "IRONHAND", "Iron_Hand"},
-    {MO_SPIRITSRECOVERY, "SPIRITSRECOVERY", "Spirit_Recovery"},
-    {MO_STEELBODY, "STEELBODY", "Steel_Body"},
-    {MO_TRIPLEATTACK, "TRIPLEATTACK", "Triple_Blows"},
-    {NPC_ATTRICHANGE, "ATTRICHANGE", "NPC_ATTRICHANGE"},
-    {NPC_BARRIER, "BARRIER", "NPC_BARRIER"},
-    {NPC_BLINDATTACK, "BLINDATTACK", "NPC_BLINDATTACK"},
-    {NPC_BLOODDRAIN, "BLOODDRAIN", "NPC_BLOODDRAIN"},
-    {NPC_CHANGEDARKNESS, "CHANGEDARKNESS", "NPC_CHANGEDARKNESS"},
-    {NPC_CHANGEFIRE, "CHANGEFIRE", "NPC_CHANGEFIRE"},
-    {NPC_CHANGEGROUND, "CHANGEGROUND", "NPC_CHANGEGROUND"},
-    {NPC_CHANGEHOLY, "CHANGEHOLY", "NPC_CHANGEHOLY"},
-    {NPC_CHANGEPOISON, "CHANGEPOISON", "NPC_CHANGEPOISON"},
-    {NPC_CHANGETELEKINESIS, "CHANGETELEKINESIS", "NPC_CHANGETELEKINESIS"},
-    {NPC_CHANGEWATER, "CHANGEWATER", "NPC_CHANGEWATER"},
-    {NPC_CHANGEWIND, "CHANGEWIND", "NPC_CHANGEWIND"},
-    {NPC_COMBOATTACK, "COMBOATTACK", "NPC_COMBOATTACK"},
-    {NPC_CRITICALSLASH, "CRITICALSLASH", "NPC_CRITICALSLASH"},
-    {NPC_CURSEATTACK, "CURSEATTACK", "NPC_CURSEATTACK"},
-    {NPC_DARKBLESSING, "DARKBLESSING", "NPC_DARKBLESSING"},
-    {NPC_DARKBREATH, "DARKBREATH", "NPC_DARKBREATH"},
-    {NPC_DARKCROSS, "DARKCROSS", "NPC_DARKCROSS"},
-    {NPC_DARKNESSATTACK, "DARKNESSATTACK", "NPC_DARKNESSATTACK"},
-    {NPC_DEFENDER, "DEFENDER", "NPC_DEFENDER"},
-    {NPC_EMOTION, "EMOTION", "NPC_EMOTION"},
-    {NPC_ENERGYDRAIN, "ENERGYDRAIN", "NPC_ENERGYDRAIN"},
-    {NPC_FIREATTACK, "FIREATTACK", "NPC_FIREATTACK"},
-    {NPC_GROUNDATTACK, "GROUNDATTACK", "NPC_GROUNDATTACK"},
-    {NPC_GUIDEDATTACK, "GUIDEDATTACK", "NPC_GUIDEDATTACK"},
-    {NPC_HALLUCINATION, "HALLUCINATION", "NPC_HALLUCINATION"},
-    {NPC_HOLYATTACK, "HOLYATTACK", "NPC_HOLYATTACK"},
-    {NPC_KEEPING, "KEEPING", "NPC_KEEPING"},
-    {NPC_LICK, "LICK", "NPC_LICK"},
-    {NPC_MAGICALATTACK, "MAGICALATTACK", "NPC_MAGICALATTACK"},
-    {NPC_MENTALBREAKER, "MENTALBREAKER", "NPC_MENTALBREAKER"},
-    {NPC_METAMORPHOSIS, "METAMORPHOSIS", "NPC_METAMORPHOSIS"},
-    {NPC_PETRIFYATTACK, "PETRIFYATTACK", "NPC_PETRIFYATTACK"},
-    {NPC_PIERCINGATT, "PIERCINGATT", "NPC_PIERCINGATT"},
-    {NPC_POISON, "POISON", "NPC_POISON"},
-    {NPC_POISONATTACK, "POISONATTACK", "NPC_POISONATTACK"},
-    {NPC_RANDOMATTACK, "RANDOMATTACK", "NPC_RANDOMATTACK"},
-    {NPC_RANGEATTACK, "RANGEATTACK", "NPC_RANGEATTACK"},
-    {NPC_REBIRTH, "REBIRTH", "NPC_REBIRTH"},
-    {NPC_SELFDESTRUCTION, "SELFDESTRUCTION", "Kabooooom!"},
-    {NPC_SELFDESTRUCTION2, "SELFDESTRUCTION2", "NPC_SELFDESTRUCTION2"},
-    {NPC_SILENCEATTACK, "SILENCEATTACK", "NPC_SILENCEATTACK"},
-    {NPC_SLEEPATTACK, "SLEEPATTACK", "NPC_SLEEPATTACK"},
-    {NPC_SMOKING, "SMOKING", "NPC_SMOKING"},
-    {NPC_SPLASHATTACK, "SPLASHATTACK", "NPC_SPLASHATTACK"},
-    {NPC_STUNATTACK, "STUNATTACK", "NPC_STUNATTACK"},
-    {NPC_SUICIDE, "SUICIDE", "NPC_SUICIDE"},
-    {NPC_SUMMONMONSTER, "SUMMONMONSTER", "NPC_SUMMONMONSTER"},
-    {NPC_SUMMONSLAVE, "SUMMONSLAVE", "NPC_SUMMONSLAVE"},
-    {NPC_TELEKINESISATTACK, "TELEKINESISATTACK", "NPC_TELEKINESISATTACK"},
-    {NPC_TRANSFORMATION, "TRANSFORMATION", "NPC_TRANSFORMATION"},
-    {NPC_WATERATTACK, "WATERATTACK", "NPC_WATERATTACK"},
-    {NPC_WINDATTACK, "WINDATTACK", "NPC_WINDATTACK"},
-    {NV_EMOTE, "EMOTE", "Emote_Skill"},
-    {NV_TRADE, "TRADE", "Trade_Skill"},
-    {NV_PARTY, "PARTY", "Party_Skill"},
-    {NV_FIRSTAID, "FIRSTAID", "First Aid"},
-    {NV_TRICKDEAD, "TRICKDEAD", "Play_Dead"},
-    {PA_GOSPEL, "GOSPEL", "Gospel"},
-    {PA_PRESSURE, "PRESSURE", "Pressure"},
-    {PA_SACRIFICE, "SACRIFICE", "Sacrificial_Ritual"},
-    {PF_FOGWALL, "FOGWALL", "Wall_of_Fog"},
-    {PF_HPCONVERSION, "HPCONVERSION", "Health_Conversion"},
-    {PF_MEMORIZE, "MEMORIZE", "Memorize"},
-    {PF_MINDBREAKER, "MINDBREAKER", "Mind_Breaker"},
-    {PF_SOULBURN, "SOULBURN", "Soul_Burn"},
-    {PF_SOULCHANGE, "SOULCHANGE", "Soul_Change"},
-    {PF_SPIDERWEB, "SPIDERWEB", "Spider_Web"},
-    {PR_ASPERSIO, "ASPERSIO", "Aspersio"},
-    {PR_BENEDICTIO, "BENEDICTIO", "B.S_Sacramenti"},
-    {PR_GLORIA, "GLORIA", "Gloria"},
-    {PR_IMPOSITIO, "IMPOSITIO", "Impositio_Manus"},
-    {PR_KYRIE, "KYRIE", "Kyrie_Eleison"},
-    {PR_LEXAETERNA, "LEXAETERNA", "Lex_Aeterna"},
-    {PR_LEXDIVINA, "LEXDIVINA", "Lex_Divina"},
-    {PR_MACEMASTERY, "MACEMASTERY", "Mace_Mastery"},
-    {PR_MAGNIFICAT, "MAGNIFICAT", "Magnificat"},
-    {PR_MAGNUS, "MAGNUS", "Magnus_Exorcismus"},
-    {PR_SANCTUARY, "SANCTUARY", "Santuary"},
-    {PR_SLOWPOISON, "SLOWPOISON", "Slow_Poison"},
-    {PR_STRECOVERY, "STRECOVERY", "Status_Recovery"},
-    {PR_SUFFRAGIUM, "SUFFRAGIUM", "Suffragium"},
-    {PR_TURNUNDEAD, "TURNUNDEAD", "Turn_Undead"},
-    {RG_BACKSTAP, "BACKSTAP", "Back_Stab"},
-    {RG_CLEANER, "CLEANER", "Remover"},
-    {RG_COMPULSION, "COMPULSION", "Compulsion_Discount"},
-    {RG_FLAGGRAFFITI, "FLAGGRAFFITI", "Flag_Graffity"},
-    {RG_GANGSTER, "GANGSTER", "Gangster's_Paradise"},
-    {RG_GRAFFITI, "GRAFFITI", "Graffiti"},
-    {RG_INTIMIDATE, "INTIMIDATE", "Intimidate"},
-    {RG_PLAGIARISM, "PLAGIARISM", "Plagiarism"},
-    {RG_RAID, "RAID", "Raid"},
-    {RG_SNATCHER, "SNATCHER", "Snatcher"},
-    {RG_STEALCOIN, "STEALCOIN", "Steal_Coin"},
-    {RG_STRIPARMOR, "STRIPARMOR", "Strip_Armor"},
-    {RG_STRIPHELM, "STRIPHELM", "Strip_Helm"},
-    {RG_STRIPSHIELD, "STRIPSHIELD", "Strip_Shield"},
-    {RG_STRIPWEAPON, "STRIPWEAPON", "Strip_Weapon"},
-    {RG_TUNNELDRIVE, "TUNNELDRIVE", "Tunnel_Drive"},
-    {SA_ABRACADABRA, "ABRACADABRA", "Hocus-pocus"},
-    {SA_ADVANCEDBOOK, "ADVANCEDBOOK", "Advanced_Book"},
-    {SA_AUTOSPELL, "AUTOSPELL", "Auto_Cast"},
-    {SA_CASTCANCEL, "CASTCANCEL", "Cast_Cancel"},
-    {SA_CLASSCHANGE, "CLASSCHANGE", "Class_Change"},
-    {SA_COMA, "COMA", "Coma"},
-    {SA_DEATH, "DEATH", "Death"},
-    {SA_DELUGE, "DELUGE", "Deluge"},
-    {SA_DISPELL, "DISPELL", "Dispel"},
-    {SA_DRAGONOLOGY, "DRAGONOLOGY", "Dragonology"},
-    {SA_FLAMELAUNCHER, "FLAMELAUNCHER", "Flame_Launcher"},
-    {SA_FORTUNE, "FORTUNE", "Fortune"},
-    {SA_FREECAST, "FREECAST", "Cast_Freedom"},
-    {SA_FROSTWEAPON, "FROSTWEAPON", "Frost_Weapon"},
-    {SA_FULLRECOVERY, "FULLRECOVERY", "Full_Recovery"},
-    {SA_GRAVITY, "GRAVITY", "Gravity"},
-    {SA_INSTANTDEATH, "INSTANTDEATH", "Instant_Death"},
-    {SA_LANDPROTECTOR, "LANDPROTECTOR", "Land_Protector"},
-    {SA_LEVELUP, "LEVELUP", "Level_Up"},
-    {SA_LIGHTNINGLOADER, "LIGHTNINGLOADER", "Lightning_Loader"},
-    {SA_MAGICROD, "MAGICROD", "Magic_Rod"},
-    {SA_MONOCELL, "MONOCELL", "Monocell"},
-    {SA_QUESTION, "QUESTION", "Question?"},
-    {SA_REVERSEORCISH, "REVERSEORCISH", "Reverse_Orcish"},
-    {SA_SEISMICWEAPON, "SEISMICWEAPON", "Seismic_Weapon"},
-    {SA_SPELLBREAKER, "SPELLBREAKER", "Break_Spell"},
-    {SA_SUMMONMONSTER, "SUMMONMONSTER", "Summon_Monster"},
-    {SA_VIOLENTGALE, "VIOLENTGALE", "Violent_Gale"},
-    {SA_VOLCANO, "VOLCANO", "Volcano"},
-    {SG_DEVIL, "DEVIL", "Devil"},
-    {SG_FEEL, "FEEL", "Feel"},
-    {SG_FRIEND, "FRIEND", "Friend"},
-    {SG_FUSION, "FUSION", "Fusion"},
-    {SG_HATE, "HATE", "Hate"},
-    {SG_KNOWLEDGE, "KNOWLEDGE", "Knowledge"},
-    {SG_MOON_ANGER, "ANGER", "Moon Anger"},
-    {SG_MOON_BLESS, "BLESS", "Moon Bless"},
-    {SG_MOON_COMFORT, "COMFORT", "Moon Comfort"},
-    {SG_MOON_WARM, "WARM", "Moon Warm"},
-    {SG_STAR_ANGER, "ANGER", "Star Anger"},
-    {SG_STAR_BLESS, "BLESS", "Star Bless"},
-    {SG_STAR_COMFORT, "COMFORT", "Star Comfort"},
-    {SG_STAR_WARM, "WARM", "Star Warm"},
-    {SG_SUN_ANGER, "ANGER", "Sun Anger"},
-    {SG_SUN_BLESS, "BLESS", "Sun Bless"},
-    {SG_SUN_COMFORT, "COMFORT", "Sun Comfort"},
-    {SG_SUN_WARM, "WARM", "Sun Warm"},
-    {SL_ALCHEMIST, "ALCHEMIST", "Alchemist"},
-    {SL_ASSASIN, "ASSASIN", "Assasin"},
-    {SL_BARDDANCER, "BARDDANCER", "Bard Dancer"},
-    {SL_BLACKSMITH, "BLACKSMITH", "Black Smith"},
-    {SL_CRUSADER, "CRUSADER", "Crusader"},
-    {SL_HUNTER, "HUNTER", "Hunter"},
-    {SL_KAAHI, "KAAHI", "Kaahi"},
-    {SL_KAINA, "KAINA", "Kaina"},
-    {SL_KAITE, "KAITE", "Kaite"},
-    {SL_KAIZEL, "KAIZEL", "Kaizel"},
-    {SL_KAUPE, "KAUPE", "Kaupe"},
-    {SL_KNIGHT, "KNIGHT", "Knight"},
-    {SL_MONK, "MONK", "Monk"},
-    {SL_PRIEST, "PRIEST", "Priest"},
-    {SL_ROGUE, "ROGUE", "Rogue"},
-    {SL_SAGE, "SAGE", "Sage"},
-    {SL_SKA, "SKA", "SKA"},
-    {SL_SKE, "SKE", "SKE"},
-    {SL_SMA, "SMA", "SMA"},
-    {SL_SOULLINKER, "SOULLINKER", "Soul Linker"},
-    {SL_STAR, "STAR", "Star"},
-    {SL_STIN, "STIN", "Stin"},
-    {SL_STUN, "STUN", "Stun"},
-    {SL_SUPERNOVICE, "SUPERNOVICE", "Super Novice"},
-    {SL_SWOO, "SWOO", "Swoo"},
-    {SL_WIZARD, "WIZARD", "Wizard"},
-    {SM_AUTOBERSERK, "AUTOBERSERK", "Auto_Berserk"},
-    {SM_BASH, "BASH", "Bash"},
-    {SM_ENDURE, "ENDURE", "Endure"},
-    {SM_FATALBLOW, "FATALBLOW", "Attack_Weak_Point"},
-    {SM_MAGNUM, "MAGNUM", "Magnum_Break"},
-    {SM_MOVINGRECOVERY, "MOVINGRECOVERY", "Moving_HP_Recovery"},
-    {SM_PROVOKE, "PROVOKE", "Provoke"},
-    {SM_RECOVERY, "RECOVERY", "Increase_HP_Recovery"},
-    {SM_SWORD, "SWORD", "Sword_Mastery"},
-    {SM_TWOHAND, "TWOHAND", "Two-Handed_Sword_Mastery"},
-    {SN_FALCONASSAULT, "FALCONASSAULT", "Falcon_Assault"},
-    {SN_SHARPSHOOTING, "SHARPSHOOTING", "Sharpshooting"},
-    {SN_SIGHT, "SIGHT", "True_Sight"},
-    {SN_WINDWALK, "WINDWALK", "Wind_Walk"},
-    {ST_CHASEWALK, "CHASEWALK", "Chase_Walk"},
-    {ST_REJECTSWORD, "REJECTSWORD", "Reject_Sword"},
-    {ST_STEALBACKPACK, "STEALBACKPACK", "Steal_Backpack"},
-    {TF_BACKSLIDING, "BACKSLIDING", "Back_Sliding"},
-    {TF_DETOXIFY, "DETOXIFY", "Detoxify"},
-    {TF_DOUBLE, "DOUBLE", "Double_Attack"},
-    {TF_HIDING, "HIDING", "Hiding"},
-    {TF_MISS, "MISS", "Improve_Dodge"},
-    {TF_PICKSTONE, "PICKSTONE", "Take_Stone"},
-    {TF_POISON, "POISON", "Envenom"},
-    {TF_SPRINKLESAND, "SPRINKLESAND", "Throw_Sand"},
-    {TF_STEAL, "STEAL", "Steal"},
-    {TF_THROWSTONE, "THROWSTONE", "Throw_Stone"},
-    {TK_COUNTER, "COUNTER", "Counter"},
-    {TK_DODGE, "DODGE", "Dodge"},
-    {TK_DOWNKICK, "DOWNKICK", "Down Kick"},
-    {TK_HIGHJUMP, "HIGHJUMP", "High Jump"},
-    {TK_HPTIME, "HPTIME", "HP Time"},
-    {TK_JUMPKICK, "JUMPKICK", "Jump Kick"},
-    {TK_POWER, "POWER", "Power"},
-    {TK_READYCOUNTER, "READYCOUNTER", "Ready Counter"},
-    {TK_READYDOWN, "READYDOWN", "Ready Down"},
-    {TK_READYSTORM, "READYSTORM", "Ready Storm"},
-    {TK_READYTURN, "READYTURN", "Ready Turn"},
-    {TK_RUN, "RUN", "TK_RUN"},
-    {TK_SEVENWIND, "SEVENWIND", "Seven Wind"},
-    {TK_SPTIME, "SPTIME", "SP Time"},
-    {TK_STORMKICK, "STORMKICK", "Storm Kick"},
-    {TK_TURNKICK, "TURNKICK", "Turn Kick"},
-    {WE_BABY, "BABY", "Adopt_Baby"},
-    {WE_CALLBABY, "CALLBABY", "Call_Baby"},
-    {WE_CALLPARENT, "CALLPARENT", "Call_Parent"},
-    {WE_CALLPARTNER, "CALLPARTNER", "I Want to See You"},
-    {WE_FEMALE, "FEMALE", "I Only Look Up to You"},
-    {WE_MALE, "MALE", "I Will Protect You"},
-    {WS_CARTBOOST, "CARTBOOST", "Cart_Boost"},
-    {WS_CREATECOIN, "CREATECOIN", "Create_Coins"},
-    {WS_CREATENUGGET, "CREATENUGGET", "Create_Nuggets"},
-    {WS_MELTDOWN, "MELTDOWN", "Meltdown"},
-    {WS_SYSTEMCREATE, "SYSTEMCREATE", "Create_System_tower"},
-    {WZ_EARTHSPIKE, "EARTHSPIKE", "Earth_Spike"},
-    {WZ_ESTIMATION, "ESTIMATION", "Sense"},
-    {WZ_FIREIVY, "FIREIVY", "Fire_Ivy"},
-    {WZ_FIREPILLAR, "FIREPILLAR", "Fire_Pillar"},
-    {WZ_FROSTNOVA, "FROSTNOVA", "Frost_Nova"},
-    {WZ_HEAVENDRIVE, "HEAVENDRIVE", "Heaven's_Drive"},
-    {WZ_ICEWALL, "ICEWALL", "Ice_Wall"},
-    {WZ_JUPITEL, "JUPITEL", "Jupitel_Thunder"},
-    {WZ_METEOR, "METEOR", "Meteor_Storm"},
-    {WZ_QUAGMIRE, "QUAGMIRE", "Quagmire"},
-    {WZ_SIGHTRASHER, "SIGHTRASHER", "Sightrasher"},
-    {WZ_STORMGUST, "STORMGUST", "Storm_Gust"},
-    {WZ_VERMILION, "VERMILION", "Lord_of_Vermilion"},
-    {WZ_WATERBALL, "WATERBALL", "Water_Ball"},
-    {0, 0, 0}
-};
-
-static const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-static const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-
-static int rdamage;
-
-/* スキルデータベース */
-struct skill_db skill_db[MAX_SKILL_DB];
-
-#define UNARMED_PLAYER_DAMAGE_MIN(bl)	(skill_power_bl((bl), TMW_BRAWLING) >> 4)   // +50 for 200
-#define UNARMED_PLAYER_DAMAGE_MAX(bl)	(skill_power_bl((bl), TMW_BRAWLING))    // +200 for 200
-
-int skill_get_hit (int id)
-{
-    return skill_db[id].hit;
-}
-
-int skill_get_inf (int id)
-{
-    return skill_db[id].inf;
-}
-
-int skill_get_pl (int id)
-{
-    return skill_db[id].pl;
-}
-
-int skill_get_nk (int id)
-{
-    return skill_db[id].nk;
-}
-
-int skill_get_max (int id)
-{
-    return skill_db[id].max;
-}
-
-int skill_get_max_raise (int id)
-{
-    return skill_db[id].max_raise;
-}
-
-int skill_get_range (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].range[lv - 1];
-}
-
-int skill_get_hp (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].hp[lv - 1];
-}
-
-int skill_get_sp (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].sp[lv - 1];
-}
-
-int skill_get_zeny (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].zeny[lv - 1];
-}
-
-int skill_get_num (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].num[lv - 1];
-}
-
-int skill_get_cast (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].cast[lv - 1];
-}
-
-int skill_get_delay (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].delay[lv - 1];
-}
-
-int skill_get_time (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].upkeep_time[lv - 1];
-}
-
-int skill_get_time2 (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].upkeep_time2[lv - 1];
-}
-
-int skill_get_castdef (int id)
-{
-    return skill_db[id].cast_def_rate;
-}
-
-int skill_get_weapontype (int id)
-{
-    return skill_db[id].weapon;
-}
-
-int skill_get_inf2 (int id)
-{
-    return skill_db[id].inf2;
-}
-
-int skill_get_maxcount (int id)
-{
-    return skill_db[id].maxcount;
-}
-
-int skill_get_blewcount (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].blewcount[lv - 1];
-}
-
-int skill_get_mhp (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].mhp[lv - 1];
-}
-
-int skill_get_castnodex (int id, int lv)
-{
-    return (lv <= 0) ? 0 : skill_db[id].castnodex[lv - 1];
-}
-
-/* プロトタイプ */
-struct skill_unit_group *skill_unitsetting (struct block_list *src,
-                                            int skillid, int skilllv, int x,
-                                            int y, int flag);
-int  skill_check_condition (struct map_session_data *sd, int type);
-int  skill_castend_damage_id (struct block_list *src, struct block_list *bl,
-                              int skillid, int skilllv, unsigned int tick,
-                              int flag);
-int  skill_frostjoke_scream (struct block_list *bl, va_list ap);
-int  skill_status_change_timer_sub (struct block_list *bl, va_list ap);
-int  skill_attack_area (struct block_list *bl, va_list ap);
-int  skill_clear_element_field (struct block_list *bl);
-int  skill_landprotector (struct block_list *bl, va_list ap);
-int  skill_trap_splash (struct block_list *bl, va_list ap);
-int  skill_count_target (struct block_list *bl, va_list ap);
-
-// [MouseJstr] - skill ok to cast? and when?
-static int skillnotok (int skillid, struct map_session_data *sd)
-{
-    if (sd == 0)
-        return 0;
-    if (pc_isGM (sd) >= 20)
-        return 0;               // gm's can do anything damn thing they want
-    switch (skillid)
-    {
-        case AL_WARP:
-        case AL_TELEPORT:
-        case MC_IDENTIFY:
-            return 0;           // always allowed
-        default:
-            return (map[sd->bl.m].flag.noskill);
-    }
-}
-
-static int distance (int x0, int y0, int x1, int y1)
-{
-    int  dx, dy;
-
-    dx = abs (x0 - x1);
-    dy = abs (y0 - y1);
-    return dx > dy ? dx : dy;
-}
-
-/* スキルユニットIDを返す(これもデータベースに入れたいな) */
-int skill_get_unit_id (int id, int flag)
-{
-
-    switch (id)
-    {
-        case MG_SAFETYWALL:
-            return 0x7e;        /* セイフティウォール */
-        case MG_FIREWALL:
-            return 0x7f;        /* ファイアーウォール */
-        case AL_WARP:
-            return (flag == 0) ? 0x81 : 0x80;   /* ワープポータル */
-        case PR_BENEDICTIO:
-            return 0x82;        /* 聖体降福 */
-        case PR_SANCTUARY:
-            return 0x83;        /* サンクチュアリ */
-        case PR_MAGNUS:
-            return 0x84;        /* マグヌスエクソシズム */
-        case AL_PNEUMA:
-            return 0x85;        /* ニューマ */
-        case MG_THUNDERSTORM:
-            return 0x86;        /* サンダーストーム */
-        case WZ_HEAVENDRIVE:
-            return 0x86;        /* ヘヴンズドライブ */
-        case WZ_SIGHTRASHER:
-            return 0x86;        /* サイトラッシャー */
-        case WZ_METEOR:
-            return 0x86;        /* メテオストーム */
-        case WZ_VERMILION:
-            return 0x86;        /* ロードオブヴァーミリオン */
-        case WZ_FROSTNOVA:
-            return 0x86;        /* フロストノヴァ */
-        case WZ_STORMGUST:
-            return 0x86;        /* ストームガスト(とりあえずLoVと同じで処理) */
-        case CR_GRANDCROSS:
-            return 0x86;        /* グランドクロス */
-        case WZ_FIREPILLAR:
-            return (flag == 0) ? 0x87 : 0x88;   /* ファイアーピラー */
-        case HT_TALKIEBOX:
-            return 0x99;        /* トーキーボックス */
-        case WZ_ICEWALL:
-            return 0x8d;        /* アイスウォール */
-        case WZ_QUAGMIRE:
-            return 0x8e;        /* クァグマイア */
-        case HT_BLASTMINE:
-            return 0x8f;        /* ブラストマイン */
-        case HT_SKIDTRAP:
-            return 0x90;        /* スキッドトラップ */
-        case HT_ANKLESNARE:
-            return 0x91;        /* アンクルスネア */
-        case AS_VENOMDUST:
-            return 0x92;        /* ベノムダスト */
-        case HT_LANDMINE:
-            return 0x93;        /* ランドマイン */
-        case HT_SHOCKWAVE:
-            return 0x94;        /* ショックウェーブトラップ */
-        case HT_SANDMAN:
-            return 0x95;        /* サンドマン */
-        case HT_FLASHER:
-            return 0x96;        /* フラッシャー */
-        case HT_FREEZINGTRAP:
-            return 0x97;        /* フリージングトラップ */
-        case HT_CLAYMORETRAP:
-            return 0x98;        /* クレイモアートラップ */
-        case SA_VOLCANO:
-            return 0x9a;        /* ボルケーノ */
-        case SA_DELUGE:
-            return 0x9b;        /* デリュージ */
-        case SA_VIOLENTGALE:
-            return 0x9c;        /* バイオレントゲイル */
-        case SA_LANDPROTECTOR:
-            return 0x9d;        /* ランドプロテクター */
-        case BD_LULLABY:
-            return 0x9e;        /* 子守歌 */
-        case BD_RICHMANKIM:
-            return 0x9f;        /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:
-            return 0xa0;        /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:
-            return 0xa1;        /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:
-            return 0xa2;        /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:
-            return 0xa3;        /* ロキの叫び */
-        case BD_INTOABYSS:
-            return 0xa4;        /* 深淵の中に */
-        case BD_SIEGFRIED:
-            return 0xa5;        /* 不死身のジークフリード */
-        case BA_DISSONANCE:
-            return 0xa6;        /* 不協和音 */
-        case BA_WHISTLE:
-            return 0xa7;        /* 口笛 */
-        case BA_ASSASSINCROSS:
-            return 0xa8;        /* 夕陽のアサシンクロス */
-        case BA_POEMBRAGI:
-            return 0xa9;        /* ブラギの詩 */
-        case BA_APPLEIDUN:
-            return 0xaa;        /* イドゥンの林檎 */
-        case DC_UGLYDANCE:
-            return 0xab;        /* 自分勝手なダンス */
-        case DC_HUMMING:
-            return 0xac;        /* ハミング */
-        case DC_DONTFORGETME:
-            return 0xad;        /* 私を忘れないで… */
-        case DC_FORTUNEKISS:
-            return 0xae;        /* 幸運のキス */
-        case DC_SERVICEFORYOU:
-            return 0xaf;        /* サービスフォーユー */
-        case RG_GRAFFITI:
-            return 0xb0;        /* グラフィティ */
-        case AM_DEMONSTRATION:
-            return 0xb1;        /* デモンストレーション */
-        case WE_CALLPARTNER:
-            return 0xb2;        /* あなたに逢いたい */
-        case PA_GOSPEL:
-            return 0xb3;        /* ゴスペル */
-        case HP_BASILICA:
-            return 0xb4;        /* バジリカ */
-        case PF_FOGWALL:
-            return 0xb6;        /* フォグウォール */
-        case PF_SPIDERWEB:
-            return 0xb7;        /* スパイダーウェッブ */
-    }
-    return 0;
-    /*
-     * 0x89,0x8a,0x8b 表示無し
-     * 0x9a 炎属性の詠唱みたいなエフェクト
-     * 0x9b 水属性の詠唱みたいなエフェクト
-     * 0x9c 風属性の詠唱みたいなエフェクト
-     * 0x9d 白い小さなエフェクト
-     * 0xb1 Alchemist Demonstration
-     * 0xb2 = Pink Warp Portal
-     * 0xb3 = Gospel For Paladin
-     * 0xb4 = Basilica
-     * 0xb5 = Empty
-     * 0xb6 = Fog Wall for Professor
-     * 0xb7 = Spider Web for Professor
-     * 0xb8 = Empty
-     * 0xb9 =
-     */
-}
-
-/*==========================================
- * スキル追加効果
- *------------------------------------------
- */
-int skill_additional_effect (struct block_list *src, struct block_list *bl,
-                             int skillid, int skilllv, int attack_type,
-                             unsigned int tick)
-{
-    /* MOB追加効果スキル用 */
-    const int sc[] = {
-        SC_POISON, SC_BLIND, SC_SILENCE, SC_STAN,
-        SC_STONE, SC_CURSE, SC_SLEEP
-    };
-    const int sc2[] = {
-        MG_STONECURSE, MG_FROSTDIVER, NPC_STUNATTACK,
-        NPC_SLEEPATTACK, TF_POISON, NPC_CURSEATTACK,
-        NPC_SILENCEATTACK, 0, NPC_BLINDATTACK
-    };
-
-    struct map_session_data *sd = NULL;
-    struct map_session_data *dstsd = NULL;
-    struct mob_data *md = NULL;
-    struct mob_data *dstmd = NULL;
-
-    int  skill, skill2;
-    int  rate, luk;
-
-    int  sc_def_mdef, sc_def_vit, sc_def_int, sc_def_luk;
-    int  sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2;
-    int  sc_def_phys_shield_spell;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, bl);
-
-    if (skilllv < 0)
-        return 0;
-
-    if (src->type == BL_PC)
-    {
-        nullpo_retr (0, sd = (struct map_session_data *) src);
-    }
-    else if (src->type == BL_MOB)
-    {
-        nullpo_retr (0, md = (struct mob_data *) src);  //未使用?
-    }
-
-    sc_def_phys_shield_spell = 0;
-    if (battle_get_sc_data (bl)[SC_PHYS_SHIELD].timer != -1)
-        sc_def_phys_shield_spell =
-            battle_get_sc_data (bl)[SC_PHYS_SHIELD].val1;
-
-    //対象の耐性
-    luk = battle_get_luk (bl);
-    sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + luk / 3);
-    sc_def_vit = 100 - (3 + battle_get_vit (bl) + luk / 3);
-    sc_def_int = 100 - (3 + battle_get_int (bl) + luk / 3);
-    sc_def_luk = 100 - (3 + luk);
-    //自分の耐性
-    luk = battle_get_luk (src);
-    sc_def_mdef2 = 100 - (3 + battle_get_mdef (src) + luk / 3);
-    sc_def_vit2 = 100 - (3 + battle_get_vit (src) + luk / 3);
-    sc_def_int2 = 100 - (3 + battle_get_int (src) + luk / 3);
-    sc_def_luk2 = 100 - (3 + luk);
-    if (bl->type == BL_PC)
-        dstsd = (struct map_session_data *) bl;
-    else if (bl->type == BL_MOB)
-    {
-        dstmd = (struct mob_data *) bl; //未使用?
-        if (sc_def_mdef > 50)
-            sc_def_mdef = 50;
-        if (sc_def_vit > 50)
-            sc_def_vit = 50;
-        if (sc_def_int > 50)
-            sc_def_int = 50;
-        if (sc_def_luk > 50)
-            sc_def_luk = 50;
-    }
-    if (sc_def_mdef < 0)
-        sc_def_mdef = 0;
-    if (sc_def_vit < 0)
-        sc_def_vit = 0;
-    if (sc_def_int < 0)
-        sc_def_int = 0;
-
-    switch (skillid)
-    {
-        case 0:                /* 通常攻撃 */
-            /* 自動鷹 */
-            if (sd && pc_isfalcon (sd) && sd->status.weapon == 11
-                && (skill = pc_checkskill (sd, HT_BLITZBEAT)) > 0
-                && MRAND (1000) <= sd->paramc[5] * 10 / 3 + 1)
-            {
-                int  lv = (sd->status.job_level + 9) / 10;
-                skill_castend_damage_id (src, bl, HT_BLITZBEAT,
-                                         (skill < lv) ? skill : lv, tick,
-                                         0xf00000);
-            }
-            // スナッチャー
-            if (sd && sd->status.weapon != 11
-                && (skill = pc_checkskill (sd, RG_SNATCHER)) > 0)
-                if ((skill * 15 + 55) +
-                    (skill2 =
-                     pc_checkskill (sd, TF_STEAL)) * 10 > MRAND (1000))
-                {
-                    if (pc_steal_item (sd, bl))
-                        clif_skill_nodamage (src, bl, TF_STEAL, skill2, 1);
-                    else
-                        clif_skill_fail (sd, skillid, 0, 0);
-                }
-            break;
-
-        case SM_BASH:          /* バッシュ(急所攻撃) */
-            if (sd && (skill = pc_checkskill (sd, SM_FATALBLOW)) > 0)
-            {
-                if (MRAND (100) < 6 * (skilllv - 5) * sc_def_vit / 100)
-                    skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                               skill_get_time2 (SM_FATALBLOW,
-                                                                skilllv), 0);
-            }
-            break;
-
-        case TF_POISON:        /* インベナム */
-        case AS_SPLASHER:      /* ベナムスプラッシャー */
-            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_POISON, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            else
-            {
-                if (sd && skillid == TF_POISON)
-                    clif_skill_fail (sd, skillid, 0, 0);
-            }
-            break;
-
-        case AS_SONICBLOW:     /* ソニックブロー */
-            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case HT_FREEZINGTRAP:  /* フリージングトラップ */
-            rate = skilllv * 3 + 35;
-            if (MRAND (100) < rate * sc_def_mdef / 100)
-                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case MG_FROSTDIVER:    /* フロストダイバー */
-        case WZ_FROSTNOVA:     /* フロストノヴァ */
-            rate =
-                (skilllv * 3 + 35) * sc_def_mdef / 100 -
-                (battle_get_int (bl) + battle_get_luk (bl)) / 15;
-            rate = rate <= 5 ? 5 : rate;
-            if (MRAND (100) < rate)
-                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            else if (sd)
-                clif_skill_fail (sd, skillid, 0, 0);
-            break;
-
-        case WZ_STORMGUST:     /* ストームガスト */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            if (sc_data)
-            {
-                sc_data[SC_FREEZE].val3++;
-                if (sc_data[SC_FREEZE].val3 >= 3)
-                    skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0,
-                                               0, skill_get_time2 (skillid,
-                                                                   skilllv),
-                                               0);
-            }
-        }
-            break;
-
-        case HT_LANDMINE:      /* ランドマイン */
-            if (MRAND (100) < (5 * skilllv + 30) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
-            if (map[bl->m].flag.pvp && dstsd)
-            {
-                dstsd->status.sp -=
-                    dstsd->status.sp * (5 + 15 * skilllv) / 100;
-                pc_calcstatus (dstsd, 0);
-            }
-            break;
-        case HT_SANDMAN:       /* サンドマン */
-            if (MRAND (100) < (5 * skilllv + 30) * sc_def_int / 100)
-                skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case TF_SPRINKLESAND:  /* 砂まき */
-            if (MRAND (100) < 15 * sc_def_int / 100)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case TF_THROWSTONE:    /* 石投げ */
-            if (MRAND (100) < 5 * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case CR_HOLYCROSS:     /* ホーリークロス */
-            if (MRAND (100) < 3 * skilllv * sc_def_int / 100)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case CR_GRANDCROSS:    /* グランドクロス */
-        {
-            int  race = battle_get_race (bl);
-            if ((battle_check_undead (race, battle_get_elem_type (bl)) || race == 6) && MRAND (100) < 100000 * sc_def_int / 100)    //強制付与だが完全耐性には無効
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-        }
-            break;
-
-        case CR_SHIELDCHARGE:  /* シールドチャージ */
-            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case RG_RAID:          /* サプライズアタック */
-            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case BA_FROSTJOKE:
-            if (MRAND (100) < (15 + 5 * skilllv) * sc_def_mdef / 100)
-                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case DC_SCREAM:
-            if (MRAND (100) < (25 + 5 * skilllv) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case BD_LULLABY:       /* 子守唄 */
-            if (MRAND (100) < 15 * sc_def_int / 100)
-                skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-            /* MOBの追加効果付きスキル */
-
-        case NPC_PETRIFYATTACK:
-            if (MRAND (100) < sc_def_mdef)
-                skill_status_change_start (bl, sc[skillid - NPC_POISON],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case NPC_POISON:
-        case NPC_SILENCEATTACK:
-        case NPC_STUNATTACK:
-            if (MRAND (100) <
-                50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) +
-                (skilllv >> 2))
-                skill_status_change_start (bl, sc[skillid - NPC_POISON],
-                                           skilllv, 0, 0, 0, skilllv, 0);
-            break;
-        case NPC_CURSEATTACK:
-            if (MRAND (100) < sc_def_luk)
-                skill_status_change_start (bl, sc[skillid - NPC_POISON],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case NPC_SLEEPATTACK:
-        case NPC_BLINDATTACK:
-            if (MRAND (100) < sc_def_int)
-                skill_status_change_start (bl, sc[skillid - NPC_POISON],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case NPC_MENTALBREAKER:
-            if (dstsd)
-            {
-                int  sp = dstsd->status.max_sp * (10 + skilllv) / 100;
-                if (sp < 1)
-                    sp = 1;
-                pc_heal (dstsd, 0, -sp);
-            }
-            break;
-
-// -- moonsoul (adding status effect chance given to wizard aoe skills meteor and vermillion)
-//
-        case WZ_METEOR:
-            if (MRAND (100) < sc_def_vit)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case WZ_VERMILION:
-            if (MRAND (100) < sc_def_int)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-// -- moonsoul (stun ability of new champion skill tigerfist)
-//
-        case CH_TIGERFIST:
-            if (MRAND (100) < (5 + skilllv * 5) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case LK_SPIRALPIERCE:
-            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case ST_REJECTSWORD:   /* フリージングトラップ */
-            if (MRAND (100) < (10 + skilllv * 5))
-                skill_status_change_start (bl, SC_AUTOCOUNTER, skilllv, 0, 0,
-                                           0, skill_get_time2 (skillid,
-                                                               skilllv), 0);
-            break;
-        case PF_FOGWALL:       /* ホーリークロス */
-            if (MRAND (100) < 3 * skilllv * sc_def_int / 100)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case LK_HEADCRUSH:     /* ヘッドクラッシュ */
-        {                       //条件が良く分からないので適当に
-            int  race = battle_get_race (bl);
-            if (!
-                (battle_check_undead (race, battle_get_elem_type (bl))
-                 || race == 6)
-                && MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_HEADCRUSH, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-        }
-            break;
-        case LK_JOINTBEAT:     /* ジョイントビート */
-            //条件が良く分からないので適当に
-            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_JOINTBEAT, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case PF_SPIDERWEB:     /* スパイダーウェッブ */
-        {
-            int  sec = skill_get_time2 (skillid, skilllv);
-            if (map[src->m].flag.pvp)   //PvPでは拘束時間半減?
-                sec = sec / 2;
-            battle_stopwalking (bl, 1);
-            skill_status_change_start (bl, SC_SPIDERWEB, skilllv, 0, 0, 0,
-                                       sec, 0);
-        }
-            break;
-        case ASC_METEORASSAULT:    /* メテオアサルト */
-            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)    //状態異常は詳細が分からないので適当に
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100)
-                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-        case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */
-            //阿修羅を使うと5分間自然回復しないようになる
-            skill_status_change_start (src, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time2 (skillid, skilllv), 0);
-            break;
-    }
-
-    if (sd && skillid != MC_CARTREVOLUTION && attack_type & BF_WEAPON)
-    {                           /* カードによる追加効果 */
-        int  i;
-        int  sc_def_card = 100;
-
-        for (i = SC_STONE; i <= SC_BLIND; i++)
-        {
-            //対象に状態異常
-            if (i == SC_STONE || i == SC_FREEZE)
-                sc_def_card = sc_def_mdef;
-            else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE)
-                sc_def_card = sc_def_vit;
-            else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND)
-                sc_def_card = sc_def_int;
-            else if (i == SC_CURSE)
-                sc_def_card = sc_def_luk;
-
-            if (!sd->state.arrow_atk)
-            {
-                if (MRAND (10000) <
-                    (sd->addeff[i - SC_STONE]) * sc_def_card / 100)
-                {
-                    if (battle_config.battle_log)
-                        printf
-                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
-                             sd->bl.id, i, sd->addeff[i - SC_STONE]);
-                    skill_status_change_start (bl, i, 7, 0, 0, 0,
-                                               (i ==
-                                                SC_CONFUSION) ? 10000 +
-                                               7000 :
-                                               skill_get_time2 (sc2
-                                                                [i -
-                                                                 SC_STONE],
-                                                                7), 0);
-                }
-            }
-            else
-            {
-                if (MRAND (10000) <
-                    (sd->addeff[i - SC_STONE] +
-                     sd->arrow_addeff[i - SC_STONE]) * sc_def_card / 100)
-                {
-                    if (battle_config.battle_log)
-                        printf
-                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
-                             sd->bl.id, i, sd->addeff[i - SC_STONE]);
-                    skill_status_change_start (bl, i, 7, 0, 0, 0,
-                                               (i ==
-                                                SC_CONFUSION) ? 10000 +
-                                               7000 :
-                                               skill_get_time2 (sc2
-                                                                [i -
-                                                                 SC_STONE],
-                                                                7), 0);
-                }
-            }
-            //自分に状態異常
-            if (i == SC_STONE || i == SC_FREEZE)
-                sc_def_card = sc_def_mdef2;
-            else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE)
-                sc_def_card = sc_def_vit2;
-            else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND)
-                sc_def_card = sc_def_int2;
-            else if (i == SC_CURSE)
-                sc_def_card = sc_def_luk2;
-
-            if (!sd->state.arrow_atk)
-            {
-                if (MRAND (10000) <
-                    (sd->addeff2[i - SC_STONE]) * sc_def_card / 100)
-                {
-                    if (battle_config.battle_log)
-                        printf
-                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
-                             src->id, i, sd->addeff2[i - SC_STONE]);
-                    skill_status_change_start (src, i, 7, 0, 0, 0,
-                                               (i ==
-                                                SC_CONFUSION) ? 10000 +
-                                               7000 :
-                                               skill_get_time2 (sc2
-                                                                [i -
-                                                                 SC_STONE],
-                                                                7), 0);
-                }
-            }
-            else
-            {
-                if (MRAND (10000) <
-                    (sd->addeff2[i - SC_STONE] +
-                     sd->arrow_addeff2[i - SC_STONE]) * sc_def_card / 100)
-                {
-                    if (battle_config.battle_log)
-                        printf
-                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
-                             src->id, i, sd->addeff2[i - SC_STONE]);
-                    skill_status_change_start (src, i, 7, 0, 0, 0,
-                                               (i ==
-                                                SC_CONFUSION) ? 10000 +
-                                               7000 :
-                                               skill_get_time2 (sc2
-                                                                [i -
-                                                                 SC_STONE],
-                                                                7), 0);
-                }
-            }
-        }
-    }
-    return 0;
-}
-
-/*=========================================================================
- スキル攻撃吹き飛ばし処理
--------------------------------------------------------------------------*/
-int skill_blown (struct block_list *src, struct block_list *target, int count)
-{
-    int  dx = 0, dy = 0, nx, ny;
-    int  x = target->x, y = target->y;
-    int  ret, prev_state = MS_IDLE;
-    int  moveblock;
-    struct map_session_data *sd = NULL;
-    struct mob_data *md = NULL;
-    struct skill_unit *su = NULL;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, target);
-
-    if (target->type == BL_PC)
-    {
-        nullpo_retr (0, sd = (struct map_session_data *) target);
-    }
-    else if (target->type == BL_MOB)
-    {
-        nullpo_retr (0, md = (struct mob_data *) target);
-    }
-    else if (target->type == BL_SKILL)
-    {
-        nullpo_retr (0, su = (struct skill_unit *) target);
-    }
-    else
-        return 0;
-
-    if (!(count & 0x10000 && (sd || md || su)))
-    {                           /* 指定なしなら位置関係から方向を求める */
-        dx = target->x - src->x;
-        dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
-        dy = target->y - src->y;
-        dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
-    }
-    if (dx == 0 && dy == 0)
-    {
-        int  dir = battle_get_dir (target);
-        if (dir >= 0 && dir < 8)
-        {
-            dx = -dirx[dir];
-            dy = -diry[dir];
-        }
-    }
-
-    ret = path_blownpos (target->m, x, y, dx, dy, count & 0xffff);
-    nx = ret >> 16;
-    ny = ret & 0xffff;
-    moveblock = (x / BLOCK_SIZE != nx / BLOCK_SIZE
-                 || y / BLOCK_SIZE != ny / BLOCK_SIZE);
-
-    if (count & 0x20000)
-    {
-        battle_stopwalking (target, 1);
-        if (sd)
-        {
-            sd->to_x = nx;
-            sd->to_y = ny;
-            sd->walktimer = 1;
-            clif_walkok (sd);
-            clif_movechar (sd);
-        }
-        else if (md)
-        {
-            md->to_x = nx;
-            md->to_y = ny;
-            prev_state = md->state.state;
-            md->state.state = MS_WALK;
-            clif_fixmobpos (md);
-        }
-    }
-    else
-        battle_stopwalking (target, 2);
-
-    dx = nx - x;
-    dy = ny - y;
-
-    if (sd)                     /* 画面外に出たので消去 */
-        map_foreachinmovearea (clif_pcoutsight, target->m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               dx, dy, 0, sd);
-    else if (md)
-        map_foreachinmovearea (clif_moboutsight, target->m, x - AREA_SIZE,
-                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
-                               dx, dy, BL_PC, md);
-
-    if (su)
-    {
-        skill_unit_move_unit_group (su->group, target->m, dx, dy);
-    }
-    else
-    {
-//      struct status_change *sc_data=battle_get_sc_data(target);
-        if (moveblock)
-            map_delblock (target);
-        target->x = nx;
-        target->y = ny;
-        if (moveblock)
-            map_addblock (target);
-/*ダンス中にエフェクトは移動しないらしい
-		if(sc_data && sc_data[SC_DANCING].timer!=-1){ //対象がダンス中なのでエフェクトも移動
-			struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2;
-			if(sg)
-				skill_unit_move_unit_group(sg,target->m,dx,dy);
-		}
-*/
-    }
-
-    if (sd)
-    {                           /* 画面内に入ってきたので表示 */
-        map_foreachinmovearea (clif_pcinsight, target->m, nx - AREA_SIZE,
-                               ny - AREA_SIZE, nx + AREA_SIZE, ny + AREA_SIZE,
-                               -dx, -dy, 0, sd);
-        if (count & 0x20000)
-            sd->walktimer = -1;
-    }
-    else if (md)
-    {
-        map_foreachinmovearea (clif_mobinsight, target->m, nx - AREA_SIZE,
-                               ny - AREA_SIZE, nx + AREA_SIZE, ny + AREA_SIZE,
-                               -dx, -dy, BL_PC, md);
-        if (count & 0x20000)
-            md->state.state = prev_state;
-    }
-
-    skill_unit_move (target, gettick (), (count & 0xffff) + 7); /* スキルユニットの判定 */
-
-    return 0;
-}
-
-/*
- * =========================================================================
- * スキル攻撃効果処理まとめ
- * flagの説明。16進図
- *	00XRTTff
- *  ff	= magicで計算に渡される)
- *	TT	= パケットのtype部分(0でデフォルト)
- *  X   = パケットのスキルLv
- *  R	= 予約(skill_area_subで使用する)
- *-------------------------------------------------------------------------
- */
-
-int skill_attack (int attack_type, struct block_list *src,
-                  struct block_list *dsrc, struct block_list *bl, int skillid,
-                  int skilllv, unsigned int tick, int flag)
-{
-    struct Damage dmg;
-    struct status_change *sc_data;
-    int  type, lv, damage;
-
-    rdamage = 0;
-    nullpo_retr (0, src);
-    nullpo_retr (0, dsrc);
-    nullpo_retr (0, bl);
-
-    sc_data = battle_get_sc_data (bl);
-
-//何もしない判定ここから
-    if (dsrc->m != bl->m)       //対象が同じマップにいなければ何もしない
-        return 0;
-    if (src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL)    //prevよくわからない※
-        return 0;
-    if (src->type == BL_PC && pc_isdead ((struct map_session_data *) src))  //術者?がPCですでに死んでいたら何もしない
-        return 0;
-    if (dsrc->type == BL_PC && pc_isdead ((struct map_session_data *) dsrc))    //術者?がPCですでに死んでいたら何もしない
-        return 0;
-    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))    //対象がPCですでに死んでいたら何もしない
-        return 0;
-    if (skillnotok (skillid, (struct map_session_data *) bl))
-        return 0;               // [MouseJstr]
-    if (sc_data && sc_data[SC_HIDING].timer != -1)
-    {                           //ハイディング状態で
-        if (skill_get_pl (skillid) != 2)    //スキルの属性が地属性でなければ何もしない
-            return 0;
-    }
-    if (sc_data && sc_data[SC_TRICKDEAD].timer != -1)   //死んだふり中は何もしない
-        return 0;
-    if (skillid == WZ_STORMGUST)
-    {                           //使用スキルがストームガストで
-        if (sc_data && sc_data[SC_FREEZE].timer != -1)  //凍結状態なら何もしない
-            return 0;
-    }
-    if (skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y)    //使用スキルがフロストノヴァで、dsrcとblが同じ場所なら何もしない
-        return 0;
-    if (src->type == BL_PC && ((struct map_session_data *) src)->chatID)    //術者がPCでチャット中なら何もしない
-        return 0;
-    if (dsrc->type == BL_PC && ((struct map_session_data *) dsrc)->chatID)  //術者がPCでチャット中なら何もしない
-        return 0;
-    if (src->type == BL_PC && bl
-        && mob_gvmobcheck (((struct map_session_data *) src), bl) == 0)
-        return 0;
-
-//何もしない判定ここまで
-
-    type = -1;
-    lv = (flag >> 20) & 0xf;
-    dmg = battle_calc_attack (attack_type, src, bl, skillid, skilllv, flag & 0xff); //ダメージ計算
-
-//マジックロッド処理ここから
-    if (attack_type & BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1
-        && src == dsrc)
-    {                           //魔法攻撃でマジックロッド状態でsrc=dsrcなら
-        dmg.damage = dmg.damage2 = 0;   //ダメージ0
-        if (bl->type == BL_PC)
-        {                       //対象がPCの場合
-            int  sp = skill_get_sp (skillid, skilllv);  //使用されたスキルのSPを吸収
-            sp = sp * sc_data[SC_MAGICROD].val2 / 100;  //吸収率計算
-            if (skillid == WZ_WATERBALL && skilllv > 1) //ウォーターボールLv1以上
-                sp = sp / ((skilllv | 1) * (skilllv | 1));  //さらに計算?
-            if (sp > 0x7fff)
-                sp = 0x7fff;    //SP多すぎの場合は理論最大値
-            else if (sp < 1)
-                sp = 1;         //1以下の場合は1
-            if (((struct map_session_data *) bl)->status.sp + sp >
-                ((struct map_session_data *) bl)->status.max_sp)
-            {                   //回復SP+現在のSPがMSPより大きい場合
-                sp = ((struct map_session_data *) bl)->status.max_sp - ((struct map_session_data *) bl)->status.sp; //SPをMSP-現在SPにする
-                ((struct map_session_data *) bl)->status.sp = ((struct map_session_data *) bl)->status.max_sp;  //現在のSPにMSPを代入
-            }
-            else                //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
-                ((struct map_session_data *) bl)->status.sp += sp;
-            clif_heal (((struct map_session_data *) bl)->fd, SP_SP, sp);    //SP回復エフェクトの表示
-            ((struct map_session_data *) bl)->canact_tick = tick + skill_delayfix (bl, skill_get_delay (SA_MAGICROD, sc_data[SC_MAGICROD].val1));   //
-        }
-        clif_skill_nodamage (bl, bl, SA_MAGICROD, sc_data[SC_MAGICROD].val1, 1);    //マジックロッドエフェクトを表示
-    }
-//マジックロッド処理ここまで
-
-    damage = dmg.damage + dmg.damage2;
-
-    if (lv == 15)
-        lv = -1;
-
-    if (flag & 0xff00)
-        type = (flag & 0xff00) >> 8;
-
-    if (damage <= 0 || damage < dmg.div_)   //吹き飛ばし判定?※
-        dmg.blewcount = 0;
-
-    if (skillid == CR_GRANDCROSS)
-    {                           //グランドクロス
-        if (battle_config.gx_disptype)
-            dsrc = src;         // 敵ダメージ白文字表示
-        if (src == bl)
-            type = 4;           // 反動はダメージモーションなし
-    }
-
-//使用者がPCの場合の処理ここから
-    if (src->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) src;
-        nullpo_retr (0, sd);
-//連打掌(MO_CHAINCOMBO)ここから
-        if (skillid == MO_CHAINCOMBO)
-        {
-            int  delay = 1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);    //基本ディレイの計算
-            if (damage < battle_get_hp (bl))
-            {                   //ダメージが対象のHPより小さい場合
-                if (pc_checkskill (sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0)   //猛龍拳(MO_COMBOFINISH)取得&気球保持時は+300ms
-                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
-
-                skill_status_change_start (src, SC_COMBO, MO_CHAINCOMBO, skilllv, 0, 0, delay, 0);  //コンボ状態に
-            }
-            sd->attackabletime = sd->canmove_tick = tick + delay;
-            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
-        }
-//連打掌(MO_CHAINCOMBO)ここまで
-//猛龍拳(MO_COMBOFINISH)ここから
-        else if (skillid == MO_COMBOFINISH)
-        {
-            int  delay =
-                700 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
-            if (damage < battle_get_hp (bl))
-            {
-                //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms
-                //伏虎拳(CH_TIGERFIST)取得時も+300ms
-                if ((pc_checkskill (sd, MO_EXTREMITYFIST) > 0
-                     && sd->spiritball >= 4
-                     && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
-                    || (pc_checkskill (sd, CH_TIGERFIST) > 0
-                        && sd->spiritball > 0)
-                    || (pc_checkskill (sd, CH_CHAINCRUSH) > 0
-                        && sd->spiritball > 1))
-                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
-
-                skill_status_change_start (src, SC_COMBO, MO_COMBOFINISH, skilllv, 0, 0, delay, 0); //コンボ状態に
-            }
-            sd->attackabletime = sd->canmove_tick = tick + delay;
-            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
-        }
-//猛龍拳(MO_COMBOFINISH)ここまで
-//伏虎拳(CH_TIGERFIST)ここから
-        else if (skillid == CH_TIGERFIST)
-        {
-            int  delay =
-                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
-            if (damage < battle_get_hp (bl))
-            {
-                if (pc_checkskill (sd, CH_CHAINCRUSH) > 0)  //連柱崩撃(CH_CHAINCRUSH)取得時は+300ms
-                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
-
-                skill_status_change_start (src, SC_COMBO, CH_TIGERFIST, skilllv, 0, 0, delay, 0);   //コンボ状態に
-            }
-            sd->attackabletime = sd->canmove_tick = tick + delay;
-            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
-        }
-//伏虎拳(CH_TIGERFIST)ここまで
-//連柱崩撃(CH_CHAINCRUSH)ここから
-        else if (skillid == CH_CHAINCRUSH)
-        {
-            int  delay =
-                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
-            if (damage < battle_get_hp (bl))
-            {
-                //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms
-                if (pc_checkskill (sd, MO_EXTREMITYFIST) > 0
-                    && sd->spiritball >= 4
-                    && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
-                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
-
-                skill_status_change_start (src, SC_COMBO, CH_CHAINCRUSH, skilllv, 0, 0, delay, 0);  //コンボ状態に
-            }
-            sd->attackabletime = sd->canmove_tick = tick + delay;
-            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
-        }
-//連柱崩撃(CH_CHAINCRUSH)ここまで
-    }
-//使用者がPCの場合の処理ここまで
-//武器スキル?ここから
-    //AppleGirl Was Here
-    if (attack_type & BF_MAGIC && damage > 0 && src != bl && src == dsrc)
-    {                           //Blah Blah
-        if (bl->type == BL_PC)
-        {                       //Blah Blah
-            struct map_session_data *tsd = (struct map_session_data *) bl;
-            if (tsd->magic_damage_return > 0)
-            {                   //More Blah
-                rdamage += damage * tsd->magic_damage_return / 100;
-                if (rdamage < 1)
-                    rdamage = 1;
-            }
-        }
-    }
-    //Stop Here
-    if (attack_type & BF_WEAPON && damage > 0 && src != bl && src == dsrc)
-    {                           //武器スキル&ダメージあり&使用者と対象者が違う&src=dsrc
-        if (dmg.flag & BF_SHORT)
-        {                       //近距離攻撃時?※
-            if (bl->type == BL_PC)
-            {                   //対象がPCの時
-                struct map_session_data *tsd = (struct map_session_data *) bl;
-                nullpo_retr (0, tsd);
-                if (tsd->short_weapon_damage_return > 0)
-                {               //近距離攻撃跳ね返し?※
-                    rdamage += damage * tsd->short_weapon_damage_return / 100;
-                    if (rdamage < 1)
-                        rdamage = 1;
-                }
-            }
-            if (sc_data && sc_data[SC_REFLECTSHIELD].timer != -1)
-            {                   //リフレクトシールド時
-                rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100;   //跳ね返し計算
-                if (rdamage < 1)
-                    rdamage = 1;
-            }
-        }
-        else if (dmg.flag & BF_LONG)
-        {                       //遠距離攻撃時?※
-            if (bl->type == BL_PC)
-            {                   //対象がPCの時
-                struct map_session_data *tsd = (struct map_session_data *) bl;
-                nullpo_retr (0, tsd);
-                if (tsd->long_weapon_damage_return > 0)
-                {               //遠距離攻撃跳ね返し?※
-                    rdamage += damage * tsd->long_weapon_damage_return / 100;
-                    if (rdamage < 1)
-                        rdamage = 1;
-                }
-            }
-        }
-        if (rdamage > 0)
-            clif_damage (src, src, tick, dmg.amotion, 0, rdamage, 1, 4, 0);
-    }
-//武器スキル?ここまで
-
-    switch (skillid)
-    {
-        case WZ_SIGHTRASHER:
-            clif_skill_damage (src, bl, tick, dmg.amotion, dmg.dmotion,
-                               damage, dmg.div_, skillid,
-                               (lv != 0) ? lv : skilllv, 5);
-            break;
-        case AS_SPLASHER:
-            clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion,
-                               damage, dmg.div_, skillid, -1, 5);
-            break;
-        case NPC_SELFDESTRUCTION:
-        case NPC_SELFDESTRUCTION2:
-            break;
-        default:
-            clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion,
-                               damage, dmg.div_, skillid,
-                               (lv != 0) ? lv : skilllv,
-                               (skillid == 0) ? 5 : type);
-    }
-    if (dmg.blewcount > 0 && !map[src->m].flag.gvg)
-    {                           /* 吹き飛ばし処理とそのパケット */
-        if (skillid == WZ_SIGHTRASHER)
-            skill_blown (src, bl, dmg.blewcount);
-        else
-            skill_blown (dsrc, bl, dmg.blewcount);
-        if (bl->type == BL_MOB)
-            clif_fixmobpos ((struct mob_data *) bl);
-        else
-            clif_fixpos (bl);
-    }
-
-    map_freeblock_lock ();
-    /* 実際にダメージ処理を行う */
-    if (skillid != KN_BOWLINGBASH || flag)
-        battle_damage (src, bl, damage, 0);
-    if (skillid == RG_INTIMIDATE && damage > 0
-        && !(battle_get_mode (bl) & 0x20) && !map[src->m].flag.gvg)
-    {
-        int  s_lv = battle_get_lv (src), t_lv = battle_get_lv (bl);
-        int  rate = 50 + skilllv * 5;
-        rate = rate + (s_lv - t_lv);
-        if (MRAND (100) < rate)
-            skill_addtimerskill (src, tick + 800, bl->id, 0, 0, skillid,
-                                 skilllv, 0, flag);
-    }
-/*
-	if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM)){
-		struct map_session_data *tsd = (struct map_session_data *)bl;
-		nullpo_retr(0, tsd);
-		if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
-			&& !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
-			//既に盗んでいるスキルがあれば該当スキルを消す
-			if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
-				tsd->status.skill[tsd->cloneskill_id].id=0;
-				tsd->status.skill[tsd->cloneskill_id].lv=0;
-				tsd->status.skill[tsd->cloneskill_id].flag=0;
-			}
-			tsd->cloneskill_id=skillid;
-			tsd->cloneskill_lv=skilllv;
-			tsd->status.skill[skillid].id=skillid;
-			tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
-							skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
-			tsd->status.skill[skillid].flag=13;//cloneskill flag
-			clif_skillinfoblock(tsd);
-		}
-	}
-*/
-    /* ダメージがあるなら追加効果判定 */
-    if (bl->prev != NULL)
-    {
-        struct map_session_data *sd = (struct map_session_data *) bl;
-        nullpo_retr (0, sd);
-        if (bl->type != BL_PC || (sd && !pc_isdead (sd)))
-        {
-            if (damage > 0)
-                skill_additional_effect (src, bl, skillid, skilllv,
-                                         attack_type, tick);
-            if (bl->type == BL_MOB && src != bl)    /* スキル使用条件のMOBスキル */
-            {
-                struct mob_data *md = (struct mob_data *) bl;
-                nullpo_retr (0, md);
-                if (battle_config.mob_changetarget_byskill == 1)
-                {
-                    int  target;
-                    target = md->target_id;
-                    if (src->type == BL_PC)
-                        md->target_id = src->id;
-                    mobskill_use (md, tick, MSC_SKILLUSED | (skillid << 16));
-                    md->target_id = target;
-                }
-                else
-                    mobskill_use (md, tick, MSC_SKILLUSED | (skillid << 16));
-            }
-        }
-    }
-
-    if (src->type == BL_PC && dmg.flag & BF_WEAPON && src != bl && src == dsrc
-        && damage > 0)
-    {
-        struct map_session_data *sd = (struct map_session_data *) src;
-        int  hp = 0, sp = 0;
-        nullpo_retr (0, sd);
-        if (sd->hp_drain_rate && sd->hp_drain_per > 0 && dmg.damage > 0
-            && MRAND (100) < sd->hp_drain_rate)
-        {
-            hp += (dmg.damage * sd->hp_drain_per) / 100;
-            if (sd->hp_drain_rate > 0 && hp < 1)
-                hp = 1;
-            else if (sd->hp_drain_rate < 0 && hp > -1)
-                hp = -1;
-        }
-        if (sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && dmg.damage2 > 0
-            && MRAND (100) < sd->hp_drain_rate_)
-        {
-            hp += (dmg.damage2 * sd->hp_drain_per_) / 100;
-            if (sd->hp_drain_rate_ > 0 && hp < 1)
-                hp = 1;
-            else if (sd->hp_drain_rate_ < 0 && hp > -1)
-                hp = -1;
-        }
-        if (sd->sp_drain_rate > 0 && sd->sp_drain_per > 0 && dmg.damage > 0
-            && MRAND (100) < sd->sp_drain_rate)
-        {
-            sp += (dmg.damage * sd->sp_drain_per) / 100;
-            if (sd->sp_drain_rate > 0 && sp < 1)
-                sp = 1;
-            else if (sd->sp_drain_rate < 0 && sp > -1)
-                sp = -1;
-        }
-        if (sd->sp_drain_rate_ > 0 && sd->sp_drain_per_ > 0 && dmg.damage2 > 0
-            && MRAND (100) < sd->sp_drain_rate_)
-        {
-            sp += (dmg.damage2 * sd->sp_drain_per_) / 100;
-            if (sd->sp_drain_rate_ > 0 && sp < 1)
-                sp = 1;
-            else if (sd->sp_drain_rate_ < 0 && sp > -1)
-                sp = -1;
-        }
-        if (hp || sp)
-            pc_heal (sd, hp, sp);
-    }
-
-    if ((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
-        battle_damage (bl, src, rdamage, 0);
-
-    if (attack_type & BF_WEAPON && sc_data
-        && sc_data[SC_AUTOCOUNTER].timer != -1
-        && sc_data[SC_AUTOCOUNTER].val4 > 0)
-    {
-        if (sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
-            battle_weapon_attack (bl, dsrc, tick,
-                                  0x8000 | sc_data[SC_AUTOCOUNTER].val1);
-        skill_status_change_end (bl, SC_AUTOCOUNTER, -1);
-    }
-
-    map_freeblock_unlock ();
-
-    return (dmg.damage + dmg.damage2);  /* 与ダメを返す */
-}
-
-/*==========================================
- * スキル範囲攻撃用(map_foreachinareaから呼ばれる)
- * flagについて:16進図を確認
- * MSB <- 00fTffff ->LSB
- *	T	=ターゲット選択用(BCT_*)
- *  ffff=自由に使用可能
- *  0	=予約。0に固定
- *------------------------------------------
- */
-static int skill_area_temp[8];  /* 一時変数。必要なら使う。 */
-typedef int (*SkillFunc) (struct block_list *, struct block_list *, int, int,
-                          unsigned int, int);
-int skill_area_sub (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    int  skill_id, skill_lv, flag;
-    unsigned int tick;
-    SkillFunc func;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    if (bl->type != BL_PC && bl->type != BL_MOB && bl->type != BL_SKILL)
-        return 0;
-
-    src = va_arg (ap, struct block_list *); //ここではsrcの値を参照していないのでNULLチェックはしない
-    skill_id = va_arg (ap, int);
-    skill_lv = va_arg (ap, int);
-    tick = va_arg (ap, unsigned int);
-    flag = va_arg (ap, int);
-    func = va_arg (ap, SkillFunc);
-
-    if (battle_check_target (src, bl, flag) > 0)
-        func (src, bl, skill_id, skill_lv, tick, flag);
-    return 0;
-}
-
-static int skill_check_unit_range_sub (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    int *c, x, y, range, sx[4], sy[4];
-    int  t_range, tx[4], ty[4];
-    int  i, r_flag, skillid;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, unit = (struct skill_unit *) bl);
-    nullpo_retr (0, c = va_arg (ap, int *));
-
-    if (bl->prev == NULL || bl->type != BL_SKILL)
-        return 0;
-
-    if (!unit->alive)
-        return 0;
-
-    x = va_arg (ap, int);
-    y = va_arg (ap, int);
-    range = va_arg (ap, int);
-    skillid = va_arg (ap, int);
-
-    if (skillid == MG_SAFETYWALL || skillid == AL_PNEUMA)
-    {
-        if (unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
-            return 0;
-    }
-    else if (skillid == AL_WARP)
-    {
-        if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99)
-            && unit->group->unit_id != 0x92)
-            return 0;
-    }
-    else if ((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP)
-             || skillid == HT_TALKIEBOX)
-    {
-        if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99)
-            && unit->group->unit_id != 0x92)
-            return 0;
-    }
-    else if (skillid == WZ_FIREPILLAR)
-    {
-        if (unit->group->unit_id != 0x87)
-            return 0;
-    }
-    else
-        return 0;
-    t_range = (unit->range != 0) ? unit->range : unit->group->range;
-    tx[0] = tx[3] = unit->bl.x - t_range;
-    tx[1] = tx[2] = unit->bl.x + t_range;
-    ty[0] = ty[1] = unit->bl.y - t_range;
-    ty[2] = ty[3] = unit->bl.y + t_range;
-    sx[0] = sx[3] = x - range;
-    sx[1] = sx[2] = x + range;
-    sy[0] = sy[1] = y - range;
-    sy[2] = sy[3] = y + range;
-    for (i = r_flag = 0; i < 4; i++)
-    {
-        if (sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0]
-            && sy[i] <= ty[2])
-        {
-            r_flag = 1;
-            break;
-        }
-        if (tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0]
-            && ty[i] <= sy[2])
-        {
-            r_flag = 1;
-            break;
-        }
-    }
-    if (r_flag)
-        (*c)++;
-
-    return 0;
-}
-
-int skill_check_unit_range (int m, int x, int y, int range, int skillid)
-{
-    int  c = 0;
-
-    map_foreachinarea (skill_check_unit_range_sub, m, x - 10, y - 10, x + 10,
-                       y + 10, BL_SKILL, &c, x, y, range, skillid);
-
-    return c;
-}
-
-static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap)
-{
-    int *c;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, c = va_arg (ap, int *));
-
-    if (bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB))
-        return 0;
-
-    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
-        return 0;
-
-    (*c)++;
-
-    return 0;
-}
-
-int skill_check_unit_range2 (int m, int x, int y, int range)
-{
-    int  c = 0;
-
-    map_foreachinarea (skill_check_unit_range2_sub, m, x - range, y - range,
-                       x + range, y + range, 0, &c);
-
-    return c;
-}
-
-/*=========================================================================
- * 範囲スキル使用処理小分けここから
- */
-/* 対象の数をカウントする。(skill_area_temp[0]を初期化しておくこと) */
-int skill_area_sub_count (struct block_list *src, struct block_list *target,
-                          int skillid, int skilllv, unsigned int tick,
-                          int flag)
-{
-    if (skill_area_temp[0] < 0xffff)
-        skill_area_temp[0]++;
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-static void skill_timerskill (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = NULL;
-    struct mob_data *md = NULL;
-    struct block_list *src = map_id2bl (id), *target;
-    struct skill_timerskill *skl = NULL;
-    int  range;
-
-    nullpo_retv (src);
-
-    if (src->prev == NULL)
-        return;
-
-    if (src->type == BL_PC)
-    {
-        nullpo_retv (sd = (struct map_session_data *) src);
-        skl = &sd->skilltimerskill[data];
-    }
-    else if (src->type == BL_MOB)
-    {
-        nullpo_retv (md = (struct mob_data *) src);
-        skl = &md->skilltimerskill[data];
-    }
-
-    else
-        return;
-
-    nullpo_retv (skl);
-
-    skl->timer = -1;
-    if (skl->target_id)
-    {
-        struct block_list tbl;
-        target = map_id2bl (skl->target_id);
-        if (skl->skill_id == RG_INTIMIDATE)
-        {
-            if (target == NULL)
-            {
-                target = &tbl;  //初期化してないのにアドレス突っ込んでいいのかな?
-                target->type = BL_NUL;
-                target->m = src->m;
-                target->prev = target->next = NULL;
-            }
-        }
-        if (target == NULL)
-            return;
-        if (target->prev == NULL && skl->skill_id != RG_INTIMIDATE)
-            return;
-        if (src->m != target->m)
-            return;
-        if (sd && pc_isdead (sd))
-            return;
-        if (target->type == BL_PC
-            && pc_isdead ((struct map_session_data *) target)
-            && skl->skill_id != RG_INTIMIDATE)
-            return;
-
-        switch (skl->skill_id)
-        {
-            case TF_BACKSLIDING:
-                clif_skill_nodamage (src, src, skl->skill_id, skl->skill_lv,
-                                     1);
-                break;
-            case RG_INTIMIDATE:
-                if (sd && !map[src->m].flag.noteleport)
-                {
-                    int  x, y, i, j, c;
-                    pc_randomwarp (sd, 3);
-                    for (i = 0; i < 16; i++)
-                    {
-                        j = MRAND (8);
-                        x = sd->bl.x + dirx[j];
-                        y = sd->bl.y + diry[j];
-                        if ((c = map_getcell (sd->bl.m, x, y)) != 1 && c != 5)
-                            break;
-                    }
-                    if (i >= 16)
-                    {
-                        x = sd->bl.x;
-                        y = sd->bl.y;
-                    }
-                    if (target->prev != NULL)
-                    {
-                        if (target->type == BL_PC
-                            && !pc_isdead ((struct map_session_data *)
-                                           target))
-                            pc_setpos ((struct map_session_data *) target,
-                                       map[sd->bl.m].name, x, y, 3);
-                        else if (target->type == BL_MOB)
-                            mob_warp ((struct mob_data *) target, -1, x, y,
-                                      3);
-                    }
-                }
-                else if (md && !map[src->m].flag.monster_noteleport)
-                {
-                    int  x, y, i, j, c;
-                    mob_warp (md, -1, -1, -1, 3);
-                    for (i = 0; i < 16; i++)
-                    {
-                        j = MRAND (8);
-                        x = md->bl.x + dirx[j];
-                        y = md->bl.y + diry[j];
-                        if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5)
-                            break;
-                    }
-                    if (i >= 16)
-                    {
-                        x = md->bl.x;
-                        y = md->bl.y;
-                    }
-                    if (target->prev != NULL)
-                    {
-                        if (target->type == BL_PC
-                            && !pc_isdead ((struct map_session_data *)
-                                           target))
-                            pc_setpos ((struct map_session_data *) target,
-                                       map[md->bl.m].name, x, y, 3);
-                        else if (target->type == BL_MOB)
-                            mob_warp ((struct mob_data *) target, -1, x, y,
-                                      3);
-                    }
-                }
-                break;
-
-            case BA_FROSTJOKE: /* 寒いジョーク */
-            case DC_SCREAM:    /* スクリーム */
-                range = 15;     //視界全体
-                map_foreachinarea (skill_frostjoke_scream, src->m,
-                                   src->x - range, src->y - range,
-                                   src->x + range, src->y + range, 0, src,
-                                   skl->skill_id, skl->skill_lv, tick);
-                break;
-
-            default:
-                skill_attack (skl->type, src, src, target, skl->skill_id,
-                              skl->skill_lv, tick, skl->flag);
-                break;
-        }
-    }
-    else
-    {
-        if (src->m != skl->map)
-            return;
-        switch (skl->skill_id)
-        {
-            case WZ_METEOR:
-                if (skl->type >= 0)
-                {
-                    skill_unitsetting (src, skl->skill_id, skl->skill_lv,
-                                       skl->type >> 16, skl->type & 0xFFFF,
-                                       0);
-                    clif_skill_poseffect (src, skl->skill_id, skl->skill_lv,
-                                          skl->x, skl->y, tick);
-                }
-                else
-                    skill_unitsetting (src, skl->skill_id, skl->skill_lv,
-                                       skl->x, skl->y, 0);
-                break;
-        }
-    }
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int skill_addtimerskill (struct block_list *src, unsigned int tick,
-                         int target, int x, int y, int skill_id, int skill_lv,
-                         int type, int flag)
-{
-    int  i;
-
-    nullpo_retr (1, src);
-
-    if (src->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) src;
-        nullpo_retr (1, sd);
-        for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
-        {
-            if (sd->skilltimerskill[i].timer == -1)
-            {
-                sd->skilltimerskill[i].timer =
-                    add_timer (tick, skill_timerskill, src->id, i);
-                sd->skilltimerskill[i].src_id = src->id;
-                sd->skilltimerskill[i].target_id = target;
-                sd->skilltimerskill[i].skill_id = skill_id;
-                sd->skilltimerskill[i].skill_lv = skill_lv;
-                sd->skilltimerskill[i].map = src->m;
-                sd->skilltimerskill[i].x = x;
-                sd->skilltimerskill[i].y = y;
-                sd->skilltimerskill[i].type = type;
-                sd->skilltimerskill[i].flag = flag;
-
-                return 0;
-            }
-        }
-        return 1;
-    }
-    else if (src->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) src;
-        nullpo_retr (1, md);
-        for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
-        {
-            if (md->skilltimerskill[i].timer == -1)
-            {
-                md->skilltimerskill[i].timer =
-                    add_timer (tick, skill_timerskill, src->id, i);
-                md->skilltimerskill[i].src_id = src->id;
-                md->skilltimerskill[i].target_id = target;
-                md->skilltimerskill[i].skill_id = skill_id;
-                md->skilltimerskill[i].skill_lv = skill_lv;
-                md->skilltimerskill[i].map = src->m;
-                md->skilltimerskill[i].x = x;
-                md->skilltimerskill[i].y = y;
-                md->skilltimerskill[i].type = type;
-                md->skilltimerskill[i].flag = flag;
-
-                return 0;
-            }
-        }
-        return 1;
-    }
-
-    return 1;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int skill_cleartimerskill (struct block_list *src)
-{
-    int  i;
-
-    nullpo_retr (0, src);
-
-    if (src->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) src;
-        nullpo_retr (0, sd);
-        for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
-        {
-            if (sd->skilltimerskill[i].timer != -1)
-            {
-                delete_timer (sd->skilltimerskill[i].timer, skill_timerskill);
-                sd->skilltimerskill[i].timer = -1;
-            }
-        }
-    }
-    else if (src->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) src;
-        nullpo_retr (0, md);
-        for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
-        {
-            if (md->skilltimerskill[i].timer != -1)
-            {
-                delete_timer (md->skilltimerskill[i].timer, skill_timerskill);
-                md->skilltimerskill[i].timer = -1;
-            }
-        }
-    }
-
-    return 0;
-}
-
-/* 範囲スキル使用処理小分けここまで
- * -------------------------------------------------------------------------
- */
-
-/*==========================================
- * スキル使用(詠唱完了、ID指定攻撃系)
- * (スパゲッティに向けて1歩前進!(ダメポ))
- *------------------------------------------
- */
-int skill_castend_damage_id (struct block_list *src, struct block_list *bl,
-                             int skillid, int skilllv, unsigned int tick,
-                             int flag)
-{
-    struct map_session_data *sd = NULL;
-    int  i;
-
-    nullpo_retr (1, src);
-    nullpo_retr (1, bl);
-
-    if (src->type == BL_PC)
-        sd = (struct map_session_data *) src;
-    if (sd && pc_isdead (sd))
-        return 1;
-
-    if ((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl)
-        bl = src;
-    if (bl->prev == NULL)
-        return 1;
-    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
-        return 1;
-    map_freeblock_lock ();
-    switch (skillid)
-    {
-            /* 武器攻撃系スキル */
-        case SM_BASH:          /* バッシュ */
-        case MC_MAMMONITE:     /* メマーナイト */
-        case AC_DOUBLE:        /* ダブルストレイフィング */
-        case AS_SONICBLOW:     /* ソニックブロー */
-        case KN_PIERCE:        /* ピアース */
-        case KN_SPEARBOOMERANG:    /* スピアブーメラン */
-        case TF_POISON:        /* インベナム */
-        case TF_SPRINKLESAND:  /* 砂まき */
-        case AC_CHARGEARROW:   /* チャージアロー */
-        case KN_SPEARSTAB:     /* スピアスタブ */
-        case RG_RAID:          /* サプライズアタック */
-        case RG_INTIMIDATE:    /* インティミデイト */
-        case BA_MUSICALSTRIKE: /* ミュージカルストライク */
-        case DC_THROWARROW:    /* 矢撃ち */
-        case BA_DISSONANCE:    /* 不協和音 */
-        case CR_HOLYCROSS:     /* ホーリークロス */
-        case CR_SHIELDCHARGE:
-        case CR_SHIELDBOOMERANG:
-
-            /* 以下MOB専用 */
-            /* 単体攻撃、SP減少攻撃、遠距離攻撃、防御無視攻撃、多段攻撃 */
-        case NPC_PIERCINGATT:
-        case NPC_MENTALBREAKER:
-        case NPC_RANGEATTACK:
-        case NPC_CRITICALSLASH:
-        case NPC_COMBOATTACK:
-            /* 必中攻撃、毒攻撃、暗黒攻撃、沈黙攻撃、スタン攻撃 */
-        case NPC_GUIDEDATTACK:
-        case NPC_POISON:
-        case NPC_BLINDATTACK:
-        case NPC_SILENCEATTACK:
-        case NPC_STUNATTACK:
-            /* 石化攻撃、呪い攻撃、睡眠攻撃、ランダムATK攻撃 */
-        case NPC_PETRIFYATTACK:
-        case NPC_CURSEATTACK:
-        case NPC_SLEEPATTACK:
-        case NPC_RANDOMATTACK:
-            /* 水属性攻撃、地属性攻撃、火属性攻撃、風属性攻撃 */
-        case NPC_WATERATTACK:
-        case NPC_GROUNDATTACK:
-        case NPC_FIREATTACK:
-        case NPC_WINDATTACK:
-            /* 毒属性攻撃、聖属性攻撃、闇属性攻撃、念属性攻撃、SP減少攻撃 */
-        case NPC_POISONATTACK:
-        case NPC_HOLYATTACK:
-        case NPC_DARKNESSATTACK:
-        case NPC_TELEKINESISATTACK:
-        case LK_AURABLADE:     /* オーラブレード */
-        case LK_SPIRALPIERCE:  /* スパイラルピアース */
-        case LK_HEADCRUSH:     /* ヘッドクラッシュ */
-        case LK_JOINTBEAT:     /* ジョイントビート */
-        case PA_PRESSURE:      /* プレッシャー */
-        case PA_SACRIFICE:     /* サクリファイス */
-        case SN_SHARPSHOOTING: /* シャープシューティング */
-        case CG_ARROWVULCAN:   /* アローバルカン */
-        case ASC_BREAKER:      /* ソウルブレーカー */
-        case HW_MAGICCRASHER:  /* マジッククラッシャー */
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-        case NPC_DARKBREATH:
-            clif_emotion (src, 7);
-            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-        case MO_INVESTIGATE:   /* 発勁 */
-        {
-            struct status_change *sc_data = battle_get_sc_data (src);
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            if (sc_data[SC_BLADESTOP].timer != -1)
-                skill_status_change_end (src, SC_BLADESTOP, -1);
-        }
-            break;
-        case SN_FALCONASSAULT: /* ファルコンアサルト */
-            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-        case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
-        {
-            struct mob_data *md = (struct mob_data *) bl;
-            nullpo_retr (1, md);
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            if (md->hp > 0)
-            {
-                skill_blown (src, bl, skill_get_blewcount (skillid, skilllv));
-                if (bl->type == BL_MOB)
-                    clif_fixmobpos ((struct mob_data *) bl);
-                else
-                    clif_fixpos (bl);
-            }
-        }
-            break;
-        case RG_BACKSTAP:      /* バックスタブ */
-        {
-            int  dir = map_calc_dir (src, bl->x, bl->y), t_dir =
-                battle_get_dir (bl);
-            int  dist = distance (src->x, src->y, bl->x, bl->y);
-            if ((dist > 0 && !map_check_dir (dir, t_dir))
-                || bl->type == BL_SKILL)
-            {
-                struct status_change *sc_data = battle_get_sc_data (src);
-                if (sc_data && sc_data[SC_HIDING].timer != -1)
-                    skill_status_change_end (src, SC_HIDING, -1);   // ハイディング解除
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              flag);
-                skill_blown (src, bl, skill_get_blewcount (skillid, skilllv));
-            }
-            else if (src->type == BL_PC)
-                clif_skill_fail (sd, sd->skillid, 0, 0);
-        }
-            break;
-
-        case AM_ACIDTERROR:    /* アシッドテラー */
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            if (bl->type == BL_PC
-                && MRAND (100) < skill_get_time (skillid, skilllv)
-                && battle_config.equipment_breaking)
-                pc_breakarmor ((struct map_session_data *) bl);
-            break;
-        case MO_FINGEROFFENSIVE:   /* 指弾 */
-        {
-            struct status_change *sc_data = battle_get_sc_data (src);
-
-            if (!battle_config.finger_offensive_type)
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              flag);
-            else
-            {
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              flag);
-                if (sd)
-                {
-                    for (i = 1; i < sd->spiritball_old; i++)
-                        skill_addtimerskill (src, tick + i * 200, bl->id, 0,
-                                             0, skillid, skilllv, BF_WEAPON,
-                                             flag);
-                    sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200;
-                }
-            }
-            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
-                skill_status_change_end (src, SC_BLADESTOP, -1);
-        }
-            break;
-        case MO_CHAINCOMBO:    /* 連打掌 */
-        {
-            struct status_change *sc_data = battle_get_sc_data (src);
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
-                skill_status_change_end (src, SC_BLADESTOP, -1);
-        }
-            break;
-        case MO_COMBOFINISH:   /* 猛龍拳 */
-        case CH_TIGERFIST:     /* 伏虎拳 */
-        case CH_CHAINCRUSH:    /* 連柱崩撃 */
-        case CH_PALMSTRIKE:    /* 猛虎硬派山 */
-            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-        case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */
-        {
-            struct status_change *sc_data = battle_get_sc_data (src);
-
-            if (sd)
-            {
-                struct walkpath_data wpd;
-                int  dx, dy;
-
-                dx = bl->x - sd->bl.x;
-                dy = bl->y - sd->bl.y;
-                if (dx > 0)
-                    dx++;
-                else if (dx < 0)
-                    dx--;
-                if (dy > 0)
-                    dy++;
-                else if (dy < 0)
-                    dy--;
-                if (dx == 0 && dy == 0)
-                    dx++;
-                if (path_search
-                    (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx,
-                     sd->bl.y + dy, 1) == -1)
-                {
-                    dx = bl->x - sd->bl.x;
-                    dy = bl->y - sd->bl.y;
-                    if (path_search
-                        (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx,
-                         sd->bl.y + dy, 1) == -1)
-                    {
-                        clif_skill_fail (sd, sd->skillid, 0, 0);
-                        break;
-                    }
-                }
-                sd->to_x = sd->bl.x + dx;
-                sd->to_y = sd->bl.y + dy;
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              flag);
-                clif_walkok (sd);
-                clif_movechar (sd);
-                if (dx < 0)
-                    dx = -dx;
-                if (dy < 0)
-                    dy = -dy;
-                sd->attackabletime = sd->canmove_tick =
-                    tick + 100 + sd->speed * ((dx > dy) ? dx : dy);
-                if (sd->canact_tick < sd->canmove_tick)
-                    sd->canact_tick = sd->canmove_tick;
-                pc_movepos (sd, sd->to_x, sd->to_y);
-                skill_status_change_end (&sd->bl, SC_COMBO, -1);
-            }
-            else
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              flag);
-            skill_status_change_end (src, SC_EXPLOSIONSPIRITS, -1);
-            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
-                skill_status_change_end (src, SC_BLADESTOP, -1);
-        }
-            break;
-            /* 武器系範囲攻撃スキル */
-        case AC_SHOWER:        /* アローシャワー */
-        case SM_MAGNUM:        /* マグナムブレイク */
-        case AS_GRIMTOOTH:     /* グリムトゥース */
-        case MC_CARTREVOLUTION:    /* カートレヴォリューション */
-        case NPC_SPLASHATTACK: /* スプラッシュアタック */
-        case ASC_METEORASSAULT:    /* メテオアサルト */
-        case AS_SPLASHER:      /* [Valaris] */
-            if (flag & 1)
-            {
-                /* 個別にダメージを与える */
-                if (bl->id != skill_area_temp[1])
-                {
-                    int  dist = 0;
-                    if (skillid == SM_MAGNUM)
-                    {           /* マグナムブレイクなら中心からの距離を計算 */
-                        int  dx = abs (bl->x - skill_area_temp[2]);
-                        int  dy = abs (bl->y - skill_area_temp[3]);
-                        dist = ((dx > dy) ? dx : dy);
-                    }
-                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
-                                  tick, 0x0500 | dist);
-                }
-            }
-            else
-            {
-                int  ar = 1;
-                int  x = bl->x, y = bl->y;
-                if (skillid == SM_MAGNUM)
-                {
-                    x = src->x;
-                    y = src->y;
-                }
-                else if (skillid == AC_SHOWER || skillid == ASC_METEORASSAULT)  /* アローシャワー、メテオアサルト範囲5*5 */
-                    ar = 2;
-                else if (skillid == AS_SPLASHER)    /* ベナムスプラッシャー範囲3*3 */
-                    ar = 1;
-                else if (skillid == NPC_SPLASHATTACK)   /* スプラッシュアタックは範囲7*7 */
-                    ar = 3;
-                skill_area_temp[1] = bl->id;
-                skill_area_temp[2] = x;
-                skill_area_temp[3] = y;
-                /* まずターゲットに攻撃を加える */
-                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
-                              0);
-                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, x - ar, y - ar, x + ar, y + ar, 0,
-                                   src, skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-            break;
-
-        case KN_BOWLINGBASH:   /* ボウリングバッシュ */
-            if (flag & 1)
-            {
-                /* 個別にダメージを与える */
-                if (bl->id != skill_area_temp[1])
-                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
-                                  tick, 0x0500);
-            }
-            else
-            {
-                int  damage;
-                map_freeblock_lock ();
-                damage =
-                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
-                                  tick, 0);
-                if (damage > 0)
-                {
-                    int  i, c;  /* 他人から聞いた動きなので間違ってる可能性大&効率が悪いっす>< */
-                    c = skill_get_blewcount (skillid, skilllv);
-                    if (map[bl->m].flag.gvg)
-                        c = 0;
-                    for (i = 0; i < c; i++)
-                    {
-                        skill_blown (src, bl, 1);
-                        if (bl->type == BL_MOB)
-                            clif_fixmobpos ((struct mob_data *) bl);
-                        else
-                            clif_fixpos (bl);
-                        skill_area_temp[0] = 0;
-                        map_foreachinarea (skill_area_sub,
-                                           bl->m, bl->x - 1, bl->y - 1,
-                                           bl->x + 1, bl->y + 1, 0, src,
-                                           skillid, skilllv, tick,
-                                           flag | BCT_ENEMY,
-                                           skill_area_sub_count);
-                        if (skill_area_temp[0] > 1)
-                            break;
-                    }
-                    skill_area_temp[1] = bl->id;
-                    skill_area_temp[2] = bl->x;
-                    skill_area_temp[3] = bl->y;
-                    /* その後ターゲット以外の範囲内の敵全体に処理を行う */
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
-                                       bl->y + 1, 0, src, skillid, skilllv,
-                                       tick, flag | BCT_ENEMY | 1,
-                                       skill_castend_damage_id);
-                    battle_damage (src, bl, damage, 1);
-                    if (rdamage > 0)
-                        battle_damage (bl, src, rdamage, 0);
-                }
-                map_freeblock_unlock ();
-            }
-            break;
-
-        case ALL_RESURRECTION: /* リザレクション */
-        case PR_TURNUNDEAD:    /* ターンアンデッド */
-            if (bl->type != BL_PC
-                && battle_check_undead (battle_get_race (bl),
-                                        battle_get_elem_type (bl)))
-                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                              flag);
-            else
-            {
-                map_freeblock_unlock ();
-                return 1;
-            }
-            break;
-
-            /* 魔法系スキル */
-        case MG_SOULSTRIKE:    /* ソウルストライク */
-        case MG_COLDBOLT:      /* コールドボルト */
-        case MG_FIREBOLT:      /* ファイアーボルト */
-        case MG_LIGHTNINGBOLT: /* ライトニングボルト */
-        case WZ_EARTHSPIKE:    /* アーススパイク */
-        case AL_HEAL:          /* ヒール */
-        case AL_HOLYLIGHT:     /* ホーリーライト */
-        case MG_FROSTDIVER:    /* フロストダイバー */
-        case WZ_JUPITEL:       /* ユピテルサンダー */
-        case NPC_MAGICALATTACK:    /* MOB:魔法打撃攻撃 */
-        case PR_ASPERSIO:      /* アスペルシオ */
-            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-
-        case WZ_WATERBALL:     /* ウォーターボール */
-            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            if (skilllv > 1)
-                skill_status_change_start (src, SC_WATERBALL, skilllv, bl->id,
-                                           0, 0, 0, 0);
-            break;
-
-        case PR_BENEDICTIO:    /* 聖体降福 */
-            if (battle_get_race (bl) == 1 || battle_get_race (bl) == 6)
-                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                              flag);
-            break;
-
-            /* 魔法系範囲攻撃スキル */
-        case MG_NAPALMBEAT:    /* ナパームビート */
-        case MG_FIREBALL:      /* ファイヤーボール */
-            if (flag & 1)
-            {
-                /* 個別にダメージを与える */
-                if (bl->id != skill_area_temp[1])
-                {
-                    if (skillid == MG_FIREBALL)
-                    {           /* ファイヤーボールなら中心からの距離を計算 */
-                        int  dx = abs (bl->x - skill_area_temp[2]);
-                        int  dy = abs (bl->y - skill_area_temp[3]);
-                        skill_area_temp[0] = ((dx > dy) ? dx : dy);
-                    }
-                    skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv,
-                                  tick, skill_area_temp[0] | 0x0500);
-                }
-            }
-            else
-            {
-                int  ar = (skillid == MG_NAPALMBEAT) ? 1 : 2;
-                skill_area_temp[1] = bl->id;
-                if (skillid == MG_NAPALMBEAT)
-                {               /* ナパームでは先に数える */
-                    skill_area_temp[0] = 0;
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
-                                       bl->y + 1, 0, src, skillid, skilllv,
-                                       tick, flag | BCT_ENEMY,
-                                       skill_area_sub_count);
-                }
-                else
-                {
-                    skill_area_temp[0] = 0;
-                    skill_area_temp[2] = bl->x;
-                    skill_area_temp[3] = bl->y;
-                }
-                /* まずターゲットに攻撃を加える */
-                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                              skill_area_temp[0]);
-                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, bl->x - ar, bl->y - ar, bl->x + ar,
-                                   bl->y + ar, 0, src, skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-            break;
-
-        case HW_NAPALMVULCAN:  // Fixed By SteelViruZ
-            if (flag & 1)
-            {
-                if (bl->id != skill_area_temp[1])
-                {
-                    skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv,
-                                  tick, skill_area_temp[0]);
-                }
-            }
-            else
-            {
-                int  ar = (skillid == HW_NAPALMVULCAN) ? 1 : 2;
-                skill_area_temp[1] = bl->id;
-                if (skillid == HW_NAPALMVULCAN)
-                {
-                    skill_area_temp[0] = 0;
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
-                                       bl->y + 1, 0, src, skillid, skilllv,
-                                       tick, flag | BCT_ENEMY,
-                                       skill_area_sub_count);
-                }
-                else
-                {
-                    skill_area_temp[0] = 0;
-                    skill_area_temp[2] = bl->x;
-                    skill_area_temp[3] = bl->y;
-                }
-                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                              skill_area_temp[0]);
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, bl->x - ar, bl->y - ar, bl->x + ar,
-                                   bl->y + ar, 0, src, skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-            break;
-
-        case WZ_FROSTNOVA:     /* フロストノヴァ */
-            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
-            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
-                          flag);
-            break;
-
-        case WZ_SIGHTRASHER:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
-            skill_status_change_end (src, SC_SIGHT, -1);
-            break;
-
-            /* その他 */
-        case HT_BLITZBEAT:     /* ブリッツビート */
-            if (flag & 1)
-            {
-                /* 個別にダメージを与える */
-                if (bl->id != skill_area_temp[1])
-                    skill_attack (BF_MISC, src, src, bl, skillid, skilllv,
-                                  tick,
-                                  skill_area_temp[0] | (flag & 0xf00000));
-            }
-            else
-            {
-                skill_area_temp[0] = 0;
-                skill_area_temp[1] = bl->id;
-                if (flag & 0xf00000)
-                    map_foreachinarea (skill_area_sub, bl->m, bl->x - 1,
-                                       bl->y - 1, bl->x + 1, bl->y + 1, 0,
-                                       src, skillid, skilllv, tick,
-                                       flag | BCT_ENEMY,
-                                       skill_area_sub_count);
-                /* まずターゲットに攻撃を加える */
-                skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
-                              skill_area_temp[0] | (flag & 0xf00000));
-                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
-                                   bl->y + 1, 0, src, skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-            break;
-
-        case CR_GRANDCROSS:    /* グランドクロス */
-            /* スキルユニット配置 */
-            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
-            if (sd)
-                sd->canmove_tick = tick + 1000;
-            else if (src->type == BL_MOB)
-                mob_changestate ((struct mob_data *) src, MS_DELAY, 1000);
-            break;
-
-        case TF_THROWSTONE:    /* 石投げ */
-        case NPC_SMOKING:      /* スモーキング */
-            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, 0);
-            break;
-
-        case NPC_SELFDESTRUCTION:  /* 自爆 */
-        case NPC_SELFDESTRUCTION2: /* 自爆2 */
-            if (flag & 1)
-            {
-                /* 個別にダメージを与える */
-                if (src->type == BL_MOB)
-                {
-                    struct mob_data *mb = (struct mob_data *) src;
-                    nullpo_retr (1, mb);
-                    mb->hp = skill_area_temp[2];
-                    if (bl->id != skill_area_temp[1])
-                        skill_attack (BF_MISC, src, src, bl,
-                                      NPC_SELFDESTRUCTION, skilllv, tick,
-                                      flag);
-                    mb->hp = 1;
-                }
-            }
-            else
-            {
-                struct mob_data *md;
-                if ((md = (struct mob_data *) src))
-                {
-                    skill_area_temp[1] = bl->id;
-                    skill_area_temp[2] = battle_get_hp (src);
-                    clif_skill_nodamage (src, src, NPC_SELFDESTRUCTION, -1,
-                                         1);
-                    map_foreachinarea (skill_area_sub, bl->m, bl->x - 5,
-                                       bl->y - 5, bl->x + 5, bl->y + 5, 0,
-                                       src, skillid, skilllv, tick,
-                                       flag | BCT_ENEMY | 1,
-                                       skill_castend_damage_id);
-                    battle_damage (src, src, md->hp, 0);
-                }
-            }
-            break;
-
-            /* HP吸収/HP吸収魔法 */
-        case NPC_BLOODDRAIN:
-        case NPC_ENERGYDRAIN:
-        {
-            int  heal;
-            heal =
-                skill_attack ((skillid ==
-                               NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, src,
-                              src, bl, skillid, skilllv, tick, flag);
-            if (heal > 0)
-            {
-                struct block_list tbl;
-                tbl.id = 0;
-                tbl.m = src->m;
-                tbl.x = src->x;
-                tbl.y = src->y;
-                clif_skill_nodamage (&tbl, src, AL_HEAL, heal, 1);
-                battle_heal (NULL, src, heal, 0, 0);
-            }
-        }
-            break;
-        case 0:
-            if (sd)
-            {
-                if (flag & 3)
-                {
-                    if (bl->id != skill_area_temp[1])
-                        skill_attack (BF_WEAPON, src, src, bl, skillid,
-                                      skilllv, tick, 0x0500);
-                }
-                else
-                {
-                    int  ar = sd->splash_range;
-                    skill_area_temp[1] = bl->id;
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, bl->x - ar, bl->y - ar,
-                                       bl->x + ar, bl->y + ar, 0, src,
-                                       skillid, skilllv, tick,
-                                       flag | BCT_ENEMY | 1,
-                                       skill_castend_damage_id);
-                }
-            }
-            break;
-
-        default:
-            map_freeblock_unlock ();
-            return 1;
-    }
-    map_freeblock_unlock ();
-
-    return 0;
-}
-
-/*==========================================
- * スキル使用(詠唱完了、ID指定支援系)
- *------------------------------------------
- */
-int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl,
-                               int skillid, int skilllv, unsigned int tick,
-                               int flag)
-{
-    struct map_session_data *sd = NULL;
-    struct map_session_data *dstsd = NULL;
-    struct mob_data *md = NULL;
-    struct mob_data *dstmd = NULL;
-    int  i;
-    int  sc_def_vit, sc_def_mdef, strip_fix, strip_time, strip_per;
-    int  sc_dex, sc_luk;
-    //クラスチェンジ用ボスモンスターID
-    int  changeclass[] =
-        { 1038, 1039, 1046, 1059, 1086, 1087, 1112, 1115, 1157, 1159, 1190,
-        1272, 1312, 1373, 1492
-    };
-    int  poringclass[] = { 1002 };
-
-    nullpo_retr (1, src);
-    nullpo_retr (1, bl);
-
-    if (src->type == BL_PC)
-        sd = (struct map_session_data *) src;
-    else if (src->type == BL_MOB)
-        md = (struct mob_data *) src;
-
-    sc_dex = battle_get_mdef (bl);
-    sc_luk = battle_get_luk (bl);
-    sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3);
-    sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3);
-    sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3);
-    strip_fix = battle_get_dex (src) - battle_get_dex (bl);
-
-    if (bl->type == BL_PC)
-    {
-        nullpo_retr (1, dstsd = (struct map_session_data *) bl);
-    }
-    else if (bl->type == BL_MOB)
-    {
-        nullpo_retr (1, dstmd = (struct mob_data *) bl);
-        if (sc_def_vit > 50)
-            sc_def_vit = 50;
-        if (sc_def_mdef > 50)
-            sc_def_mdef = 50;
-    }
-    if (sc_def_vit < 0)
-        sc_def_vit = 0;
-    if (sc_def_mdef < 0)
-        sc_def_mdef = 0;
-    if (strip_fix < 0)
-        strip_fix = 0;
-
-    if (bl == NULL || bl->prev == NULL)
-        return 1;
-    if (sd && pc_isdead (sd))
-        return 1;
-    if (dstsd && pc_isdead (dstsd) && skillid != ALL_RESURRECTION)
-        return 1;
-    if (battle_get_class (bl) == 1288)
-        return 1;
-    if (skillnotok (skillid, (struct map_session_data *) bl))   // [MouseJstr]
-        return 0;
-
-    map_freeblock_lock ();
-    switch (skillid)
-    {
-        case AL_HEAL:          /* ヒール */
-        {
-            int  heal = skill_calc_heal (src, skilllv);
-            int  heal_get_jobexp;
-            int  skill;
-            struct pc_base_job s_class;
-
-            if (dstsd && dstsd->special_state.no_magic_damage)
-                heal = 0;       /* 黄金蟲カード(ヒール量0) */
-            if (sd)
-            {
-                s_class = pc_calc_base_job (sd->status.pc_class);
-                if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ
-                    heal += heal * (skill * 2 / 100);
-                if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0)  //自分も対象もPC、対象が自分のパートナー、自分がスパノビ、自分が♀なら
-                    heal = heal * 2;    //スパノビの嫁が旦那にヒールすると2倍になる
-            }
-
-            clif_skill_nodamage (src, bl, skillid, heal, 1);
-            heal_get_jobexp = battle_heal (NULL, bl, heal, 0, 0);
-
-            // JOB経験値獲得
-            if (src->type == BL_PC && bl->type == BL_PC && heal > 0
-                && src != bl && battle_config.heal_exp > 0)
-            {
-                heal_get_jobexp =
-                    heal_get_jobexp * battle_config.heal_exp / 100;
-                if (heal_get_jobexp <= 0)
-                    heal_get_jobexp = 1;
-                pc_gainexp ((struct map_session_data *) src, 0,
-                            heal_get_jobexp);
-            }
-        }
-            break;
-
-        case ALL_RESURRECTION: /* リザレクション */
-            if (bl->type == BL_PC)
-            {
-                int  per = 0;
-                struct map_session_data *tsd = (struct map_session_data *) bl;
-                nullpo_retr (1, tsd);
-                if ((map[bl->m].flag.pvp) && tsd->pvp_point < 0)
-                    break;      /* PVPで復活不可能状態 */
-
-                if (pc_isdead (tsd))
-                {               /* 死亡判定 */
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                    switch (skilllv)
-                    {
-                        case 1:
-                            per = 10;
-                            break;
-                        case 2:
-                            per = 30;
-                            break;
-                        case 3:
-                            per = 50;
-                            break;
-                        case 4:
-                            per = 80;
-                            break;
-                    }
-                    tsd->status.hp = tsd->status.max_hp * per / 100;
-                    if (tsd->status.hp <= 0)
-                        tsd->status.hp = 1;
-                    if (tsd->special_state.restart_full_recover)
-                    {           /* オシリスカード */
-                        tsd->status.hp = tsd->status.max_hp;
-                        tsd->status.sp = tsd->status.max_sp;
-                    }
-                    pc_setstand (tsd);
-                    if (battle_config.pc_invincible_time > 0)
-                        pc_setinvincibletimer (tsd,
-                                               battle_config.pc_invincible_time);
-                    clif_updatestatus (tsd, SP_HP);
-                    clif_resurrection (&tsd->bl, 1);
-                    if (src != bl && sd && battle_config.resurrection_exp > 0)
-                    {
-                        int  exp = 0, jexp = 0;
-                        int  lv =
-                            tsd->status.base_level - sd->status.base_level,
-                            jlv =
-                            tsd->status.job_level - sd->status.job_level;
-                        if (lv > 0)
-                        {
-                            exp =
-                                (int) ((double) tsd->status.base_exp *
-                                       (double) lv *
-                                       (double) battle_config.resurrection_exp
-                                       / 1000000.);
-                            if (exp < 1)
-                                exp = 1;
-                        }
-                        if (jlv > 0)
-                        {
-                            jexp =
-                                (int) ((double) tsd->status.job_exp *
-                                       (double) lv *
-                                       (double) battle_config.resurrection_exp
-                                       / 1000000.);
-                            if (jexp < 1)
-                                jexp = 1;
-                        }
-                        if (exp > 0 || jexp > 0)
-                            pc_gainexp (sd, exp, jexp);
-                    }
-                }
-            }
-            break;
-
-        case AL_DECAGI:        /* 速度減少 */
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (MRAND (100) <
-                (50 + skilllv * 3 +
-                 (battle_get_lv (src) + battle_get_int (src) / 5) -
-                 sc_def_mdef))
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-            }
-            break;
-
-        case AL_CRUCIS:
-            if (flag & 1)
-            {
-                int  race = battle_get_race (bl), ele =
-                    battle_get_elem_type (bl);
-                if (battle_check_target (src, bl, BCT_ENEMY)
-                    && (race == 6 || battle_check_undead (race, ele)))
-                {
-                    int  slv = battle_get_lv (src), tlv =
-                        battle_get_lv (bl), rate;
-                    rate = 25 + skilllv * 2 + slv - tlv;
-                    if (MRAND (100) < rate)
-                        skill_status_change_start (bl,
-                                                   SkillStatusChangeTable
-                                                   [skillid], skilllv, 0, 0,
-                                                   0, 0, 0);
-                }
-            }
-            else
-            {
-                int  range = 15;
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                map_foreachinarea (skill_area_sub,
-                                   src->m, src->x - range, src->y - range,
-                                   src->x + range, src->y + range, 0, src,
-                                   skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_nodamage_id);
-            }
-            break;
-
-        case PR_LEXDIVINA:     /* レックスディビーナ */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (sc_data && sc_data[SC_DIVINA].timer != -1)
-                skill_status_change_end (bl, SC_DIVINA, -1);
-            else if (MRAND (100) < sc_def_vit)
-            {
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-            }
-        }
-            break;
-        case SA_ABRACADABRA:
-            break;
-        case SA_COMA:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (dstsd)
-            {
-                dstsd->status.hp = 1;
-                dstsd->status.sp = 1;
-                clif_updatestatus (dstsd, SP_HP);
-                clif_updatestatus (dstsd, SP_SP);
-            }
-            if (dstmd)
-                dstmd->hp = 1;
-            break;
-        case SA_FULLRECOVERY:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (dstsd)
-                pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp);
-            if (dstmd)
-                dstmd->hp = battle_get_max_hp (&dstmd->bl);
-            break;
-        case SA_SUMMONMONSTER:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-                mob_once_spawn (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y,
-                                "--ja--", -1, 1, "");
-            break;
-        case SA_LEVELUP:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd && pc_nextbaseexp (sd))
-                pc_gainexp (sd, pc_nextbaseexp (sd) * 10 / 100, 0);
-            break;
-
-        case SA_INSTANTDEATH:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-                pc_damage (NULL, sd, sd->status.max_hp);
-            break;
-
-        case SA_QUESTION:
-        case SA_GRAVITY:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            break;
-        case SA_CLASSCHANGE:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (dstmd)
-                mob_class_change (dstmd, changeclass);
-            break;
-        case SA_MONOCELL:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (dstmd)
-                mob_class_change (dstmd, poringclass);
-            break;
-        case SA_DEATH:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (dstsd)
-                pc_damage (NULL, dstsd, dstsd->status.max_hp);
-            if (dstmd)
-                mob_damage (NULL, dstmd, dstmd->hp, 1);
-            break;
-        case SA_REVERSEORCISH:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (dstsd)
-                pc_setoption (dstsd, dstsd->status.option | 0x0800);
-            break;
-        case SA_FORTUNE:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-                pc_getzeny (sd, battle_get_lv (bl) * 100);
-            break;
-        case AL_INCAGI:        /* 速度増加 */
-        case AL_BLESSING:      /* ブレッシング */
-        case PR_SLOWPOISON:
-        case PR_IMPOSITIO:     /* イムポシティオマヌス */
-        case PR_LEXAETERNA:    /* レックスエーテルナ */
-        case PR_SUFFRAGIUM:    /* サフラギウム */
-        case PR_BENEDICTIO:    /* 聖体降福 */
-        case CR_PROVIDENCE:    /* プロヴィデンス */
-        case CG_MARIONETTE:    /* マリオネットコントロール */
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            }
-            else
-            {
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            }
-            break;
-
-        case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
-        case SA_FROSTWEAPON:
-        case SA_LIGHTNINGLOADER:
-        case SA_SEISMICWEAPON:
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-                break;
-            }
-            if (bl->type == BL_PC)
-            {
-                struct map_session_data *sd2 = (struct map_session_data *) bl;
-                if (sd2->status.weapon == 0
-                    || sd2->sc_data[SC_FLAMELAUNCHER].timer != -1
-                    || sd2->sc_data[SC_FROSTWEAPON].timer != -1
-                    || sd2->sc_data[SC_LIGHTNINGLOADER].timer != -1
-                    || sd2->sc_data[SC_SEISMICWEAPON].timer != -1
-                    || sd2->sc_data[SC_ENCPOISON].timer != -1)
-                {
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-                    break;
-                }
-            }
-            if (MRAND (100) > (75 + skilllv * 1) && (skilllv != 5))
-            {
-                clif_skill_fail (sd, skillid, 0, 0);
-                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-                if (bl->type == BL_PC && battle_config.equipment_breaking)
-                {
-                    struct map_session_data *sd2 =
-                        (struct map_session_data *) bl;
-                    if (sd != sd2)
-                        clif_displaymessage (sd->fd,
-                                             "You broke target's weapon");
-                    pc_breakweapon (sd2);
-                }
-                break;
-            }
-            else
-            {
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            }
-            break;
-
-        case PR_ASPERSIO:      /* アスペルシオ */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (bl->type == BL_MOB)
-                break;
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case PR_KYRIE:         /* キリエエレイソン */
-            clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case KN_AUTOCOUNTER:   /* オートカウンター */
-        case KN_TWOHANDQUICKEN:    /* ツーハンドクイッケン */
-        case CR_SPEARQUICKEN:  /* スピアクイッケン */
-        case CR_REFLECTSHIELD:
-        case AS_POISONREACT:   /* ポイズンリアクト */
-        case MC_LOUD:          /* ラウドボイス */
-        case MG_ENERGYCOAT:    /* エナジーコート */
-        case SM_ENDURE:        /* インデュア */
-        case MG_SIGHT:         /* サイト */
-        case AL_RUWACH:        /* ルアフ */
-        case MO_EXPLOSIONSPIRITS:  // 爆裂波動
-        case MO_STEELBODY:     // 金剛
-        case LK_AURABLADE:     /* オーラブレード */
-        case LK_PARRYING:      /* パリイング */
-        case LK_CONCENTRATION: /* コンセントレーション */
-        case LK_BERSERK:       /* バーサーク */
-        case HP_ASSUMPTIO:     /*  */
-        case WS_CARTBOOST:     /* カートブースト */
-        case SN_SIGHT:         /* トゥルーサイト */
-        case WS_MELTDOWN:      /* メルトダウン */
-        case ST_REJECTSWORD:   /* リジェクトソード */
-        case HW_MAGICPOWER:    /* 魔法力増幅 */
-        case PF_MEMORIZE:      /* メモライズ */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
-            if (bl->type == BL_PC)
-            {
-                struct map_session_data *sd2 = (struct map_session_data *) bl;
-                if (sd2->sc_data[SC_FLAMELAUNCHER].timer != -1
-                    || sd2->sc_data[SC_FROSTWEAPON].timer != -1
-                    || sd2->sc_data[SC_LIGHTNINGLOADER].timer != -1
-                    || sd2->sc_data[SC_SEISMICWEAPON].timer != -1
-                    || sd2->sc_data[SC_ENCPOISON].timer != -1)
-                {
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    break;
-                }
-            }
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case LK_TENSIONRELAX:  /* テンションリラックス */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            pc_setsit (sd);
-            clif_sitting (sd->fd, sd);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case MC_CHANGECART:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            break;
-        case AC_CONCENTRATION: /* 集中力向上 */
-        {
-            int  range = 1;
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            map_foreachinarea (skill_status_change_timer_sub, src->m,
-                               src->x - range, src->y - range, src->x + range,
-                               src->y + range, 0, src,
-                               SkillStatusChangeTable[skillid], tick);
-        }
-            break;
-        case SM_PROVOKE:       /* プロボック */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-
-            /* MVPmobと不死には効かない */
-            if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl)))   //不死には効かない
-            {
-                map_freeblock_unlock ();
-                return 1;
-            }
-
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-
-            if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel)   // 詠唱妨害
-                skill_castcancel (bl, 0);
-            if (dstsd && dstsd->skilltimer != -1
-                && (!dstsd->special_state.no_castcancel
-                    || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel
-                && !dstsd->special_state.no_castcancel2)
-                skill_castcancel (bl, 0);
-
-            if (sc_data)
-            {
-                if (sc_data[SC_FREEZE].timer != -1)
-                    skill_status_change_end (bl, SC_FREEZE, -1);
-                if (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0)
-                    skill_status_change_end (bl, SC_STONE, -1);
-                if (sc_data[SC_SLEEP].timer != -1)
-                    skill_status_change_end (bl, SC_SLEEP, -1);
-            }
-
-            if (bl->type == BL_MOB)
-            {
-                int  range = skill_get_range (skillid, skilllv);
-                if (range < 0)
-                    range = battle_get_range (src) - (range + 1);
-                mob_target ((struct mob_data *) bl, src, range);
-            }
-        }
-            break;
-
-        case CR_DEVOTION:      /* ディボーション */
-            if (sd && dstsd)
-            {
-                //転生や養子の場合の元の職業を算出する
-
-                int  lv = sd->status.base_level - dstsd->status.base_level;
-                lv = (lv < 0) ? -lv : lv;
-                if ((dstsd->bl.type != BL_PC)   // 相手はPCじゃないとだめ
-                    || (sd->bl.id == dstsd->bl.id)  // 相手が自分はだめ
-                    || (lv > 10)    // レベル差±10まで
-                    || (!sd->status.party_id && !sd->status.guild_id)   // PTにもギルドにも所属無しはだめ
-                    || ((sd->status.party_id != dstsd->status.party_id) // 同じパーティーか、
-                        || (sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ
-                    || (dstsd->status.pc_class == 14 || dstsd->status.pc_class == 21
-                        || dstsd->status.pc_class == 4015
-                        || dstsd->status.pc_class == 4022))
-                {               // クルセだめ
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    map_freeblock_unlock ();
-                    return 1;
-                }
-                for (i = 0; i < skilllv; i++)
-                {
-                    if (!sd->dev.val1[i])
-                    {           // 空きがあったら入れる
-                        sd->dev.val1[i] = bl->id;
-                        sd->dev.val2[i] = bl->id;
-                        break;
-                    }
-                    else if (i == skilllv - 1)
-                    {           // 空きがなかった
-                        clif_skill_fail (sd, skillid, 0, 0);
-                        map_freeblock_unlock ();
-                        return 1;
-                    }
-                }
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                clif_devotion (sd, bl->id);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           src->id, 1, 0, 0,
-                                           1000 * (15 + 15 * skilllv), 0);
-            }
-            else
-                clif_skill_fail (sd, skillid, 0, 0);
-            break;
-        case MO_CALLSPIRITS:   // 気功
-            if (sd)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                pc_addspiritball (sd, skill_get_time (skillid, skilllv),
-                                  skilllv);
-            }
-            break;
-        case CH_SOULCOLLECT:   // 狂気功
-            if (sd)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                for (i = 0; i < 5; i++)
-                    pc_addspiritball (sd, skill_get_time (skillid, skilllv),
-                                      5);
-            }
-            break;
-        case MO_BLADESTOP:     // 白刃取り
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (src, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case MO_ABSORBSPIRITS: // 気奪
-            i = 0;
-            if (sd && dstsd)
-            {
-                if (sd == dstsd || map[sd->bl.m].flag.pvp
-                    || map[sd->bl.m].flag.gvg)
-                {
-                    if (dstsd->spiritball > 0)
-                    {
-                        clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                        i = dstsd->spiritball * 7;
-                        pc_delspiritball (dstsd, dstsd->spiritball, 0);
-                        if (i > 0x7FFF)
-                            i = 0x7FFF;
-                        if (sd->status.sp + i > sd->status.max_sp)
-                            i = sd->status.max_sp - sd->status.sp;
-                    }
-                }
-            }
-            else if (sd && dstmd)
-            {                   //対象がモンスターの場合
-                //20%の確率で対象のLv*2のSPを回復する。成功したときはターゲット(σ゚Д゚)σゲッツ!!
-                if (MRAND (100) < 20)
-                {
-                    i = 2 * mob_db[dstmd->mob_class].lv;
-                    mob_target (dstmd, src, 0);
-                }
-            }
-            if (i)
-            {
-                sd->status.sp += i;
-                clif_heal (sd->fd, SP_SP, i);
-            }
-            else
-                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-            break;
-
-        case AC_MAKINGARROW:   /* 矢作成 */
-/*		if(sd) {
-			clif_arrow_create_list(sd);
-			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		}*/
-            break;
-
-        case AM_PHARMACY:      /* ポーション作成 */
-/*		if(sd) {
-			clif_skill_produce_mix_list(sd,32);
-			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		}*/
-            break;
-        case WS_CREATECOIN:    /* クリエイトコイン */
-/*		if(sd) {
-			clif_skill_produce_mix_list(sd,64);
-			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		}*/
-            break;
-        case WS_CREATENUGGET:  /* 塊製造 */
-/*		if(sd) {
-			clif_skill_produce_mix_list(sd,128);
-			clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		}*/
-            break;
-        case BS_HAMMERFALL:    /* ハンマーフォール */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_weapon_damage)
-                break;
-            if (MRAND (100) < (20 + 10 * skilllv) * sc_def_vit / 100)
-            {
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            }
-            break;
-
-        case RG_RAID:          /* サプライズアタック */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            {
-                int  x = bl->x, y = bl->y;
-                skill_area_temp[1] = bl->id;
-                skill_area_temp[2] = x;
-                skill_area_temp[3] = y;
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, x - 1, y - 1, x + 1, y + 1, 0,
-                                   src, skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-            skill_status_change_end (src, SC_HIDING, -1);   // ハイディング解除
-            break;
-
-        case KN_BRANDISHSPEAR: /*ブランディッシュスピア */
-        {
-            int  c, n = 4, ar;
-            int  dir = map_calc_dir (src, bl->x, bl->y);
-            struct square tc;
-            int  x = bl->x, y = bl->y;
-            ar = skilllv / 3;
-            skill_brandishspear_first (&tc, dir, x, y);
-            skill_brandishspear_dir (&tc, dir, 4);
-            /* 範囲C */
-            if (skilllv == 10)
-            {
-                for (c = 1; c < 4; c++)
-                {
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, tc.val1[c], tc.val2[c],
-                                       tc.val1[c], tc.val2[c], 0, src,
-                                       skillid, skilllv, tick,
-                                       flag | BCT_ENEMY | n,
-                                       skill_castend_damage_id);
-                }
-            }
-            /* 範囲BA */
-            if (skilllv > 6)
-            {
-                skill_brandishspear_dir (&tc, dir, -1);
-                n--;
-            }
-            else
-            {
-                skill_brandishspear_dir (&tc, dir, -2);
-                n -= 2;
-            }
-
-            if (skilllv > 3)
-            {
-                for (c = 0; c < 5; c++)
-                {
-                    map_foreachinarea (skill_area_sub,
-                                       bl->m, tc.val1[c], tc.val2[c],
-                                       tc.val1[c], tc.val2[c], 0, src,
-                                       skillid, skilllv, tick,
-                                       flag | BCT_ENEMY | n,
-                                       skill_castend_damage_id);
-                    if (skilllv > 6 && n == 3 && c == 4)
-                    {
-                        skill_brandishspear_dir (&tc, dir, -1);
-                        n--;
-                        c = -1;
-                    }
-                }
-            }
-            /* 範囲@ */
-            for (c = 0; c < 10; c++)
-            {
-                if (c == 0 || c == 5)
-                    skill_brandishspear_dir (&tc, dir, -1);
-                map_foreachinarea (skill_area_sub,
-                                   bl->m, tc.val1[c % 5], tc.val2[c % 5],
-                                   tc.val1[c % 5], tc.val2[c % 5], 0, src,
-                                   skillid, skilllv, tick,
-                                   flag | BCT_ENEMY | 1,
-                                   skill_castend_damage_id);
-            }
-        }
-            break;
-
-            /* パーティスキル */
-        case AL_ANGELUS:       /* エンジェラス */
-        case PR_MAGNIFICAT:    /* マグニフィカート */
-        case PR_GLORIA:        /* グロリア */
-        case SN_WINDWALK:      /* ウインドウォーク */
-            if (sd == NULL || sd->status.party_id == 0 || (flag & 1))
-            {
-                /* 個別の処理 */
-                clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
-                if (bl->type == BL_PC
-                    && ((struct map_session_data *) bl)->
-                    special_state.no_magic_damage)
-                    break;
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-            }
-            else
-            {
-                /* パーティ全体への処理 */
-                party_foreachsamemap (skill_area_sub,
-                                      sd, 1,
-                                      src, skillid, skilllv, tick,
-                                      flag | BCT_PARTY | 1,
-                                      skill_castend_nodamage_id);
-            }
-            break;
-        case BS_ADRENALINE:    /* アドレナリンラッシュ */
-        case BS_WEAPONPERFECT: /* ウェポンパーフェクション */
-        case BS_OVERTHRUST:    /* オーバートラスト */
-            if (sd == NULL || sd->status.party_id == 0 || (flag & 1))
-            {
-                /* 個別の処理 */
-                clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, (src == bl) ? 1 : 0, 0, 0,
-                                           skill_get_time (skillid, skilllv),
-                                           0);
-            }
-            else
-            {
-                /* パーティ全体への処理 */
-                party_foreachsamemap (skill_area_sub,
-                                      sd, 1,
-                                      src, skillid, skilllv, tick,
-                                      flag | BCT_PARTY | 1,
-                                      skill_castend_nodamage_id);
-            }
-            break;
-
-            /*(付加と解除が必要) */
-        case BS_MAXIMIZE:      /* マキシマイズパワー */
-        case NV_TRICKDEAD:     /* 死んだふり */
-        case CR_DEFENDER:      /* ディフェンダー */
-        case CR_AUTOGUARD:     /* オートガード */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            int  sc = SkillStatusChangeTable[skillid];
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (tsc_data)
-            {
-                if (tsc_data[sc].timer == -1)
-                    /* 付加する */
-                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
-                                               skill_get_time (skillid,
-                                                               skilllv), 0);
-                else
-                    /* 解除する */
-                    skill_status_change_end (bl, sc, -1);
-            }
-        }
-            break;
-
-        case TF_HIDING:        /* ハイディング */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            int  sc = SkillStatusChangeTable[skillid];
-            clif_skill_nodamage (src, bl, skillid, -1, 1);
-            if (tsc_data)
-            {
-                if (tsc_data[sc].timer == -1)
-                    /* 付加する */
-                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
-                                               skill_get_time (skillid,
-                                                               skilllv), 0);
-                else
-                    /* 解除する */
-                    skill_status_change_end (bl, sc, -1);
-            }
-        }
-            break;
-
-        case AS_CLOAKING:      /* クローキング */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            int  sc = SkillStatusChangeTable[skillid];
-            clif_skill_nodamage (src, bl, skillid, -1, 1);
-            if (tsc_data)
-            {
-                if (tsc_data[sc].timer == -1)
-                    /* 付加する */
-                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
-                                               skill_get_time (skillid,
-                                                               skilllv), 0);
-                else
-                    /* 解除する */
-                    skill_status_change_end (bl, sc, -1);
-            }
-
-            skill_check_cloaking (bl);
-        }
-            break;
-
-        case ST_CHASEWALK:     /* ハイディング */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            int  sc = SkillStatusChangeTable[skillid];
-            clif_skill_nodamage (src, bl, skillid, -1, 1);
-            if (tsc_data)
-            {
-                if (tsc_data[sc].timer == -1)
-                    /* 付加する */
-                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
-                                               skill_get_time (skillid,
-                                                               skilllv), 0);
-                else
-                    /* 解除する */
-                    skill_status_change_end (bl, sc, -1);
-            }
-        }
-            break;
-
-            /* 対地スキル */
-        case BD_LULLABY:       /* 子守唄 */
-        case BD_RICHMANKIM:    /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-        case BA_DISSONANCE:    /* 不協和音 */
-        case BA_POEMBRAGI:     /* ブラギの詩 */
-        case BA_WHISTLE:       /* 口笛 */
-        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
-        case BA_APPLEIDUN:     /* イドゥンの林檎 */
-        case DC_UGLYDANCE:     /* 自分勝手なダンス */
-        case DC_HUMMING:       /* ハミング */
-        case DC_DONTFORGETME:  /* 私を忘れないで… */
-        case DC_FORTUNEKISS:   /* 幸運のキス */
-        case DC_SERVICEFORYOU: /* サービスフォーユー */
-        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0);
-            break;
-
-        case HP_BASILICA:      /* バジリカ */
-        case PA_GOSPEL:        /* ゴスペル */
-            skill_clear_unitgroup (src);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0);
-            break;
-
-        case BD_ADAPTATION:    /* アドリブ */
-        {
-            struct status_change *sc_data = battle_get_sc_data (src);
-            if (sc_data && sc_data[SC_DANCING].timer != -1)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_stop_dancing (src, 0);
-            }
-        }
-            break;
-
-        case BA_FROSTJOKE:     /* 寒いジョーク */
-        case DC_SCREAM:        /* スクリーム */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_addtimerskill (src, tick + 3000, bl->id, 0, 0, skillid,
-                                 skilllv, 0, flag);
-            break;
-
-        case TF_STEAL:         // スティール
-            if (sd)
-            {
-                if (pc_steal_item (sd, bl))
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                else
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-            }
-            break;
-
-        case RG_STEALCOIN:     // スティールコイン
-            if (sd)
-            {
-                if (pc_steal_coin (sd, bl))
-                {
-                    int  range = skill_get_range (skillid, skilllv);
-                    if (range < 0)
-                        range = battle_get_range (src) - (range + 1);
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                    mob_target ((struct mob_data *) bl, src, range);
-                }
-                else
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
-            }
-            break;
-
-        case MG_STONECURSE:    /* ストーンカース */
-            if (bl->type == BL_MOB && battle_get_mode (bl) & 0x20)
-            {
-                clif_skill_fail (sd, sd->skillid, 0, 0);
-                break;
-            }
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (MRAND (100) < skilllv * 4 + 20
-                && !battle_check_undead (battle_get_race (bl),
-                                         battle_get_elem_type (bl)))
-                skill_status_change_start (bl, SC_STONE, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            else if (sd)
-                clif_skill_fail (sd, skillid, 0, 0);
-            break;
-
-        case NV_FIRSTAID:      /* 応急手当 */
-            clif_skill_nodamage (src, bl, skillid, 5, 1);
-            battle_heal (NULL, bl, 5, 0, 0);
-            break;
-
-        case AL_CURE:          /* キュアー */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            skill_status_change_end (bl, SC_SILENCE, -1);
-            skill_status_change_end (bl, SC_BLIND, -1);
-            skill_status_change_end (bl, SC_CONFUSION, -1);
-            if (battle_check_undead
-                (battle_get_race (bl), battle_get_elem_type (bl)))
-            {                   //アンデッドなら暗闇効果
-                skill_status_change_start (bl, SC_CONFUSION, 1, 0, 0, 0, 6000,
-                                           0);
-            }
-            break;
-
-        case TF_DETOXIFY:      /* 解毒 */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_end (bl, SC_POISON, -1);
-            break;
-
-        case PR_STRECOVERY:    /* リカバリー */
-        {
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            skill_status_change_end (bl, SC_FREEZE, -1);
-            skill_status_change_end (bl, SC_STONE, -1);
-            skill_status_change_end (bl, SC_SLEEP, -1);
-            skill_status_change_end (bl, SC_STAN, -1);
-            if (battle_check_undead
-                (battle_get_race (bl), battle_get_elem_type (bl)))
-            {                   //アンデッドなら暗闇効果
-                int  blind_time;
-                //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15;
-                blind_time =
-                    30 * (100 -
-                          (battle_get_int (bl) +
-                           battle_get_vit (bl)) / 2) / 100;
-                if (MRAND (100) <
-                    (100 -
-                     (battle_get_int (bl) / 2 + battle_get_vit (bl) / 3 +
-                      battle_get_luk (bl) / 10)))
-                    skill_status_change_start (bl, SC_BLIND, 1, 0, 0, 0,
-                                               blind_time, 0);
-            }
-            if (dstmd)
-            {
-                dstmd->attacked_id = 0;
-                dstmd->target_id = 0;
-                dstmd->state.targettype = NONE_ATTACKABLE;
-                dstmd->state.skillstate = MSS_IDLE;
-                dstmd->next_walktime = tick + MRAND (3000) + 3000;
-            }
-        }
-            break;
-
-        case WZ_ESTIMATION:    /* モンスター情報 */
-            if (src->type == BL_PC)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                clif_skill_estimation ((struct map_session_data *) src, bl);
-            }
-            break;
-
-        case MC_IDENTIFY:      /* アイテム鑑定 */
-            if (sd)
-                clif_item_identify_list (sd);
-            break;
-
-        case BS_REPAIRWEAPON:  /* 武器修理 */
-            if (sd)
-//動作しないのでとりあえずコメントアウト
-//          clif_item_repair_list(sd);
-                break;
-
-        case AL_TELEPORT:      /* テレポート */
-            if (sd)
-            {
-                if (map[sd->bl.m].flag.noteleport)
-                {               /* テレポ禁止 */
-                    clif_skill_teleportmessage (sd, 0);
-                    break;
-                }
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                if (sd->skilllv == 1)
-                    clif_skill_warppoint (sd, sd->skillid, "Random", "", "",
-                                          "");
-                else
-                {
-                    clif_skill_warppoint (sd, sd->skillid, "Random",
-                                          sd->status.save_point.map, "", "");
-                }
-            }
-            else if (bl->type == BL_MOB)
-                mob_warp ((struct mob_data *) bl, -1, -1, -1, 3);
-            break;
-
-        case AL_HOLYWATER:     /* アクアベネディクタ */
-            if (sd)
-            {
-                int  eflag;
-                struct item item_tmp;
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                memset (&item_tmp, 0, sizeof (item_tmp));
-                item_tmp.nameid = 523;
-                item_tmp.identify = 1;
-                if (battle_config.holywater_name_input)
-                {
-                    item_tmp.card[0] = 0xfe;
-                    item_tmp.card[1] = 0;
-                    *((unsigned long *) (&item_tmp.card[2])) = sd->char_id; /* キャラID */
-                }
-                eflag = pc_additem (sd, &item_tmp, 1);
-                if (eflag)
-                {
-                    clif_additem (sd, 0, 0, eflag);
-                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
-                                      sd->bl.y, NULL, NULL, NULL, 0);
-                }
-            }
-            break;
-        case TF_PICKSTONE:
-            if (sd)
-            {
-                int  eflag;
-                struct item item_tmp;
-                struct block_list tbl;
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                memset (&item_tmp, 0, sizeof (item_tmp));
-                memset (&tbl, 0, sizeof (tbl)); // [MouseJstr]
-                item_tmp.nameid = 7049;
-                item_tmp.identify = 1;
-                tbl.id = 0;
-                clif_takeitem (&sd->bl, &tbl);
-                eflag = pc_additem (sd, &item_tmp, 1);
-                if (eflag)
-                {
-                    clif_additem (sd, 0, 0, eflag);
-                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
-                                      sd->bl.y, NULL, NULL, NULL, 0);
-                }
-            }
-            break;
-
-        case RG_STRIPWEAPON:   /* ストリップウェポン */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-
-            if (tsc_data && tsc_data[SC_CP_WEAPON].timer != -1)
-                break;
-            strip_per = 5 + 2 * skilllv + strip_fix / 5;
-            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
-            if (MRAND (100) < strip_per)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0, strip_time, 0);
-                if (dstsd)
-                {
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (dstsd->status.inventory[i].equip
-                            && dstsd->status.inventory[i].equip & 0x0002)
-                        {
-                            pc_unequipitem (dstsd, i, 0);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-            break;
-
-        case RG_STRIPSHIELD:   /* ストリップシールド */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-
-            if (tsc_data && tsc_data[SC_CP_SHIELD].timer != -1)
-                break;
-            strip_per = 5 + 2 * skilllv + strip_fix / 5;
-            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
-            if (MRAND (100) < strip_per)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0, strip_time, 0);
-                if (dstsd)
-                {
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (dstsd->status.inventory[i].equip
-                            && dstsd->status.inventory[i].equip & 0x0020)
-                        {
-                            pc_unequipitem (dstsd, i, 0);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-            break;
-
-        case RG_STRIPARMOR:    /* ストリップアーマー */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-
-            if (tsc_data && tsc_data[SC_CP_ARMOR].timer != -1)
-                break;
-            strip_per = 5 + 2 * skilllv + strip_fix / 5;
-            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
-            if (MRAND (100) < strip_per)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0, strip_time, 0);
-                if (dstsd)
-                {
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (dstsd->status.inventory[i].equip
-                            && dstsd->status.inventory[i].equip & 0x0010)
-                        {
-                            pc_unequipitem (dstsd, i, 0);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-            break;
-        case RG_STRIPHELM:     /* ストリップヘルム */
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-
-            if (tsc_data && tsc_data[SC_CP_HELM].timer != -1)
-                break;
-            strip_per = 5 + 2 * skilllv + strip_fix / 5;
-            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
-            if (MRAND (100) < strip_per)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                skill_status_change_start (bl,
-                                           SkillStatusChangeTable[skillid],
-                                           skilllv, 0, 0, 0, strip_time, 0);
-                if (dstsd)
-                {
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (dstsd->status.inventory[i].equip
-                            && dstsd->status.inventory[i].equip & 0x0100)
-                        {
-                            pc_unequipitem (dstsd, i, 0);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-            break;
-            /* PotionPitcher */
-        case AM_POTIONPITCHER: /* ポーションピッチャー */
-        {
-            struct block_list tbl;
-            int  i, x, hp = 0, sp = 0;
-            if (sd)
-            {
-                if (sd == dstsd)
-                {               // cancel use on oneself
-                    map_freeblock_unlock ();
-                    return 1;
-                }
-                x = skilllv % 11 - 1;
-                i = pc_search_inventory (sd, skill_db[skillid].itemid[x]);
-                if (i < 0 || skill_db[skillid].itemid[x] <= 0)
-                {
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    map_freeblock_unlock ();
-                    return 1;
-                }
-                if (sd->inventory_data[i] == NULL
-                    || sd->status.inventory[i].amount <
-                    skill_db[skillid].amount[x])
-                {
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    map_freeblock_unlock ();
-                    return 1;
-                }
-                sd->state.potionpitcher_flag = 1;
-                sd->potion_hp = sd->potion_sp = sd->potion_per_hp =
-                    sd->potion_per_sp = 0;
-                sd->skilltarget = bl->id;
-                run_script (sd->inventory_data[i]->use_script, 0, sd->bl.id,
-                            0);
-                pc_delitem (sd, i, skill_db[skillid].amount[x], 0);
-                sd->state.potionpitcher_flag = 0;
-                if (sd->potion_per_hp > 0 || sd->potion_per_sp > 0)
-                {
-                    hp = battle_get_max_hp (bl) * sd->potion_per_hp / 100;
-                    hp = hp * (100 +
-                               pc_checkskill (sd,
-                                              AM_POTIONPITCHER) * 10 +
-                               pc_checkskill (sd,
-                                              AM_LEARNINGPOTION) * 5) / 100;
-                    if (dstsd)
-                    {
-                        sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
-                        sp = sp * (100 +
-                                   pc_checkskill (sd,
-                                                  AM_POTIONPITCHER) +
-                                   pc_checkskill (sd,
-                                                  AM_LEARNINGPOTION) * 5) /
-                            100;
-                    }
-                }
-                else
-                {
-                    if (sd->potion_hp > 0)
-                    {
-                        hp = sd->potion_hp * (100 +
-                                              pc_checkskill (sd,
-                                                             AM_POTIONPITCHER)
-                                              * 10 + pc_checkskill (sd,
-                                                                    AM_LEARNINGPOTION)
-                                              * 5) / 100;
-                        hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100;
-                        if (dstsd)
-                            hp = hp * (100 +
-                                       pc_checkskill (dstsd,
-                                                      SM_RECOVERY) * 10) /
-                                100;
-                    }
-                    if (sd->potion_sp > 0)
-                    {
-                        sp = sd->potion_sp * (100 +
-                                              pc_checkskill (sd,
-                                                             AM_POTIONPITCHER)
-                                              + pc_checkskill (sd,
-                                                               AM_LEARNINGPOTION)
-                                              * 5) / 100;
-                        sp = sp * (100 + (battle_get_int (bl) << 1)) / 100;
-                        if (dstsd)
-                            sp = sp * (100 +
-                                       pc_checkskill (dstsd,
-                                                      MG_SRECOVERY) * 10) /
-                                100;
-                    }
-                }
-            }
-            else
-            {
-                hp = (1 + MRAND (400)) * (100 + skilllv * 10) / 100;
-                hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100;
-                if (dstsd)
-                    hp = hp * (100 +
-                               pc_checkskill (dstsd, SM_RECOVERY) * 10) / 100;
-            }
-            tbl.id = 0;
-            tbl.m = src->m;
-            tbl.x = src->x;
-            tbl.y = src->y;
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (hp > 0 || (hp <= 0 && sp <= 0))
-                clif_skill_nodamage (&tbl, bl, AL_HEAL, hp, 1);
-            if (sp > 0)
-                clif_skill_nodamage (&tbl, bl, MG_SRECOVERY, sp, 1);
-            battle_heal (src, bl, hp, sp, 0);
-        }
-            break;
-        case AM_CP_WEAPON:
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1)
-                skill_status_change_end (bl, SC_STRIPWEAPON, -1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-        }
-            break;
-        case AM_CP_SHIELD:
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1)
-                skill_status_change_end (bl, SC_STRIPSHIELD, -1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-        }
-            break;
-        case AM_CP_ARMOR:
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (tsc_data && tsc_data[SC_STRIPARMOR].timer != -1)
-                skill_status_change_end (bl, SC_STRIPARMOR, -1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-        }
-            break;
-        case AM_CP_HELM:
-        {
-            struct status_change *tsc_data = battle_get_sc_data (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (tsc_data && tsc_data[SC_STRIPHELM].timer != -1)
-                skill_status_change_end (bl, SC_STRIPHELM, -1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-        }
-            break;
-        case SA_DISPELL:       /* ディスペル */
-        {
-            int  i;
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            for (i = 0; i < 136; i++)
-            {
-                if (i == SC_RIDING || i == SC_FALCON || i == SC_HALLUCINATION
-                    || i == SC_WEIGHT50 || i == SC_WEIGHT90
-                    || i == SC_STRIPWEAPON || i == SC_STRIPSHIELD
-                    || i == SC_STRIPARMOR || i == SC_STRIPHELM
-                    || i == SC_CP_WEAPON || i == SC_CP_SHIELD
-                    || i == SC_CP_ARMOR || i == SC_CP_HELM || i == SC_COMBO)
-                    continue;
-                skill_status_change_end (bl, i, -1);
-            }
-        }
-            break;
-
-        case TF_BACKSLIDING:   /* バックステップ */
-            battle_stopwalking (src, 1);
-            skill_blown (src, bl,
-                         skill_get_blewcount (skillid, skilllv) | 0x10000);
-            if (src->type == BL_MOB)
-                clif_fixmobpos ((struct mob_data *) src);
-            else if (src->type == BL_PC)
-                clif_fixpos (src);
-            skill_addtimerskill (src, tick + 200, src->id, 0, 0, skillid,
-                                 skilllv, 0, flag);
-            break;
-
-        case SA_CASTCANCEL:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_castcancel (src, 1);
-            if (sd)
-            {
-                int  sp = skill_get_sp (sd->skillid_old, sd->skilllv_old);
-                sp = sp * (90 - (skilllv - 1) * 20) / 100;
-                if (sp < 0)
-                    sp = 0;
-                pc_heal (sd, 0, -sp);
-            }
-            break;
-        case SA_SPELLBREAKER:  // スペルブレイカー
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  sp;
-            if (sc_data && sc_data[SC_MAGICROD].timer != -1)
-            {
-                if (dstsd)
-                {
-                    sp = skill_get_sp (skillid, skilllv);
-                    sp = sp * sc_data[SC_MAGICROD].val2 / 100;
-                    if (sp > 0x7fff)
-                        sp = 0x7fff;
-                    else if (sp < 1)
-                        sp = 1;
-                    if (dstsd->status.sp + sp > dstsd->status.max_sp)
-                    {
-                        sp = dstsd->status.max_sp - dstsd->status.sp;
-                        dstsd->status.sp = dstsd->status.max_sp;
-                    }
-                    else
-                        dstsd->status.sp += sp;
-                    clif_heal (dstsd->fd, SP_SP, sp);
-                }
-                clif_skill_nodamage (bl, bl, SA_MAGICROD,
-                                     sc_data[SC_MAGICROD].val1, 1);
-                if (sd)
-                {
-                    sp = sd->status.max_sp / 5;
-                    if (sp < 1)
-                        sp = 1;
-                    pc_heal (sd, 0, -sp);
-                }
-            }
-            else
-            {
-                int  bl_skillid = 0, bl_skilllv = 0;
-                if (bl->type == BL_PC)
-                {
-                    if (dstsd && dstsd->skilltimer != -1)
-                    {
-                        bl_skillid = dstsd->skillid;
-                        bl_skilllv = dstsd->skilllv;
-                    }
-                }
-                else if (bl->type == BL_MOB)
-                {
-                    if (dstmd && dstmd->skilltimer != -1)
-                    {
-                        bl_skillid = dstmd->skillid;
-                        bl_skilllv = dstmd->skilllv;
-                    }
-                }
-                if (bl_skillid > 0
-                    && skill_db[bl_skillid].skill_type == BF_MAGIC)
-                {
-                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                    skill_castcancel (bl, 0);
-                    sp = skill_get_sp (bl_skillid, bl_skilllv);
-                    if (dstsd)
-                        pc_heal (dstsd, 0, -sp);
-                    if (sd)
-                    {
-                        sp = sp * (25 * (skilllv - 1)) / 100;
-                        if (skilllv > 1 && sp < 1)
-                            sp = 1;
-                        if (sp > 0x7fff)
-                            sp = 0x7fff;
-                        else if (sp < 1)
-                            sp = 1;
-                        if (sd->status.sp + sp > sd->status.max_sp)
-                        {
-                            sp = sd->status.max_sp - sd->status.sp;
-                            sd->status.sp = sd->status.max_sp;
-                        }
-                        else
-                            sd->status.sp += sp;
-                        clif_heal (sd->fd, SP_SP, sp);
-                    }
-                }
-                else if (sd)
-                    clif_skill_fail (sd, skillid, 0, 0);
-            }
-        }
-            break;
-        case SA_MAGICROD:
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case SA_AUTOSPELL:     /* オートスペル */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-                clif_autospell (sd, skilllv);
-            else
-            {
-                int  maxlv = 1, spellid = 0;
-                static const int spellarray[3] =
-                    { MG_COLDBOLT, MG_FIREBOLT, MG_LIGHTNINGBOLT };
-                if (skilllv >= 10)
-                {
-                    spellid = MG_FROSTDIVER;
-                    maxlv = skilllv - 9;
-                }
-                else if (skilllv >= 8)
-                {
-                    spellid = MG_FIREBALL;
-                    maxlv = skilllv - 7;
-                }
-                else if (skilllv >= 5)
-                {
-                    spellid = MG_SOULSTRIKE;
-                    maxlv = skilllv - 4;
-                }
-                else if (skilllv >= 2)
-                {
-                    int  i = MRAND (3);
-                    spellid = spellarray[i];
-                    maxlv = skilllv - 1;
-                }
-                else if (skilllv > 0)
-                {
-                    spellid = MG_NAPALMBEAT;
-                    maxlv = 3;
-                }
-                if (spellid > 0)
-                    skill_status_change_start (src, SC_AUTOSPELL, skilllv,
-                                               spellid, maxlv, 0,
-                                               skill_get_time (SA_AUTOSPELL,
-                                                               skilllv), 0);
-            }
-            break;
-
-            /* ランダム属性変化、水属性変化、地、火、風 */
-        case NPC_ATTRICHANGE:
-        case NPC_CHANGEWATER:
-        case NPC_CHANGEGROUND:
-        case NPC_CHANGEFIRE:
-        case NPC_CHANGEWIND:
-            /* 毒、聖、念、闇 */
-        case NPC_CHANGEPOISON:
-        case NPC_CHANGEHOLY:
-        case NPC_CHANGEDARKNESS:
-        case NPC_CHANGETELEKINESIS:
-            if (md)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                md->def_ele = skill_get_pl (skillid);
-                if (md->def_ele == 0)   /* ランダム変化、ただし、 */
-                    md->def_ele = MRAND (10);   /* 不死属性は除く */
-                md->def_ele += (1 + MRAND (4)) * 20;    /* 属性レベルはランダム */
-            }
-            break;
-
-        case NPC_HALLUCINATION:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-
-        case NPC_KEEPING:
-        case NPC_BARRIER:
-        {
-            int  skill_time = skill_get_time (skillid, skilllv);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0, skill_time, 0);
-            mob_changestate ((struct mob_data *) src, MS_DELAY, skill_time);
-        }
-            break;
-
-        case NPC_DARKBLESSING:
-        {
-            int  sc_def = 100 - battle_get_mdef (bl);
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (battle_get_elem_type (bl) == 7 || battle_get_race (bl) == 6)
-                break;
-            if (MRAND (100) < sc_def * (50 + skilllv * 5) / 100)
-            {
-                if (dstsd)
-                {
-                    int  hp = battle_get_hp (bl) - 1;
-                    pc_heal (dstsd, -hp, 0);
-                }
-                else if (dstmd)
-                    dstmd->hp = 1;
-            }
-        }
-            break;
-
-        case NPC_SELFDESTRUCTION:  /* 自爆 */
-        case NPC_SELFDESTRUCTION2: /* 自爆2 */
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, skillid, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case NPC_LICK:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_weapon_damage)
-                break;
-            if (dstsd)
-                pc_heal (dstsd, 0, -100);
-            if (MRAND (100) < (skilllv * 5) * sc_def_vit / 100)
-                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
-                                           skill_get_time2 (skillid, skilllv),
-                                           0);
-            break;
-
-        case NPC_SUICIDE:      /* 自決 */
-            if (src && bl && md)
-            {
-                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-                mob_damage (NULL, md, md->hp, 0);
-            }
-            break;
-
-        case NPC_SUMMONSLAVE:  /* 手下召喚 */
-        case NPC_SUMMONMONSTER:    /* MOB召喚 */
-            if (md && !md->master_id)
-            {
-                mob_summonslave (md,
-                                 mob_db[md->mob_class].skill[md->skillidx].val,
-                                 skilllv,
-                                 (skillid == NPC_SUMMONSLAVE) ? 1 : 0);
-            }
-            break;
-
-        case NPC_TRANSFORMATION:
-        case NPC_METAMORPHOSIS:
-            if (md)
-                mob_class_change (md,
-                                  mob_db[md->mob_class].skill[md->skillidx].val);
-            break;
-
-        case NPC_EMOTION:      /* エモーション */
-            if (md)
-                clif_emotion (&md->bl,
-                              mob_db[md->mob_class].skill[md->skillidx].val[0]);
-            break;
-
-        case NPC_DEFENDER:
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            break;
-
-        case WE_MALE:          /* 君だけは護るよ */
-            if (sd && dstsd)
-            {
-                int  hp_rate =
-                    (skilllv <=
-                     0) ? 0 : skill_db[skillid].hp_rate[skilllv - 1];
-                int  gain_hp = sd->status.max_hp * abs (hp_rate) / 100; // 15%
-                clif_skill_nodamage (src, bl, skillid, gain_hp, 1);
-                battle_heal (NULL, bl, gain_hp, 0, 0);
-            }
-            break;
-        case WE_FEMALE:        /* あなたの為に犠牲になります */
-            if (sd && dstsd)
-            {
-                int  sp_rate =
-                    (skilllv <=
-                     0) ? 0 : skill_db[skillid].sp_rate[skilllv - 1];
-                int  gain_sp = sd->status.max_sp * abs (sp_rate) / 100; // 15%
-                clif_skill_nodamage (src, bl, skillid, gain_sp, 1);
-                battle_heal (NULL, bl, 0, gain_sp, 0);
-            }
-            break;
-
-        case WE_CALLPARTNER:   /* あなたに会いたい */
-            if (sd && dstsd)
-            {
-                if (map[sd->bl.m].flag.nomemo)
-                {
-                    clif_skill_teleportmessage (sd, 1);
-                    return 0;
-                }
-                if ((dstsd = pc_get_partner (sd)) == NULL)
-                {
-                    clif_skill_fail (sd, skillid, 0, 0);
-                    return 0;
-                }
-                skill_unitsetting (src, skillid, skilllv, sd->bl.x, sd->bl.y,
-                                   0);
-            }
-            break;
-
-        case PF_HPCONVERSION:  /* ライフ置き換え */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-            {
-                int  conv_hp = 0, conv_sp = 0;
-                conv_hp = sd->status.hp / 10;   //基本はHPの10%
-                sd->status.hp -= conv_hp;   //HPを減らす
-                conv_sp = conv_hp * 20 * skilllv / 100;
-                conv_sp =
-                    (sd->status.sp + conv_sp >
-                     sd->status.max_sp) ? sd->status.max_sp -
-                    sd->status.sp : conv_sp;
-                sd->status.sp += conv_sp;   //SPを増やす
-                pc_heal (sd, -conv_hp, conv_sp);
-                clif_heal (sd->fd, SP_SP, conv_sp);
-            }
-            break;
-        case HT_REMOVETRAP:    /* リムーブトラップ */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            {
-                struct skill_unit *su = NULL;
-                struct item item_tmp;
-                int  flag;
-                if ((bl->type == BL_SKILL) &&
-                    (su = (struct skill_unit *) bl) &&
-                    (su->group->src_id == src->id || map[bl->m].flag.pvp
-                     || map[bl->m].flag.gvg) && (su->group->unit_id >= 0x8f
-                                                 && su->group->unit_id <=
-                                                 0x99)
-                    && (su->group->unit_id != 0x92))
-                {               //罠を取り返す
-                    if (sd)
-                    {
-                        if (battle_config.skill_removetrap_type == 1)
-                        {
-                            for (i = 0; i < 10; i++)
-                            {
-                                if (skill_db[su->group->skill_id].itemid[i] >
-                                    0)
-                                {
-                                    memset (&item_tmp, 0, sizeof (item_tmp));
-                                    item_tmp.nameid =
-                                        skill_db[su->group->
-                                                 skill_id].itemid[i];
-                                    item_tmp.identify = 1;
-                                    if (item_tmp.nameid
-                                        && (flag =
-                                            pc_additem (sd, &item_tmp,
-                                                        skill_db[su->
-                                                                 group->skill_id].amount
-                                                        [i])))
-                                    {
-                                        clif_additem (sd, 0, 0, flag);
-                                        map_addflooritem (&item_tmp,
-                                                          skill_db[su->
-                                                                   group->skill_id].amount
-                                                          [i], sd->bl.m,
-                                                          sd->bl.x, sd->bl.y,
-                                                          NULL, NULL, NULL,
-                                                          0);
-                                    }
-                                }
-                            }
-                        }
-                        else
-                        {
-                            memset (&item_tmp, 0, sizeof (item_tmp));
-                            item_tmp.nameid = 1065;
-                            item_tmp.identify = 1;
-                            if (item_tmp.nameid
-                                && (flag = pc_additem (sd, &item_tmp, 1)))
-                            {
-                                clif_additem (sd, 0, 0, flag);
-                                map_addflooritem (&item_tmp, 1, sd->bl.m,
-                                                  sd->bl.x, sd->bl.y, NULL,
-                                                  NULL, NULL, 0);
-                            }
-                        }
-
-                    }
-                    if (su->group->unit_id == 0x91 && su->group->val2)
-                    {
-                        struct block_list *target =
-                            map_id2bl (su->group->val2);
-                        if (target
-                            && (target->type == BL_PC
-                                || target->type == BL_MOB))
-                            skill_status_change_end (target, SC_ANKLE, -1);
-                    }
-                    skill_delunit (su);
-                }
-            }
-            break;
-        case HT_SPRINGTRAP:    /* スプリングトラップ */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            {
-                struct skill_unit *su = NULL;
-                if ((bl->type == BL_SKILL) && (su = (struct skill_unit *) bl)
-                    && (su->group))
-                {
-                    switch (su->group->unit_id)
-                    {
-                        case 0x8f: /* ブラストマイン */
-                        case 0x90: /* スキッドトラップ */
-                        case 0x93: /* ランドマイン */
-                        case 0x94: /* ショックウェーブトラップ */
-                        case 0x95: /* サンドマン */
-                        case 0x96: /* フラッシャー */
-                        case 0x97: /* フリージングトラップ */
-                        case 0x98: /* クレイモアートラップ */
-                        case 0x99: /* トーキーボックス */
-                            su->group->unit_id = 0x8c;
-                            clif_changelook (bl, LOOK_BASE,
-                                             su->group->unit_id);
-                            su->group->limit =
-                                DIFF_TICK (tick + 1500, su->group->tick);
-                            su->limit =
-                                DIFF_TICK (tick + 1500, su->group->tick);
-                    }
-                }
-            }
-            break;
-        case BD_ENCORE:        /* アンコール */
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            if (sd)
-                skill_use_id (sd, src->id, sd->skillid_dance,
-                              sd->skilllv_dance);
-            break;
-        case AS_SPLASHER:      /* ベナムスプラッシャー */
-            if ((double) battle_get_max_hp (bl) * 2 / 3 < battle_get_hp (bl))   //HPが2/3以上残っていたら失敗
-                return 1;
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, skillid, src->id, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-            break;
-        case PF_MINDBREAKER:   /* プロボック */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-
-            /* MVPmobと不死には効かない */
-            if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl)))   //不死には効かない
-            {
-                map_freeblock_unlock ();
-                return 1;
-            }
-
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
-                                       skilllv, 0, 0, 0,
-                                       skill_get_time (skillid, skilllv), 0);
-
-            if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel)   // 詠唱妨害
-                skill_castcancel (bl, 0);
-            if (dstsd && dstsd->skilltimer != -1
-                && (!dstsd->special_state.no_castcancel
-                    || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel
-                && !dstsd->special_state.no_castcancel2)
-                skill_castcancel (bl, 0);
-
-            if (sc_data)
-            {
-                if (sc_data[SC_FREEZE].timer != -1)
-                    skill_status_change_end (bl, SC_FREEZE, -1);
-                if (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0)
-                    skill_status_change_end (bl, SC_STONE, -1);
-                if (sc_data[SC_SLEEP].timer != -1)
-                    skill_status_change_end (bl, SC_SLEEP, -1);
-            }
-
-            if (bl->type == BL_MOB)
-            {
-                int  range = skill_get_range (skillid, skilllv);
-                if (range < 0)
-                    range = battle_get_range (src) - (range + 1);
-                mob_target ((struct mob_data *) bl, src, range);
-            }
-        }
-            break;
-
-        case RG_CLEANER:       //AppleGirl
-            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
-            {
-                struct skill_unit *su = NULL;
-                if ((bl->type == BL_SKILL) &&
-                    (su = (struct skill_unit *) bl) &&
-                    (su->group->src_id == src->id || map[bl->m].flag.pvp
-                     || map[bl->m].flag.gvg) && (su->group->unit_id == 0xb0))
-                {               //罠を取り返す
-                    if (sd)
-                        skill_delunit (su);
-                }
-            }
-            break;
-        default:
-            printf ("Unknown skill used:%d\n", skillid);
-            map_freeblock_unlock ();
-            return 1;
-    }
-
-    map_freeblock_unlock ();
-    return 0;
-}
-
-/*==========================================
- * スキル使用(詠唱完了、ID指定)
- *------------------------------------------
- */
-void skill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ;
-    struct block_list *bl;
-    int  range, inf2;
-
-    nullpo_retv ( sd);
-
-    if (sd->bl.prev == NULL)    //prevが無いのはありなの?
-        return;
-
-    if (sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid)  /* タイマIDの確認 */
-        return;
-    if (sd->skillid != SA_CASTCANCEL && sd->skilltimer != -1
-        && pc_checkskill (sd, SA_FREECAST) > 0)
-    {
-        sd->speed = sd->prev_speed;
-        clif_updatestatus (sd, SP_SPEED);
-    }
-    if (sd->skillid != SA_CASTCANCEL)
-        sd->skilltimer = -1;
-
-    if ((bl = map_id2bl (sd->skilltarget)) == NULL || bl->prev == NULL)
-    {
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-    if (sd->bl.m != bl->m || pc_isdead (sd))
-    {                           //マップが違うか自分が死んでいる
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-
-    if (sd->skillid == PR_LEXAETERNA)
-    {
-        struct status_change *sc_data = battle_get_sc_data (bl);
-        if (sc_data
-            && (sc_data[SC_FREEZE].timer != -1
-                || (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0)))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            sd->skillitem = sd->skillitemlv = -1;
-            return;
-        }
-    }
-    else if (sd->skillid == RG_BACKSTAP)
-    {
-        int  dir = map_calc_dir (&sd->bl, bl->x, bl->y), t_dir =
-            battle_get_dir (bl);
-        int  dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y);
-        if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir)))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            sd->skillitem = sd->skillitemlv = -1;
-            return;
-        }
-    }
-
-    inf2 = skill_get_inf2 (sd->skillid);
-    if (((skill_get_inf (sd->skillid) & 1) || inf2 & 4) &&  // 彼我敵対関係チェック
-        battle_check_target (&sd->bl, bl, BCT_ENEMY) <= 0)
-    {
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-    if (inf2 & 0xC00 && sd->bl.id != bl->id)
-    {
-        int  fail_flag = 1;
-        if (inf2 & 0x400 && battle_check_target (&sd->bl, bl, BCT_PARTY) > 0)
-            fail_flag = 0;
-        if (inf2 & 0x800 && sd->status.guild_id > 0
-            && sd->status.guild_id == battle_get_guild_id (bl))
-            fail_flag = 0;
-        if (fail_flag)
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            sd->skillitem = sd->skillitemlv = -1;
-            return;
-        }
-    }
-
-    range = skill_get_range (sd->skillid, sd->skilllv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    range += battle_config.pc_skill_add_range;
-    if ((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1
-         && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
-        || (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1
-            && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
-        || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1
-            && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
-        || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1
-            && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST))
-        range +=
-            skill_get_blewcount (MO_COMBOFINISH, sd->sc_data[SC_COMBO].val2);
-    if (battle_config.skill_out_range_consume)
-    {                           // changed to allow casting when target walks out of range [Valaris]
-        if (range < distance (sd->bl.x, sd->bl.y, bl->x, bl->y))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            sd->skillitem = sd->skillitemlv = -1;
-            return;
-        }
-    }
-    if (!skill_check_condition (sd, 1))
-    {                           /* 使用条件チェック */
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-    sd->skillitem = sd->skillitemlv = -1;
-    if (battle_config.skill_out_range_consume)
-    {
-        if (range < distance (sd->bl.x, sd->bl.y, bl->x, bl->y))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            return;
-        }
-    }
-
-    if (battle_config.pc_skill_log)
-        printf ("PC %d skill castend skill=%d\n", sd->bl.id, sd->skillid);
-    pc_stop_walking (sd, 0);
-
-    switch (skill_get_nk (sd->skillid))
-    {
-            /* 攻撃系/吹き飛ばし系 */
-        case 0:
-        case 2:
-            skill_castend_damage_id (&sd->bl, bl, sd->skillid, sd->skilllv,
-                                     tick, 0);
-            break;
-        case 1:                /* 支援系 */
-            if ((sd->skillid == AL_HEAL
-                 || (sd->skillid == ALL_RESURRECTION && bl->type != BL_PC)
-                 || sd->skillid == PR_ASPERSIO)
-                && battle_check_undead (battle_get_race (bl),
-                                        battle_get_elem_type (bl)))
-                skill_castend_damage_id (&sd->bl, bl, sd->skillid,
-                                         sd->skilllv, tick, 0);
-            else
-                skill_castend_nodamage_id (&sd->bl, bl, sd->skillid,
-                                           sd->skilllv, tick, 0);
-            break;
-    }
-}
-
-/*==========================================
- * スキル使用(詠唱完了、場所指定の実際の処理)
- *------------------------------------------
- */
-int skill_castend_pos2 (struct block_list *src, int x, int y, int skillid,
-                        int skilllv, unsigned int tick, int flag)
-{
-    struct map_session_data *sd = NULL;
-    int  i, tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
-
-    nullpo_retr (0, src);
-
-    if (src->type == BL_PC)
-    {
-        nullpo_retr (0, sd = (struct map_session_data *) src);
-    }
-    if (skillid != WZ_METEOR &&
-        skillid != WZ_SIGHTRASHER &&
-        skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE)
-        clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
-
-    if (skillnotok (skillid, sd))   // [MouseJstr]
-        return 0;
-
-    switch (skillid)
-    {
-        case PR_BENEDICTIO:    /* 聖体降福 */
-            skill_area_temp[1] = src->id;
-            map_foreachinarea (skill_area_sub,
-                               src->m, x - 1, y - 1, x + 1, y + 1, 0,
-                               src, skillid, skilllv, tick,
-                               flag | BCT_NOENEMY | 1,
-                               skill_castend_nodamage_id);
-            map_foreachinarea (skill_area_sub, src->m, x - 1, y - 1, x + 1,
-                               y + 1, 0, src, skillid, skilllv, tick,
-                               flag | BCT_ENEMY | 1, skill_castend_damage_id);
-            break;
-
-        case BS_HAMMERFALL:    /* ハンマーフォール */
-            skill_area_temp[1] = src->id;
-            skill_area_temp[2] = x;
-            skill_area_temp[3] = y;
-            map_foreachinarea (skill_area_sub,
-                               src->m, x - 2, y - 2, x + 2, y + 2, 0,
-                               src, skillid, skilllv, tick,
-                               flag | BCT_ENEMY | 2,
-                               skill_castend_nodamage_id);
-            break;
-
-        case HT_DETECTING:     /* ディテクティング */
-        {
-            const int range = 7;
-            map_foreachinarea (skill_status_change_timer_sub,
-                               src->m, src->x - range, src->y - range,
-                               src->x + range, src->y + range, 0, src,
-                               SC_SIGHT, tick);
-        }
-            break;
-
-        case MG_SAFETYWALL:    /* セイフティウォール */
-        case MG_FIREWALL:      /* ファイヤーウォール */
-        case MG_THUNDERSTORM:  /* サンダーストーム */
-        case AL_PNEUMA:        /* ニューマ */
-        case WZ_ICEWALL:       /* アイスウォール */
-        case WZ_FIREPILLAR:    /* ファイアピラー */
-        case WZ_SIGHTRASHER:
-        case WZ_QUAGMIRE:      /* クァグマイア */
-        case WZ_VERMILION:     /* ロードオブヴァーミリオン */
-        case WZ_FROSTNOVA:     /* フロストノヴァ */
-        case WZ_STORMGUST:     /* ストームガスト */
-        case WZ_HEAVENDRIVE:   /* ヘヴンズドライブ */
-        case PR_SANCTUARY:     /* サンクチュアリ */
-        case PR_MAGNUS:        /* マグヌスエクソシズム */
-        case CR_GRANDCROSS:    /* グランドクロス */
-        case HT_SKIDTRAP:      /* スキッドトラップ */
-        case HT_LANDMINE:      /* ランドマイン */
-        case HT_ANKLESNARE:    /* アンクルスネア */
-        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
-        case HT_SANDMAN:       /* サンドマン */
-        case HT_FLASHER:       /* フラッシャー */
-        case HT_FREEZINGTRAP:  /* フリージングトラップ */
-        case HT_BLASTMINE:     /* ブラストマイン */
-        case HT_CLAYMORETRAP:  /* クレイモアートラップ */
-        case AS_VENOMDUST:     /* ベノムダスト */
-        case AM_DEMONSTRATION: /* デモンストレーション */
-        case PF_SPIDERWEB:     /* スパイダーウェッブ */
-        case PF_FOGWALL:       /* フォグウォール */
-        case HT_TALKIEBOX:     /* トーキーボックス */
-            skill_unitsetting (src, skillid, skilllv, x, y, 0);
-            break;
-
-        case RG_GRAFFITI:      /* Graffiti [Valaris] */
-            skill_clear_unitgroup (src);
-            skill_unitsetting (src, skillid, skilllv, x, y, 0);
-            break;
-
-        case SA_VOLCANO:       /* ボルケーノ */
-        case SA_DELUGE:        /* デリュージ */
-        case SA_VIOLENTGALE:   /* バイオレントゲイル */
-        case SA_LANDPROTECTOR: /* ランドプロテクター */
-            skill_clear_element_field (src);    //既に自分が発動している属性場をクリア
-            skill_unitsetting (src, skillid, skilllv, x, y, 0);
-            break;
-
-        case WZ_METEOR:        //メテオストーム
-        {
-            int  flag = 0;
-            for (i = 0; i < 2 + (skilllv >> 1); i++)
-            {
-                int  j = 0, c;
-                do
-                {
-                    tmpx = x + (MRAND (7) - 3);
-                    tmpy = y + (MRAND (7) - 3);
-                    if (tmpx < 0)
-                        tmpx = 0;
-                    else if (tmpx >= map[src->m].xs)
-                        tmpx = map[src->m].xs - 1;
-                    if (tmpy < 0)
-                        tmpy = 0;
-                    else if (tmpy >= map[src->m].ys)
-                        tmpy = map[src->m].ys - 1;
-                    j++;
-                }
-                while (((c = map_getcell (src->m, tmpx, tmpy)) == 1 || c == 5)
-                       && j < 100);
-                if (j >= 100)
-                    continue;
-                if (flag == 0)
-                {
-                    clif_skill_poseffect (src, skillid, skilllv, tmpx, tmpy,
-                                          tick);
-                    flag = 1;
-                }
-                if (i > 0)
-                    skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy,
-                                         skillid, skilllv, (x1 << 16) | y1,
-                                         flag);
-                x1 = tmpx;
-                y1 = tmpy;
-            }
-            skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy, skillid,
-                                 skilllv, -1, flag);
-        }
-            break;
-
-        case AL_WARP:          /* ワープポータル */
-            if (sd)
-            {
-                if (map[sd->bl.m].flag.noteleport)  /* テレポ禁止 */
-                    break;
-                clif_skill_warppoint (sd, sd->skillid,
-                                      sd->status.save_point.map,
-                                      (sd->skilllv >
-                                       1) ? sd->status.memo_point[0].map : "",
-                                      (sd->skilllv >
-                                       2) ? sd->status.memo_point[1].map : "",
-                                      (sd->skilllv >
-                                       3) ? sd->status.
-                                      memo_point[2].map : "");
-            }
-            break;
-        case MO_BODYRELOCATION:
-            if (sd)
-            {
-                pc_movepos (sd, x, y);
-            }
-            else if (src->type == BL_MOB)
-                mob_warp ((struct mob_data *) src, -1, x, y, 0);
-            break;
-        case AM_CANNIBALIZE:   // バイオプラント
-            if (sd)
-            {
-                int  mx, my, id = 0;
-                struct mob_data *md;
-
-                mx = x;         // + (rand()%10 - 5);
-                my = y;         // + (rand()%10 - 5);
-                id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1118, 1,
-                                     "");
-                if ((md = (struct mob_data *) map_id2bl (id)) != NULL)
-                {
-                    md->master_id = sd->bl.id;
-                    md->hp = 2210 + skilllv * 200;
-                    md->state.special_mob_ai = 1;
-                    md->deletetimer =
-                        add_timer (gettick () +
-                                   skill_get_time (skillid, skilllv),
-                                   mob_timer_delete, id, 0);
-                }
-                clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
-            }
-            break;
-        case AM_SPHEREMINE:    // スフィアーマイン
-            if (sd)
-            {
-                int  mx, my, id = 0;
-                struct mob_data *md;
-
-                mx = x;         // + (rand()%10 - 5);
-                my = y;         // + (rand()%10 - 5);
-                id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1142, 1,
-                                     "");
-                if ((md = (struct mob_data *) map_id2bl (id)) != NULL)
-                {
-                    md->master_id = sd->bl.id;
-                    md->hp = 1000 + skilllv * 200;
-                    md->state.special_mob_ai = 2;
-                    md->deletetimer =
-                        add_timer (gettick () +
-                                   skill_get_time (skillid, skilllv),
-                                   mob_timer_delete, id, 0);
-                }
-                clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
-            }
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スキル使用(詠唱完了、map指定)
- *------------------------------------------
- */
-int skill_castend_map (struct map_session_data *sd, int skill_num,
-                       const char *map)
-{
-    int  x = 0, y = 0;
-
-    nullpo_retr (0, sd);
-    if (sd->bl.prev == NULL || pc_isdead (sd))
-        return 0;
-
-    if (sd->opt1 > 0 || sd->status.option & 2)
-        return 0;
-    //スキルが使えない状態異常中
-    if (sd->sc_data)
-    {
-        if (sd->sc_data[SC_DIVINA].timer != -1 ||
-            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
-            sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
-            sd->sc_data[SC_STEELBODY].timer != -1 ||
-            sd->sc_data[SC_DANCING].timer != -1 ||
-            sd->sc_data[SC_BERSERK].timer != -1)
-            return 0;
-    }
-
-    if (skill_num != sd->skillid)   /* 不正パケットらしい */
-        return 0;
-
-    pc_stopattack (sd);
-
-    if (battle_config.pc_skill_log)
-        printf ("PC %d skill castend skill =%d map=%s\n", sd->bl.id,
-                skill_num, map);
-    pc_stop_walking (sd, 0);
-
-    if (strcmp (map, "cancel") == 0)
-        return 0;
-
-    switch (skill_num)
-    {
-        case AL_TELEPORT:      /* テレポート */
-            if (strcmp (map, "Random") == 0)
-                pc_randomwarp (sd, 3);
-            else
-                pc_setpos (sd, sd->status.save_point.map,
-                           sd->status.save_point.x, sd->status.save_point.y,
-                           3);
-            break;
-
-        case AL_WARP:          /* ワープポータル */
-        {
-            const struct point *p[] = {
-                &sd->status.save_point, &sd->status.memo_point[0],
-                &sd->status.memo_point[1], &sd->status.memo_point[2],
-            };
-            struct skill_unit_group *group;
-            int  i;
-            int  maxcount = 0;
-
-            if ((maxcount = skill_get_maxcount (sd->skillid)) > 0)
-            {
-                int  c;
-                for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
-                {
-                    if (sd->skillunit[i].alive_count > 0
-                        && sd->skillunit[i].skill_id == sd->skillid)
-                        c++;
-                }
-                if (c >= maxcount)
-                {
-                    clif_skill_fail (sd, sd->skillid, 0, 0);
-                    sd->canact_tick = gettick ();
-                    sd->canmove_tick = gettick ();
-                    sd->skillitem = sd->skillitemlv = -1;
-                    return 0;
-                }
-            }
-
-            for (i = 0; i < sd->skilllv; i++)
-            {
-                if (strcmp (map, p[i]->map) == 0)
-                {
-                    x = p[i]->x;
-                    y = p[i]->y;
-                    break;
-                }
-            }
-            if (x == 0 || y == 0)   /* 不正パケット? */
-                return 0;
-
-            if (!skill_check_condition (sd, 3))
-                return 0;
-            if ((group =
-                 skill_unitsetting (&sd->bl, sd->skillid, sd->skilllv,
-                                    sd->skillx, sd->skilly, 0)) == NULL)
-                return 0;
-            CREATE (group->valstr, char, 24);
-            memcpy (group->valstr, map, 24);
-            group->val2 = (x << 16) | y;
-        }
-            break;
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニット設定処理
- *------------------------------------------
- */
-struct skill_unit_group *skill_unitsetting (struct block_list *src,
-                                            int skillid, int skilllv, int x,
-                                            int y, int flag)
-{
-    struct skill_unit_group *group;
-    int  i, count = 1, limit = 10000, val1 = 0, val2 = 0;
-    int  target = BCT_ENEMY, interval = 1000, range = 0;
-    int  dir = 0, aoe_diameter = 0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
-
-    nullpo_retr (0, src);
-
-    switch (skillid)
-    {                           /* 設定 */
-
-        case MG_SAFETYWALL:    /* セイフティウォール */
-            limit = skill_get_time (skillid, skilllv);
-            val2 = skilllv + 1;
-            interval = -1;
-            target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL;
-            break;
-
-        case MG_FIREWALL:      /* ファイヤーウォール */
-            if (src->x == x && src->y == y)
-                dir = 2;
-            else
-                dir = map_calc_dir (src, x, y);
-            if (dir & 1)
-                count = 5;
-            else
-                count = 3;
-            limit = skill_get_time (skillid, skilllv);
-            val2 = 4 + skilllv;
-            interval = 1;
-            break;
-
-        case AL_PNEUMA:        /* ニューマ */
-            limit = skill_get_time (skillid, skilllv);
-            interval = -1;
-            target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL;
-            count = 9;
-            break;
-
-        case AL_WARP:          /* ワープポータル */
-            target = BCT_ALL;
-            val1 = skilllv + 6;
-            if (flag == 0)
-                limit = 2000;
-            else
-                limit = skill_get_time (skillid, skilllv);
-            break;
-
-        case PR_SANCTUARY:     /* サンクチュアリ */
-            count = 21;
-            limit = skill_get_time (skillid, skilllv);
-            val1 = skilllv + 3;
-            val2 = (skilllv > 6) ? 777 : skilllv * 100;
-            target = BCT_ALL;
-            range = 1;
-            break;
-
-        case PR_MAGNUS:        /* マグヌスエクソシズム */
-            count = 33;
-            limit = skill_get_time (skillid, skilllv);
-            interval = 3000;
-            break;
-
-        case WZ_FIREPILLAR:    /* ファイアーピラー */
-            if (flag == 0)
-                limit = skill_get_time (skillid, skilllv);
-            else
-                limit = 1000;
-            interval = 2000;
-            val1 = skilllv + 2;
-            range = 1;
-            break;
-
-        case MG_THUNDERSTORM:  /* サンダーストーム */
-            limit = 500;
-            range = 1;
-            break;
-
-        case WZ_FROSTNOVA:     /* フロストノヴァ */
-            limit = 500;
-            range = 5;
-            break;
-        case WZ_HEAVENDRIVE:   /* ヘヴンズドライブ */
-            limit = 500;
-            range = 2;
-            break;
-
-        case WZ_METEOR:        /* メテオストーム */
-            limit = 500;
-            range = 3;
-            break;
-
-        case WZ_SIGHTRASHER:
-            limit = 500;
-            count = 41;
-            break;
-
-        case WZ_VERMILION:     /* ロードオブヴァーミリオン */
-            limit = 4100;
-            interval = 1000;
-            range = 6;
-            break;
-
-        case WZ_ICEWALL:       /* アイスウォール */
-            limit = skill_get_time (skillid, skilllv);
-            count = 5;
-            break;
-
-        case WZ_STORMGUST:     /* ストームガスト */
-            limit = 4600;
-            interval = 450;
-            range = 5;
-            break;
-
-        case WZ_QUAGMIRE:      /* クァグマイア */
-            limit = skill_get_time (skillid, skilllv);
-            interval = 200;
-            count = 25;
-            break;
-
-        case HT_SKIDTRAP:      /* スキッドトラップ */
-        case HT_LANDMINE:      /* ランドマイン */
-        case HT_ANKLESNARE:    /* アンクルスネア */
-        case HT_SANDMAN:       /* サンドマン */
-        case PF_SPIDERWEB:     /* スパイダーウェッブ */
-        case HT_FLASHER:       /* フラッシャー */
-        case HT_FREEZINGTRAP:  /* フリージングトラップ */
-        case HT_BLASTMINE:     /* ブラストマイン */
-        case HT_CLAYMORETRAP:  /* クレイモアートラップ */
-            limit = skill_get_time (skillid, skilllv);
-            range = 1;
-            break;
-
-        case HT_TALKIEBOX:     /* トーキーボックス */
-            limit = skill_get_time (skillid, skilllv);
-            range = 1;
-            target = BCT_ALL;
-            break;
-
-        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
-            limit = skill_get_time (skillid, skilllv);
-            range = 1;
-            val1 = skilllv * 15 + 10;
-            break;
-
-        case AS_VENOMDUST:     /* ベノムダスト */
-            limit = skill_get_time (skillid, skilllv);
-            interval = 1000;
-            count = 5;
-            break;
-
-        case CR_GRANDCROSS:    /* グランドクロス */
-            count = 29;
-            limit = 1000;
-            interval = 300;
-            break;
-
-        case SA_VOLCANO:       /* ボルケーノ */
-        case SA_DELUGE:        /* デリュージ */
-        case SA_VIOLENTGALE:   /* バイオレントゲイル */
-            limit = skill_get_time (skillid, skilllv);
-            count = skilllv <= 2 ? 25 : (skilllv <= 4 ? 49 : 81);
-            target = BCT_ALL;
-            break;
-
-        case SA_LANDPROTECTOR: /* グランドクロス */
-            limit = skill_get_time (skillid, skilllv);  // changed to get duration from cast_db (moonsoul)
-            val1 = skilllv * 15 + 10;
-            aoe_diameter = skilllv + skilllv % 2 + 5;
-            target = BCT_ALL;
-            count = aoe_diameter * aoe_diameter;    // -- this will not function if changed to ^2 (moonsoul)
-            break;
-
-        case BD_LULLABY:       /* 子守唄 */
-        case BD_ETERNALCHAOS:  /* エターナルカオス */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-            count = 81;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_ALL;
-            break;
-        case BD_RICHMANKIM:
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-            count = 81;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_PARTY;
-            break;
-
-        case BA_WHISTLE:       /* 口笛 */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      BA_MUSICALLESSON) + 1) >> 1;
-            val2 = ((battle_get_agi (src) / 10) & 0xffff) << 16;
-            val2 |= (battle_get_luk (src) / 10) & 0xffff;
-            break;
-        case DC_HUMMING:       /* ハミング */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      DC_DANCINGLESSON) + 1) >> 1;
-            val2 = battle_get_dex (src) / 10;
-            break;
-
-        case BA_DISSONANCE:    /* 不協和音 */
-        case DC_UGLYDANCE:     /* 自分勝手なダンス */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_ENEMY;
-            break;
-
-        case DC_DONTFORGETME:  /* 私を忘れないで… */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_ENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      DC_DANCINGLESSON) + 1) >> 1;
-            val2 = ((battle_get_str (src) / 20) & 0xffff) << 16;
-            val2 |= (battle_get_agi (src) / 10) & 0xffff;
-            break;
-        case BA_POEMBRAGI:     /* ブラギの詩 */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    pc_checkskill ((struct map_session_data *) src,
-                                   BA_MUSICALLESSON);
-            val2 = ((battle_get_dex (src) / 10) & 0xffff) << 16;
-            val2 |= (battle_get_int (src) / 5) & 0xffff;
-            break;
-        case BA_APPLEIDUN:     /* イドゥンの林檎 */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    ((pc_checkskill
-                      ((struct map_session_data *) src,
-                       BA_MUSICALLESSON)) & 0xffff) << 16;
-            else
-                val1 = 0;
-            val1 |= (battle_get_vit (src)) & 0xffff;
-            val2 = 0;           //回復用タイムカウンタ(6秒毎に1増加)
-            break;
-        case DC_SERVICEFORYOU: /* サービスフォーユー */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_PARTY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      DC_DANCINGLESSON) + 1) >> 1;
-            val2 = battle_get_int (src) / 10;
-            break;
-        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      BA_MUSICALLESSON) + 1) >> 1;
-            val2 = battle_get_agi (src) / 20;
-            break;
-        case DC_FORTUNEKISS:   /* 幸運のキス */
-            count = 49;
-            limit = skill_get_time (skillid, skilllv);
-            range = 5;
-            target = BCT_NOENEMY;
-            if (src->type == BL_PC)
-                val1 =
-                    (pc_checkskill
-                     ((struct map_session_data *) src,
-                      DC_DANCINGLESSON) + 1) >> 1;
-            val2 = battle_get_luk (src) / 10;
-            break;
-        case AM_DEMONSTRATION: /* デモンストレーション */
-            limit = skill_get_time (skillid, skilllv);
-            interval = 1000;
-            range = 1;
-            target = BCT_ENEMY;
-            break;
-        case WE_CALLPARTNER:   /* あなたに逢いたい */
-            limit = skill_get_time (skillid, skilllv);
-            range = -1;
-            break;
-
-        case HP_BASILICA:      /* バジリカ */
-            limit = skill_get_time (skillid, skilllv);
-            target = BCT_ALL;
-            range = 3;
-            //Fix to prevent the priest from walking while Basilica is up.
-            battle_stopwalking (src, 1);
-            skill_status_change_start (src, SC_ANKLE, skilllv, 0, 0, 0, limit,
-                                       0);
-            break;
-        case PA_GOSPEL:        /* ゴスペル */
-            count = 49;
-            target = BCT_PARTY;
-            limit = skill_get_time (skillid, skilllv);
-            break;
-        case PF_FOGWALL:       /* フォグウォール */
-            count = 15;
-            limit = skill_get_time (skillid, skilllv);
-            break;
-        case RG_GRAFFITI:      /* Graffiti */
-            count = 1;          // Leave this at 1 [Valaris]
-            limit = 600000;     // Time length [Valaris]
-            break;
-    };
-
-    nullpo_retr (NULL, group =
-                 skill_initunitgroup (src, count, skillid, skilllv,
-                                      skill_get_unit_id (skillid, flag & 1)));
-    group->limit = limit;
-    group->val1 = val1;
-    group->val2 = val2;
-    group->target_flag = target;
-    group->interval = interval;
-    group->range = range;
-    if (skillid == HT_TALKIEBOX || skillid == RG_GRAFFITI)
-    {
-        CREATE (group->valstr, char, 80);
-        memcpy (group->valstr, talkie_mes, 80);
-    }
-    for (i = 0; i < count; i++)
-    {
-        struct skill_unit *unit;
-        int  ux = x, uy = y, val1 = skilllv, val2 = 0, limit =
-            group->limit, alive = 1;
-        int  range = group->range;
-        switch (skillid)
-        {                       /* 設定 */
-            case AL_PNEUMA:    /* ニューマ */
-            {
-                static const int dx[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
-                static const int dy[9] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-            case MG_FIREWALL:  /* ファイヤーウォール */
-            {
-                if (dir & 1)
-                {               /* 斜め配置 */
-                    static const int dx[][5] = {
-                        {1, 1, 0, 0, -1}, {-1, -1, 0, 0, 1},
-                    }, dy[][5] =
-                    {
-                        {
-                        1, 0, 0, -1, -1},
-                        {
-                    1, 0, 0, -1, -1},};
-                    ux += dx[(dir >> 1) & 1][i];
-                    uy += dy[(dir >> 1) & 1][i];
-                }
-                else
-                {               /* 上下配置 */
-                    if (dir % 4 == 0)   /* 上下 */
-                        ux += i - 1;
-                    else        /* 左右 */
-                        uy += i - 1;
-                }
-                val2 = group->val2;
-            }
-                break;
-
-            case PR_SANCTUARY: /* サンクチュアリ */
-            {
-                static const int dx[] = {
-                    -1, 0, 1, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1,
-                    2, -1, 0, 1
-                };
-                static const int dy[] = {
-                    -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
-                    1, 2, 2, 2,
-                };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-
-            case PR_MAGNUS:    /* マグヌスエクソシズム */
-            {
-                static const int dx[] =
-                    { -1, 0, 1, -1, 0, 1, -3, -2, -1, 0, 1, 2, 3,
-                    -3, -2, -1, 0, 1, 2, 3, -3, -2, -1, 0, 1, 2, 3, -1, 0, 1,
-                    -1, 0, 1,
-                };
-                static const int dy[] = {
-                    -3, -3, -3, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1,
-                    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3
-                };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-
-            case WZ_SIGHTRASHER:
-            {
-                static const int dx[] = {
-                    -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5, -4,
-                    -3, -2, -1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3,
-                    0, 3, -4, 0, 4, -5, 0, 5
-                };
-                static const int dy[] = {
-                    -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1,
-                    -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
-                    3, 3, 3, 4, 4, 4, 5, 5, 5
-                };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-
-            case WZ_ICEWALL:   /* アイスウォール */
-            {
-                static const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
-                static const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
-                if (skilllv <= 1)
-                    val1 = 500;
-                else
-                    val1 = 200 + 200 * skilllv;
-                if (src->x == x && src->y == y)
-                    dir = 2;
-                else
-                    dir = map_calc_dir (src, x, y);
-                ux += (2 - i) * diry[dir];
-                uy += (i - 2) * dirx[dir];
-            }
-                break;
-
-            case WZ_QUAGMIRE:  /* クァグマイア */
-                ux += (i % 5 - 2);
-                uy += (i / 5 - 2);
-                if (i == 12)
-                    range = 2;
-                else
-                    range = -1;
-
-                break;
-
-            case AS_VENOMDUST: /* ベノムダスト */
-            {
-                static const int dx[] = { -1, 0, 0, 0, 1 };
-                static const int dy[] = { 0, -1, 0, 1, 0 };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-
-            case CR_GRANDCROSS:    /* グランドクロス */
-            {
-                static const int dx[] = {
-                    0, 0, -1, 0, 1, -2, -1, 0, 1, 2, -4, -3, -2, -1, 0, 1, 2,
-                    3, 4, -2, -1, 0, 1, 2, -1, 0, 1, 0, 0,
-                };
-                static const int dy[] = {
-                    -4, -3, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0,
-                    0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4,
-                };
-                ux += dx[i];
-                uy += dy[i];
-            }
-                break;
-            case SA_VOLCANO:   /* ボルケーノ */
-            case SA_DELUGE:    /* デリュージ */
-            case SA_VIOLENTGALE:   /* バイオレントゲイル */
-            {
-                int  u_range = 0, central = 0;
-                if (skilllv <= 2)
-                {
-                    u_range = 2;
-                    central = 12;
-                }
-                else if (skilllv <= 4)
-                {
-                    u_range = 3;
-                    central = 24;
-                }
-                else if (skilllv >= 5)
-                {
-                    u_range = 4;
-                    central = 40;
-                }
-                ux += (i % (u_range * 2 + 1) - u_range);
-                uy += (i / (u_range * 2 + 1) - u_range);
-
-                if (i == central)
-                    range = u_range;    //中央のユニットの効果範囲は全範囲
-                else
-                    range = -1; //中央以外のユニットは飾り
-            }
-                break;
-            case SA_LANDPROTECTOR: /* ランドプロテクター */
-            {
-                int  u_range = 0;
-
-                if (skilllv <= 2)
-                    u_range = 3;
-                else if (skilllv <= 4)
-                    u_range = 4;
-                else if (skilllv >= 5)
-                    u_range = 5;
-
-                ux += (i % (u_range * 2 + 1) - u_range);
-                uy += (i / (u_range * 2 + 1) - u_range);
-
-                range = 0;
-            }
-                break;
-
-                /* ダンスなど */
-            case BD_LULLABY:   /* 子守歌 */
-            case BD_RICHMANKIM:    /* ニヨルドの宴 */
-            case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-            case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-            case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-            case BD_ROKISWEIL: /* ロキの叫び */
-            case BD_INTOABYSS: /* 深淵の中に */
-            case BD_SIEGFRIED: /* 不死身のジークフリード */
-                ux += (i % 9 - 4);
-                uy += (i / 9 - 4);
-                if (i == 40)
-                    range = 4;  /* 中心の場合は範囲を4にオーバーライド */
-                else
-                    range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */
-                break;
-            case BA_DISSONANCE:    /* 不協和音 */
-            case BA_WHISTLE:   /* 口笛 */
-            case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
-            case BA_POEMBRAGI: /* ブラギの詩 */
-            case BA_APPLEIDUN: /* イドゥンの林檎 */
-            case DC_UGLYDANCE: /* 自分勝手なダンス */
-            case DC_HUMMING:   /* ハミング */
-            case DC_DONTFORGETME:  /* 私を忘れないで… */
-            case DC_FORTUNEKISS:   /* 幸運のキス */
-            case DC_SERVICEFORYOU: /* サービスフォーユー */
-                ux += (i % 7 - 3);
-                uy += (i / 7 - 3);
-                if (i == 40)
-                    range = 4;  /* 中心の場合は範囲を4にオーバーライド */
-                else
-                    range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */
-                break;
-            case PA_GOSPEL:    /* ゴスペル */
-                ux += (i % 7 - 3);
-                uy += (i / 7 - 3);
-                break;
-            case PF_FOGWALL:   /* フォグウォール */
-                ux += (i % 5 - 2);
-                uy += (i / 5 - 1);
-                break;
-            case RG_GRAFFITI:  /* Graffiti [Valaris] */
-                ux += (i % 5 - 2);
-                uy += (i / 5 - 2);
-                break;
-        }
-        //直上スキルの場合設置座標上にランドプロテクターがないかチェック
-        if (range <= 0)
-            map_foreachinarea (skill_landprotector, src->m, ux, uy, ux, uy,
-                               BL_SKILL, skillid, &alive);
-
-        if (skillid == WZ_ICEWALL && alive)
-        {
-            val2 = map_getcell (src->m, ux, uy);
-            if (val2 == 5 || val2 == 1)
-                alive = 0;
-            else
-            {
-                map_setcell (src->m, ux, uy, 5);
-                clif_changemapcell (src->m, ux, uy, 5, 0);
-            }
-        }
-
-        if (alive)
-        {
-            nullpo_retr (NULL, unit = skill_initunit (group, i, ux, uy));
-            unit->val1 = val1;
-            unit->val2 = val2;
-            unit->limit = limit;
-            unit->range = range;
-        }
-    }
-    return group;
-}
-
-/*==========================================
- * スキルユニットの発動イベント
- *------------------------------------------
- */
-int skill_unit_onplace (struct skill_unit *src, struct block_list *bl,
-                        unsigned int tick)
-{
-    struct skill_unit_group *sg;
-    struct block_list *ss;
-    struct skill_unit_group_tickset *ts;
-    struct map_session_data *srcsd = NULL;
-    int  diff, goflag, splash_count = 0;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, bl);
-
-    if (bl->prev == NULL || !src->alive
-        || (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl)))
-        return 0;
-
-    nullpo_retr (0, sg = src->group);
-    nullpo_retr (0, ss = map_id2bl (sg->src_id));
-
-    if (ss->type == BL_PC)
-        nullpo_retr (0, srcsd = (struct map_session_data *) ss);
-    if (srcsd && srcsd->chatID)
-        return 0;
-
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-        return 0;
-    nullpo_retr (0, ts = skill_unitgrouptickset_search (bl, sg->group_id));
-    diff = DIFF_TICK (tick, ts->tick);
-    goflag = (diff > sg->interval || diff < 0);
-    if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit)  // 重なっていたら3HITしない
-        goflag = (diff > sg->interval * map_count_oncell (bl->m, bl->x, bl->y)
-                  || diff < 0);
-
-    //対象がLP上に居る場合は無効
-    map_foreachinarea (skill_landprotector, bl->m, bl->x, bl->y, bl->x, bl->y,
-                       BL_SKILL, 0, &goflag);
-
-    if (!goflag)
-        return 0;
-    ts->tick = tick;
-    ts->group_id = sg->group_id;
-
-    switch (sg->unit_id)
-    {
-        case 0x83:             /* サンクチュアリ */
-        {
-            int  race = battle_get_race (bl);
-            int  damage_flag =
-                (battle_check_undead (race, battle_get_elem_type (bl))
-                 || race == 6) ? 1 : 0;
-
-            if (battle_get_hp (bl) >= battle_get_max_hp (bl) && !damage_flag)
-                break;
-
-            if ((sg->val1--) <= 0)
-            {
-                skill_delunitgroup (sg);
-                return 0;
-            }
-            if (!damage_flag)
-            {
-                int  heal = sg->val2;
-                if (bl->type == BL_PC
-                    && ((struct map_session_data *) bl)->
-                    special_state.no_magic_damage)
-                    heal = 0;   /* 黄金蟲カード(ヒール量0) */
-                clif_skill_nodamage (&src->bl, bl, AL_HEAL, heal, 1);
-                battle_heal (NULL, bl, heal, 0, 0);
-            }
-            else
-                skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
-                              sg->skill_lv, tick, 0);
-        }
-            break;
-
-        case 0x84:             /* マグヌスエクソシズム */
-        {
-            int  race = battle_get_race (bl);
-            int  damage_flag =
-                (battle_check_undead (race, battle_get_elem_type (bl))
-                 || race == 6) ? 1 : 0;
-
-            if (!damage_flag)
-                return 0;
-            skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
-                          sg->skill_lv, tick, 0);
-        }
-            break;
-
-        case 0x85:             /* ニューマ */
-        {
-            struct skill_unit *unit2;
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SC_PNEUMA;
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
-                                           0, 0, 0, 0);
-            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
-                     && unit2 != src)
-            {
-                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
-                    skill_status_change_start (bl, type, sg->skill_lv,
-                                               (int) src, 0, 0, 0, 0);
-                ts->tick -= sg->interval;
-            }
-        }
-            break;
-        case 0x7e:             /* セイフティウォール */
-        {
-            struct skill_unit *unit2;
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SC_SAFETYWALL;
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
-                                           0, 0, 0, 0);
-            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
-                     && unit2 != src)
-            {
-                if (sg->val1 < unit2->group->val1)
-                    skill_status_change_start (bl, type, sg->skill_lv,
-                                               (int) src, 0, 0, 0, 0);
-                ts->tick -= sg->interval;
-            }
-        }
-            break;
-
-        case 0x86:             /* ロードオブヴァーミリオン(&ストームガスト &グランドクロス) */
-            skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
-                          sg->skill_lv, tick, 0);
-            break;
-
-        case 0x7f:             /* ファイヤーウォール */
-            if ((src->val2--) > 0)
-                skill_attack (BF_MAGIC, ss, &src->bl, bl,
-                              sg->skill_id, sg->skill_lv, tick, 0);
-            if (src->val2 <= 0)
-                skill_delunit (src);
-            break;
-
-        case 0x87:             /* ファイアーピラー(発動前) */
-            skill_delunit (src);
-            skill_unitsetting (ss, sg->skill_id, sg->skill_lv, src->bl.x,
-                               src->bl.y, 1);
-            break;
-
-        case 0x88:             /* ファイアーピラー(発動後) */
-            if (DIFF_TICK (tick, sg->tick) < 150)
-                skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
-                              sg->skill_lv, tick, 0);
-            break;
-
-        case 0x90:             /* スキッドトラップ */
-        {
-            int  i, c = skill_get_blewcount (sg->skill_id, sg->skill_lv);
-            if (map[bl->m].flag.gvg)
-                c = 0;
-            for (i = 0; i < c; i++)
-                skill_blown (&src->bl, bl, 1 | 0x30000);
-            sg->unit_id = 0x8c;
-            clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
-        }
-            break;
-
-        case 0x93:             /* ランドマイン */
-            skill_attack (BF_MISC, ss, &src->bl, bl, sg->skill_id,
-                          sg->skill_lv, tick, 0);
-            sg->unit_id = 0x8c;
-            clif_changelook (&src->bl, LOOK_BASE, 0x88);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
-            break;
-
-        case 0x8f:             /* ブラストマイン */
-        case 0x94:             /* ショックウェーブトラップ */
-        case 0x95:             /* サンドマン */
-        case 0x96:             /* フラッシャー */
-        case 0x97:             /* フリージングトラップ */
-        case 0x98:             /* クレイモアートラップ */
-            map_foreachinarea (skill_count_target, src->bl.m,
-                               src->bl.x - src->range, src->bl.y - src->range,
-                               src->bl.x + src->range, src->bl.y + src->range,
-                               0, &src->bl, &splash_count);
-            map_foreachinarea (skill_trap_splash, src->bl.m,
-                               src->bl.x - src->range, src->bl.y - src->range,
-                               src->bl.x + src->range, src->bl.y + src->range,
-                               0, &src->bl, tick, splash_count);
-            sg->unit_id = 0x8c;
-            clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
-            break;
-
-        case 0x91:             /* アンクルスネア */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            if (sg->val2 == 0 && sc_data && sc_data[SC_ANKLE].timer == -1)
-            {
-                int  moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE
-                                  || bl->y / BLOCK_SIZE !=
-                                  src->bl.y / BLOCK_SIZE);
-                int  sec = skill_get_time2 (sg->skill_id,
-                                            sg->skill_lv) -
-                    (double) battle_get_agi (bl) * 0.1;
-                if (battle_get_mode (bl) & 0x20)
-                    sec = sec / 5;
-                battle_stopwalking (bl, 1);
-                skill_status_change_start (bl, SC_ANKLE, sg->skill_lv, 0, 0,
-                                           0, sec, 0);
-
-                if (moveblock)
-                    map_delblock (bl);
-                bl->x = src->bl.x;
-                bl->y = src->bl.y;
-                if (moveblock)
-                    map_addblock (bl);
-                if (bl->type == BL_MOB)
-                    clif_fixmobpos ((struct mob_data *) bl);
-                else
-                    clif_fixpos (bl);
-                clif_01ac (&src->bl);
-                sg->limit = DIFF_TICK (tick, sg->tick) + sec;
-                sg->val2 = bl->id;
-            }
-        }
-            break;
-
-        case 0x80:             /* ワープポータル(発動後) */
-            if (bl->type == BL_PC)
-            {
-                struct map_session_data *sd = (struct map_session_data *) bl;
-                if (sd && src->bl.m == bl->m && src->bl.x == bl->x
-                    && src->bl.y == bl->y && src->bl.x == sd->to_x
-                    && src->bl.y == sd->to_y)
-                {
-                    if (battle_config.chat_warpportal || !sd->chatID)
-                    {
-                        if ((sg->val1--) > 0)
-                        {
-                            pc_setpos (sd, sg->valstr, sg->val2 >> 16,
-                                       sg->val2 & 0xffff, 3);
-                            if (sg->src_id == bl->id
-                                || (strcmp (map[src->bl.m].name, sg->valstr)
-                                    == 0 && src->bl.x == (sg->val2 >> 16)
-                                    && src->bl.y == (sg->val2 & 0xffff)))
-                                skill_delunitgroup (sg);
-                        }
-                        else
-                            skill_delunitgroup (sg);
-                    }
-                }
-            }
-            else if (bl->type == BL_MOB && battle_config.mob_warpportal)
-            {
-                int  m = map_mapname2mapid (sg->valstr);
-                struct mob_data *md;
-                md = (struct mob_data *) bl;
-                mob_warp ((struct mob_data *) bl, m, sg->val2 >> 16,
-                          sg->val2 & 0xffff, 3);
-            }
-            break;
-
-        case 0x8e:             /* クァグマイア */
-        {
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (bl->type == BL_PC
-                && ((struct map_session_data *) bl)->
-                special_state.no_magic_damage)
-                break;
-            if (battle_get_sc_data (bl)[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
-                                           0, 0,
-                                           skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv), 0);
-        }
-            break;
-        case 0x92:             /* ベノムダスト */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
-                                           0, 0,
-                                           skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv), 0);
-        }
-            break;
-        case 0x9a:             /* ボルケーノ */
-        case 0x9b:             /* デリュージ */
-        case 0x9c:             /* バイオレントゲイル */
-        {
-            struct skill_unit *unit2;
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
-                                           0, 0,
-                                           skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv), 0);
-            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
-                     && unit2 != src)
-            {
-                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
-                    skill_status_change_start (bl, type, sg->skill_lv,
-                                               (int) src, 0, 0,
-                                               skill_get_time2 (sg->skill_id,
-                                                                sg->skill_lv),
-                                               0);
-                ts->tick -= sg->interval;
-            }
-        } break;
-
-        case 0x9e:             /* 子守唄 */
-        case 0x9f:             /* ニヨルドの宴 */
-        case 0xa0:             /* 永遠の混沌 */
-        case 0xa1:             /* 戦太鼓の響き */
-        case 0xa2:             /* ニーベルングの指輪 */
-        case 0xa3:             /* ロキの叫び */
-        case 0xa4:             /* 深淵の中に */
-        case 0xa5:             /* 不死身のジークフリード */
-        case 0xa6:             /* 不協和音 */
-        case 0xa7:             /* 口笛 */
-        case 0xa8:             /* 夕陽のアサシンクロス */
-        case 0xa9:             /* ブラギの詩 */
-        case 0xab:             /* 自分勝手なダンス */
-        case 0xac:             /* ハミング */
-        case 0xad:             /* 私を忘れないで… */
-        case 0xae:             /* 幸運のキス */
-        case 0xaf:             /* サービスフォーユー */
-        case 0xb4:
-        {
-            struct skill_unit *unit2;
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sg->src_id == bl->id)
-                break;
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv, sg->val1,
-                                           sg->val2, (int) src,
-                                           skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv), 0);
-            else if ((unit2 = (struct skill_unit *) sc_data[type].val4)
-                     && unit2 != src)
-            {
-                if (unit2->group
-                    && DIFF_TICK (sg->tick, unit2->group->tick) > 0)
-                    skill_status_change_start (bl, type, sg->skill_lv,
-                                               sg->val1, sg->val2, (int) src,
-                                               skill_get_time2 (sg->skill_id,
-                                                                sg->skill_lv),
-                                               0);
-                ts->tick -= sg->interval;
-            }
-        } break;
-
-        case 0xaa:             /* イドゥンの林檎 */
-        {
-            struct skill_unit *unit2;
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sg->src_id == bl->id)
-                break;
-            if (sc_data && sc_data[type].timer == -1)
-                skill_status_change_start (bl, type, sg->skill_lv,
-                                           (sg->val1) >> 16,
-                                           (sg->val1) & 0xffff, (int) src,
-                                           skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv), 0);
-            else if ((unit2 = (struct skill_unit *) sc_data[type].val4)
-                     && unit2 != src)
-            {
-                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
-                    skill_status_change_start (bl, type, sg->skill_lv,
-                                               (sg->val1) >> 16,
-                                               (sg->val1) & 0xffff, (int) src,
-                                               skill_get_time2 (sg->skill_id,
-                                                                sg->skill_lv),
-                                               0);
-                ts->tick -= sg->interval;
-            }
-        } break;
-
-        case 0xb1:             /* デモンストレーション */
-            skill_attack (BF_WEAPON, ss, &src->bl, bl, sg->skill_id,
-                          sg->skill_lv, tick, 0);
-            if (bl->type == BL_PC && MRAND (100) < sg->skill_lv
-                && battle_config.equipment_breaking)
-                pc_breakweapon ((struct map_session_data *) bl);
-            break;
-        case 0x99:             /* トーキーボックス */
-            if (sg->src_id == bl->id)   //自分が踏んでも発動しない
-                break;
-            if (sg->val2 == 0)
-            {
-                clif_talkiebox (&src->bl, sg->valstr);
-                sg->unit_id = 0x8c;
-                clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
-                sg->limit = DIFF_TICK (tick, sg->tick) + 5000;
-                sg->val2 = -1;  //踏んだ
-            }
-            break;
-        case 0xb2:             /* あなたを_会いたいです */
-        case 0xb3:             /* ゴスペル */
-        case 0xb6:             /* フォグウォール */
-            //とりあえず何もしない
-            break;
-
-        case 0xb7:             /* スパイダーウェッブ */
-            if (sg->val2 == 0)
-            {
-                int  moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE
-                                  || bl->y / BLOCK_SIZE !=
-                                  src->bl.y / BLOCK_SIZE);
-                skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv,
-                                         BF_MISC, tick);
-                if (moveblock)
-                    map_delblock (bl);
-                bl->x = (&src->bl)->x;
-                bl->y = (&src->bl)->y;
-                if (moveblock)
-                    map_addblock (bl);
-                if (bl->type == BL_MOB)
-                    clif_fixmobpos ((struct mob_data *) bl);
-                else
-                    clif_fixpos (bl);
-                clif_01ac (&src->bl);
-                sg->limit =
-                    DIFF_TICK (tick,
-                               sg->tick) + skill_get_time2 (sg->skill_id,
-                                                            sg->skill_lv);
-                sg->val2 = bl->id;
-            }
-            break;
-
-/*	default:
-		if(battle_config.error_log)
-			printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
-		break;*/
-    }
-    if (bl->type == BL_MOB && ss != bl) /* スキル使用条件のMOBスキル */
-    {
-        if (battle_config.mob_changetarget_byskill == 1)
-        {
-            int  target = ((struct mob_data *) bl)->target_id;
-            if (ss->type == BL_PC)
-                ((struct mob_data *) bl)->target_id = ss->id;
-            mobskill_use ((struct mob_data *) bl, tick,
-                          MSC_SKILLUSED | (sg->skill_id << 16));
-            ((struct mob_data *) bl)->target_id = target;
-        }
-        else
-            mobskill_use ((struct mob_data *) bl, tick,
-                          MSC_SKILLUSED | (sg->skill_id << 16));
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニットから離脱する(もしくはしている)場合
- *------------------------------------------
- */
-int skill_unit_onout (struct skill_unit *src, struct block_list *bl,
-                      unsigned int tick)
-{
-    struct skill_unit_group *sg;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, bl);
-    nullpo_retr (0, sg = src->group);
-
-    if (bl->prev == NULL || !src->alive)
-        return 0;
-
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-        return 0;
-
-    switch (sg->unit_id)
-    {
-        case 0x7e:             /* セイフティウォール */
-        case 0x85:             /* ニューマ */
-        case 0x8e:             /* クァグマイア */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            int  type =
-                (sg->unit_id == 0x85) ? SC_PNEUMA :
-                ((sg->unit_id == 0x7e) ? SC_SAFETYWALL : SC_QUAGMIRE);
-            if ((type != SC_QUAGMIRE || bl->type != BL_MOB) &&
-                sc_data && sc_data[type].timer != -1
-                && ((struct skill_unit *) sc_data[type].val2) == src)
-            {
-                skill_status_change_end (bl, type, -1);
-            }
-        } break;
-
-        case 0x91:             /* アンクルスネア */
-        {
-            struct block_list *target = map_id2bl (sg->val2);
-            if (target && target == bl)
-            {
-                skill_status_change_end (bl, SC_ANKLE, -1);
-                sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
-            }
-        }
-            break;
-        case 0xb5:
-        case 0xb8:
-        {
-            struct block_list *target = map_id2bl (sg->val2);
-            if (target == bl)
-                skill_status_change_end (bl, SC_SPIDERWEB, -1);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
-        }
-            break;
-        case 0xb6:
-        {
-            struct block_list *target = map_id2bl (sg->val2);
-            if (target == bl)
-                skill_status_change_end (bl, SC_FOGWALL, -1);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
-        }
-            break;
-        case 0x9a:             /* ボルケーノ */
-        case 0x9b:             /* デリュージ */
-        case 0x9c:             /* バイオレントゲイル */
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            struct skill_unit *su;
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sc_data && sc_data[type].timer != -1
-                && (su = ((struct skill_unit *) sc_data[type].val2))
-                && su == src)
-            {
-                skill_status_change_end (bl, type, -1);
-            }
-        }
-            break;
-
-        case 0x9e:             /* 子守唄 */
-        case 0x9f:             /* ニヨルドの宴 */
-        case 0xa0:             /* 永遠の混沌 */
-        case 0xa1:             /* 戦太鼓の響き */
-        case 0xa2:             /* ニーベルングの指輪 */
-        case 0xa3:             /* ロキの叫び */
-        case 0xa4:             /* 深淵の中に */
-        case 0xa5:             /* 不死身のジークフリード */
-        case 0xa6:             /* 不協和音 */
-        case 0xa7:             /* 口笛 */
-        case 0xa8:             /* 夕陽のアサシンクロス */
-        case 0xa9:             /* ブラギの詩 */
-        case 0xaa:             /* イドゥンの林檎 */
-        case 0xab:             /* 自分勝手なダンス */
-        case 0xac:             /* ハミング */
-        case 0xad:             /* 私を忘れないで… */
-        case 0xae:             /* 幸運のキス */
-        case 0xaf:             /* サービスフォーユー */
-        case 0xb4:
-        {
-            struct status_change *sc_data = battle_get_sc_data (bl);
-            struct skill_unit *su;
-            int  type = SkillStatusChangeTable[sg->skill_id];
-            if (sc_data && sc_data[type].timer != -1
-                && (su = ((struct skill_unit *) sc_data[type].val4))
-                && su == src)
-            {
-                skill_status_change_end (bl, type, -1);
-            }
-        }
-            break;
-        case 0xb7:             /* スパイダーウェッブ */
-        {
-            struct block_list *target = map_id2bl (sg->val2);
-            if (target && target == bl)
-                skill_status_change_end (bl, SC_SPIDERWEB, -1);
-            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
-        }
-            break;
-
-/*	default:
-		if(battle_config.error_log)
-			printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
-		break;*/
-    }
-    skill_unitgrouptickset_delete (bl, sg->group_id);
-    return 0;
-}
-
-/*==========================================
- * スキルユニットの削除イベント
- *------------------------------------------
- */
-int skill_unit_ondelete (struct skill_unit *src, struct block_list *bl,
-                         unsigned int tick)
-{
-    struct skill_unit_group *sg;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, bl);
-    nullpo_retr (0, sg = src->group);
-
-    if (bl->prev == NULL || !src->alive)
-        return 0;
-
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-        return 0;
-
-    switch (sg->unit_id)
-    {
-        case 0x85:             /* ニューマ */
-        case 0x7e:             /* セイフティウォール */
-        case 0x8e:             /* クァグマイヤ */
-        case 0x9a:             /* ボルケーノ */
-        case 0x9b:             /* デリュージ */
-        case 0x9c:             /* バイオレントゲイル */
-        case 0x9e:             /* 子守唄 */
-        case 0x9f:             /* ニヨルドの宴 */
-        case 0xa0:             /* 永遠の混沌 */
-        case 0xa1:             /* 戦太鼓の響き */
-        case 0xa2:             /* ニーベルングの指輪 */
-        case 0xa3:             /* ロキの叫び */
-        case 0xa4:             /* 深淵の中に */
-        case 0xa5:             /* 不死身のジークフリード */
-        case 0xa6:             /* 不協和音 */
-        case 0xa7:             /* 口笛 */
-        case 0xa8:             /* 夕陽のアサシンクロス */
-        case 0xa9:             /* ブラギの詩 */
-        case 0xaa:             /* イドゥンの林檎 */
-        case 0xab:             /* 自分勝手なダンス */
-        case 0xac:             /* ハミング */
-        case 0xad:             /* 私を忘れないで… */
-        case 0xae:             /* 幸運のキス */
-        case 0xaf:             /* サービスフォーユー */
-        case 0xb4:
-            return skill_unit_onout (src, bl, tick);
-
-/*	default:
-		if(battle_config.error_log)
-			printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
-		break;*/
-    }
-    skill_unitgrouptickset_delete (bl, sg->group_id);
-    return 0;
-}
-
-/*==========================================
- * スキルユニットの限界イベント
- *------------------------------------------
- */
-int skill_unit_onlimit (struct skill_unit *src, unsigned int tick)
-{
-    struct skill_unit_group *sg;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, sg = src->group);
-
-    switch (sg->unit_id)
-    {
-        case 0x81:             /* ワープポータル(発動前) */
-        {
-            struct skill_unit_group *group =
-                skill_unitsetting (map_id2bl (sg->src_id), sg->skill_id,
-                                   sg->skill_lv,
-                                   src->bl.x, src->bl.y, 1);
-            if (group == NULL)
-                return 0;
-            CREATE (group->valstr, char, 24);
-            memcpy (group->valstr, sg->valstr, 24);
-            group->val2 = sg->val2;
-        }
-            break;
-
-        case 0x8d:             /* アイスウォール */
-            map_setcell (src->bl.m, src->bl.x, src->bl.y, src->val2);
-            clif_changemapcell (src->bl.m, src->bl.x, src->bl.y, src->val2,
-                                1);
-            break;
-        case 0xb2:             /* あなたに会いたい */
-        {
-            struct map_session_data *sd = NULL;
-            struct map_session_data *p_sd = NULL;
-            if ((sd =
-                 (struct map_session_data *) (map_id2bl (sg->src_id))) ==
-                NULL)
-                return 0;
-            if ((p_sd = pc_get_partner (sd)) == NULL)
-                return 0;
-
-            pc_setpos (p_sd, map[src->bl.m].name, src->bl.x, src->bl.y, 3);
-        }
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * スキルユニットのダメージイベント
- *------------------------------------------
- */
-int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl,
-                          int damage, unsigned int tick)
-{
-    struct skill_unit_group *sg;
-
-    nullpo_retr (0, src);
-    nullpo_retr (0, sg = src->group);
-
-    switch (sg->unit_id)
-    {
-        case 0x8d:             /* アイスウォール */
-            src->val1 -= damage;
-            break;
-        case 0x8f:             /* ブラストマイン */
-        case 0x98:             /* クレイモアートラップ */
-            skill_blown (bl, &src->bl, 2);  //吹き飛ばしてみる
-            break;
-        default:
-            damage = 0;
-            break;
-    }
-    return damage;
-}
-
-/*---------------------------------------------------------------------------- */
-
-/*==========================================
- * スキル使用(詠唱完了、場所指定)
- *------------------------------------------
- */
-void skill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ;
-    int  range, maxcount;
-
-    nullpo_retv (sd);
-
-    if (sd->bl.prev == NULL)
-        return;
-    if (sd->skilltimer != tid)  /* タイマIDの確認 */
-        return;
-    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) > 0)
-    {
-        sd->speed = sd->prev_speed;
-        clif_updatestatus (sd, SP_SPEED);
-    }
-    sd->skilltimer = -1;
-    if (pc_isdead (sd))
-    {
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-
-    if (battle_config.pc_skill_reiteration == 0)
-    {
-        range = -1;
-        switch (sd->skillid)
-        {
-            case MG_SAFETYWALL:
-            case WZ_FIREPILLAR:
-            case HT_SKIDTRAP:
-            case HT_LANDMINE:
-            case HT_ANKLESNARE:
-            case HT_SHOCKWAVE:
-            case HT_SANDMAN:
-            case HT_FLASHER:
-            case HT_FREEZINGTRAP:
-            case HT_BLASTMINE:
-            case HT_CLAYMORETRAP:
-            case HT_TALKIEBOX:
-            case AL_WARP:
-            case PF_SPIDERWEB: /* スパイダーウェッブ */
-            case RG_GRAFFITI:  /* グラフィティ */
-                range = 0;
-                break;
-            case AL_PNEUMA:
-                range = 1;
-                break;
-        }
-        if (range >= 0)
-        {
-            if (skill_check_unit_range
-                (sd->bl.m, sd->skillx, sd->skilly, range, sd->skillid) > 0)
-            {
-                clif_skill_fail (sd, sd->skillid, 0, 0);
-                sd->canact_tick = tick;
-                sd->canmove_tick = tick;
-                sd->skillitem = sd->skillitemlv = -1;
-                return;
-            }
-        }
-    }
-    if (battle_config.pc_skill_nofootset)
-    {
-        range = -1;
-        switch (sd->skillid)
-        {
-            case WZ_FIREPILLAR:
-            case HT_SKIDTRAP:
-            case HT_LANDMINE:
-            case HT_ANKLESNARE:
-            case HT_SHOCKWAVE:
-            case HT_SANDMAN:
-            case HT_FLASHER:
-            case HT_FREEZINGTRAP:
-            case HT_BLASTMINE:
-            case HT_CLAYMORETRAP:
-            case HT_TALKIEBOX:
-            case PF_SPIDERWEB: /* スパイダーウェッブ */
-            case WZ_ICEWALL:
-                range = 1;
-                break;
-            case AL_WARP:
-                range = 0;
-                break;
-        }
-        if (range >= 0)
-        {
-            if (skill_check_unit_range2
-                (sd->bl.m, sd->skillx, sd->skilly, range) > 0)
-            {
-                clif_skill_fail (sd, sd->skillid, 0, 0);
-                sd->canact_tick = tick;
-                sd->canmove_tick = tick;
-                sd->skillitem = sd->skillitemlv = -1;
-                return;
-            }
-        }
-    }
-
-    if (battle_config.pc_land_skill_limit)
-    {
-        maxcount = skill_get_maxcount (sd->skillid);
-        if (maxcount > 0)
-        {
-            int  i, c;
-            for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
-            {
-                if (sd->skillunit[i].alive_count > 0
-                    && sd->skillunit[i].skill_id == sd->skillid)
-                    c++;
-            }
-            if (c >= maxcount)
-            {
-                clif_skill_fail (sd, sd->skillid, 0, 0);
-                sd->canact_tick = tick;
-                sd->canmove_tick = tick;
-                sd->skillitem = sd->skillitemlv = -1;
-                return;
-            }
-        }
-    }
-
-    range = skill_get_range (sd->skillid, sd->skilllv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    range += battle_config.pc_skill_add_range;
-    if (battle_config.skill_out_range_consume)
-    {                           // changed to allow casting when target walks out of range [Valaris]
-        if (range < distance (sd->bl.x, sd->bl.y, sd->skillx, sd->skilly))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            sd->skillitem = sd->skillitemlv = -1;
-            return;
-        }
-    }
-    if (!skill_check_condition (sd, 1))
-    {                           /* 使用条件チェック */
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        sd->skillitem = sd->skillitemlv = -1;
-        return;
-    }
-    sd->skillitem = sd->skillitemlv = -1;
-    if (battle_config.skill_out_range_consume)
-    {
-        if (range < distance (sd->bl.x, sd->bl.y, sd->skillx, sd->skilly))
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            sd->canact_tick = tick;
-            sd->canmove_tick = tick;
-            return;
-        }
-    }
-
-    if (battle_config.pc_skill_log)
-        printf ("PC %d skill castend skill=%d\n", sd->bl.id, sd->skillid);
-    pc_stop_walking (sd, 0);
-
-    skill_castend_pos2 (&sd->bl, sd->skillx, sd->skilly, sd->skillid,
-                        sd->skilllv, tick, 0);
-}
-
-/*==========================================
- * 範囲内キャラ存在確認判定処理(foreachinarea)
- *------------------------------------------
- */
-
-static int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
-{
-    int *c;
-    struct block_list *src;
-    struct map_session_data *sd;
-    struct map_session_data *ssd;
-    struct pc_base_job s_class;
-    struct pc_base_job ss_class;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = (struct map_session_data *) bl);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    nullpo_retr (0, c = va_arg (ap, int *));
-    nullpo_retr (0, ssd = (struct map_session_data *) src);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-    //チェックしない設定ならcにありえない大きな数字を返して終了
-    if (!battle_config.player_skill_partner_check)
-    {                           //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
-        (*c) = 99;
-        return 0;
-    }
-
-    ;
-    ss_class = pc_calc_base_job (ssd->status.pc_class);
-
-    switch (ssd->skillid)
-    {
-        case PR_BENEDICTIO:    /* 聖体降福 */
-            if (sd != ssd
-                && (sd->status.pc_class == 4 || sd->status.pc_class == 8
-                    || sd->status.pc_class == 15 || sd->status.pc_class == 4005
-                    || sd->status.pc_class == 4009 || sd->status.pc_class == 4016)
-                && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1)
-                && sd->status.sp >= 10)
-                (*c)++;
-            break;
-        case BD_LULLABY:       /* 子守歌 */
-        case BD_RICHMANKIM:    /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-        case BD_RAGNAROK:      /* 神々の黄昏 */
-        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
-            if (sd != ssd &&
-                ((ssd->status.pc_class == 19 && sd->status.pc_class == 20) ||
-                 (ssd->status.pc_class == 20 && sd->status.pc_class == 19) ||
-                 (ssd->status.pc_class == 4020 && sd->status.pc_class == 4021) ||
-                 (ssd->status.pc_class == 4021 && sd->status.pc_class == 4020) ||
-                 (ssd->status.pc_class == 20 && sd->status.pc_class == 4020) ||
-                 (ssd->status.pc_class == 19 && sd->status.pc_class == 4021)) &&
-                pc_checkskill (sd, ssd->skillid) > 0 &&
-                (*c) == 0 &&
-                sd->status.party_id == ssd->status.party_id &&
-                !pc_issit (sd) && sd->sc_data[SC_DANCING].timer == -1)
-                (*c) = pc_checkskill (sd, ssd->skillid);
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * 範囲内キャラ存在確認判定後スキル使用処理(foreachinarea)
- *------------------------------------------
- */
-
-static int skill_check_condition_use_sub (struct block_list *bl, va_list ap)
-{
-    int *c;
-    struct block_list *src;
-    struct map_session_data *sd;
-    struct map_session_data *ssd;
-    struct pc_base_job s_class;
-    struct pc_base_job ss_class;
-    int  skillid, skilllv;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, sd = (struct map_session_data *) bl);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    nullpo_retr (0, c = va_arg (ap, int *));
-    nullpo_retr (0, ssd = (struct map_session_data *) src);
-
-    s_class = pc_calc_base_job (sd->status.pc_class);
-
-    //チェックしない設定ならcにありえない大きな数字を返して終了
-    if (!battle_config.player_skill_partner_check)
-    {                           //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
-        (*c) = 99;
-        return 0;
-    }
-
-    ss_class = pc_calc_base_job (ssd->status.pc_class);
-    skillid = ssd->skillid;
-    skilllv = ssd->skilllv;
-    switch (skillid)
-    {
-        case PR_BENEDICTIO:    /* 聖体降福 */
-            if (sd != ssd
-                && (sd->status.pc_class == 4 || sd->status.pc_class == 8
-                    || sd->status.pc_class == 15 || sd->status.pc_class == 4005
-                    || sd->status.pc_class == 4009 || sd->status.pc_class == 4016)
-                && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1)
-                && sd->status.sp >= 10)
-            {
-                sd->status.sp -= 10;
-                pc_calcstatus (sd, 0);
-                (*c)++;
-            }
-            break;
-        case BD_LULLABY:       /* 子守歌 */
-        case BD_RICHMANKIM:    /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-        case BD_RAGNAROK:      /* 神々の黄昏 */
-        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
-            if (sd != ssd &&    //本人以外で
-                ((ssd->status.pc_class == 19 && sd->status.pc_class == 20) ||
-                (ssd->status.pc_class == 20 && sd->status.pc_class == 19) ||
-                (ssd->status.pc_class == 4020 && sd->status.pc_class == 4021) ||
-                (ssd->status.pc_class == 4021 && sd->status.pc_class == 4020) ||
-                (ssd->status.pc_class == 20 && sd->status.pc_class == 4020) ||
-                (ssd->status.pc_class == 19 && sd->status.pc_class == 4021)) && //自分がダンサーならバードで
-                pc_checkskill (sd, skillid) > 0 &&  //スキルを持っていて
-                (*c) == 0 &&    //最初の一人で
-                sd->status.party_id == ssd->status.party_id &&  //パーティーが同じで
-                !pc_issit (sd) &&   //座ってない
-                sd->sc_data[SC_DANCING].timer == -1 //ダンス中じゃない
-                )
-            {
-                ssd->sc_data[SC_DANCING].val4 = bl->id;
-                clif_skill_nodamage (bl, src, skillid, skilllv, 1);
-                skill_status_change_start (bl, SC_DANCING, skillid,
-                                           ssd->sc_data[SC_DANCING].val2, 0,
-                                           src->id, skill_get_time (skillid,
-                                                                    skilllv) +
-                                           1000, 0);
-                sd->skillid_dance = sd->skillid = skillid;
-                sd->skilllv_dance = sd->skilllv = skilllv;
-                (*c)++;
-            }
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * 範囲内バイオプラント、スフィアマイン用Mob存在確認判定処理(foreachinarea)
- *------------------------------------------
- */
-
-static int skill_check_condition_mob_master_sub (struct block_list *bl,
-                                                 va_list ap)
-{
-    int *c, src_id = 0, mob_class = 0;
-    struct mob_data *md;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, md = (struct mob_data *) bl);
-
-    if (!(src_id = va_arg (ap, int)))
-        return 0;
-    if (!(mob_class = va_arg (ap, int)))
-        return 0;
-    nullpo_retr (0, c = va_arg (ap, int *));
-
-    if (md->mob_class == mob_class && md->master_id == src_id)
-        (*c)++;
-    return 0;
-}
-
-/*==========================================
- * スキル使用条件(偽で使用失敗)
- *------------------------------------------
- */
-int skill_check_condition (struct map_session_data *sd, int type)
-{
-    int  i, hp, sp, hp_rate, sp_rate, zeny, weapon, state, spiritball, skill,
-        lv, mhp;
-    int  index[10], itemid[10], amount[10];
-
-    nullpo_retr (0, sd);
-
-    if (battle_config.gm_skilluncond > 0
-        && pc_isGM (sd) >= battle_config.gm_skilluncond)
-    {
-        sd->skillitem = sd->skillitemlv = -1;
-        return 1;
-    }
-
-    if (sd->opt1 > 0)
-    {
-        clif_skill_fail (sd, sd->skillid, 0, 0);
-        sd->skillitem = sd->skillitemlv = -1;
-        return 0;
-    }
-    if (pc_is90overweight (sd))
-    {
-        clif_skill_fail (sd, sd->skillid, 9, 0);
-        sd->skillitem = sd->skillitemlv = -1;
-        return 0;
-    }
-
-    if (sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1)
-    {
-        sd->skillitem = sd->skillitemlv = -1;
-        return 0;
-    }
-    /*if(sd->skillid == AM_PHARMACY &&  sd->state.produce_flag == 1) {
-     * sd->skillitem = sd->skillitemlv = -1;
-     * return 0;
-     * } */
-
-    if (sd->skillitem == sd->skillid)
-    {                           /* アイテムの場合無条件成功 */
-        if (type & 1)
-            sd->skillitem = sd->skillitemlv = -1;
-        return 1;
-    }
-    if (sd->opt1 > 0)
-    {
-        clif_skill_fail (sd, sd->skillid, 0, 0);
-        return 0;
-    }
-    if (sd->sc_data)
-    {
-        if (sd->sc_data[SC_DIVINA].timer != -1 ||
-            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
-            (sd->sc_data[SC_AUTOCOUNTER].timer != -1
-             && sd->skillid != KN_AUTOCOUNTER)
-            || sd->sc_data[SC_STEELBODY].timer != -1
-            || sd->sc_data[SC_BERSERK].timer != -1)
-        {
-            clif_skill_fail (sd, sd->skillid, 0, 0);
-            return 0;           /* 状態異常や沈黙など */
-        }
-    }
-    skill = sd->skillid;
-    lv = sd->skilllv;
-    hp = skill_get_hp (skill, lv);  /* 消費HP */
-    sp = skill_get_sp (skill, lv);  /* 消費SP */
-    if ((sd->skillid_old == BD_ENCORE) && skill == sd->skillid_dance)
-        sp = sp / 2;            //アンコール時はSP消費が半分
-    hp_rate = (lv <= 0) ? 0 : skill_db[skill].hp_rate[lv - 1];
-    sp_rate = (lv <= 0) ? 0 : skill_db[skill].sp_rate[lv - 1];
-    zeny = skill_get_zeny (skill, lv);
-    weapon = skill_db[skill].weapon;
-    state = skill_db[skill].state;
-    spiritball = (lv <= 0) ? 0 : skill_db[skill].spiritball[lv - 1];
-    mhp = skill_get_mhp (skill, lv);    /* 消費HP */
-    for (i = 0; i < 10; i++)
-    {
-        itemid[i] = skill_db[skill].itemid[i];
-        amount[i] = skill_db[skill].amount[i];
-    }
-    if (mhp > 0)
-        hp += (sd->status.max_hp * mhp) / 100;
-    if (hp_rate > 0)
-        hp += (sd->status.hp * hp_rate) / 100;
-    else
-        hp += (sd->status.max_hp * abs (hp_rate)) / 100;
-    if (sp_rate > 0)
-        sp += (sd->status.sp * sp_rate) / 100;
-    else
-        sp += (sd->status.max_sp * abs (sp_rate)) / 100;
-    if (sd->dsprate != 100)
-        sp = sp * sd->dsprate / 100;    /* 消費SP修正 */
-
-    switch (skill)
-    {
-        case SA_CASTCANCEL:
-            if (sd->skilltimer == -1)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case BS_MAXIMIZE:      /* マキシマイズパワー */
-        case NV_TRICKDEAD:     /* 死んだふり */
-        case TF_HIDING:        /* ハイディング */
-        case AS_CLOAKING:      /* クローキング */
-        case CR_AUTOGUARD:     /* オートガード */
-        case CR_DEFENDER:      /* ディフェンダー */
-        case ST_CHASEWALK:
-            if (sd->sc_data[SkillStatusChangeTable[skill]].timer != -1)
-                return 1;       /* 解除する場合はSP消費しない */
-            break;
-        case AL_TELEPORT:
-        case AL_WARP:
-            if (map[sd->bl.m].flag.noteleport)
-            {
-                clif_skill_teleportmessage (sd, 0);
-                return 0;
-            }
-            break;
-        case MO_CALLSPIRITS:   /* 気功 */
-            if (sd->spiritball >= lv)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case CH_SOULCOLLECT:   /* 狂気功 */
-            if (sd->spiritball >= 5)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case MO_FINGEROFFENSIVE:   //指弾
-            if (sd->spiritball > 0 && sd->spiritball < spiritball)
-            {
-                spiritball = sd->spiritball;
-                sd->spiritball_old = sd->spiritball;
-            }
-            else
-                sd->spiritball_old = lv;
-            break;
-        case MO_CHAINCOMBO:    //連打掌
-            if (sd->sc_data[SC_BLADESTOP].timer == -1)
-            {
-                if (sd->sc_data[SC_COMBO].timer == -1
-                    || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
-                    return 0;
-            }
-            break;
-        case MO_COMBOFINISH:   //猛龍拳
-            if (sd->sc_data[SC_COMBO].timer == -1
-                || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO)
-                return 0;
-            break;
-        case CH_TIGERFIST:     //伏虎拳
-            if (sd->sc_data[SC_COMBO].timer == -1
-                || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
-                return 0;
-            break;
-        case CH_CHAINCRUSH:    //連柱崩撃
-            if (sd->sc_data[SC_COMBO].timer == -1)
-                return 0;
-            if (sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH
-                && sd->sc_data[SC_COMBO].val1 != CH_TIGERFIST)
-                return 0;
-            break;
-        case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
-            if ((sd->sc_data[SC_COMBO].timer != -1
-                 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH
-                     || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH))
-                || sd->sc_data[SC_BLADESTOP].timer != -1)
-                spiritball--;
-            break;
-        case BD_ADAPTATION:    /* アドリブ */
-        {
-            struct skill_unit_group *group = NULL;
-            if (sd->sc_data[SC_DANCING].timer == -1
-                ||
-                ((group =
-                  (struct skill_unit_group *) sd->sc_data[SC_DANCING].val2)
-                 &&
-                 (skill_get_time
-                  (sd->sc_data[SC_DANCING].val1,
-                   group->skill_lv) - sd->sc_data[SC_DANCING].val3 * 1000) <=
-                 skill_get_time2 (skill, lv)))
-            {                   //ダンス中で使用後5秒以上のみ?
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-        }
-            break;
-        case PR_BENEDICTIO:    /* 聖体降福 */
-        {
-            int  range = 1;
-            int  c = 0;
-            if (!(type & 1))
-            {
-                map_foreachinarea (skill_check_condition_char_sub, sd->bl.m,
-                                   sd->bl.x - range, sd->bl.y - range,
-                                   sd->bl.x + range, sd->bl.y + range, BL_PC,
-                                   &sd->bl, &c);
-                if (c < 2)
-                {
-                    clif_skill_fail (sd, skill, 0, 0);
-                    return 0;
-                }
-            }
-            else
-            {
-                map_foreachinarea (skill_check_condition_use_sub, sd->bl.m,
-                                   sd->bl.x - range, sd->bl.y - range,
-                                   sd->bl.x + range, sd->bl.y + range, BL_PC,
-                                   &sd->bl, &c);
-            }
-        }
-            break;
-        case WE_CALLPARTNER:   /* あなたに逢いたい */
-            if (!sd->status.partner_id)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case AM_CANNIBALIZE:   /* バイオプラント */
-        case AM_SPHEREMINE:    /* スフィアーマイン */
-            if (type & 1)
-            {
-                int  c = 0;
-                int  maxcount = skill_get_maxcount (skill);
-                int  mob_class = (skill == AM_CANNIBALIZE) ? 1118 : 1142;
-                if (battle_config.pc_land_skill_limit && maxcount > 0)
-                {
-                    map_foreachinarea (skill_check_condition_mob_master_sub,
-                                       sd->bl.m, 0, 0, map[sd->bl.m].xs,
-                                       map[sd->bl.m].ys, BL_MOB, sd->bl.id,
-                                       mob_class, &c);
-                    if (c >= maxcount)
-                    {
-                        clif_skill_fail (sd, skill, 0, 0);
-                        return 0;
-                    }
-                }
-            }
-            break;
-        case MG_FIREWALL:      /* ファイアーウォール */
-            /* 数制限 */
-            if (battle_config.pc_land_skill_limit)
-            {
-                int  maxcount = skill_get_maxcount (skill);
-                if (maxcount > 0)
-                {
-                    int  i, c;
-                    for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
-                    {
-                        if (sd->skillunit[i].alive_count > 0
-                            && sd->skillunit[i].skill_id == skill)
-                            c++;
-                    }
-                    if (c >= maxcount)
-                    {
-                        clif_skill_fail (sd, skill, 0, 0);
-                        return 0;
-                    }
-                }
-            }
-            break;
-    }
-
-    if (!(type & 2))
-    {
-        if (hp > 0 && sd->status.hp < hp)
-        {                       /* HPチェック */
-            clif_skill_fail (sd, skill, 2, 0);  /* HP不足:失敗通知 */
-            return 0;
-        }
-        if (sp > 0 && sd->status.sp < sp)
-        {                       /* SPチェック */
-            clif_skill_fail (sd, skill, 1, 0);  /* SP不足:失敗通知 */
-            return 0;
-        }
-        if (zeny > 0 && sd->status.zeny < zeny)
-        {
-            clif_skill_fail (sd, skill, 5, 0);
-            return 0;
-        }
-        if (!(weapon & (1 << sd->status.weapon)))
-        {
-            clif_skill_fail (sd, skill, 6, 0);
-            return 0;
-        }
-        if (spiritball > 0 && sd->spiritball < spiritball)
-        {
-            clif_skill_fail (sd, skill, 0, 0);  // 氣球不足
-            return 0;
-        }
-    }
-
-    switch (state)
-    {
-        case ST_HIDING:
-            if (!(sd->status.option & 2))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_CLOAKING:
-            if (!(sd->status.option & 4))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_HIDDEN:
-            if (!pc_ishiding (sd))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_RIDING:
-            if (!pc_isriding (sd))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_FALCON:
-            if (!pc_isfalcon (sd))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_CART:
-            if (!pc_iscarton (sd))
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_SHIELD:
-            if (sd->status.shield <= 0)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_SIGHT:
-            if (sd->sc_data[SC_SIGHT].timer == -1 && type & 1)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_EXPLOSIONSPIRITS:
-            if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_RECOV_WEIGHT_RATE:
-            if (battle_config.natural_heal_weight_rate <= 100
-                && sd->weight * 100 / sd->max_weight >=
-                battle_config.natural_heal_weight_rate)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-        case ST_MOVE_ENABLE:
-        {
-            struct walkpath_data wpd;
-            if (path_search
-                (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->skillx, sd->skilly,
-                 1) == -1)
-            {
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-        }
-            break;
-        case ST_WATER:
-            if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) != 3
-                && (sd->sc_data[SC_DELUGE].timer == -1))
-            {                   //水場判定
-                clif_skill_fail (sd, skill, 0, 0);
-                return 0;
-            }
-            break;
-    }
-
-    for (i = 0; i < 10; i++)
-    {
-        int  x = lv % 11 - 1;
-        index[i] = -1;
-        if (itemid[i] <= 0)
-            continue;
-        if (itemid[i] >= 715 && itemid[i] <= 717
-            && sd->special_state.no_gemstone)
-            continue;
-        if (((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065)
-            && sd->sc_data[SC_INTOABYSS].timer != -1)
-            continue;
-        if (skill == AM_POTIONPITCHER && i != x)
-            continue;
-
-        index[i] = pc_search_inventory (sd, itemid[i]);
-        if (index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i])
-        {
-            if (itemid[i] == 716 || itemid[i] == 717)
-                clif_skill_fail (sd, skill, (7 + (itemid[i] - 716)), 0);
-            else
-                clif_skill_fail (sd, skill, 0, 0);
-            return 0;
-        }
-    }
-
-    if (!(type & 1))
-        return 1;
-
-    if (skill != AM_POTIONPITCHER)
-    {
-        if (skill == AL_WARP && !(type & 2))
-            return 1;
-        for (i = 0; i < 10; i++)
-        {
-            if (index[i] >= 0)
-                pc_delitem (sd, index[i], amount[i], 0);    // アイテム消費
-        }
-    }
-
-    if (type & 2)
-        return 1;
-
-    pc_heal (sd, -sp, -hp);     // [Fate] This might suppress some dupe messages
-
-/* 	if(sp > 0) {					// SP消費 */
-/* 		sd->status.sp-=sp; */
-/* 		clif_updatestatus(sd,SP_SP); */
-/* 	} */
-/* 	if(hp > 0) {					// HP消費 */
-/* 		sd->status.hp-=hp; */
-/* 		clif_updatestatus(sd,SP_HP); */
-/* 	} */
-    if (zeny > 0)               // Zeny消費
-        pc_payzeny (sd, zeny);
-    if (spiritball > 0)         // 氣球消費
-        pc_delspiritball (sd, spiritball, 0);
-
-    return 1;
-}
-
-/*==========================================
- * 詠唱時間計算
- *------------------------------------------
- */
-int skill_castfix (struct block_list *bl, int time)
-{
-    struct map_session_data *sd;
-    struct mob_data *md;        // [Valaris]
-    struct status_change *sc_data;
-    int  dex;
-    int  castrate = 100;
-    int  skill, lv, castnodex;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_MOB)
-    {                           // Crash fix [Valaris]
-        md = (struct mob_data *) bl;
-        skill = md->skillid;
-        lv = md->skilllv;
-    }
-
-    else
-    {
-        sd = (struct map_session_data *) bl;
-        skill = sd->skillid;
-        lv = sd->skilllv;
-    }
-
-    sc_data = battle_get_sc_data (bl);
-    dex = battle_get_dex (bl);
-
-    if (skill > MAX_SKILL_DB || skill < 0)
-        return 0;
-
-    castnodex = skill_get_castnodex (skill, lv);
-
-    if (time == 0)
-        return 0;
-    if (castnodex > 0 && bl->type == BL_PC)
-        castrate = ((struct map_session_data *) bl)->castrate;
-    else if (castnodex <= 0 && bl->type == BL_PC)
-    {
-        castrate = ((struct map_session_data *) bl)->castrate;
-        time =
-            time * castrate * (battle_config.castrate_dex_scale -
-                               dex) / (battle_config.castrate_dex_scale *
-                                       100);
-        time = time * battle_config.cast_rate / 100;
-    }
-
-    /* サフラギウム */
-    if (sc_data && sc_data[SC_SUFFRAGIUM].timer != -1)
-    {
-        time = time * (100 - sc_data[SC_SUFFRAGIUM].val1 * 15) / 100;
-        skill_status_change_end (bl, SC_SUFFRAGIUM, -1);
-    }
-    /* ブラギの詩 */
-    if (sc_data && sc_data[SC_POEMBRAGI].timer != -1)
-        time =
-            time * (100 -
-                    (sc_data[SC_POEMBRAGI].val1 * 3 +
-                     sc_data[SC_POEMBRAGI].val2 +
-                     (sc_data[SC_POEMBRAGI].val3 >> 16))) / 100;
-
-    return (time > 0) ? time : 0;
-}
-
-/*==========================================
- * ディレイ計算
- *------------------------------------------
- */
-int skill_delayfix (struct block_list *bl, int time)
-{
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-
-    sc_data = battle_get_sc_data (bl);
-    if (time <= 0)
-        return 0;
-
-    if (bl->type == BL_PC)
-    {
-        if (battle_config.delay_dependon_dex)   /* dexの影響を計算する */
-            time =
-                time * (battle_config.castrate_dex_scale -
-                        battle_get_dex (bl)) /
-                battle_config.castrate_dex_scale;
-        time = time * battle_config.delay_rate / 100;
-    }
-
-    /* ブラギの詩 */
-    if (sc_data && sc_data[SC_POEMBRAGI].timer != -1)
-        time =
-            time * (100 -
-                    (sc_data[SC_POEMBRAGI].val1 * 3 +
-                     sc_data[SC_POEMBRAGI].val2 +
-                     (sc_data[SC_POEMBRAGI].val3 & 0xffff))) / 100;
-
-    return (time > 0) ? time : 0;
-}
-
-/*==========================================
- * スキル使用(ID指定)
- *------------------------------------------
- */
-int skill_use_id (struct map_session_data *sd, int target_id,
-                  int skill_num, int skill_lv)
-{
-    unsigned int tick;
-    int  casttime = 0, delay = 0, skill, range;
-    struct map_session_data *target_sd = NULL;
-    int  forcecast = 0;
-    struct block_list *bl;
-    struct status_change *sc_data;
-    tick = gettick ();
-
-    nullpo_retr (0, sd);
-
-    if ((bl = map_id2bl (target_id)) == NULL)
-    {
-/*		if(battle_config.error_log)
-			printf("skill target not found %d\n",target_id); */
-        return 0;
-    }
-    if (sd->bl.m != bl->m || pc_isdead (sd))
-        return 0;
-
-    if (skillnotok (skill_num, sd)) // [MouseJstr]
-        return 0;
-
-    if (sd->skillid == WZ_ICEWALL && map[sd->bl.m].flag.noicewall
-        && !map[sd->bl.m].flag.pvp)
-    {                           // noicewall flag [Valaris]
-        clif_skill_fail (sd, sd->skillid, 0, 0);
-        return 0;
-    }
-    sc_data = sd->sc_data;
-
-    /* 沈黙や異常(ただし、グリムなどの判定をする) */
-    if (sd->opt1 > 0)
-        return 0;
-    if (sd->sc_data)
-    {
-        if (sc_data[SC_CHASEWALK].timer != -1)
-            return 0;
-        if (sc_data[SC_VOLCANO].timer != -1)
-        {
-            if (skill_num == WZ_ICEWALL)
-                return 0;
-        }
-        if (sc_data[SC_ROKISWEIL].timer != -1)
-        {
-            if (skill_num == BD_ADAPTATION)
-                return 0;
-        }
-        if (sd->sc_data[SC_DIVINA].timer != -1 ||
-            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
-            (sd->sc_data[SC_AUTOCOUNTER].timer != -1
-             && sd->skillid != KN_AUTOCOUNTER)
-            || sd->sc_data[SC_STEELBODY].timer != -1
-            || sd->sc_data[SC_BERSERK].timer != -1)
-        {
-            return 0;           /* 状態異常や沈黙など */
-        }
-
-        if (sc_data[SC_BLADESTOP].timer != -1)
-        {
-            int  lv = sc_data[SC_BLADESTOP].val1;
-            if (sc_data[SC_BLADESTOP].val2 == 1)
-                return 0;       //白羽された側なのでダメ
-            if (lv == 1)
-                return 0;
-            if (lv == 2 && skill_num != MO_FINGEROFFENSIVE)
-                return 0;
-            if (lv == 3 && skill_num != MO_FINGEROFFENSIVE
-                && skill_num != MO_INVESTIGATE)
-                return 0;
-            if (lv == 4 && skill_num != MO_FINGEROFFENSIVE
-                && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO)
-                return 0;
-            if (lv == 5 && skill_num != MO_FINGEROFFENSIVE
-                && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO
-                && skill_num != MO_EXTREMITYFIST)
-                return 0;
-        }
-    }
-
-    if (sd->status.option & 4 && skill_num == TF_HIDING)
-        return 0;
-    if (sd->status.option & 2 && skill_num != TF_HIDING
-        && skill_num != AS_GRIMTOOTH && skill_num != RG_BACKSTAP
-        && skill_num != RG_RAID)
-        return 0;
-
-    if (map[sd->bl.m].flag.gvg)
-    {                           //GvGで使用できないスキル
-        switch (skill_num)
-        {
-            case SM_ENDURE:
-            case AL_TELEPORT:
-            case AL_WARP:
-            case WZ_ICEWALL:
-            case TF_BACKSLIDING:
-            case LK_BERSERK:
-            case HP_BASILICA:
-            case ST_CHASEWALK:
-                return 0;
-        }
-    }
-
-    /* 演奏/ダンス中 */
-    if (sc_data && sc_data[SC_DANCING].timer != -1)
-    {
-//      if(battle_config.pc_skill_log)
-//          printf("dancing! %d\n",skill_num);
-        if (sc_data[SC_DANCING].val4 && skill_num != BD_ADAPTATION) //合奏中はアドリブ以外不可
-            return 0;
-        if (skill_num != BD_ADAPTATION && skill_num != BA_MUSICALSTRIKE
-            && skill_num != DC_THROWARROW)
-        {
-            return 0;
-        }
-    }
-
-    if (skill_get_inf2 (skill_num) & 0x200 && sd->bl.id == target_id)
-        return 0;
-    //直前のスキルが何か覚える必要のあるスキル
-    switch (skill_num)
-    {
-        case SA_CASTCANCEL:
-            if (sd->skillid != skill_num)
-            {                   //キャストキャンセル自体は覚えない
-                sd->skillid_old = sd->skillid;
-                sd->skilllv_old = sd->skilllv;
-                break;
-            }
-        case BD_ENCORE:        /* アンコール */
-            if (!sd->skillid_dance)
-            {                   //前回使用した踊りがないとだめ
-                clif_skill_fail (sd, skill_num, 0, 0);
-                return 0;
-            }
-            else
-            {
-                sd->skillid_old = skill_num;
-            }
-            break;
-    }
-
-    sd->skillid = skill_num;
-    sd->skilllv = skill_lv;
-
-    switch (skill_num)
-    {                           //事前にレベルが変わったりするスキル
-        case BD_LULLABY:       /* 子守歌 */
-        case BD_RICHMANKIM:    /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-        case BD_RAGNAROK:      /* 神々の黄昏 */
-        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
-        {
-            int  range = 1;
-            int  c = 0;
-            map_foreachinarea (skill_check_condition_char_sub, sd->bl.m,
-                               sd->bl.x - range, sd->bl.y - range,
-                               sd->bl.x + range, sd->bl.y + range, BL_PC,
-                               &sd->bl, &c);
-            if (c < 1)
-            {
-                clif_skill_fail (sd, skill_num, 0, 0);
-                return 0;
-            }
-            else if (c == 99)
-            {                   //相方不要設定だった
-                ;
-            }
-            else
-            {
-                sd->skilllv = (c + skill_lv) / 2;
-            }
-        }
-            break;
-    }
-
-    if (!skill_check_condition (sd, 0))
-        return 0;
-
-    /* 射程と障害物チェック */
-    range = skill_get_range (skill_num, skill_lv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    if (!battle_check_range (&sd->bl, bl, range))
-        return 0;
-
-    if (bl->type == BL_PC)
-    {
-        target_sd = (struct map_session_data *) bl;
-        if (target_sd && skill_num == ALL_RESURRECTION
-            && !pc_isdead (target_sd))
-            return 0;
-    }
-    if ((skill_num != MO_CHAINCOMBO &&
-         skill_num != MO_COMBOFINISH &&
-         skill_num != MO_EXTREMITYFIST &&
-         skill_num != CH_TIGERFIST &&
-         skill_num != CH_CHAINCRUSH) ||
-        (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag))
-        pc_stopattack (sd);
-
-    casttime = skill_castfix (&sd->bl, skill_get_cast (skill_num, skill_lv));
-    if (skill_num != SA_MAGICROD)
-        delay =
-            skill_delayfix (&sd->bl, skill_get_delay (skill_num, skill_lv));
-    sd->state.skillcastcancel = skill_db[skill_num].castcancel;
-
-    switch (skill_num)
-    {                           /* 何か特殊な処理が必要 */
-//  case AL_HEAL:   /* ヒール */
-//      if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
-//          forcecast=1;    /* ヒールアタックなら詠唱エフェクト有り */
-//      break;
-        case ALL_RESURRECTION: /* リザレクション */
-            if (bl->type != BL_PC
-                && battle_check_undead (battle_get_race (bl),
-                                        battle_get_elem_type (bl)))
-            {                   /* 敵がアンデッドなら */
-                forcecast = 1;  /* ターンアンデットと同じ詠唱時間 */
-                casttime =
-                    skill_castfix (&sd->bl,
-                                   skill_get_cast (PR_TURNUNDEAD, skill_lv));
-            }
-            break;
-        case MO_FINGEROFFENSIVE:   /* 指弾 */
-            casttime +=
-                casttime *
-                ((skill_lv > sd->spiritball) ? sd->spiritball : skill_lv);
-            break;
-        case MO_CHAINCOMBO:    /*連打掌 */
-            target_id = sd->attacktarget;
-            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
-            {
-                struct block_list *tbl;
-                if ((tbl = (struct block_list *) sc_data[SC_BLADESTOP].val4) == NULL)   //ターゲットがいない?
-                    return 0;
-                target_id = tbl->id;
-            }
-            break;
-        case MO_COMBOFINISH:   /*猛龍拳 */
-        case CH_TIGERFIST:     /* 伏虎拳 */
-        case CH_CHAINCRUSH:    /* 連柱崩撃 */
-            target_id = sd->attacktarget;
-            break;
-
-// -- moonsoul  (altered to allow proper usage of extremity from new champion combos)
-//
-        case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */
-            if (sc_data && sc_data[SC_COMBO].timer != -1
-                && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH
-                    || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH))
-            {
-                casttime = 0;
-                target_id = sd->attacktarget;
-            }
-            forcecast = 1;
-            break;
-        case SA_MAGICROD:
-        case SA_SPELLBREAKER:
-            forcecast = 1;
-            break;
-        case WE_MALE:
-        case WE_FEMALE:
-        {
-            struct map_session_data *p_sd = NULL;
-            if ((p_sd = pc_get_partner (sd)) == NULL)
-                return 0;
-            target_id = p_sd->bl.id;
-            //rangeをもう1回検査
-            range = skill_get_range (skill_num, skill_lv);
-            if (range < 0)
-                range = battle_get_range (&sd->bl) - (range + 1);
-            if (!battle_check_range (&sd->bl, &p_sd->bl, range))
-            {
-                return 0;
-            }
-        }
-            break;
-        case AS_SPLASHER:      /* ベナムスプラッシャー */
-        {
-            struct status_change *t_sc_data = battle_get_sc_data (bl);
-            if (t_sc_data && t_sc_data[SC_POISON].timer == -1)
-            {
-                clif_skill_fail (sd, skill_num, 0, 10);
-                return 0;
-            }
-        }
-            break;
-        case PF_MEMORIZE:      /* メモライズ */
-            casttime = 12000;
-            break;
-
-    }
-
-    //メモライズ状態ならキャストタイムが1/3
-    if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0)
-    {
-        casttime = casttime / 3;
-        if ((--sc_data[SC_MEMORIZE].val2) <= 0)
-            skill_status_change_end (&sd->bl, SC_MEMORIZE, -1);
-    }
-
-    if (battle_config.pc_skill_log)
-        printf ("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",
-                sd->bl.id, target_id, skill_num, skill_lv, casttime);
-
-//  if(sd->skillitem == skill_num)
-//      casttime = delay = 0;
-
-    if (casttime > 0 || forcecast)
-    {                           /* 詠唱が必要 */
-        struct mob_data *md;
-        clif_skillcasting (&sd->bl,
-                           sd->bl.id, target_id, 0, 0, skill_num, casttime);
-
-        /* 詠唱反応モンスター */
-        if (bl->type == BL_MOB && (md = (struct mob_data *) bl)
-            && mob_db[md->mob_class].mode & 0x10 && md->state.state != MS_ATTACK
-            && sd->invincible_timer == -1)
-        {
-            md->target_id = sd->bl.id;
-            md->state.targettype = ATTACKABLE;
-            md->min_chase = 13;
-        }
-    }
-
-    if (casttime <= 0)          /* 詠唱の無いものはキャンセルされない */
-        sd->state.skillcastcancel = 0;
-
-    sd->skilltarget = target_id;
-/*	sd->cast_target_bl	= bl; */
-    sd->skillx = 0;
-    sd->skilly = 0;
-    sd->canact_tick = tick + casttime + delay;
-    sd->canmove_tick = tick;
-    if (!(battle_config.pc_cloak_check_type & 2) && sc_data
-        && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
-        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
-    if (casttime > 0)
-    {
-        sd->skilltimer =
-            add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0);
-        if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0)
-        {
-            sd->prev_speed = sd->speed;
-            sd->speed = sd->speed * (175 - skill * 5) / 100;
-            clif_updatestatus (sd, SP_SPEED);
-        }
-        else
-            pc_stop_walking (sd, 0);
-    }
-    else
-    {
-        if (skill_num != SA_CASTCANCEL)
-            sd->skilltimer = -1;
-        skill_castend_id (sd->skilltimer, tick, sd->bl.id, 0);
-    }
-
-    //マジックパワーの効果終了
-    if (sc_data && sc_data[SC_MAGICPOWER].timer != -1
-        && skill_num != HW_MAGICPOWER)
-        skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1);
-
-    return 0;
-}
-
-/*==========================================
- * スキル使用(場所指定)
- *------------------------------------------
- */
-int skill_use_pos (struct map_session_data *sd,
-                   int skill_x, int skill_y, int skill_num, int skill_lv)
-{
-    struct block_list bl;
-    struct status_change *sc_data;
-    unsigned int tick;
-    int  casttime = 0, delay = 0, skill, range;
-
-    nullpo_retr (0, sd);
-
-    if (pc_isdead (sd))
-        return 0;
-
-    if (skillnotok (skill_num, sd)) // [MoueJstr]
-        return 0;
-
-    sc_data = sd->sc_data;
-
-    if (sd->opt1 > 0)
-        return 0;
-    if (sc_data)
-    {
-        if (sc_data[SC_DIVINA].timer != -1 ||
-            sc_data[SC_ROKISWEIL].timer != -1 ||
-            sc_data[SC_AUTOCOUNTER].timer != -1 ||
-            sc_data[SC_STEELBODY].timer != -1 ||
-            sc_data[SC_DANCING].timer != -1 ||
-            sc_data[SC_BERSERK].timer != -1)
-            return 0;           /* 状態異常や沈黙など */
-    }
-
-    if (sd->status.option & 2)
-        return 0;
-
-    if (map[sd->bl.m].flag.gvg
-        && (skill_num == SM_ENDURE || skill_num == AL_TELEPORT
-            || skill_num == AL_WARP || skill_num == WZ_ICEWALL
-            || skill_num == TF_BACKSLIDING))
-        return 0;
-
-    sd->skillid = skill_num;
-    sd->skilllv = skill_lv;
-    sd->skillx = skill_x;
-    sd->skilly = skill_y;
-    if (!skill_check_condition (sd, 0))
-        return 0;
-
-    /* 射程と障害物チェック */
-    bl.type = BL_NUL;
-    bl.m = sd->bl.m;
-    bl.x = skill_x;
-    bl.y = skill_y;
-    range = skill_get_range (skill_num, skill_lv);
-    if (range < 0)
-        range = battle_get_range (&sd->bl) - (range + 1);
-    if (!battle_check_range (&sd->bl, &bl, range))
-        return 0;
-
-    pc_stopattack (sd);
-
-    casttime = skill_castfix (&sd->bl, skill_get_cast (skill_num, skill_lv));
-    delay = skill_delayfix (&sd->bl, skill_get_delay (skill_num, skill_lv));
-    sd->state.skillcastcancel = skill_db[skill_num].castcancel;
-
-    if (battle_config.pc_skill_log)
-        printf ("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",
-                sd->bl.id, skill_x, skill_y, skill_num, skill_lv, casttime);
-
-//  if(sd->skillitem == skill_num)
-//      casttime = delay = 0;
-    //メモライズ状態ならキャストタイムが1/3
-    if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0)
-    {
-        casttime = casttime / 3;
-        if ((--sc_data[SC_MEMORIZE].val2) <= 0)
-            skill_status_change_end (&sd->bl, SC_MEMORIZE, -1);
-    }
-
-    if (casttime > 0)           /* 詠唱が必要 */
-        clif_skillcasting (&sd->bl,
-                           sd->bl.id, 0, skill_x, skill_y, skill_num,
-                           casttime);
-
-    if (casttime <= 0)          /* 詠唱の無いものはキャンセルされない */
-        sd->state.skillcastcancel = 0;
-
-    sd->skilltarget = 0;
-/*	sd->cast_target_bl	= NULL; */
-    tick = gettick ();
-    sd->canact_tick = tick + casttime + delay;
-    sd->canmove_tick = tick;
-    if (!(battle_config.pc_cloak_check_type & 2) && sc_data
-        && sc_data[SC_CLOAKING].timer != -1)
-        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
-    if (casttime > 0)
-    {
-        sd->skilltimer =
-            add_timer (tick + casttime, skill_castend_pos, sd->bl.id, 0);
-        if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0)
-        {
-            sd->prev_speed = sd->speed;
-            sd->speed = sd->speed * (175 - skill * 5) / 100;
-            clif_updatestatus (sd, SP_SPEED);
-        }
-        else
-            pc_stop_walking (sd, 0);
-    }
-    else
-    {
-        sd->skilltimer = -1;
-        skill_castend_pos (sd->skilltimer, tick, sd->bl.id, 0);
-    }
-    //マジックパワーの効果終了
-    if (sc_data && sc_data[SC_MAGICPOWER].timer != -1
-        && skill_num != HW_MAGICPOWER)
-        skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1);
-
-    return 0;
-}
-
-/*==========================================
- * スキル詠唱キャンセル
- *------------------------------------------
- */
-int skill_castcancel (struct block_list *bl, int type)
-{
-    int  inf;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-    {
-        struct map_session_data *sd = (struct map_session_data *) bl;
-        unsigned long tick = gettick ();
-        nullpo_retr (0, sd);
-        sd->canact_tick = tick;
-        sd->canmove_tick = tick;
-        if (sd->skilltimer != -1)
-        {
-            if (pc_checkskill (sd, SA_FREECAST) > 0)
-            {
-                sd->speed = sd->prev_speed;
-                clif_updatestatus (sd, SP_SPEED);
-            }
-            if (!type)
-            {
-                if ((inf = skill_get_inf (sd->skillid)) == 2 || inf == 32)
-                    delete_timer (sd->skilltimer, skill_castend_pos);
-                else
-                    delete_timer (sd->skilltimer, skill_castend_id);
-            }
-            else
-            {
-                if ((inf = skill_get_inf (sd->skillid_old)) == 2 || inf == 32)
-                    delete_timer (sd->skilltimer, skill_castend_pos);
-                else
-                    delete_timer (sd->skilltimer, skill_castend_id);
-            }
-            sd->skilltimer = -1;
-            clif_skillcastcancel (bl);
-        }
-
-        return 0;
-    }
-    else if (bl->type == BL_MOB)
-    {
-        struct mob_data *md = (struct mob_data *) bl;
-        nullpo_retr (0, md);
-        if (md->skilltimer != -1)
-        {
-            if ((inf = skill_get_inf (md->skillid)) == 2 || inf == 32)
-                delete_timer (md->skilltimer, mobskill_castend_pos);
-            else
-                delete_timer (md->skilltimer, mobskill_castend_id);
-            md->skilltimer = -1;
-            clif_skillcastcancel (bl);
-        }
-        return 0;
-    }
-    return 1;
-}
-
-/*=========================================
- * ブランディッシュスピア 初期範囲決定
- *----------------------------------------
- */
-void skill_brandishspear_first (struct square *tc, int dir, int x, int y)
-{
-
-    nullpo_retv (tc);
-
-    if (dir == 0)
-    {
-        tc->val1[0] = x - 2;
-        tc->val1[1] = x - 1;
-        tc->val1[2] = x;
-        tc->val1[3] = x + 1;
-        tc->val1[4] = x + 2;
-        tc->val2[0] =
-            tc->val2[1] = tc->val2[2] = tc->val2[3] = tc->val2[4] = y - 1;
-    }
-    else if (dir == 2)
-    {
-        tc->val1[0] =
-            tc->val1[1] = tc->val1[2] = tc->val1[3] = tc->val1[4] = x + 1;
-        tc->val2[0] = y + 2;
-        tc->val2[1] = y + 1;
-        tc->val2[2] = y;
-        tc->val2[3] = y - 1;
-        tc->val2[4] = y - 2;
-    }
-    else if (dir == 4)
-    {
-        tc->val1[0] = x - 2;
-        tc->val1[1] = x - 1;
-        tc->val1[2] = x;
-        tc->val1[3] = x + 1;
-        tc->val1[4] = x + 2;
-        tc->val2[0] =
-            tc->val2[1] = tc->val2[2] = tc->val2[3] = tc->val2[4] = y + 1;
-    }
-    else if (dir == 6)
-    {
-        tc->val1[0] =
-            tc->val1[1] = tc->val1[2] = tc->val1[3] = tc->val1[4] = x - 1;
-        tc->val2[0] = y + 2;
-        tc->val2[1] = y + 1;
-        tc->val2[2] = y;
-        tc->val2[3] = y - 1;
-        tc->val2[4] = y - 2;
-    }
-    else if (dir == 1)
-    {
-        tc->val1[0] = x - 1;
-        tc->val1[1] = x;
-        tc->val1[2] = x + 1;
-        tc->val1[3] = x + 2;
-        tc->val1[4] = x + 3;
-        tc->val2[0] = y - 4;
-        tc->val2[1] = y - 3;
-        tc->val2[2] = y - 1;
-        tc->val2[3] = y;
-        tc->val2[4] = y + 1;
-    }
-    else if (dir == 3)
-    {
-        tc->val1[0] = x + 3;
-        tc->val1[1] = x + 2;
-        tc->val1[2] = x + 1;
-        tc->val1[3] = x;
-        tc->val1[4] = x - 1;
-        tc->val2[0] = y - 1;
-        tc->val2[1] = y;
-        tc->val2[2] = y + 1;
-        tc->val2[3] = y + 2;
-        tc->val2[4] = y + 3;
-    }
-    else if (dir == 5)
-    {
-        tc->val1[0] = x + 1;
-        tc->val1[1] = x;
-        tc->val1[2] = x - 1;
-        tc->val1[3] = x - 2;
-        tc->val1[4] = x - 3;
-        tc->val2[0] = y + 3;
-        tc->val2[1] = y + 2;
-        tc->val2[2] = y + 1;
-        tc->val2[3] = y;
-        tc->val2[4] = y - 1;
-    }
-    else if (dir == 7)
-    {
-        tc->val1[0] = x - 3;
-        tc->val1[1] = x - 2;
-        tc->val1[2] = x - 1;
-        tc->val1[3] = x;
-        tc->val1[4] = x + 1;
-        tc->val2[1] = y;
-        tc->val2[0] = y + 1;
-        tc->val2[2] = y - 1;
-        tc->val2[3] = y - 2;
-        tc->val2[4] = y - 3;
-    }
-
-}
-
-/*=========================================
- * ブランディッシュスピア 方向判定 範囲拡張
- *-----------------------------------------
- */
-void skill_brandishspear_dir (struct square *tc, int dir, int are)
-{
-
-    int  c;
-
-    nullpo_retv (tc);
-
-    for (c = 0; c < 5; c++)
-    {
-        if (dir == 0)
-        {
-            tc->val2[c] += are;
-        }
-        else if (dir == 1)
-        {
-            tc->val1[c] -= are;
-            tc->val2[c] += are;
-        }
-        else if (dir == 2)
-        {
-            tc->val1[c] -= are;
-        }
-        else if (dir == 3)
-        {
-            tc->val1[c] -= are;
-            tc->val2[c] -= are;
-        }
-        else if (dir == 4)
-        {
-            tc->val2[c] -= are;
-        }
-        else if (dir == 5)
-        {
-            tc->val1[c] += are;
-            tc->val2[c] -= are;
-        }
-        else if (dir == 6)
-        {
-            tc->val1[c] += are;
-        }
-        else if (dir == 7)
-        {
-            tc->val1[c] += are;
-            tc->val2[c] += are;
-        }
-    }
-}
-
-/*==========================================
- * ディボーション 有効確認
- *------------------------------------------
- */
-void skill_devotion (struct map_session_data *md, int target)
-{
-    // 総確認
-    int  n;
-
-    nullpo_retv (md);
-
-    for (n = 0; n < 5; n++)
-    {
-        if (md->dev.val1[n])
-        {
-            struct map_session_data *sd = map_id2sd (md->dev.val1[n]);
-            // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる
-            if (sd == NULL
-                || (sd->sc_data
-                    && (md->bl.id != sd->sc_data[SC_DEVOTION].val1))
-                || skill_devotion3 (&md->bl, md->dev.val1[n]))
-            {
-                skill_devotion_end (md, sd, n);
-            }
-        }
-    }
-}
-
-void skill_devotion2 (struct block_list *bl, int crusader)
-{
-    // 被ディボーションが歩いた時の距離チェック
-    struct map_session_data *sd = map_id2sd (crusader);
-
-    nullpo_retv (bl);
-
-    if (sd)
-        skill_devotion3 (&sd->bl, bl->id);
-}
-
-int skill_devotion3 (struct block_list *bl, int target)
-{
-    // クルセが歩いた時の距離チェック
-    struct map_session_data *md;
-    struct map_session_data *sd;
-    int  n, r = 0;
-
-    nullpo_retr (1, bl);
-
-    if ((md = (struct map_session_data *) bl) == NULL
-        || (sd = map_id2sd (target)) == NULL)
-        return 1;
-    else
-        r = distance (bl->x, bl->y, sd->bl.x, sd->bl.y);
-
-    if (pc_checkskill (sd, CR_DEVOTION) + 6 < r)
-    {                           // 許容範囲を超えてた
-        for (n = 0; n < 5; n++)
-            if (md->dev.val1[n] == target)
-                md->dev.val2[n] = 0;    // 離れた時は、糸を切るだけ
-        clif_devotion (md, sd->bl.id);
-        return 1;
-    }
-    return 0;
-}
-
-void skill_devotion_end (struct map_session_data *md,
-                         struct map_session_data *sd, int target)
-{
-    // クルセと被ディボキャラのリセット
-    nullpo_retv (md);
-    nullpo_retv (sd);
-
-    md->dev.val1[target] = md->dev.val2[target] = 0;
-    if (sd && sd->sc_data)
-    {
-        //  skill_status_change_end(sd->bl,SC_DEVOTION,-1);
-        sd->sc_data[SC_DEVOTION].val1 = 0;
-        sd->sc_data[SC_DEVOTION].val2 = 0;
-        clif_status_change (&sd->bl, SC_DEVOTION, 0);
-        clif_devotion (md, sd->bl.id);
-    }
-}
-
-/*==========================================
- * オートスペル
- *------------------------------------------
- */
-int skill_autospell (struct map_session_data *sd, int skillid)
-{
-    int  skilllv;
-    int  maxlv = 1, lv;
-
-    nullpo_retr (0, sd);
-
-    skilllv = pc_checkskill (sd, SA_AUTOSPELL);
-
-    if (skillid == MG_NAPALMBEAT)
-        maxlv = 3;
-    else if (skillid == MG_COLDBOLT || skillid == MG_FIREBOLT
-             || skillid == MG_LIGHTNINGBOLT)
-    {
-        if (skilllv == 2)
-            maxlv = 1;
-        else if (skilllv == 3)
-            maxlv = 2;
-        else if (skilllv >= 4)
-            maxlv = 3;
-    }
-    else if (skillid == MG_SOULSTRIKE)
-    {
-        if (skilllv == 5)
-            maxlv = 1;
-        else if (skilllv == 6)
-            maxlv = 2;
-        else if (skilllv >= 7)
-            maxlv = 3;
-    }
-    else if (skillid == MG_FIREBALL)
-    {
-        if (skilllv == 8)
-            maxlv = 1;
-        else if (skilllv >= 9)
-            maxlv = 2;
-    }
-    else if (skillid == MG_FROSTDIVER)
-        maxlv = 1;
-    else
-        return 0;
-
-    if (maxlv > (lv = pc_checkskill (sd, skillid)))
-        maxlv = lv;
-
-    skill_status_change_start (&sd->bl, SC_AUTOSPELL, skilllv, skillid, maxlv, 0,   // val1:スキルID val2:使用最大Lv
-                               skill_get_time (SA_AUTOSPELL, skilllv), 0);  // にしてみたけどbscriptが書き易い・・・?
-    return 0;
-}
-
-/*==========================================
- * ギャングスターパラダイス判定処理(foreachinarea)
- *------------------------------------------
- */
-
-static int skill_gangster_count (struct block_list *bl, va_list ap)
-{
-    int *c;
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    sd = (struct map_session_data *) bl;
-    c = va_arg (ap, int *);
-
-    if (sd && c && pc_issit (sd) && pc_checkskill (sd, RG_GANGSTER) > 0)
-        (*c)++;
-    return 0;
-}
-
-static int skill_gangster_in (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    sd = (struct map_session_data *) bl;
-    if (sd && pc_issit (sd) && pc_checkskill (sd, RG_GANGSTER) > 0)
-        sd->state.gangsterparadise = 1;
-    return 0;
-}
-
-static int skill_gangster_out (struct block_list *bl, va_list ap)
-{
-    struct map_session_data *sd;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    sd = (struct map_session_data *) bl;
-    if (sd && sd->state.gangsterparadise)
-        sd->state.gangsterparadise = 0;
-    return 0;
-}
-
-int skill_gangsterparadise (struct map_session_data *sd, int type)
-{
-    int  range = 1;
-    int  c = 0;
-
-    nullpo_retr (0, sd);
-
-    if (pc_checkskill (sd, RG_GANGSTER) <= 0)
-        return 0;
-
-    if (type == 1)
-    {                           /* 座った時の処理 */
-        map_foreachinarea (skill_gangster_count, sd->bl.m,
-                           sd->bl.x - range, sd->bl.y - range,
-                           sd->bl.x + range, sd->bl.y + range, BL_PC, &c);
-        if (c > 0)
-        {                       /*ギャングスター成功したら自分にもギャングスター属性付与 */
-            map_foreachinarea (skill_gangster_in, sd->bl.m,
-                               sd->bl.x - range, sd->bl.y - range,
-                               sd->bl.x + range, sd->bl.y + range, BL_PC);
-            sd->state.gangsterparadise = 1;
-        }
-        return 0;
-    }
-    else if (type == 0)
-    {                           /* 立ち上がったときの処理 */
-        map_foreachinarea (skill_gangster_count, sd->bl.m,
-                           sd->bl.x - range, sd->bl.y - range,
-                           sd->bl.x + range, sd->bl.y + range, BL_PC, &c);
-        if (c < 1)
-            map_foreachinarea (skill_gangster_out, sd->bl.m,
-                               sd->bl.x - range, sd->bl.y - range,
-                               sd->bl.x + range, sd->bl.y + range, BL_PC);
-        sd->state.gangsterparadise = 0;
-        return 0;
-    }
-    return 0;
-}
-
-/*==========================================
- * 寒いジョーク・スクリーム判定処理(foreachinarea)
- *------------------------------------------
- */
-int skill_frostjoke_scream (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    int  skillnum, skilllv;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-
-    skillnum = va_arg (ap, int);
-    skilllv = va_arg (ap, int);
-    tick = va_arg (ap, unsigned int);
-
-    if (src == bl)              //自分には効かない
-        return 0;
-
-    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
-        skill_additional_effect (src, bl, skillnum, skilllv, BF_MISC, tick);
-    else if (battle_check_target (src, bl, BCT_PARTY) > 0)
-    {
-        if (MRAND (100) < 10)   //PTメンバにも低確率でかかる(とりあえず10%)
-            skill_additional_effect (src, bl, skillnum, skilllv, BF_MISC,
-                                     tick);
-    }
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int skill_attack_area (struct block_list *bl, va_list ap)
-{
-    struct block_list *src, *dsrc;
-    int  atk_type, skillid, skilllv, flag, type;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    atk_type = va_arg (ap, int);
-    if ((src = va_arg (ap, struct block_list *)) == NULL)
-        return 0;
-    if ((dsrc = va_arg (ap, struct block_list *)) == NULL)
-        return 0;
-    skillid = va_arg (ap, int);
-    skilllv = va_arg (ap, int);
-    tick = va_arg (ap, unsigned int);
-    flag = va_arg (ap, int);
-    type = va_arg (ap, int);
-
-    if (battle_check_target (dsrc, bl, type) > 0)
-        skill_attack (atk_type, src, dsrc, bl, skillid, skilllv, tick, flag);
-
-    return 0;
-}
-
-/*==========================================
- *
- *------------------------------------------
- */
-int skill_clear_element_field (struct block_list *bl)
-{
-    struct mob_data *md = NULL;
-    struct map_session_data *sd = NULL;
-    int  i, skillid;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_MOB)
-        md = (struct mob_data *) bl;
-    if (bl->type == BL_PC)
-        sd = (struct map_session_data *) bl;
-
-    for (i = 0; i < MAX_MOBSKILLUNITGROUP; i++)
-    {
-        if (sd)
-        {
-            skillid = sd->skillunit[i].skill_id;
-            if (skillid == SA_DELUGE || skillid == SA_VOLCANO
-                || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR)
-                skill_delunitgroup (&sd->skillunit[i]);
-        }
-        else if (md)
-        {
-            skillid = md->skillunit[i].skill_id;
-            if (skillid == SA_DELUGE || skillid == SA_VOLCANO
-                || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR)
-                skill_delunitgroup (&md->skillunit[i]);
-        }
-    }
-    return 0;
-}
-
-/*==========================================
- * ランドプロテクターチェック(foreachinarea)
- *------------------------------------------
- */
-int skill_landprotector (struct block_list *bl, va_list ap)
-{
-    int  skillid;
-    int *alive;
-    struct skill_unit *unit;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    skillid = va_arg (ap, int);
-    alive = va_arg (ap, int *);
-    if ((unit = (struct skill_unit *) bl) == NULL)
-        return 0;
-
-    if (skillid == SA_LANDPROTECTOR)
-    {
-        skill_delunit (unit);
-    }
-    else
-    {
-        if (alive && unit->group->skill_id == SA_LANDPROTECTOR)
-            (*alive) = 0;
-    }
-    return 0;
-}
-
-/*==========================================
- * イドゥンの林檎の回復処理(foreachinarea)
- *------------------------------------------
- */
-int skill_idun_heal (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    struct skill_unit_group *sg;
-    int  heal;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, unit = va_arg (ap, struct skill_unit *));
-    nullpo_retr (0, sg = unit->group);
-
-    heal =
-        30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 +
-        ((sg->val1) & 0xfff) / 2;
-
-    if (bl->type == BL_SKILL || bl->id == sg->src_id)
-        return 0;
-
-    if (bl->type == BL_PC || bl->type == BL_MOB)
-    {
-        clif_skill_nodamage (&unit->bl, bl, AL_HEAL, heal, 1);
-        battle_heal (NULL, bl, heal, 0, 0);
-    }
-    return 0;
-}
-
-/*==========================================
- * 指定範囲内でsrcに対して有効なターゲットのblの数を数える(foreachinarea)
- *------------------------------------------
- */
-int skill_count_target (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    int *c;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-
-    if ((src = va_arg (ap, struct block_list *)) == NULL)
-        return 0;
-    if ((c = va_arg (ap, int *)) == NULL)
-        return 0;
-    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
-        (*c)++;
-    return 0;
-}
-
-/*==========================================
- * トラップ範囲処理(foreachinarea)
- *------------------------------------------
- */
-int skill_trap_splash (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    int  tick;
-    int  splash_count;
-    struct skill_unit *unit;
-    struct skill_unit_group *sg;
-    struct block_list *ss;
-    int  i;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    nullpo_retr (0, unit = (struct skill_unit *) src);
-    nullpo_retr (0, sg = unit->group);
-    nullpo_retr (0, ss = map_id2bl (sg->src_id));
-
-    tick = va_arg (ap, int);
-    splash_count = va_arg (ap, int);
-
-    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
-    {
-        switch (sg->unit_id)
-        {
-            case 0x95:         /* サンドマン */
-            case 0x96:         /* フラッシャー */
-            case 0x94:         /* ショックウェーブトラップ */
-                skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv,
-                                         BF_MISC, tick);
-                break;
-            case 0x8f:         /* ブラストマイン */
-            case 0x98:         /* クレイモアートラップ */
-                for (i = 0; i < splash_count; i++)
-                {
-                    skill_attack (BF_MISC, ss, src, bl, sg->skill_id,
-                                  sg->skill_lv, tick,
-                                  (sg->val2) ? 0x0500 : 0);
-                }
-            case 0x97:         /* フリージングトラップ */
-                skill_attack (BF_WEAPON, ss, src, bl, sg->skill_id,
-                              sg->skill_lv, tick, (sg->val2) ? 0x0500 : 0);
-                break;
-            default:
-                break;
-        }
-    }
-
-    return 0;
-}
-
-/*----------------------------------------------------------------------------
- * ステータス異常
- *----------------------------------------------------------------------------
- */
-
-/*==========================================
- * ステータス異常タイマー範囲処理
- *------------------------------------------
- */
-int skill_status_change_timer_sub (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    int  type;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    type = va_arg (ap, int);
-    tick = va_arg (ap, unsigned int);
-
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-        return 0;
-
-    switch (type)
-    {
-        case SC_SIGHT:         /* サイト */
-        case SC_CONCENTRATE:
-            if ((*battle_get_option (bl)) & 6)
-            {
-                skill_status_change_end (bl, SC_HIDING, -1);
-                skill_status_change_end (bl, SC_CLOAKING, -1);
-            }
-            break;
-        case SC_RUWACH:        /* ルアフ */
-            if ((*battle_get_option (bl)) & 6)
-            {
-                skill_status_change_end (bl, SC_HIDING, -1);
-                skill_status_change_end (bl, SC_CLOAKING, -1);
-                if (battle_check_target (src, bl, BCT_ENEMY) > 0)
-                {
-                    struct status_change *sc_data = battle_get_sc_data (bl);
-                    skill_attack (BF_MAGIC, src, src, bl, AL_RUWACH,
-                                  sc_data[type].val1, tick, 0);
-                }
-            }
-            break;
-    }
-    return 0;
-}
-
-/*==========================================
- * ステータス異常終了
- *------------------------------------------
- */
-int skill_status_change_active (struct block_list *bl, int type)
-{
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-    {
-        if (battle_config.error_log)
-            printf ("skill_status_change_active: neither MOB nor PC !\n");
-        return 0;
-    }
-
-    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
-
-    return sc_data[type].timer != -1;
-}
-
-int skill_status_change_end (struct block_list *bl, int type, int tid)
-{
-    struct status_change *sc_data;
-    int  opt_flag = 0, calc_flag = 0;
-    short *sc_count, *option, *opt1, *opt2, *opt3;
-
-    nullpo_retr (0, bl);
-    if (bl->type != BL_PC && bl->type != BL_MOB)
-    {
-        if (battle_config.error_log)
-            printf ("skill_status_change_end: neither MOB nor PC !\n");
-        return 0;
-    }
-    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
-    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
-    nullpo_retr (0, option = battle_get_option (bl));
-    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
-    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
-    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
-
-    if ((*sc_count) > 0 && sc_data[type].timer != -1
-        && (sc_data[type].timer == tid || tid == -1))
-    {
-
-        if (tid == -1)          // タイマから呼ばれていないならタイマ削除をする
-            delete_timer (sc_data[type].timer, skill_status_change_timer);
-
-        /* 該当の異常を正常に戻す */
-        sc_data[type].timer = -1;
-        (*sc_count)--;
-
-        switch (type)
-        {                       /* 異常の種類ごとの処理 */
-            case SC_PROVOKE:   /* プロボック */
-            case SC_CONCENTRATE:   /* 集中力向上 */
-            case SC_BLESSING:  /* ブレッシング */
-            case SC_ANGELUS:   /* アンゼルス */
-            case SC_INCREASEAGI:   /* 速度上昇 */
-            case SC_DECREASEAGI:   /* 速度減少 */
-            case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
-            case SC_HIDING:
-            case SC_TWOHANDQUICKEN:    /* 2HQ */
-            case SC_ADRENALINE:    /* アドレナリンラッシュ */
-            case SC_ENCPOISON: /* エンチャントポイズン */
-            case SC_IMPOSITIO: /* インポシティオマヌス */
-            case SC_GLORIA:    /* グロリア */
-            case SC_LOUD:      /* ラウドボイス */
-            case SC_QUAGMIRE:  /* クァグマイア */
-            case SC_PROVIDENCE:    /* プロヴィデンス */
-            case SC_SPEARSQUICKEN: /* スピアクイッケン */
-            case SC_VOLCANO:
-            case SC_DELUGE:
-            case SC_VIOLENTGALE:
-            case SC_ETERNALCHAOS:  /* エターナルカオス */
-            case SC_DRUMBATTLE:    /* 戦太鼓の響き */
-            case SC_NIBELUNGEN:    /* ニーベルングの指輪 */
-            case SC_SIEGFRIED: /* 不死身のジークフリード */
-            case SC_WHISTLE:   /* 口笛 */
-            case SC_ASSNCROS:  /* 夕陽のアサシンクロス */
-            case SC_HUMMING:   /* ハミング */
-            case SC_DONTFORGETME:  /* 私を忘れないで */
-            case SC_FORTUNE:   /* 幸運のキス */
-            case SC_SERVICE4U: /* サービスフォーユー */
-            case SC_EXPLOSIONSPIRITS:  // 爆裂波動
-            case SC_STEELBODY: // 金剛
-            case SC_DEFENDER:
-            case SC_SPEEDPOTION0:  /* 増速ポーション */
-            case SC_SPEEDPOTION1:
-            case SC_SPEEDPOTION2:
-            case SC_APPLEIDUN: /* イドゥンの林檎 */
-            case SC_RIDING:
-            case SC_BLADESTOP_WAIT:
-            case SC_AURABLADE: /* オーラブレード */
-            case SC_PARRYING:  /* パリイング */
-            case SC_CONCENTRATION: /* コンセントレーション */
-            case SC_TENSIONRELAX:  /* テンションリラックス */
-            case SC_ASSUMPTIO: /* アシャンプティオ */
-            case SC_WINDWALK:  /* ウインドウォーク */
-            case SC_TRUESIGHT: /* トゥルーサイト */
-            case SC_SPIDERWEB: /* スパイダーウェッブ */
-            case SC_MAGICPOWER:    /* 魔法力増幅 */
-            case SC_CHASEWALK:
-            case SC_ATKPOT:    /* attack potion [Valaris] */
-            case SC_MATKPOT:   /* magic attack potion [Valaris] */
-            case SC_WEDDING:   //結婚用(結婚衣裳になって歩くのが遅いとか)
-            case SC_MELTDOWN:  /* メルトダウン */
-            case SC_PHYS_SHIELD:
-            case SC_HASTE:
-                calc_flag = 1;
-                break;
-            case SC_BERSERK:   /* バーサーク */
-                calc_flag = 1;
-                clif_status_change (bl, SC_INCREASEAGI, 0); /* アイコン消去 */
-                break;
-            case SC_DEVOTION:  /* ディボーション */
-            {
-                struct map_session_data *md = map_id2sd (sc_data[type].val1);
-                sc_data[type].val1 = sc_data[type].val2 = 0;
-                skill_devotion (md, bl->id);
-                calc_flag = 1;
-            }
-                break;
-            case SC_BLADESTOP:
-            {
-                struct status_change *t_sc_data =
-                    battle_get_sc_data ((struct block_list *)
-                                        sc_data[type].val4);
-                //片方が切れたので相手の白刃状態が切れてないのなら解除
-                if (t_sc_data && t_sc_data[SC_BLADESTOP].timer != -1)
-                    skill_status_change_end ((struct block_list *)
-                                             sc_data[type].val4, SC_BLADESTOP,
-                                             -1);
-
-                if (sc_data[type].val2 == 2)
-                    clif_bladestop ((struct block_list *) sc_data[type].val3,
-                                    (struct block_list *) sc_data[type].val4,
-                                    0);
-            }
-                break;
-            case SC_DANCING:
-            {
-                struct map_session_data *dsd;
-                struct status_change *d_sc_data;
-                if (sc_data[type].val4
-                    && (dsd = map_id2sd (sc_data[type].val4)))
-                {
-                    d_sc_data = dsd->sc_data;
-                    //合奏で相手がいる場合相手のval4を0にする
-                    if (d_sc_data && d_sc_data[type].timer != -1)
-                        d_sc_data[type].val4 = 0;
-                }
-            }
-                calc_flag = 1;
-                break;
-            case SC_GRAFFITI:
-            {
-                struct skill_unit_group *sg = (struct skill_unit_group *) sc_data[type].val4;   //val4がグラフィティのgroup_id
-                if (sg)
-                    skill_delunitgroup (sg);
-            }
-                break;
-            case SC_NOCHAT:    //チャット禁止状態
-            {
-                struct map_session_data *sd = NULL;
-                if (bl->type == BL_PC
-                    && (sd = (struct map_session_data *) bl))
-                {
-                    sd->status.manner = 0;
-                    clif_updatestatus (sd, SP_MANNER);
-                }
-            }
-                break;
-            case SC_SPLASHER:  /* ベナムスプラッシャー */
-            {
-                struct block_list *src = map_id2bl (sc_data[type].val3);
-                if (src && tid != -1)
-                {
-                    //自分にダメージ&周囲3*3にダメージ
-                    skill_castend_damage_id (src, bl, sc_data[type].val2,
-                                             sc_data[type].val1, gettick (),
-                                             0);
-                }
-            }
-                break;
-            case SC_SELFDESTRUCTION:   /* 自爆 */
-            {
-                //自分のダメージは0にして
-                struct mob_data *md = NULL;
-                if (bl->type == BL_MOB && (md = (struct mob_data *) bl))
-                    skill_castend_damage_id (bl, bl, sc_data[type].val2,
-                                             sc_data[type].val1, gettick (),
-                                             0);
-            }
-                break;
-                /* option1 */
-            case SC_FREEZE:
-                sc_data[type].val3 = 0;
-                break;
-
-                /* option2 */
-            case SC_POISON:    /* 毒 */
-            case SC_BLIND:     /* 暗黒 */
-            case SC_CURSE:
-                calc_flag = 1;
-                break;
-        }
-
-        if (bl->type == BL_PC && type < SC_SENDMAX)
-            clif_status_change (bl, type, 0);   /* アイコン消去 */
-
-        switch (type)
-        {                       /* 正常に戻るときなにか処理が必要 */
-            case SC_STONE:
-            case SC_FREEZE:
-            case SC_STAN:
-            case SC_SLEEP:
-                *opt1 = 0;
-                opt_flag = 1;
-                break;
-
-            case SC_POISON:
-            case SC_CURSE:
-            case SC_SILENCE:
-            case SC_BLIND:
-                *opt2 &= ~(1 << (type - SC_POISON));
-                opt_flag = 1;
-                break;
-
-            case SC_SLOWPOISON:
-                if (sc_data[SC_POISON].timer != -1)
-                    *opt2 |= 0x1;
-                *opt2 &= ~0x200;
-                opt_flag = 1;
-                break;
-
-            case SC_SIGNUMCRUCIS:
-                *opt2 &= ~0x40;
-                opt_flag = 1;
-                break;
-
-            case SC_SPEEDPOTION0:
-                *opt2 &= ~0x20;
-                opt_flag = 1;
-                break;
-
-            case SC_ATKPOT:
-                *opt2 &= ~0x80;
-                opt_flag = 1;
-                break;
-
-            case SC_HIDING:
-            case SC_CLOAKING:
-                *option &= ~((type == SC_HIDING) ? 2 : 4);
-                opt_flag = 1;
-                break;
-
-            case SC_CHASEWALK:
-                *option &= ~16388;
-                opt_flag = 1;
-                break;
-
-            case SC_SIGHT:
-                *option &= ~1;
-                opt_flag = 1;
-                break;
-            case SC_WEDDING:   //結婚用(結婚衣裳になって歩くのが遅いとか)
-                *option &= ~4096;
-                opt_flag = 1;
-                break;
-            case SC_RUWACH:
-                *option &= ~8192;
-                opt_flag = 1;
-                break;
-
-                //opt3
-            case SC_TWOHANDQUICKEN:    /* 2HQ */
-            case SC_SPEARSQUICKEN: /* スピアクイッケン */
-            case SC_CONCENTRATION: /* コンセントレーション */
-                *opt3 &= ~1;
-                break;
-            case SC_OVERTHRUST:    /* オーバースラスト */
-                *opt3 &= ~2;
-                break;
-            case SC_ENERGYCOAT:    /* エナジーコート */
-                *opt3 &= ~4;
-                break;
-            case SC_EXPLOSIONSPIRITS:  // 爆裂波動
-                *opt3 &= ~8;
-                break;
-            case SC_STEELBODY: // 金剛
-                *opt3 &= ~16;
-                break;
-            case SC_BLADESTOP: /* 白刃取り */
-                *opt3 &= ~32;
-                break;
-            case SC_BERSERK:   /* バーサーク */
-                *opt3 &= ~128;
-                break;
-            case SC_MARIONETTE:    /* マリオネットコントロール */
-                *opt3 &= ~1024;
-                break;
-            case SC_ASSUMPTIO: /* アスムプティオ */
-                *opt3 &= ~2048;
-                break;
-        }
-
-        if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0
-            && bl->type == BL_PC)
-        {                       // by [Yor]
-            *opt2 |= STATE_BLIND;
-            opt_flag = 1;
-        }
-
-        if (opt_flag)           /* optionの変更を伝える */
-            clif_changeoption (bl);
-
-        if (bl->type == BL_PC && calc_flag)
-            pc_calcstatus ((struct map_session_data *) bl, 0);  /* ステータス再計算 */
-    }
-
-    return 0;
-}
-
-int skill_update_heal_animation (struct map_session_data *sd)
-{
-    const int mask = 0x100;
-    int  was_active;
-    int  is_active;
-
-    nullpo_retr (0, sd);
-    was_active = sd->opt2 & mask;
-    is_active = sd->quick_regeneration_hp.amount > 0;
-
-    if ((was_active && is_active) || (!was_active && !is_active))
-        return 0;               // no update
-
-    if (is_active)
-        sd->opt2 |= mask;
-    else
-        sd->opt2 &= ~mask;
-
-    return clif_changeoption (&sd->bl);
-}
-
-/*==========================================
- * ステータス異常終了タイマー
- *------------------------------------------
- */
-void skill_status_change_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    int  type = data;
-    struct block_list *bl;
-    struct map_session_data *sd = NULL;
-    struct status_change *sc_data;
-    //short *sc_count; //使ってない?
-
-    if ((bl = map_id2bl (id)) == NULL)
-        return;               //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる
-    nullpo_retv (sc_data = battle_get_sc_data (bl));
-
-    if (bl->type == BL_PC)
-        sd = (struct map_session_data *) bl;
-
-    //sc_count=battle_get_sc_count(bl); //使ってない?
-
-    if (sc_data[type].timer != tid)
-    {
-        if (battle_config.error_log)
-            printf ("skill_status_change_timer %d != %d\n", tid,
-                    sc_data[type].timer);
-    }
-
-    if (sc_data[type].spell_invocation)
-    {                           // Must report termination
-        spell_effect_report_termination (sc_data[type].spell_invocation,
-                                         bl->id, type, 0);
-        sc_data[type].spell_invocation = 0;
-    }
-
-    switch (type)
-    {                           /* 特殊な処理になる場合 */
-        case SC_MAXIMIZEPOWER: /* マキシマイズパワー */
-        case SC_CLOAKING:      /* クローキング */
-        case SC_CHASEWALK:
-            if (sd)
-            {
-                if (sd->status.sp > 0)
-                {               /* SP切れるまで持続 */
-                    sd->status.sp--;
-                    clif_updatestatus (sd, SP_SP);
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        sc_data[type].val2 +
-                                                        tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-            break;
-
-        case SC_HIDING:        /* ハイディング */
-            if (sd)
-            {                   /* SPがあって、時間制限の間は持続 */
-                if (sd->status.sp > 0 && (--sc_data[type].val2) > 0)
-                {
-                    if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0)
-                    {
-                        sd->status.sp--;
-                        clif_updatestatus (sd, SP_SP);
-                    }
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        1000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-            break;
-
-        case SC_SIGHT:         /* サイト */
-        {
-            const int range = 7;
-            map_foreachinarea (skill_status_change_timer_sub,
-                               bl->m, bl->x - range, bl->y - range,
-                               bl->x + range, bl->y + range, 0, bl, type,
-                               tick);
-
-            if ((--sc_data[type].val2) > 0)
-            {
-                sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                    250 + tick,
-                                                    skill_status_change_timer,
-                                                    bl->id, data);
-                return;
-            }
-        }
-            break;
-        case SC_RUWACH:        /* ルアフ */
-        {
-            const int range = 5;
-            map_foreachinarea (skill_status_change_timer_sub,
-                               bl->m, bl->x - range, bl->y - range,
-                               bl->x + range, bl->y + range, 0, bl, type,
-                               tick);
-
-            if ((--sc_data[type].val2) > 0)
-            {
-                sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                    250 + tick,
-                                                    skill_status_change_timer,
-                                                    bl->id, data);
-                return;
-            }
-        }
-            break;
-
-        case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
-        {
-            int  race = battle_get_race (bl);
-            if (race == 6
-                || battle_check_undead (race, battle_get_elem_type (bl)))
-            {
-                sc_data[type].timer =
-                    add_timer (1000 * 600 + tick, skill_status_change_timer,
-                               bl->id, data);
-                return;
-            }
-        }
-            break;
-
-        case SC_PROVOKE:       /* プロボック/オートバーサーク */
-            if (sc_data[type].val2 != 0)
-            {                   /* オートバーサーク(1秒ごとにHPチェック) */
-                if (sd && sd->status.hp > sd->status.max_hp >> 2)   /* 停止 */
-                    break;
-                sc_data[type].timer =
-                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
-                               data);
-                return;
-            }
-            break;
-
-        case SC_WATERBALL:     /* ウォーターボール */
-        {
-            struct block_list *target = map_id2bl (sc_data[type].val2);
-            if (target == NULL || target->prev == NULL)
-                break;
-            skill_attack (BF_MAGIC, bl, bl, target, WZ_WATERBALL,
-                          sc_data[type].val1, tick, 0);
-            if ((--sc_data[type].val3) > 0)
-            {
-                sc_data[type].timer =
-                    add_timer (150 + tick, skill_status_change_timer, bl->id,
-                               data);
-                return;
-            }
-        }
-            break;
-
-        case SC_ENDURE:        /* インデュア */
-            if (sd && sd->special_state.infinite_endure)
-            {
-                sc_data[type].timer =
-                    add_timer (1000 * 600 + tick, skill_status_change_timer,
-                               bl->id, data);
-                sc_data[type].val2 = 1;
-                return;
-            }
-            break;
-
-        case SC_DISSONANCE:    /* 不協和音 */
-            if ((--sc_data[type].val2) > 0)
-            {
-                struct skill_unit *unit =
-                    (struct skill_unit *) sc_data[type].val4;
-                struct block_list *src;
-
-                if (!unit || !unit->group)
-                    break;
-                src = map_id2bl (unit->group->src_id);
-                if (!src)
-                    break;
-                skill_attack (BF_MISC, src, &unit->bl, bl,
-                              unit->group->skill_id, sc_data[type].val1, tick,
-                              0);
-                sc_data[type].timer =
-                    add_timer (skill_get_time2
-                               (unit->group->skill_id,
-                                unit->group->skill_lv) + tick,
-                               skill_status_change_timer, bl->id, data);
-                return;
-            }
-            break;
-
-        case SC_LULLABY:       /* 子守唄 */
-            if ((--sc_data[type].val2) > 0)
-            {
-                struct skill_unit *unit =
-                    (struct skill_unit *) sc_data[type].val4;
-                if (!unit || !unit->group || unit->group->src_id == bl->id)
-                    break;
-                skill_additional_effect (bl, bl, unit->group->skill_id,
-                                         sc_data[type].val1,
-                                         BF_LONG | BF_SKILL | BF_MISC, tick);
-                sc_data[type].timer =
-                    add_timer (skill_get_time
-                               (unit->group->skill_id,
-                                unit->group->skill_lv) / 10 + tick,
-                               skill_status_change_timer, bl->id, data);
-                return;
-            }
-            break;
-
-        case SC_STONE:
-            if (sc_data[type].val2 != 0)
-            {
-                short *opt1 = battle_get_opt1 (bl);
-                sc_data[type].val2 = 0;
-                sc_data[type].val4 = 0;
-                battle_stopwalking (bl, 1);
-                if (opt1)
-                {
-                    *opt1 = 1;
-                    clif_changeoption (bl);
-                }
-                sc_data[type].timer =
-                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
-                               data);
-                return;
-            }
-            else if ((--sc_data[type].val3) > 0)
-            {
-                int  hp = battle_get_max_hp (bl);
-                if ((++sc_data[type].val4) % 5 == 0
-                    && battle_get_hp (bl) > hp >> 2)
-                {
-                    hp = hp / 100;
-                    if (hp < 1)
-                        hp = 1;
-                    if (bl->type == BL_PC)
-                        pc_heal ((struct map_session_data *) bl, -hp, 0);
-                    else if (bl->type == BL_MOB)
-                    {
-                        struct mob_data *md;
-                        if ((md = ((struct mob_data *) bl)) == NULL)
-                            break;
-                        md->hp -= hp;
-                    }
-                }
-                sc_data[type].timer =
-                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
-                               data);
-                return;
-            }
-            break;
-        case SC_POISON:
-            if (sc_data[SC_SLOWPOISON].timer == -1)
-            {
-                const int resist_poison =
-                    skill_power_bl (bl, TMW_RESIST_POISON) >> 3;
-                if (resist_poison)
-                    sc_data[type].val1 -= MRAND (resist_poison + 1);
-
-                if ((--sc_data[type].val1) > 0)
-                {
-
-                    int  hp = battle_get_max_hp (bl);
-                    if (battle_get_hp (bl) > hp >> 4)
-                    {
-                        if (bl->type == BL_PC)
-                        {
-                            hp = 3 + hp * 3 / 200;
-                            pc_heal ((struct map_session_data *) bl, -hp, 0);
-                        }
-                        else if (bl->type == BL_MOB)
-                        {
-                            struct mob_data *md;
-                            if ((md = ((struct mob_data *) bl)) == NULL)
-                                break;
-                            hp = 3 + hp / 200;
-                            md->hp -= hp;
-                        }
-                    }
-                    sc_data[type].timer =
-                        add_timer (1000 + tick, skill_status_change_timer,
-                                   bl->id, data);
-                }
-            }
-            else
-                sc_data[type].timer =
-                    add_timer (2000 + tick, skill_status_change_timer, bl->id,
-                               data);
-            break;
-
-        case SC_TENSIONRELAX:  /* テンションリラックス */
-            if (sd)
-            {                   /* SPがあって、HPが満タンでなければ継続 */
-                if (sd->status.sp > 12 && sd->status.max_hp > sd->status.hp)
-                {
-                    if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0)
-                    {
-                        sd->status.sp -= 12;
-                        clif_updatestatus (sd, SP_SP);
-                    }
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        10000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-                if (sd->status.max_hp <= sd->status.hp)
-                    skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1);
-            }
-            break;
-
-            /* 時間切れ無し?? */
-        case SC_AETERNA:
-        case SC_TRICKDEAD:
-        case SC_RIDING:
-        case SC_FALCON:
-        case SC_WEIGHT50:
-        case SC_WEIGHT90:
-        case SC_MAGICPOWER:    /* 魔法力増幅 */
-        case SC_REJECTSWORD:   /* リジェクトソード */
-        case SC_MEMORIZE:      /* メモライズ */
-        case SC_BROKNWEAPON:
-        case SC_BROKNARMOR:
-            if (sc_data[type].timer == tid)
-                sc_data[type].timer =
-                    add_timer (1000 * 600 + tick, skill_status_change_timer,
-                               bl->id, data);
-            return;
-
-        case SC_DANCING:       //ダンススキルの時間SP消費
-        {
-            int  s = 0;
-            if (sd)
-            {
-                if (sd->status.sp > 0 && (--sc_data[type].val3) > 0)
-                {
-                    switch (sc_data[type].val1)
-                    {
-                        case BD_RICHMANKIM:    /* ニヨルドの宴 3秒にSP1 */
-                        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き 3秒にSP1 */
-                        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 3秒にSP1 */
-                        case BD_SIEGFRIED: /* 不死身のジークフリード 3秒にSP1 */
-                        case BA_DISSONANCE:    /* 不協和音 3秒でSP1 */
-                        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */
-                        case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */
-                            s = 3;
-                            break;
-                        case BD_LULLABY:   /* 子守歌 4秒にSP1 */
-                        case BD_ETERNALCHAOS:  /* 永遠の混沌 4秒にSP1 */
-                        case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */
-                        case DC_FORTUNEKISS:   /* 幸運のキス 4秒でSP1 */
-                            s = 4;
-                            break;
-                        case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */
-                        case BA_WHISTLE:   /* 口笛 5秒でSP1 */
-                        case DC_HUMMING:   /* ハミング 5秒でSP1 */
-                        case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */
-                        case DC_SERVICEFORYOU: /* サービスフォーユー 5秒でSP1 */
-                            s = 5;
-                            break;
-                        case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */
-                            s = 6;
-                            break;
-                        case DC_DONTFORGETME:  /* 私を忘れないで… 10秒でSP1 */
-                        case CG_MOONLIT:   /* 月明りの泉に落ちる花びら 10秒でSP1? */
-                            s = 10;
-                            break;
-                    }
-                    if (s && ((sc_data[type].val3 % s) == 0))
-                    {
-                        sd->status.sp--;
-                        clif_updatestatus (sd, SP_SP);
-                    }
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        1000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-        }
-            break;
-        case SC_BERSERK:       /* バーサーク */
-            if (sd)
-            {                   /* HPが100以上なら継続 */
-                if ((sd->status.hp - sd->status.hp / 100) > 100)
-                {
-                    sd->status.hp -= sd->status.hp / 100;
-                    clif_updatestatus (sd, SP_HP);
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        15000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-            break;
-        case SC_WEDDING:       //結婚用(結婚衣裳になって歩くのが遅いとか)
-            if (sd)
-            {
-                time_t timer;
-                if (time (&timer) < ((sc_data[type].val2) + 3600))
-                {               //1時間たっていないので継続
-                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                        10000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-            break;
-        case SC_NOCHAT:        //チャット禁止状態
-            if (sd && battle_config.muting_players)
-            {
-                time_t timer;
-                if ((++sd->status.manner)
-                    && time (&timer) <
-                    ((sc_data[type].val2) + 60 * (0 - sd->status.manner)))
-                {               //開始からstatus.manner分経ってないので継続
-                    clif_updatestatus (sd, SP_MANNER);
-                    sc_data[type].timer = add_timer (   /* タイマー再設定(60秒) */
-                                                        60000 + tick,
-                                                        skill_status_change_timer,
-                                                        bl->id, data);
-                    return;
-                }
-            }
-            break;
-        case SC_SELFDESTRUCTION:   /* 自爆 */
-            if (--sc_data[type].val3 > 0)
-            {
-                struct mob_data *md;
-                if (bl->type == BL_MOB && (md = (struct mob_data *) bl)
-                    && md->stats[MOB_SPEED] > 250)
-                {
-                    md->stats[MOB_SPEED] -= 250;
-                    md->next_walktime = tick;
-                }
-                sc_data[type].timer = add_timer (   /* タイマー再設定 */
-                                                    1000 + tick,
-                                                    skill_status_change_timer,
-                                                    bl->id, data);
-                return;
-            }
-            break;
-
-        case SC_FLYING_BACKPACK:
-            clif_updatestatus (sd, SP_WEIGHT);
-            break;
-
-    }
-
-    skill_status_change_end (bl, type, tid);
-}
-
-/*==========================================
- * ステータス異常終了
- *------------------------------------------
- */
-int skill_encchant_eremental_end (struct block_list *bl, int type)
-{
-    struct status_change *sc_data;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
-
-    if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1)  /* エンチャントポイズン解除 */
-        skill_status_change_end (bl, SC_ENCPOISON, -1);
-    if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1)    /* アスペルシオ解除 */
-        skill_status_change_end (bl, SC_ASPERSIO, -1);
-    if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1)  /* フレイムランチャ解除 */
-        skill_status_change_end (bl, SC_FLAMELAUNCHER, -1);
-    if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1)  /* フロストウェポン解除 */
-        skill_status_change_end (bl, SC_FROSTWEAPON, -1);
-    if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1)  /* ライトニングローダー解除 */
-        skill_status_change_end (bl, SC_LIGHTNINGLOADER, -1);
-    if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1)  /* サイスミックウェポン解除 */
-        skill_status_change_end (bl, SC_SEISMICWEAPON, -1);
-
-    return 0;
-}
-
-/*==========================================
- * ステータス異常開始
- *------------------------------------------
- */
-int skill_status_change_start (struct block_list *bl, int type, int val1,
-                               int val2, int val3, int val4, int tick,
-                               int flag)
-{
-    return skill_status_effect (bl, type, val1, val2, val3, val4, tick, flag,
-                                0);
-}
-
-int skill_status_effect (struct block_list *bl, int type, int val1, int val2,
-                         int val3, int val4, int tick, int flag,
-                         int spell_invocation)
-{
-    struct map_session_data *sd = NULL;
-    struct status_change *sc_data;
-    short *sc_count, *option, *opt1, *opt2, *opt3;
-    int  opt_flag = 0, calc_flag = 0, updateflag =
-        0, race, mode, elem, undead_flag;
-    int  scdef = 0;
-
-    nullpo_retr (0, bl);
-    if (bl->type == BL_SKILL)
-        return 0;
-    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
-    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
-    nullpo_retr (0, option = battle_get_option (bl));
-    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
-    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
-    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
-
-    race = battle_get_race (bl);
-    mode = battle_get_mode (bl);
-    elem = battle_get_elem_type (bl);
-    undead_flag = battle_check_undead (race, elem);
-
-    if (type == SC_AETERNA
-        && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1))
-        return 0;
-
-    switch (type)
-    {
-        case SC_STONE:
-        case SC_FREEZE:
-            scdef = 3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3;
-            break;
-        case SC_STAN:
-        case SC_SILENCE:
-        case SC_POISON:
-            scdef = 3 + battle_get_vit (bl) + battle_get_luk (bl) / 3;
-            break;
-        case SC_SLEEP:
-        case SC_BLIND:
-            scdef = 3 + battle_get_int (bl) + battle_get_luk (bl) / 3;
-            break;
-        case SC_CURSE:
-            scdef = 3 + battle_get_luk (bl);
-            break;
-
-//      case SC_CONFUSION:
-        default:
-            scdef = 0;
-    }
-    if (scdef >= 100)
-        return 0;
-    if (bl->type == BL_PC)
-    {
-        sd = (struct map_session_data *) bl;
-        if (sd && type == SC_ADRENALINE
-            && !(skill_get_weapontype (BS_ADRENALINE) &
-                 (1 << sd->status.weapon)))
-            return 0;
-
-        if (SC_STONE <= type && type <= SC_BLIND)
-        {                       /* カードによる耐性 */
-            if (sd && sd->reseff[type - SC_STONE] > 0
-                && MRAND (10000) < sd->reseff[type - SC_STONE])
-            {
-                if (battle_config.battle_log)
-                    printf ("PC %d skill_sc_start: cardによる異常耐性発動\n",
-                            sd->bl.id);
-                return 0;
-            }
-        }
-    }
-    else if (bl->type == BL_MOB)
-    {
-    }
-    else
-    {
-        if (battle_config.error_log)
-            printf ("skill_status_change_start: neither MOB nor PC !\n");
-        return 0;
-    }
-
-    if (type == SC_FREEZE && undead_flag && !(flag & 1))
-        return 0;
-
-    if ((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION
-         || type == SC_OVERTHRUST) && sc_data[type].timer != -1
-        && sc_data[type].val2 && !val2)
-        return 0;
-
-    if (mode & 0x20 && (type == SC_STONE || type == SC_FREEZE ||
-                        type == SC_STAN || type == SC_SLEEP
-                        || type == SC_SILENCE || type == SC_QUAGMIRE
-                        || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS
-                        || type == SC_PROVOKE || (type == SC_BLESSING
-                                                  && (undead_flag
-                                                      || race == 6)))
-        && !(flag & 1))
-    {
-        /* ボスには効かない(ただしカードによる効果は適用される) */
-        return 0;
-    }
-    if (type == SC_FREEZE || type == SC_STAN || type == SC_SLEEP)
-        battle_stopwalking (bl, 1);
-
-    if (sc_data[type].timer != -1)
-    {                           /* すでに同じ異常になっている場合タイマ解除 */
-        if (sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
-            return 0;
-        if (type >= SC_STAN && type <= SC_BLIND)
-            return 0;           /* 継ぎ足しができない状態異常である時は状態異常を行わない */
-        if (type == SC_GRAFFITI)
-        {                       //異常中にもう一度状態異常になった時に解除してから再度かかる
-            skill_status_change_end (bl, type, -1);
-        }
-        else
-        {
-            (*sc_count)--;
-            delete_timer (sc_data[type].timer, skill_status_change_timer);
-            sc_data[type].timer = -1;
-        }
-    }
-
-    switch (type)
-    {                           /* 異常の種類ごとの処理 */
-        case SC_PROVOKE:       /* プロボック */
-            calc_flag = 1;
-            if (tick <= 0)
-                tick = 1000;    /* (オートバーサーク) */
-            break;
-        case SC_ENDURE:        /* インデュア */
-            if (tick <= 0)
-                tick = 1000 * 60;
-            break;
-        case SC_CONCENTRATE:   /* 集中力向上 */
-            calc_flag = 1;
-            break;
-        case SC_BLESSING:      /* ブレッシング */
-        {
-            if (bl->type == BL_PC || (!undead_flag && race != 6))
-            {
-                if (sc_data[SC_CURSE].timer != -1)
-                    skill_status_change_end (bl, SC_CURSE, -1);
-                if (sc_data[SC_STONE].timer != -1
-                    && sc_data[SC_STONE].val2 == 0)
-                    skill_status_change_end (bl, SC_STONE, -1);
-            }
-            calc_flag = 1;
-        }
-            break;
-        case SC_ANGELUS:       /* アンゼルス */
-            calc_flag = 1;
-            break;
-        case SC_INCREASEAGI:   /* 速度上昇 */
-            calc_flag = 1;
-            if (sc_data[SC_DECREASEAGI].timer != -1)
-                skill_status_change_end (bl, SC_DECREASEAGI, -1);
-            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
-                skill_status_change_end (bl, SC_WINDWALK, -1);
-            break;
-        case SC_DECREASEAGI:   /* 速度減少 */
-            calc_flag = 1;
-            if (sc_data[SC_INCREASEAGI].timer != -1)
-                skill_status_change_end (bl, SC_INCREASEAGI, -1);
-            break;
-        case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
-            calc_flag = 1;
-//          val2 = 14 + val1;
-            val2 = 10 + val1 * 2;
-            tick = 600 * 1000;
-            clif_emotion (bl, 4);
-            break;
-        case SC_SLOWPOISON:
-            if (sc_data[SC_POISON].timer == -1)
-                return 0;
-            break;
-        case SC_TWOHANDQUICKEN:    /* 2HQ */
-            *opt3 |= 1;
-            calc_flag = 1;
-            break;
-        case SC_ADRENALINE:    /* アドレナリンラッシュ */
-            calc_flag = 1;
-            break;
-        case SC_WEAPONPERFECTION:  /* ウェポンパーフェクション */
-            if (battle_config.party_skill_penaly && !val2)
-                tick /= 5;
-            break;
-        case SC_OVERTHRUST:    /* オーバースラスト */
-            *opt3 |= 2;
-            if (battle_config.party_skill_penaly && !val2)
-                tick /= 10;
-            break;
-        case SC_MAXIMIZEPOWER: /* マキシマイズパワー(SPが1減る時間,val2にも) */
-            if (bl->type == BL_PC)
-                val2 = tick;
-            else
-                tick = 5000 * val1;
-            break;
-        case SC_ENCPOISON:     /* エンチャントポイズン */
-            calc_flag = 1;
-            val2 = (((val1 - 1) / 2) + 3) * 100;    /* 毒付与確率 */
-            skill_encchant_eremental_end (bl, SC_ENCPOISON);
-            break;
-        case SC_POISONREACT:   /* ポイズンリアクト */
-            break;
-        case SC_IMPOSITIO:     /* インポシティオマヌス */
-            calc_flag = 1;
-            break;
-        case SC_ASPERSIO:      /* アスペルシオ */
-            skill_encchant_eremental_end (bl, SC_ASPERSIO);
-            break;
-        case SC_SUFFRAGIUM:    /* サフラギム */
-        case SC_BENEDICTIO:    /* 聖体 */
-        case SC_MAGNIFICAT:    /* マグニフィカート */
-        case SC_AETERNA:       /* エーテルナ */
-            break;
-        case SC_ENERGYCOAT:    /* エナジーコート */
-            *opt3 |= 4;
-            break;
-        case SC_MAGICROD:
-            val2 = val1 * 20;
-            break;
-        case SC_KYRIE:         /* キリエエレイソン */
-            val2 = battle_get_max_hp (bl) * (val1 * 2 + 10) / 100;  /* 耐久度 */
-            val3 = (val1 / 2 + 5);  /* 回数 */
-// -- moonsoul (added to undo assumptio status if target has it)
-            if (sc_data[SC_ASSUMPTIO].timer != -1)
-                skill_status_change_end (bl, SC_ASSUMPTIO, -1);
-            break;
-        case SC_MINDBREAKER:
-            calc_flag = 1;
-            if (tick <= 0)
-                tick = 1000;    /* (オートバーサーク) */
-        case SC_GLORIA:        /* グロリア */
-            calc_flag = 1;
-            break;
-        case SC_LOUD:          /* ラウドボイス */
-            calc_flag = 1;
-            break;
-        case SC_TRICKDEAD:     /* 死んだふり */
-            break;
-        case SC_QUAGMIRE:      /* クァグマイア */
-            calc_flag = 1;
-            if (sc_data[SC_CONCENTRATE].timer != -1)    /* 集中力向上解除 */
-                skill_status_change_end (bl, SC_CONCENTRATE, -1);
-            if (sc_data[SC_INCREASEAGI].timer != -1)    /* 速度上昇解除 */
-                skill_status_change_end (bl, SC_INCREASEAGI, -1);
-            if (sc_data[SC_TWOHANDQUICKEN].timer != -1)
-                skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1);
-            if (sc_data[SC_SPEARSQUICKEN].timer != -1)
-                skill_status_change_end (bl, SC_SPEARSQUICKEN, -1);
-            if (sc_data[SC_ADRENALINE].timer != -1)
-                skill_status_change_end (bl, SC_ADRENALINE, -1);
-            if (sc_data[SC_LOUD].timer != -1)
-                skill_status_change_end (bl, SC_LOUD, -1);
-            if (sc_data[SC_TRUESIGHT].timer != -1)  /* トゥルーサイト */
-                skill_status_change_end (bl, SC_TRUESIGHT, -1);
-            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
-                skill_status_change_end (bl, SC_WINDWALK, -1);
-            if (sc_data[SC_CARTBOOST].timer != -1)  /* カートブースト */
-                skill_status_change_end (bl, SC_CARTBOOST, -1);
-            break;
-        case SC_FLAMELAUNCHER: /* フレームランチャー */
-            skill_encchant_eremental_end (bl, SC_FLAMELAUNCHER);
-            break;
-        case SC_FROSTWEAPON:   /* フロストウェポン */
-            skill_encchant_eremental_end (bl, SC_FROSTWEAPON);
-            break;
-        case SC_LIGHTNINGLOADER:   /* ライトニングローダー */
-            skill_encchant_eremental_end (bl, SC_LIGHTNINGLOADER);
-            break;
-        case SC_SEISMICWEAPON: /* サイズミックウェポン */
-            skill_encchant_eremental_end (bl, SC_SEISMICWEAPON);
-            break;
-        case SC_DEVOTION:      /* ディボーション */
-            calc_flag = 1;
-            break;
-        case SC_PROVIDENCE:    /* プロヴィデンス */
-            calc_flag = 1;
-            val2 = val1 * 5;
-            break;
-        case SC_REFLECTSHIELD:
-            val2 = 10 + val1 * 3;
-            break;
-        case SC_STRIPWEAPON:
-        case SC_STRIPSHIELD:
-        case SC_STRIPARMOR:
-        case SC_STRIPHELM:
-        case SC_CP_WEAPON:
-        case SC_CP_SHIELD:
-        case SC_CP_ARMOR:
-        case SC_CP_HELM:
-            break;
-
-        case SC_AUTOSPELL:     /* オートスペル */
-            val4 = 5 + val1 * 2;
-            break;
-
-        case SC_VOLCANO:
-            calc_flag = 1;
-            val3 = val1 * 10;
-            val4 =
-                val1 >= 5 ? 20 : (val1 ==
-                                  4 ? 19 : (val1 ==
-                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
-            break;
-        case SC_DELUGE:
-            calc_flag = 1;
-            val3 =
-                val1 >= 5 ? 15 : (val1 ==
-                                  4 ? 14 : (val1 ==
-                                            3 ? 12 : (val1 == 2 ? 9 : 5)));
-            val4 =
-                val1 >= 5 ? 20 : (val1 ==
-                                  4 ? 19 : (val1 ==
-                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
-            break;
-        case SC_VIOLENTGALE:
-            calc_flag = 1;
-            val3 = val1 * 3;
-            val4 =
-                val1 >= 5 ? 20 : (val1 ==
-                                  4 ? 19 : (val1 ==
-                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
-            break;
-
-        case SC_SPEARSQUICKEN: /* スピアクイッケン */
-            calc_flag = 1;
-            val2 = 20 + val1;
-            *opt3 |= 1;
-            break;
-        case SC_COMBO:
-            break;
-        case SC_BLADESTOP_WAIT:    /* 白刃取り(待ち) */
-            break;
-        case SC_BLADESTOP:     /* 白刃取り */
-            if (val2 == 2)
-                clif_bladestop ((struct block_list *) val3,
-                                (struct block_list *) val4, 1);
-            *opt3 |= 32;
-            break;
-
-        case SC_LULLABY:       /* 子守唄 */
-            val2 = 11;
-            break;
-        case SC_RICHMANKIM:
-            break;
-        case SC_ETERNALCHAOS:  /* エターナルカオス */
-            calc_flag = 1;
-            break;
-        case SC_DRUMBATTLE:    /* 戦太鼓の響き */
-            calc_flag = 1;
-            val2 = (val1 + 1) * 25;
-            val3 = (val1 + 1) * 2;
-            break;
-        case SC_NIBELUNGEN:    /* ニーベルングの指輪 */
-            calc_flag = 1;
-            val2 = (val1 + 2) * 50;
-            val3 = (val1 + 2) * 25;
-            break;
-        case SC_ROKISWEIL:     /* ロキの叫び */
-            break;
-        case SC_INTOABYSS:     /* 深淵の中に */
-            break;
-        case SC_SIEGFRIED:     /* 不死身のジークフリード */
-            calc_flag = 1;
-            val2 = 40 + val1 * 5;
-            val3 = val1 * 10;
-            break;
-        case SC_DISSONANCE:    /* 不協和音 */
-            val2 = 10;
-            break;
-        case SC_WHISTLE:       /* 口笛 */
-            calc_flag = 1;
-            break;
-        case SC_ASSNCROS:      /* 夕陽のアサシンクロス */
-            calc_flag = 1;
-            break;
-        case SC_POEMBRAGI:     /* ブラギの詩 */
-            break;
-        case SC_APPLEIDUN:     /* イドゥンの林檎 */
-            calc_flag = 1;
-            break;
-        case SC_UGLYDANCE:     /* 自分勝手なダンス */
-            val2 = 10;
-            break;
-        case SC_HUMMING:       /* ハミング */
-            calc_flag = 1;
-            break;
-        case SC_DONTFORGETME:  /* 私を忘れないで */
-            calc_flag = 1;
-            if (sc_data[SC_INCREASEAGI].timer != -1)    /* 速度上昇解除 */
-                skill_status_change_end (bl, SC_INCREASEAGI, -1);
-            if (sc_data[SC_TWOHANDQUICKEN].timer != -1)
-                skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1);
-            if (sc_data[SC_SPEARSQUICKEN].timer != -1)
-                skill_status_change_end (bl, SC_SPEARSQUICKEN, -1);
-            if (sc_data[SC_ADRENALINE].timer != -1)
-                skill_status_change_end (bl, SC_ADRENALINE, -1);
-            if (sc_data[SC_ASSNCROS].timer != -1)
-                skill_status_change_end (bl, SC_ASSNCROS, -1);
-            if (sc_data[SC_TRUESIGHT].timer != -1)  /* トゥルーサイト */
-                skill_status_change_end (bl, SC_TRUESIGHT, -1);
-            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
-                skill_status_change_end (bl, SC_WINDWALK, -1);
-            if (sc_data[SC_CARTBOOST].timer != -1)  /* カートブースト */
-                skill_status_change_end (bl, SC_CARTBOOST, -1);
-            break;
-        case SC_FORTUNE:       /* 幸運のキス */
-            calc_flag = 1;
-            break;
-        case SC_SERVICE4U:     /* サービスフォーユー */
-            calc_flag = 1;
-            break;
-        case SC_DANCING:       /* ダンス/演奏中 */
-            calc_flag = 1;
-            val3 = tick / 1000;
-            tick = 1000;
-            break;
-
-        case SC_EXPLOSIONSPIRITS:  // 爆裂波動
-            calc_flag = 1;
-            val2 = 75 + 25 * val1;
-            *opt3 |= 8;
-            break;
-        case SC_STEELBODY:     // 金剛
-            calc_flag = 1;
-            *opt3 |= 16;
-            break;
-        case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */
-            break;
-        case SC_AUTOCOUNTER:
-            val3 = val4 = 0;
-            break;
-
-        case SC_SPEEDPOTION0:  /* 増速ポーション */
-            *opt2 |= 0x20;
-        case SC_SPEEDPOTION1:
-        case SC_SPEEDPOTION2:
-            calc_flag = 1;
-            tick = 1000 * tick;
-//          val2 = 5*(2+type-SC_SPEEDPOTION0);
-            break;
-
-            /* atk & matk potions [Valaris] */
-        case SC_ATKPOT:
-            *opt2 |= 0x80;
-        case SC_MATKPOT:
-            calc_flag = 1;
-            tick = 1000 * tick;
-            break;
-        case SC_WEDDING:       //結婚用(結婚衣裳になって歩くのが遅いとか)
-        {
-            time_t timer;
-
-            calc_flag = 1;
-            tick = 10000;
-            if (!val2)
-                val2 = time (&timer);
-        }
-            break;
-        case SC_NOCHAT:        //チャット禁止状態
-        {
-            time_t timer;
-
-            if (!battle_config.muting_players)
-                break;
-
-            tick = 60000;
-            if (!val2)
-                val2 = time (&timer);
-            updateflag = SP_MANNER;
-        }
-            break;
-        case SC_SELFDESTRUCTION:   //自爆
-            clif_skillcasting (bl, bl->id, bl->id, 0, 0, 331,
-                               skill_get_time (val2, val1));
-            val3 = tick / 1000;
-            tick = 1000;
-            break;
-
-            /* option1 */
-        case SC_STONE:         /* 石化 */
-            if (!(flag & 2))
-            {
-                int  sc_def = battle_get_mdef (bl) * 200;
-                tick = tick - sc_def;
-            }
-            val3 = tick / 1000;
-            if (val3 < 1)
-                val3 = 1;
-            tick = 5000;
-            val2 = 1;
-            break;
-        case SC_SLEEP:         /* 睡眠 */
-            if (!(flag & 2))
-            {
-//              int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
-//              tick = tick * sc_def / 100;
-//              if(tick < 1000) tick = 1000;
-                tick = 30000;   //睡眠はステータス耐性に関わらず30秒
-            }
-            break;
-        case SC_FREEZE:        /* 凍結 */
-            if (!(flag & 2))
-            {
-                int  sc_def = 100 - battle_get_mdef (bl);
-                tick = tick * sc_def / 100;
-            }
-            break;
-        case SC_STAN:          /* スタン(val2にミリ秒セット) */
-            if (!(flag & 2))
-            {
-                int  sc_def =
-                    100 - (battle_get_vit (bl) + battle_get_luk (bl) / 3);
-                tick = tick * sc_def / 100;
-            }
-            break;
-
-            /* option2 */
-        case SC_POISON:        /* 毒 */
-            calc_flag = 1;
-            if (!(flag & 2))
-            {
-                int  sc_def =
-                    100 - (battle_get_vit (bl) + battle_get_luk (bl) / 5);
-                tick = tick * sc_def / 100;
-            }
-            val3 = tick / 1000;
-            if (val3 < 1)
-                val3 = 1;
-            tick = 1000;
-            break;
-        case SC_SILENCE:       /* 沈黙(レックスデビーナ) */
-            if (!(flag & 2))
-            {
-                int  sc_def = 100 - battle_get_vit (bl);
-                tick = tick * sc_def / 100;
-            }
-            break;
-        case SC_BLIND:         /* 暗黒 */
-            calc_flag = 1;
-            if (!(flag & 2))
-            {
-                int  sc_def =
-                    battle_get_lv (bl) / 10 + battle_get_int (bl) / 15;
-                tick = 30000 - sc_def;
-            }
-            break;
-        case SC_CURSE:
-            calc_flag = 1;
-            if (!(flag & 2))
-            {
-                int  sc_def = 100 - battle_get_vit (bl);
-                tick = tick * sc_def / 100;
-            }
-            break;
-
-            /* option */
-        case SC_HIDING:        /* ハイディング */
-            calc_flag = 1;
-            if (bl->type == BL_PC)
-            {
-                val2 = tick / 1000; /* 持続時間 */
-                tick = 1000;
-            }
-            break;
-        case SC_CHASEWALK:
-        case SC_CLOAKING:      /* クローキング */
-            if (bl->type == BL_PC)
-                val2 = tick;
-            else
-                tick = 5000 * val1;
-            break;
-        case SC_SIGHT:         /* サイト/ルアフ */
-        case SC_RUWACH:
-            val2 = tick / 250;
-            tick = 10;
-            break;
-
-            /* セーフティウォール、ニューマ */
-        case SC_SAFETYWALL:
-        case SC_PNEUMA:
-            tick = ((struct skill_unit *) val2)->group->limit;
-            break;
-
-            /* アンクル */
-        case SC_ANKLE:
-            break;
-
-            /* ウォーターボール */
-        case SC_WATERBALL:
-            tick = 150;
-            if (val1 > 5)       //レベルが5以上の場合は25発に制限(1発目はすでに打ってるので-1)
-                val3 = 5 * 5 - 1;
-            else
-                val3 = (val1 | 1) * (val1 | 1) - 1;
-            break;
-
-            /* スキルじゃない/時間に関係しない */
-        case SC_RIDING:
-            calc_flag = 1;
-            tick = 600 * 1000;
-            break;
-        case SC_FALCON:
-        case SC_WEIGHT50:
-        case SC_WEIGHT90:
-        case SC_BROKNWEAPON:
-        case SC_BROKNARMOR:
-            tick = 600 * 1000;
-            break;
-
-        case SC_AUTOGUARD:
-        {
-            int  i, t;
-            for (i = val2 = 0; i < val1; i++)
-            {
-                t = 5 - (i >> 1);
-                val2 += (t < 0) ? 1 : t;
-            }
-        }
-            break;
-
-        case SC_DEFENDER:
-            calc_flag = 1;
-            val2 = 5 + val1 * 15;
-            break;
-
-        case SC_KEEPING:
-        case SC_BARRIER:
-        case SC_HALLUCINATION:
-            break;
-        case SC_CONCENTRATION: /* コンセントレーション */
-            *opt3 |= 1;
-            calc_flag = 1;
-            break;
-        case SC_TENSIONRELAX:  /* テンションリラックス */
-            calc_flag = 1;
-            if (bl->type == BL_PC)
-            {
-                tick = 10000;
-            }
-            break;
-        case SC_AURABLADE:     /* オーラブレード */
-        case SC_PARRYING:      /* パリイング */
-//      case SC_ASSUMPTIO:      /*  */
-        case SC_HEADCRUSH:     /* ヘッドクラッシュ */
-        case SC_JOINTBEAT:     /* ジョイントビート */
-//      case SC_MARIONETTE:     /* マリオネットコントロール */
-
-            //とりあえず手抜き
-            break;
-
-// -- moonsoul  (for new upper class related skill status effects)
-/*
-		case SC_AURABLADE:
-			val2 = val1*10;
-			break;
-		case SC_PARRYING:
-			val2=val1*3;
-			break;
-		case SC_CONCENTRATION:
-			calc_flag=1;
-			val2=val1*10;
-			val3=val1*5;
-			break;
-		case SC_TENSIONRELAX:
-//			val2 = 10;
-//			val3 = 15;
-			break;
-		case SC_BERSERK:
-			calc_flag=1;
-			break;
-		case SC_ASSUMPTIO:
-			if(sc_data[SC_KYRIE].timer!=-1 )
-				skill_status_change_end(bl,SC_KYRIE,-1);
-				break;
-*/
-        case SC_WINDWALK:      /* ウインドウォーク */
-            calc_flag = 1;
-            val2 = (val1 / 2);  //Flee上昇率
-            break;
-        case SC_BERSERK:       /* バーサーク */
-            if (sd)
-            {
-                sd->status.sp = 0;
-                clif_updatestatus (sd, SP_SP);
-                clif_status_change (bl, SC_INCREASEAGI, 1); /* アイコン表示 */
-            }
-            *opt3 |= 128;
-            tick = 1000;
-            calc_flag = 1;
-            break;
-        case SC_ASSUMPTIO:     /* アスムプティオ */
-            *opt3 |= 2048;
-            break;
-        case SC_MARIONETTE:    /* マリオネットコントロール */
-            *opt3 |= 1024;
-            break;
-        case SC_MELTDOWN:      /* メルトダウン */
-        case SC_CARTBOOST:     /* カートブースト */
-        case SC_TRUESIGHT:     /* トゥルーサイト */
-        case SC_SPIDERWEB:     /* スパイダーウェッブ */
-        case SC_MAGICPOWER:    /* 魔法力増幅 */
-            calc_flag = 1;
-            break;
-        case SC_REJECTSWORD:   /* リジェクトソード */
-            val2 = 3;           //3回攻撃を跳ね返す
-            break;
-        case SC_MEMORIZE:      /* メモライズ */
-            val2 = 3;           //3回詠唱を1/3にする
-            break;
-        case SC_GRAFFITI:      /* グラフィティ */
-        {
-            struct skill_unit_group *sg =
-                skill_unitsetting (bl, RG_GRAFFITI, val1, val2, val3, 0);
-            if (sg)
-                val4 = (int) sg;
-        }
-            break;
-        case SC_HASTE:
-            calc_flag = 1;
-        case SC_SPLASHER:      /* ベナムスプラッシャー */
-        case SC_PHYS_SHIELD:
-        case SC_MBARRIER:
-        case SC_HALT_REGENERATE:
-        case SC_HIDE:
-            break;
-        case SC_FLYING_BACKPACK:
-            updateflag = SP_WEIGHT;
-            break;
-        default:
-            if (battle_config.error_log)
-                printf ("UnknownStatusChange [%d]\n", type);
-            return 0;
-    }
-
-    if (bl->type == BL_PC && type < SC_SENDMAX)
-        clif_status_change (bl, type, 1);   /* アイコン表示 */
-
-    /* optionの変更 */
-    switch (type)
-    {
-        case SC_STONE:
-        case SC_FREEZE:
-        case SC_STAN:
-        case SC_SLEEP:
-            battle_stopattack (bl); /* 攻撃停止 */
-            skill_stop_dancing (bl, 0); /* 演奏/ダンスの中断 */
-            {                   /* 同時に掛からないステータス異常を解除 */
-                int  i;
-                for (i = SC_STONE; i <= SC_SLEEP; i++)
-                {
-                    if (sc_data[i].timer != -1)
-                    {
-                        (*sc_count)--;
-                        delete_timer (sc_data[i].timer,
-                                      skill_status_change_timer);
-                        sc_data[i].timer = -1;
-                    }
-                }
-            }
-            if (type == SC_STONE)
-                *opt1 = 6;
-            else
-                *opt1 = type - SC_STONE + 1;
-            opt_flag = 1;
-            break;
-        case SC_POISON:
-            if (sc_data[SC_SLOWPOISON].timer == -1)
-            {
-                *opt2 |= 0x1;
-                opt_flag = 1;
-            }
-            break;
-
-        case SC_CURSE:
-        case SC_SILENCE:
-        case SC_BLIND:
-            *opt2 |= 1 << (type - SC_POISON);
-            opt_flag = 1;
-            break;
-        case SC_SLOWPOISON:
-            *opt2 &= ~0x1;
-            *opt2 |= 0x200;
-            opt_flag = 1;
-            break;
-        case SC_SIGNUMCRUCIS:
-            *opt2 |= 0x40;
-            opt_flag = 1;
-            break;
-        case SC_HIDING:
-        case SC_CLOAKING:
-            battle_stopattack (bl); /* 攻撃停止 */
-            *option |= ((type == SC_HIDING) ? 2 : 4);
-            opt_flag = 1;
-            break;
-        case SC_CHASEWALK:
-            battle_stopattack (bl); /* 攻撃停止 */
-            *option |= 16388;
-            opt_flag = 1;
-            break;
-        case SC_SIGHT:
-            *option |= 1;
-            opt_flag = 1;
-            break;
-        case SC_RUWACH:
-            *option |= 8192;
-            opt_flag = 1;
-            break;
-        case SC_WEDDING:
-            *option |= 4096;
-            opt_flag = 1;
-    }
-
-    if (opt_flag)               /* optionの変更 */
-        clif_changeoption (bl);
-
-    (*sc_count)++;              /* ステータス異常の数 */
-
-    sc_data[type].val1 = val1;
-    sc_data[type].val2 = val2;
-    sc_data[type].val3 = val3;
-    sc_data[type].val4 = val4;
-    if (sc_data[type].spell_invocation) // Supplant by newer spell
-        spell_effect_report_termination (sc_data[type].spell_invocation,
-                                         bl->id, type, 1);
-
-    sc_data[type].spell_invocation = spell_invocation;
-
-    /* タイマー設定 */
-    sc_data[type].timer =
-        add_timer (gettick () + tick, skill_status_change_timer, bl->id,
-                   type);
-
-    if (bl->type == BL_PC && calc_flag)
-        pc_calcstatus (sd, 0);  /* ステータス再計算 */
-
-    if (bl->type == BL_PC && updateflag)
-        clif_updatestatus (sd, updateflag); /* ステータスをクライアントに送る */
-
-    return 0;
-}
-
-/*==========================================
- * ステータス異常全解除
- *------------------------------------------
- */
-int skill_status_change_clear (struct block_list *bl, int type)
-{
-    struct status_change *sc_data;
-    short *sc_count, *option, *opt1, *opt2, *opt3;
-    int  i;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
-    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
-    nullpo_retr (0, option = battle_get_option (bl));
-    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
-    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
-    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
-
-    if (*sc_count == 0)
-        return 0;
-    for (i = 0; i < MAX_STATUSCHANGE; i++)
-    {
-        if (sc_data[i].timer != -1)
-        {                       /* 異常があるならタイマーを削除する */
-/*
-			delete_timer(sc_data[i].timer, skill_status_change_timer);
-			sc_data[i].timer = -1;
-
-			if (!type && i < SC_SENDMAX)
-				clif_status_change(bl, i, 0);
-*/
-
-            skill_status_change_end (bl, i, -1);
-        }
-    }
-    *sc_count = 0;
-    *opt1 = 0;
-    *opt2 = 0;
-    *opt3 = 0;
-    *option &= OPTION_MASK;
-
-    if (night_flag == 1 && type == BL_PC)   // by [Yor]
-        *opt2 |= STATE_BLIND;
-
-    if (!type || type & 2)
-        clif_changeoption (bl);
-
-    return 0;
-}
-
-/* クローキング検査(周りに移動不可能地帯があるか) */
-int skill_check_cloaking (struct block_list *bl)
-{
-    struct map_session_data *sd = NULL;
-    static int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
-    static int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
-    int  end = 1, i;
-
-    nullpo_retr (0, bl);
-
-    if (pc_checkskill (sd, AS_CLOAKING) > 2)
-        return 0;
-    if (bl->type == BL_PC && battle_config.pc_cloak_check_type & 1)
-        return 0;
-    if (bl->type == BL_MOB && battle_config.monster_cloak_check_type & 1)
-        return 0;
-    for (i = 0; i < sizeof (dx) / sizeof (dx[0]); i++)
-    {
-        int  c = map_getcell (bl->m, bl->x + dx[i], bl->y + dy[i]);
-        if (c == 1 || c == 5)
-            end = 0;
-    }
-    if (end)
-    {
-        skill_status_change_end (bl, SC_CLOAKING, -1);
-        *battle_get_option (bl) &= ~4;  /* 念のための処理 */
-    }
-    return end;
-}
-
-/*
- *----------------------------------------------------------------------------
- * スキルユニット
- *----------------------------------------------------------------------------
- */
-
-/*==========================================
- * 演奏/ダンススキルかどうか判定
- * 引数 スキルID
- * 戻り ダンスじゃない=0 合奏=2 それ以外のダンス=1
- *------------------------------------------
- */
-int skill_is_danceskill (int id)
-{
-    int  i;
-    switch (id)
-    {
-        case BD_LULLABY:       /* 子守歌 */
-        case BD_RICHMANKIM:    /* ニヨルドの宴 */
-        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-        case BD_ROKISWEIL:     /* ロキの叫び */
-        case BD_INTOABYSS:     /* 深淵の中に */
-        case BD_SIEGFRIED:     /* 不死身のジークフリード */
-        case BD_RAGNAROK:      /* 神々の黄昏 */
-        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
-            i = 2;
-            break;
-        case BA_DISSONANCE:    /* 不協和音 */
-        case BA_FROSTJOKE:     /* 寒いジョーク */
-        case BA_WHISTLE:       /* 口笛 */
-        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
-        case BA_POEMBRAGI:     /* ブラギの詩 */
-        case BA_APPLEIDUN:     /* イドゥンの林檎 */
-        case DC_UGLYDANCE:     /* 自分勝手なダンス */
-        case DC_SCREAM:        /* スクリーム */
-        case DC_HUMMING:       /* ハミング */
-        case DC_DONTFORGETME:  /* 私を忘れないで… */
-        case DC_FORTUNEKISS:   /* 幸運のキス */
-        case DC_SERVICEFORYOU: /* サービスフォーユー */
-            i = 1;
-            break;
-        default:
-            i = 0;
-    }
-    return i;
-}
-
-/*==========================================
- * 演奏/ダンスをやめる
- * flag 1で合奏中なら相方にユニットを任せる
- *
- *------------------------------------------
- */
-void skill_stop_dancing (struct block_list *src, int flag)
-{
-    struct status_change *sc_data;
-    struct skill_unit_group *group;
-
-    nullpo_retv (src);
-
-    sc_data = battle_get_sc_data (src);
-    if (sc_data && sc_data[SC_DANCING].timer == -1)
-        return;
-    group = (struct skill_unit_group *) sc_data[SC_DANCING].val2;   //ダンスのスキルユニットIDはval2に入ってる
-    if (group && src->type == BL_PC && sc_data && sc_data[SC_DANCING].val4)
-    {                           //合奏中断
-        struct map_session_data *dsd = map_id2sd (sc_data[SC_DANCING].val4);    //相方のsd取得
-        if (flag)
-        {                       //ログアウトなど片方が落ちても演奏が継続される
-            if (dsd && src->id == group->src_id)
-            {                   //グループを持ってるPCが落ちる
-                group->src_id = sc_data[SC_DANCING].val4;   //相方にグループを任せる
-                if (flag & 1)   //ログアウト
-                    dsd->sc_data[SC_DANCING].val4 = 0;  //相方の相方を0にして合奏終了→通常のダンス状態
-                if (flag & 2)   //ハエ飛びなど
-                    return;     //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり
-            }
-            else if (dsd && dsd->bl.id == group->src_id)
-            {                   //相方がグループを持っているPCが落ちる(自分はグループを持っていない)
-                if (flag & 1)   //ログアウト
-                    dsd->sc_data[SC_DANCING].val4 = 0;  //相方の相方を0にして合奏終了→通常のダンス状態
-                if (flag & 2)   //ハエ飛びなど
-                    return;     //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり
-            }
-            skill_status_change_end (src, SC_DANCING, -1);  //自分のステータスを終了させる
-            //そしてグループは消さない&消さないのでステータス計算もいらない?
-            return;
-        }
-        else
-        {
-            if (dsd && src->id == group->src_id)
-            {                   //グループを持ってるPCが止める
-                skill_status_change_end ((struct block_list *) dsd, SC_DANCING, -1);    //相手のステータスを終了させる
-            }
-            if (dsd && dsd->bl.id == group->src_id)
-            {                   //相方がグループを持っているPCが止める(自分はグループを持っていない)
-                skill_status_change_end (src, SC_DANCING, -1);  //自分のステータスを終了させる
-            }
-        }
-    }
-    if (flag & 2 && group && src->type == BL_PC)
-    {                           //ハエで飛んだときとかはユニットも飛ぶ
-        struct map_session_data *sd = (struct map_session_data *) src;
-        skill_unit_move_unit_group (group, sd->bl.m, (sd->to_x - sd->bl.x),
-                                    (sd->to_y - sd->bl.y));
-        return;
-    }
-    skill_delunitgroup (group);
-    if (src->type == BL_PC)
-        pc_calcstatus ((struct map_session_data *) src, 0);
-}
-
-/*==========================================
- * スキルユニット初期化
- *------------------------------------------
- */
-struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx,
-                                   int x, int y)
-{
-    struct skill_unit *unit;
-
-    nullpo_retr (NULL, group);
-    nullpo_retr (NULL, unit = &group->unit[idx]);
-
-    if (!unit->alive)
-        group->alive_count++;
-
-    unit->bl.id = map_addobject (&unit->bl);
-    unit->bl.type = BL_SKILL;
-    unit->bl.m = group->map;
-    unit->bl.x = x;
-    unit->bl.y = y;
-    unit->group = group;
-    unit->val1 = unit->val2 = 0;
-    unit->alive = 1;
-
-    map_addblock (&unit->bl);
-    clif_skill_setunit (unit);
-    return unit;
-}
-
-int  skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap);
-/*==========================================
- * スキルユニット削除
- *------------------------------------------
- */
-int skill_delunit (struct skill_unit *unit)
-{
-    struct skill_unit_group *group;
-    int  range;
-
-    nullpo_retr (0, unit);
-    if (!unit->alive)
-        return 0;
-    nullpo_retr (0, group = unit->group);
-
-    /* onlimitイベント呼び出し */
-    skill_unit_onlimit (unit, gettick ());
-
-    /* ondeleteイベント呼び出し */
-    range = group->range;
-    map_foreachinarea (skill_unit_timer_sub_ondelete, unit->bl.m,
-                       unit->bl.x - range, unit->bl.y - range,
-                       unit->bl.x + range, unit->bl.y + range, 0, &unit->bl,
-                       gettick ());
-
-    clif_skill_delunit (unit);
-
-    unit->group = NULL;
-    unit->alive = 0;
-    map_delobjectnofree (unit->bl.id, BL_SKILL);
-    if (group->alive_count > 0 && (--group->alive_count) <= 0)
-        skill_delunitgroup (group);
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニットグループ初期化
- *------------------------------------------
- */
-static int skill_unit_group_newid = 10;
-struct skill_unit_group *skill_initunitgroup (struct block_list *src,
-                                              int count, int skillid,
-                                              int skilllv, int unit_id)
-{
-    int  i;
-    struct skill_unit_group *group = NULL, *list = NULL;
-    int  maxsug = 0;
-
-    nullpo_retr (NULL, src);
-
-    if (src->type == BL_PC)
-    {
-        list = ((struct map_session_data *) src)->skillunit;
-        maxsug = MAX_SKILLUNITGROUP;
-    }
-    else if (src->type == BL_MOB)
-    {
-        list = ((struct mob_data *) src)->skillunit;
-        maxsug = MAX_MOBSKILLUNITGROUP;
-    }
-    if (list)
-    {
-        for (i = 0; i < maxsug; i++)    /* 空いているもの検索 */
-            if (list[i].group_id == 0)
-            {
-                group = &list[i];
-                break;
-            }
-
-        if (group == NULL)
-        {                       /* 空いてないので古いもの検索 */
-            int  j = 0;
-            unsigned maxdiff = 0, x, tick = gettick ();
-            for (i = 0; i < maxsug; i++)
-                if ((x = DIFF_TICK (tick, list[i].tick)) > maxdiff)
-                {
-                    maxdiff = x;
-                    j = i;
-                }
-            skill_delunitgroup (&list[j]);
-            group = &list[j];
-        }
-    }
-
-    if (group == NULL)
-    {
-        printf ("skill_initunitgroup: error unit group !\n");
-        exit (1);
-    }
-
-    group->src_id = src->id;
-    group->party_id = battle_get_party_id (src);
-    group->guild_id = battle_get_guild_id (src);
-    group->group_id = skill_unit_group_newid++;
-    if (skill_unit_group_newid <= 0)
-        skill_unit_group_newid = 10;
-    CREATE (group->unit, struct skill_unit, count);
-    group->unit_count = count;
-    group->val1 = group->val2 = 0;
-    group->skill_id = skillid;
-    group->skill_lv = skilllv;
-    group->unit_id = unit_id;
-    group->map = src->m;
-    group->range = 0;
-    group->limit = 10000;
-    group->interval = 1000;
-    group->tick = gettick ();
-    group->valstr = NULL;
-
-    if (skill_is_danceskill (skillid))
-    {
-        struct map_session_data *sd = NULL;
-        if (src->type == BL_PC && (sd = (struct map_session_data *) src))
-        {
-            sd->skillid_dance = skillid;
-            sd->skilllv_dance = skilllv;
-        }
-        skill_status_change_start (src, SC_DANCING, skillid, (int) group, 0,
-                                   0, skill_get_time (skillid,
-                                                      skilllv) + 1000, 0);
-        switch (skillid)
-        {                       //合奏スキルは相方をダンス状態にする
-            case BD_LULLABY:   /* 子守歌 */
-            case BD_RICHMANKIM:    /* ニヨルドの宴 */
-            case BD_ETERNALCHAOS:  /* 永遠の混沌 */
-            case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
-            case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
-            case BD_ROKISWEIL: /* ロキの叫び */
-            case BD_INTOABYSS: /* 深淵の中に */
-            case BD_SIEGFRIED: /* 不死身のジークフリード */
-            case BD_RAGNAROK:  /* 神々の黄昏 */
-            case CG_MOONLIT:   /* 月明りの泉に落ちる花びら */
-            {
-                int  range = 1;
-                int  c = 0;
-                if (sd)
-                {
-                    map_foreachinarea (skill_check_condition_use_sub,
-                                       sd->bl.m, sd->bl.x - range,
-                                       sd->bl.y - range, sd->bl.x + range,
-                                       sd->bl.y + range, BL_PC, &sd->bl, &c);
-                }
-            }
-        }
-    }
-    return group;
-}
-
-/*==========================================
- * スキルユニットグループ削除
- *------------------------------------------
- */
-int skill_delunitgroup (struct skill_unit_group *group)
-{
-    struct block_list *src;
-    int  i;
-
-    nullpo_retr (0, group);
-    if (group->unit_count <= 0)
-        return 0;
-
-    src = map_id2bl (group->src_id);
-    if (skill_is_danceskill (group->skill_id))
-    {                           //ダンススキルはダンス状態を解除する
-        if (src)
-            skill_status_change_end (src, SC_DANCING, -1);
-    }
-
-    group->alive_count = 0;
-    if (group->unit != NULL)
-    {
-        for (i = 0; i < group->unit_count; i++)
-            if (group->unit[i].alive)
-                skill_delunit (&group->unit[i]);
-    }
-    if (group->valstr != NULL)
-    {
-        map_freeblock (group->valstr);
-        group->valstr = NULL;
-    }
-
-    map_freeblock (group->unit);    /* free()の替わり */
-    group->unit = NULL;
-    group->src_id = 0;
-    group->group_id = 0;
-    group->unit_count = 0;
-    return 0;
-}
-
-/*==========================================
- * スキルユニットグループ全削除
- *------------------------------------------
- */
-int skill_clear_unitgroup (struct block_list *src)
-{
-    struct skill_unit_group *group = NULL;
-    int  maxsug = 0;
-
-    nullpo_retr (0, src);
-
-    if (src->type == BL_PC)
-    {
-        group = ((struct map_session_data *) src)->skillunit;
-        maxsug = MAX_SKILLUNITGROUP;
-    }
-    else if (src->type == BL_MOB)
-    {
-        group = ((struct mob_data *) src)->skillunit;
-        maxsug = MAX_MOBSKILLUNITGROUP;
-    }
-    if (group)
-    {
-        int  i;
-        for (i = 0; i < maxsug; i++)
-            if (group[i].group_id > 0 && group[i].src_id == src->id)
-                skill_delunitgroup (&group[i]);
-    }
-    return 0;
-}
-
-/*==========================================
- * スキルユニットグループの被影響tick検索
- *------------------------------------------
- */
-struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct
-                                                                block_list
-                                                                *bl,
-                                                                int group_id)
-{
-    int  i, j = 0, k, s = group_id % MAX_SKILLUNITGROUPTICKSET;
-    struct skill_unit_group_tickset *set = NULL;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-    {
-        set = ((struct map_session_data *) bl)->skillunittick;
-    }
-    else
-    {
-        set = ((struct mob_data *) bl)->skillunittick;
-    }
-    if (set == NULL)
-        return 0;
-    for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++)
-        if (set[(k = (i + s) % MAX_SKILLUNITGROUPTICKSET)].group_id ==
-            group_id)
-            return &set[k];
-        else if (set[k].group_id == 0)
-            j = k;
-
-    return &set[j];
-}
-
-/*==========================================
- * スキルユニットグループの被影響tick削除
- *------------------------------------------
- */
-int skill_unitgrouptickset_delete (struct block_list *bl, int group_id)
-{
-    int  i, s = group_id % MAX_SKILLUNITGROUPTICKSET;
-    struct skill_unit_group_tickset *set = NULL, *ts;
-
-    nullpo_retr (0, bl);
-
-    if (bl->type == BL_PC)
-    {
-        set = ((struct map_session_data *) bl)->skillunittick;
-    }
-    else
-    {
-        set = ((struct mob_data *) bl)->skillunittick;
-    }
-
-    if (set != NULL)
-    {
-
-        for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++)
-            if ((ts =
-                 &set[(i + s) % MAX_SKILLUNITGROUPTICKSET])->group_id ==
-                group_id)
-                ts->group_id = 0;
-
-    }
-    return 0;
-}
-
-/*==========================================
- * スキルユニットタイマー発動処理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_timer_sub_onplace (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    struct skill_unit *su;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    src = va_arg (ap, struct block_list *);
-
-    tick = va_arg (ap, unsigned int);
-    su = (struct skill_unit *) src;
-
-    if (su && su->alive)
-    {
-        struct skill_unit_group *sg;
-        sg = su->group;
-        if (sg && battle_check_target (src, bl, sg->target_flag) > 0)
-            skill_unit_onplace (su, bl, tick);
-    }
-    return 0;
-}
-
-/*==========================================
- * スキルユニットタイマー削除処理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap)
-{
-    struct block_list *src;
-    struct skill_unit *su;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    src = va_arg (ap, struct block_list *);
-
-    tick = va_arg (ap, unsigned int);
-    su = (struct skill_unit *) src;
-
-    if (su && su->alive)
-    {
-        struct skill_unit_group *sg;
-        sg = su->group;
-        if (sg && battle_check_target (src, bl, sg->target_flag) > 0)
-            skill_unit_ondelete (su, bl, tick);
-    }
-    return 0;
-}
-
-/*==========================================
- * スキルユニットタイマー処理用(foreachobject)
- *------------------------------------------
- */
-int skill_unit_timer_sub (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    struct skill_unit_group *group;
-    int  range;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, unit = (struct skill_unit *) bl);
-    nullpo_retr (0, group = unit->group);
-    tick = va_arg (ap, unsigned int);
-
-    if (!unit->alive)
-        return 0;
-
-    range = (unit->range != 0) ? unit->range : group->range;
-
-    /* onplaceイベント呼び出し */
-    if (unit->alive && unit->range >= 0)
-    {
-        map_foreachinarea (skill_unit_timer_sub_onplace, bl->m,
-                           bl->x - range, bl->y - range, bl->x + range,
-                           bl->y + range, 0, bl, tick);
-        if (group->unit_id == 0xaa
-            && DIFF_TICK (tick, group->tick) >= 6000 * group->val2)
-        {
-            map_foreachinarea (skill_idun_heal, bl->m,
-                               bl->x - range, bl->y - range, bl->x + range,
-                               bl->y + range, 0, unit);
-            group->val2++;
-        }
-    }
-    /* 時間切れ削除 */
-    if (unit->alive &&
-        (DIFF_TICK (tick, group->tick) >= group->limit
-         || DIFF_TICK (tick, group->tick) >= unit->limit))
-    {
-        switch (group->unit_id)
-        {
-
-            case 0x8f:         /* ブラストマイン */
-                group->unit_id = 0x8c;
-                clif_changelook (bl, LOOK_BASE, group->unit_id);
-                group->limit = DIFF_TICK (tick + 1500, group->tick);
-                unit->limit = DIFF_TICK (tick + 1500, group->tick);
-                break;
-            case 0x90:         /* スキッドトラップ */
-            case 0x91:         /* アンクルスネア */
-            case 0x93:         /* ランドマイン */
-            case 0x94:         /* ショックウェーブトラップ */
-            case 0x95:         /* サンドマン */
-            case 0x96:         /* フラッシャー */
-            case 0x97:         /* フリージングトラップ */
-            case 0x98:         /* クレイモアートラップ */
-            case 0x99:         /* トーキーボックス */
-            {
-                struct block_list *src = map_id2bl (group->src_id);
-                if (group->unit_id == 0x91 && group->val2);
-                else
-                {
-                    if (src && src->type == BL_PC)
-                    {
-                        struct item item_tmp;
-                        memset (&item_tmp, 0, sizeof (item_tmp));
-                        item_tmp.nameid = 1065;
-                        item_tmp.identify = 1;
-                        map_addflooritem (&item_tmp, 1, bl->m, bl->x, bl->y, NULL, NULL, NULL, 0);  // 罠返還
-                    }
-                }
-            }
-            default:
-                skill_delunit (unit);
-        }
-    }
-
-    if (group->unit_id == 0x8d)
-    {
-        unit->val1 -= 5;
-        if (unit->val1 <= 0 && unit->limit + group->tick > tick + 700)
-            unit->limit = DIFF_TICK (tick + 700, group->tick);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニットタイマー処理
- *------------------------------------------
- */
-void skill_unit_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
-{
-    map_freeblock_lock ();
-
-    map_foreachobject (skill_unit_timer_sub, BL_SKILL, tick);
-
-    map_freeblock_unlock ();
-}
-
-/*==========================================
- * スキルユニット移動時処理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_out_all_sub (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    struct skill_unit_group *group;
-    struct block_list *src;
-    int  range;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    nullpo_retr (0, unit = (struct skill_unit *) bl);
-    nullpo_retr (0, group = unit->group);
-
-    tick = va_arg (ap, unsigned int);
-
-    if (!unit->alive || src->prev == NULL)
-        return 0;
-
-    range = (unit->range != 0) ? unit->range : group->range;
-
-    if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0)
-        return 0;
-
-    if (src->x >= bl->x - range && src->x <= bl->x + range &&
-        src->y >= bl->y - range && src->y <= bl->y + range)
-        skill_unit_onout (unit, src, tick);
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニット移動時処理
- *------------------------------------------
- */
-int skill_unit_out_all (struct block_list *bl, unsigned int tick, int range)
-{
-    nullpo_retr (0, bl);
-
-    if (bl->prev == NULL)
-        return 0;
-
-    if (range < 7)
-        range = 7;
-    map_foreachinarea (skill_unit_out_all_sub,
-                       bl->m, bl->x - range, bl->y - range, bl->x + range,
-                       bl->y + range, BL_SKILL, bl, tick);
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニット移動時処理用(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_move_sub (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    struct skill_unit_group *group;
-    struct block_list *src;
-    int  range;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, unit = (struct skill_unit *) bl);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-
-    tick = va_arg (ap, unsigned int);
-
-    if (!unit->alive || src->prev == NULL)
-        return 0;
-
-    if ((group = unit->group) == NULL)
-        return 0;
-    range = (unit->range != 0) ? unit->range : group->range;
-
-    if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0)
-        return 0;
-
-    if (src->x >= bl->x - range && src->x <= bl->x + range &&
-        src->y >= bl->y - range && src->y <= bl->y + range)
-        skill_unit_onplace (unit, src, tick);
-    else
-        skill_unit_onout (unit, src, tick);
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニット移動時処理
- *------------------------------------------
- */
-int skill_unit_move (struct block_list *bl, unsigned int tick, int range)
-{
-    nullpo_retr (0, bl);
-
-    if (bl->prev == NULL)
-        return 0;
-
-    if (range < 7)
-        range = 7;
-    map_foreachinarea (skill_unit_move_sub,
-                       bl->m, bl->x - range, bl->y - range, bl->x + range,
-                       bl->y + range, BL_SKILL, bl, tick);
-
-    return 0;
-}
-
-/*==========================================
- * スキルユニット自体の移動時処理(foreachinarea)
- *------------------------------------------
- */
-int skill_unit_move_unit_group_sub (struct block_list *bl, va_list ap)
-{
-    struct skill_unit *unit;
-    struct skill_unit_group *group;
-    struct block_list *src;
-    int  range;
-    unsigned int tick;
-
-    nullpo_retr (0, bl);
-    nullpo_retr (0, ap);
-    nullpo_retr (0, src = va_arg (ap, struct block_list *));
-    nullpo_retr (0, unit = (struct skill_unit *) src);
-    nullpo_retr (0, group = unit->group);
-
-    tick = va_arg (ap, unsigned int);
-
-    if (!unit->alive || bl->prev == NULL)
-        return 0;
-
-    range = (unit->range != 0) ? unit->range : group->range;
-
-    if (range < 0 || battle_check_target (src, bl, group->target_flag) <= 0)
-        return 0;
-    if (bl->x >= src->x - range && bl->x <= src->x + range &&
-        bl->y >= src->y - range && bl->y <= src->y + range)
-        skill_unit_onplace (unit, bl, tick);
-    else
-        skill_unit_onout (unit, bl, tick);
-    return 0;
-}
-
-/*==========================================
- * スキルユニット自体の移動時処理
- * 引数はグループと移動量
- *------------------------------------------
- */
-int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx,
-                                int dy)
-{
-    nullpo_retr (0, group);
-
-    if (group->unit_count <= 0)
-        return 0;
-
-    if (group->unit != NULL)
-    {
-        if (!battle_config.unit_movement_type)
-        {
-            int  i;
-            for (i = 0; i < group->unit_count; i++)
-            {
-                struct skill_unit *unit = &group->unit[i];
-                if (unit->alive && !(m == unit->bl.m && dx == 0 && dy == 0))
-                {
-                    int  range = unit->range;
-                    map_delblock (&unit->bl);
-                    unit->bl.m = m;
-                    unit->bl.x += dx;
-                    unit->bl.y += dy;
-                    map_addblock (&unit->bl);
-                    clif_skill_setunit (unit);
-                    if (range > 0)
-                    {
-                        if (range < 7)
-                            range = 7;
-                        map_foreachinarea (skill_unit_move_unit_group_sub,
-                                           unit->bl.m, unit->bl.x - range,
-                                           unit->bl.y - range,
-                                           unit->bl.x + range,
-                                           unit->bl.y + range, 0, &unit->bl,
-                                           gettick ());
-                    }
-                }
-            }
-        }
-        else
-        {
-            int  i, j, *r_flag, *s_flag, *m_flag;
-            struct skill_unit *unit1;
-            struct skill_unit *unit2;
-            r_flag = (int *) malloc (sizeof (int) * group->unit_count);
-            s_flag = (int *) malloc (sizeof (int) * group->unit_count);
-            m_flag = (int *) malloc (sizeof (int) * group->unit_count);
-            memset (r_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
-            memset (s_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
-            memset (m_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
-
-            //先にフラグを全部決める
-            for (i = 0; i < group->unit_count; i++)
-            {
-                int  move_check = 0;    // かぶりフラグ
-                unit1 = &group->unit[i];
-                for (j = 0; j < group->unit_count; j++)
-                {
-                    unit2 = &group->unit[j];
-                    if (unit1->bl.m == m && unit1->bl.x + dx == unit2->bl.x
-                        && unit1->bl.y + dy == unit2->bl.y)
-                    {
-                        //移動先にユニットがかぶってたら
-                        s_flag[i] = 1;  // 移動前のユニットナンバーの継承フラグon
-                        r_flag[j] = 1;  // かぶるユニットナンバーの残留フラグon
-                        move_check = 1; //ユニットがかぶった。
-                        break;
-                    }
-                }
-                if (!move_check)    // ユニットがかぶってなかったら
-                    m_flag[i] = 1;  // 移動前ユニットナンバーの移動フラグon
-            }
-
-            //フラグに基づいてユニット移動
-            for (i = 0; i < group->unit_count; i++)
-            {
-                unit1 = &group->unit[i];
-                if (m_flag[i])
-                {               // 移動フラグがonで
-                    if (!r_flag[i])
-                    {           // 残留フラグがoffなら
-                        //単純移動(rangeも継承の必要無し)
-                        int  range = unit1->range;
-                        map_delblock (&unit1->bl);
-                        unit1->bl.m = m;
-                        unit1->bl.x += dx;
-                        unit1->bl.y += dy;
-                        map_addblock (&unit1->bl);
-                        clif_skill_setunit (unit1);
-                        if (range > 0)
-                        {
-                            if (range < 7)
-                                range = 7;
-                            map_foreachinarea (skill_unit_move_unit_group_sub,
-                                               unit1->bl.m,
-                                               unit1->bl.x - range,
-                                               unit1->bl.y - range,
-                                               unit1->bl.x + range,
-                                               unit1->bl.y + range, 0,
-                                               &unit1->bl, gettick ());
-                        }
-                    }
-                    else
-                    {           // 残留フラグがonなら
-                        //空ユニットになるので、継承可能なユニットを探す
-                        for (j = 0; j < group->unit_count; j++)
-                        {
-                            unit2 = &group->unit[j];
-                            if (s_flag[j] && !r_flag[j])
-                            {
-                                // 継承移動(range継承付き)
-                                int  range = unit1->range;
-                                map_delblock (&unit2->bl);
-                                unit2->bl.m = m;
-                                unit2->bl.x = unit1->bl.x + dx;
-                                unit2->bl.y = unit1->bl.y + dy;
-                                unit2->range = unit1->range;
-                                map_addblock (&unit2->bl);
-                                clif_skill_setunit (unit2);
-                                if (range > 0)
-                                {
-                                    if (range < 7)
-                                        range = 7;
-                                    map_foreachinarea
-                                        (skill_unit_move_unit_group_sub,
-                                         unit2->bl.m, unit2->bl.x - range,
-                                         unit2->bl.y - range,
-                                         unit2->bl.x + range,
-                                         unit2->bl.y + range, 0, &unit2->bl,
-                                         gettick ());
-                                }
-                                s_flag[j] = 0;  // 継承完了したのでoff
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            free (r_flag);
-            free (s_flag);
-            free (m_flag);
-        }
-    }
-    return 0;
-}
-
-/*----------------------------------------------------------------------------
- * アイテム合成
- *----------------------------------------------------------------------------
- */
-
-/*----------------------------------------------------------------------------
- * 初期化系
- */
-
-static int scan_stat (char *statname)
-{
-    if (!strcasecmp (statname, "str"))
-        return SP_STR;
-    if (!strcasecmp (statname, "dex"))
-        return SP_DEX;
-    if (!strcasecmp (statname, "agi"))
-        return SP_AGI;
-    if (!strcasecmp (statname, "vit"))
-        return SP_VIT;
-    if (!strcasecmp (statname, "int"))
-        return SP_INT;
-    if (!strcasecmp (statname, "luk"))
-        return SP_LUK;
-    if (!strcasecmp (statname, "none"))
-        return 0;
-
-    else
-        fprintf (stderr, "Unknown stat `%s'\n", statname);
-    return 0;
-}
-
-extern void skill_pool_register (int id);   // [Fate] Remember that a certain skill ID belongs to a pool skill
-
-/*==========================================
- * スキル関係ファイル読み込み
- * skill_db.txt スキルデータ
- * skill_cast_db.txt スキルの詠唱時間とディレイデータ
- *------------------------------------------
- */
-int skill_readdb (void)
-{
-    int  i, j, k, l;
-    FILE *fp;
-    char line[1024], *p;
-
-    /* The main skill database */
-    memset (skill_db, 0, sizeof (skill_db));
-    fp = fopen_ ("db/skill_db.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/skill_db.txt\n");
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        char *split[50], *split2[MAX_SKILL_LEVEL];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 18 && p; j++)
-        {
-            while (*p == '\t' || *p == ' ')
-                p++;
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (split[17] == NULL || j < 18)
-        {
-            fprintf (stderr, "Incomplete skill db data online (%d entries)\n",
-                     j);
-            continue;
-        }
-
-        i = atoi (split[0]);
-        if (i < 0 || i > MAX_SKILL_DB)
-            continue;
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].range[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-        skill_db[i].hit = atoi (split[2]);
-        skill_db[i].inf = atoi (split[3]);
-        skill_db[i].pl = atoi (split[4]);
-        skill_db[i].nk = atoi (split[5]);
-        skill_db[i].max_raise = atoi (split[6]);
-        skill_db[i].max = atoi (split[7]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[8]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].num[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        if (strcasecmp (split[9], "yes") == 0)
-            skill_db[i].castcancel = 1;
-        else
-            skill_db[i].castcancel = 0;
-        skill_db[i].cast_def_rate = atoi (split[9]);
-        skill_db[i].inf2 = atoi (split[10]);
-        skill_db[i].maxcount = atoi (split[11]);
-        if (strcasecmp (split[13], "weapon") == 0)
-            skill_db[i].skill_type = BF_WEAPON;
-        else if (strcasecmp (split[12], "magic") == 0)
-            skill_db[i].skill_type = BF_MAGIC;
-        else if (strcasecmp (split[12], "misc") == 0)
-            skill_db[i].skill_type = BF_MISC;
-        else
-            skill_db[i].skill_type = 0;
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[14]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].blewcount[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        if (!strcasecmp (split[15], "passive"))
-        {
-            skill_pool_register (i);
-            skill_db[i].poolflags = SKILL_POOL_FLAG;
-        }
-        else if (!strcasecmp (split[15], "active"))
-        {
-            skill_pool_register (i);
-            skill_db[i].poolflags = SKILL_POOL_FLAG | SKILL_POOL_ACTIVE;
-        }
-        else
-            skill_db[i].poolflags = 0;
-
-        skill_db[i].stat = scan_stat (split[16]);
-
-        skill_names[i].desc = strdup (split[17]);
-        {                       // replace "_" by " "
-            char *s = skill_names[i].desc;
-            while ((s = strchr (s, '_')))
-                *s = ' ';
-            if ((s = strchr (skill_names[i].desc, '\t'))
-                || (s = strchr (skill_names[i].desc, ' '))
-                || (s = strchr (skill_names[i].desc, '\n')))
-                *s = '\000';
-        }
-    }
-    fclose_ (fp);
-    printf ("read db/skill_db.txt done\n");
-
-    fp = fopen_ ("db/skill_require_db.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/skill_require_db.txt\n");
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        char *split[51], *split2[MAX_SKILL_LEVEL];
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 30 && p; j++)
-        {
-            while (*p == '\t' || *p == ' ')
-                p++;
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (split[29] == NULL || j < 30)
-            continue;
-
-        i = atoi (split[0]);
-        if (i < 0 || i > MAX_SKILL_DB)
-            continue;
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].hp[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].mhp[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].sp[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].hp_rate[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[5]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].sp_rate[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[6]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].zeny[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[7]; j < 32 && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < 32 && split2[k]; k++)
-        {
-            l = atoi (split2[k]);
-            if (l == 99)
-            {
-                skill_db[i].weapon = 0xffffffff;
-                break;
-            }
-            else
-                skill_db[i].weapon |= 1 << l;
-        }
-
-        if (strcasecmp (split[8], "hiding") == 0)
-            skill_db[i].state = ST_HIDING;
-        else if (strcasecmp (split[8], "cloaking") == 0)
-            skill_db[i].state = ST_CLOAKING;
-        else if (strcasecmp (split[8], "hidden") == 0)
-            skill_db[i].state = ST_HIDDEN;
-        else if (strcasecmp (split[8], "riding") == 0)
-            skill_db[i].state = ST_RIDING;
-        else if (strcasecmp (split[8], "falcon") == 0)
-            skill_db[i].state = ST_FALCON;
-        else if (strcasecmp (split[8], "cart") == 0)
-            skill_db[i].state = ST_CART;
-        else if (strcasecmp (split[8], "shield") == 0)
-            skill_db[i].state = ST_SHIELD;
-        else if (strcasecmp (split[8], "sight") == 0)
-            skill_db[i].state = ST_SIGHT;
-        else if (strcasecmp (split[8], "explosionspirits") == 0)
-            skill_db[i].state = ST_EXPLOSIONSPIRITS;
-        else if (strcasecmp (split[8], "recover_weight_rate") == 0)
-            skill_db[i].state = ST_RECOV_WEIGHT_RATE;
-        else if (strcasecmp (split[8], "move_enable") == 0)
-            skill_db[i].state = ST_MOVE_ENABLE;
-        else if (strcasecmp (split[8], "water") == 0)
-            skill_db[i].state = ST_WATER;
-        else
-            skill_db[i].state = ST_NONE;
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[9]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].spiritball[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-        skill_db[i].itemid[0] = atoi (split[10]);
-        skill_db[i].amount[0] = atoi (split[11]);
-        skill_db[i].itemid[1] = atoi (split[12]);
-        skill_db[i].amount[1] = atoi (split[13]);
-        skill_db[i].itemid[2] = atoi (split[14]);
-        skill_db[i].amount[2] = atoi (split[15]);
-        skill_db[i].itemid[3] = atoi (split[16]);
-        skill_db[i].amount[3] = atoi (split[17]);
-        skill_db[i].itemid[4] = atoi (split[18]);
-        skill_db[i].amount[4] = atoi (split[19]);
-        skill_db[i].itemid[5] = atoi (split[20]);
-        skill_db[i].amount[5] = atoi (split[21]);
-        skill_db[i].itemid[6] = atoi (split[22]);
-        skill_db[i].amount[6] = atoi (split[23]);
-        skill_db[i].itemid[7] = atoi (split[24]);
-        skill_db[i].amount[7] = atoi (split[25]);
-        skill_db[i].itemid[8] = atoi (split[26]);
-        skill_db[i].amount[8] = atoi (split[27]);
-        skill_db[i].itemid[9] = atoi (split[28]);
-        skill_db[i].amount[9] = atoi (split[29]);
-    }
-    fclose_ (fp);
-    printf ("read db/skill_require_db.txt done\n");
-
-    /* ? */
-    fp = fopen_ ("db/skill_cast_db.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/skill_cast_db.txt\n");
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        char *split[50], *split2[MAX_SKILL_LEVEL];
-        memset (split, 0, sizeof (split));  // [Valaris] thanks to fov
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 5 && p; j++)
-        {
-            while (*p == '\t' || *p == ' ')
-                p++;
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-        if (split[4] == NULL || j < 5)
-            continue;
-
-        i = atoi (split[0]);
-        if (i < 0 || i > MAX_SKILL_DB)
-            continue;
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].cast[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].delay[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].upkeep_time[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].upkeep_time2[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-    }
-    fclose_ (fp);
-    printf ("read db/skill_cast_db.txt done\n");
-
-    fp = fopen_ ("db/skill_castnodex_db.txt", "r");
-    if (fp == NULL)
-    {
-        printf ("can't read db/skill_castnodex_db.txt\n");
-        return 1;
-    }
-    while (fgets (line, 1020, fp))
-    {
-        char *split[50], *split2[MAX_SKILL_LEVEL];
-        memset (split, 0, sizeof (split));
-        if (line[0] == '/' && line[1] == '/')
-            continue;
-        for (j = 0, p = line; j < 2 && p; j++)
-        {
-            while (*p == '\t' || *p == ' ')
-                p++;
-            split[j] = p;
-            p = strchr (p, ',');
-            if (p)
-                *p++ = 0;
-        }
-
-        i = atoi (split[0]);
-        if (i < 0 || i > MAX_SKILL_DB)
-            continue;
-
-        memset (split2, 0, sizeof (split2));
-        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
-        {
-            split2[j] = p;
-            p = strchr (p, ':');
-            if (p)
-                *p++ = 0;
-        }
-        for (k = 0; k < MAX_SKILL_LEVEL; k++)
-            skill_db[i].castnodex[k] =
-                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
-    }
-    fclose_ (fp);
-    printf ("read db/skill_castnodex_db.txt done\n");
-
-    return 0;
-}
-
-void skill_reload (void)
-{
-    /*
-     *
-     * <empty skill database>
-     * <?>
-     *
-     */
-
-    do_init_skill ();
-}
-
-/*==========================================
- * スキル関係初期化処理
- *------------------------------------------
- */
-int do_init_skill (void)
-{
-    skill_readdb ();
-
-    add_timer_interval (gettick () + SKILLUNITTIMER_INVERVAL,
-                        skill_unit_timer, 0, 0, SKILLUNITTIMER_INVERVAL);
-
-    return 0;
-}
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
new file mode 100644
index 0000000..779af98
--- /dev/null
+++ b/src/map/skill.cpp
@@ -0,0 +1,12279 @@
+// $Id: skill.c,v 1.8 2004/09/25 05:32:19 MouseJstr Exp $
+/* スキル関係 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/timer.hpp"
+#include "../common/nullpo.hpp"
+#include "../common/mt_rand.hpp"
+#include "magic.hpp"
+
+#include "battle.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "../common/socket.hpp"
+
+#ifdef MEMWATCH
+#include "memwatch.hpp"
+#endif
+
+#define SKILLUNITTIMER_INVERVAL	100
+
+#define STATE_BLIND 0x10
+
+/* スキル番号=>ステータス異常番号変換テーブル */
+int  SkillStatusChangeTable[] = {   /* skill.hのenumのSC_***とあわせること */
+/* 0- */
+    -1, -1, -1, -1, -1, -1,
+    SC_PROVOKE,                 /* プロボック */
+    -1, 1, -1,
+/* 10- */
+    SC_SIGHT,                   /* サイト */
+    -1, -1, -1, -1,
+    SC_FREEZE,                  /* フロストダイバー */
+    SC_STONE,                   /* ストーンカース */
+    -1, -1, -1,
+/* 20- */
+    -1, -1, -1, -1,
+    SC_RUWACH,                  /* ルアフ */
+    -1, -1, -1, -1,
+    SC_INCREASEAGI,             /* 速度増加 */
+/* 30- */
+    SC_DECREASEAGI,             /* 速度減少 */
+    -1,
+    SC_SIGNUMCRUCIS,            /* シグナムクルシス */
+    SC_ANGELUS,                 /* エンジェラス */
+    SC_BLESSING,                /* ブレッシング */
+    -1, -1, -1, -1, -1,
+/* 40- */
+    -1, -1, -1, -1, -1,
+    SC_CONCENTRATE,             /* 集中力向上 */
+    -1, -1, -1, -1,
+/* 50- */
+    -1,
+    SC_HIDING,                  /* ハイディング */
+    -1, -1, -1, -1, -1, -1, -1, -1,
+/* 60- */
+    SC_TWOHANDQUICKEN,          /* 2HQ */
+    SC_AUTOCOUNTER,
+    -1, -1, -1, -1,
+    SC_IMPOSITIO,               /* インポシティオマヌス */
+    SC_SUFFRAGIUM,              /* サフラギウム */
+    SC_ASPERSIO,                /* アスペルシオ */
+    SC_BENEDICTIO,              /* 聖体降福 */
+/* 70- */
+    -1,
+    SC_SLOWPOISON,
+    -1,
+    SC_KYRIE,                   /* キリエエレイソン */
+    SC_MAGNIFICAT,              /* マグニフィカート */
+    SC_GLORIA,                  /* グロリア */
+    SC_DIVINA,                  /* レックスディビーナ */
+    -1,
+    SC_AETERNA,                 /* レックスエーテルナ */
+    -1,
+/* 80- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 90- */
+    -1, -1,
+    SC_QUAGMIRE,                /* クァグマイア */
+    -1, -1, -1, -1, -1, -1, -1,
+/* 100- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 110- */
+    -1,
+    SC_ADRENALINE,              /* アドレナリンラッシュ */
+    SC_WEAPONPERFECTION,        /* ウェポンパーフェクション */
+    SC_OVERTHRUST,              /* オーバートラスト */
+    SC_MAXIMIZEPOWER,           /* マキシマイズパワー */
+    -1, -1, -1, -1, -1,
+/* 120- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 130- */
+    -1, -1, -1, -1, -1,
+    SC_CLOAKING,                /* クローキング */
+    SC_STAN,                    /* ソニックブロー */
+    -1,
+    SC_ENCPOISON,               /* エンチャントポイズン */
+    SC_POISONREACT,             /* ポイズンリアクト */
+/* 140- */
+    SC_POISON,                  /* ベノムダスト */
+    SC_SPLASHER,                /* ベナムスプラッシャー */
+    -1,
+    SC_TRICKDEAD,               /* 死んだふり */
+    -1, -1, -1, -1, -1, -1,
+/* 150- */
+    -1, -1, -1, -1, -1,
+    SC_LOUD,                    /* ラウドボイス */
+    -1,
+    SC_ENERGYCOAT,              /* エナジーコート */
+    -1, -1,
+/* 160- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1,
+    SC_SELFDESTRUCTION,
+    -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1,
+    SC_KEEPING,
+    -1, -1,
+    SC_BARRIER,
+    -1, -1,
+    SC_HALLUCINATION,
+    -1, -1,
+/* 210- */
+    -1, -1, -1, -1, -1,
+    SC_STRIPWEAPON,
+    SC_STRIPSHIELD,
+    SC_STRIPARMOR,
+    SC_STRIPHELM,
+    -1,
+/* 220- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 230- */
+    -1, -1, -1, -1,
+    SC_CP_WEAPON,
+    SC_CP_SHIELD,
+    SC_CP_ARMOR,
+    SC_CP_HELM,
+    -1, -1,
+/* 240- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    SC_AUTOGUARD,
+/* 250- */
+    -1, -1,
+    SC_REFLECTSHIELD,
+    -1, -1,
+    SC_DEVOTION,
+    SC_PROVIDENCE,
+    SC_DEFENDER,
+    SC_SPEARSQUICKEN,
+    -1,
+/* 260- */
+    -1, -1, -1, -1, -1, -1, -1, -1,
+    SC_STEELBODY,
+    SC_BLADESTOP_WAIT,
+/* 270- */
+    SC_EXPLOSIONSPIRITS,
+    SC_EXTREMITYFIST,
+    -1, -1, -1, -1,
+    SC_MAGICROD,
+    -1, -1, -1,
+/* 280- */
+    SC_FLAMELAUNCHER,
+    SC_FROSTWEAPON,
+    SC_LIGHTNINGLOADER,
+    SC_SEISMICWEAPON,
+    -1,
+    SC_VOLCANO,
+    SC_DELUGE,
+    SC_VIOLENTGALE,
+    SC_LANDPROTECTOR,
+    -1,
+/* 290- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 300- */
+    -1, -1, -1, -1, -1, -1,
+    SC_LULLABY,
+    SC_RICHMANKIM,
+    SC_ETERNALCHAOS,
+    SC_DRUMBATTLE,
+/* 310- */
+    SC_NIBELUNGEN,
+    SC_ROKISWEIL,
+    SC_INTOABYSS,
+    SC_SIEGFRIED,
+    -1, -1, -1,
+    SC_DISSONANCE,
+    -1,
+    SC_WHISTLE,
+/* 320- */
+    SC_ASSNCROS,
+    SC_POEMBRAGI,
+    SC_APPLEIDUN,
+    -1, -1,
+    SC_UGLYDANCE,
+    -1,
+    SC_HUMMING,
+    SC_DONTFORGETME,
+    SC_FORTUNE,
+/* 330- */
+    SC_SERVICE4U,
+    SC_SELFDESTRUCTION,
+    -1, -1, -1, -1, -1, -1, -1, -1,
+/* 340- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 350- */
+    -1, -1, -1, -1, -1,
+    SC_AURABLADE,
+    SC_PARRYING,
+    SC_CONCENTRATION,
+    SC_TENSIONRELAX,
+    SC_BERSERK,
+/* 360- */
+    SC_BERSERK,
+    SC_ASSUMPTIO,
+    SC_BASILICA,
+    -1, -1, -1,
+    SC_MAGICPOWER,
+    -1, -1,
+    SC_GOSPEL,
+/* 370- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+/* 380- */
+    SC_TRUESIGHT,
+    -1, -1,
+    SC_WINDWALK,
+    SC_MELTDOWN,
+    -1, -1,
+    SC_CARTBOOST,
+    -1,
+    SC_CHASEWALK,
+/* 390- */
+    SC_REJECTSWORD,
+    -1, -1, -1, -1, -1,
+    SC_MARIONETTE,
+    -1,
+    SC_HEADCRUSH,
+    SC_JOINTBEAT,
+/* 400 */
+    -1, -1,
+    SC_MINDBREAKER,
+    SC_MEMORIZE,
+    SC_FOGWALL,
+    SC_SPIDERWEB,
+    -1, -1, -1, -1,
+/* 410- */
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+struct skill_name_db skill_names[] = {
+    {AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow"},
+    {AC_CONCENTRATION, "CONCENTRATION", "Improve_Concentration"},
+    {AC_DOUBLE, "DOUBLE", "Double_Strafe"},
+    {AC_MAKINGARROW, "MAKINGARROW", "Arrow_Creation"},
+    {AC_OWL, "OWL", "Owl's_Eye"},
+    {AC_SHOWER, "SHOWER", "Arrow_Shower"},
+    {AC_VULTURE, "VULTURE", "Vulture's_Eye"},
+    {ALL_RESURRECTION, "RESURRECTION", "Resurrection"},
+    {AL_ANGELUS, "ANGELUS", "Angelus"},
+    {AL_BLESSING, "BLESSING", "Blessing"},
+    {AL_CRUCIS, "CRUCIS", "Signum_Crusis"},
+    {AL_CURE, "CURE", "Cure"},
+    {AL_DECAGI, "DECAGI", "Decrease_AGI"},
+    {AL_DEMONBANE, "DEMONBANE", "Demon_Bane"},
+    {AL_DP, "DP", "Divine_Protection"},
+    {AL_HEAL, "HEAL", "Heal"},
+    {AL_HOLYLIGHT, "HOLYLIGHT", "Holy_Light"},
+    {AL_HOLYWATER, "HOLYWATER", "Aqua_Benedicta"},
+    {AL_INCAGI, "INCAGI", "Increase_AGI"},
+    {AL_PNEUMA, "PNEUMA", "Pneuma"},
+    {AL_RUWACH, "RUWACH", "Ruwach"},
+    {AL_TELEPORT, "TELEPORT", "Teleport"},
+    {AL_WARP, "WARP", "Warp_Portal"},
+    {AM_ACIDTERROR, "ACIDTERROR", "Acid_Terror"},
+    {AM_AXEMASTERY, "AXEMASTERY", "Axe_Mastery"},
+    {AM_BERSERKPITCHER, "BERSERKPITCHER", "Berserk Pitcher"},
+    {AM_BIOETHICS, "BIOETHICS", "Bioethics"},
+    {AM_BIOTECHNOLOGY, "BIOTECHNOLOGY", "Biotechnology"},
+    {AM_CALLHOMUN, "CALLHOMUN", "Call_Homunculus"},
+    {AM_CANNIBALIZE, "CANNIBALIZE", "Bio_Cannibalize"},
+    {AM_CP_ARMOR, "ARMOR", "Chemical_Protection_Armor"},
+    {AM_CP_HELM, "HELM", "Chemical_Protection_Helm"},
+    {AM_CP_SHIELD, "SHIELD", "Chemical_Protection_Shield"},
+    {AM_CP_WEAPON, "WEAPON", "Chemical_Protection_Weapon"},
+    {AM_CREATECREATURE, "CREATECREATURE", "Life_Creation"},
+    {AM_CULTIVATION, "CULTIVATION", "Cultivation"},
+    {AM_DEMONSTRATION, "DEMONSTRATION", "Demonstration"},
+    {AM_DRILLMASTER, "DRILLMASTER", "Drillmaster"},
+    {AM_FLAMECONTROL, "FLAMECONTROL", "Flame_Control"},
+    {AM_HEALHOMUN, "HEALHOMUN", "Heal_Homunculus"},
+    {AM_LEARNINGPOTION, "LEARNINGPOTION", "AM_LEARNINGPOTION"},
+    {AM_PHARMACY, "PHARMACY", "Pharmacy"},
+    {AM_POTIONPITCHER, "POTIONPITCHER", "Potion_Pitcher"},
+    {AM_REST, "REST", "Sabbath"},
+    {AM_RESURRECTHOMUN, "RESURRECTHOMUN", "Ressurect_Homunculus"},
+    {AM_SPHEREMINE, "SPHEREMINE", "Sphere_Mine"},
+    {ASC_BREAKER, "BREAKER", "Breaker"},
+    {ASC_CDP, "CDP", "Create_Deadly_Poison"},
+    {ASC_EDP, "EDP", "Deadly_Poison_Enchantment"},
+    {ASC_HALLUCINATION, "HALLUCINATION", "Hallucination_Walk"},
+    {ASC_KATAR, "KATAR", "Advanced_Katar_Mastery"},
+    {ASC_METEORASSAULT, "METEORASSAULT", "Meteor_Assault"},
+    {AS_CLOAKING, "CLOAKING", "Cloaking"},
+    {AS_ENCHANTPOISON, "ENCHANTPOISON", "Enchant_Poison"},
+    {AS_GRIMTOOTH, "GRIMTOOTH", "Grimtooth"},
+    {AS_KATAR, "KATAR", "Katar_Mastery"},
+    {AS_LEFT, "LEFT", "Lefthand_Mastery"},
+    {AS_POISONREACT, "POISONREACT", "Poison_React"},
+    {AS_RIGHT, "RIGHT", "Righthand_Mastery"},
+    {AS_SONICBLOW, "SONICBLOW", "Sonic_Blow"},
+    {AS_SPLASHER, "SPLASHER", "Venom_Splasher"},
+    {AS_VENOMDUST, "VENOMDUST", "Venom_Dust"},
+    {BA_APPLEIDUN, "APPLEIDUN", "Apple_of_Idun"},
+    {BA_ASSASSINCROSS, "ASSASSINCROSS", "Assassin_Cross"},
+    {BA_DISSONANCE, "DISSONANCE", "Dissonance"},
+    {BA_FROSTJOKE, "FROSTJOKE", "Dumb_Joke"},
+    {BA_MUSICALLESSON, "MUSICALLESSON", "Musical_Lesson"},
+    {BA_MUSICALSTRIKE, "MUSICALSTRIKE", "Musical_Strike"},
+    {BA_POEMBRAGI, "POEMBRAGI", "Poem_of_Bragi"},
+    {BA_WHISTLE, "WHISTLE", "Whistle"},
+    {BD_ADAPTATION, "ADAPTATION", "Adaption"},
+    {BD_DRUMBATTLEFIELD, "DRUMBATTLEFIELD", "Drumb_BattleField"},
+    {BD_ENCORE, "ENCORE", "Encore"},
+    {BD_ETERNALCHAOS, "ETERNALCHAOS", "Eternal_Chaos"},
+    {BD_INTOABYSS, "INTOABYSS", "Into_the_Abyss"},
+    {BD_LULLABY, "LULLABY", "Lullaby"},
+    {BD_RAGNAROK, "RAGNAROK", "Ragnarok"},
+    {BD_RICHMANKIM, "RICHMANKIM", "Rich_Mankim"},
+    {BD_RINGNIBELUNGEN, "RINGNIBELUNGEN", "Ring_of_Nibelugen"},
+    {BD_ROKISWEIL, "ROKISWEIL", "Loki's_Wail"},
+    {BD_SIEGFRIED, "SIEGFRIED", "Invulnerable_Siegfried"},
+    {BS_ADRENALINE, "ADRENALINE", "Adrenaline_Rush"},
+    {BS_ADRENALINE2, "ADRENALINE2", "Adrenaline Rush 2"},
+    {BS_AXE, "AXE", "Smith_Axe"},
+    {BS_DAGGER, "DAGGER", "Smith_Dagger"},
+    {BS_ENCHANTEDSTONE, "ENCHANTEDSTONE", "Enchantedstone_Craft"},
+    {BS_FINDINGORE, "FINDINGORE", "Ore_Discovery"},
+    {BS_HAMMERFALL, "HAMMERFALL", "Hammer_Fall"},
+    {BS_HILTBINDING, "HILTBINDING", "Hilt_Binding"},
+    {BS_IRON, "IRON", "Iron_Tempering"},
+    {BS_KNUCKLE, "KNUCKLE", "Smith_Knucklebrace"},
+    {BS_MACE, "MACE", "Smith_Mace"},
+    {BS_MAXIMIZE, "MAXIMIZE", "Power_Maximize"},
+    {BS_ORIDEOCON, "ORIDEOCON", "Orideocon_Research"},
+    {BS_OVERTHRUST, "OVERTHRUST", "Power-Thrust"},
+    {BS_REPAIRWEAPON, "REPAIRWEAPON", "Weapon_Repair"},
+    {BS_SKINTEMPER, "SKINTEMPER", "Skin_Tempering"},
+    {BS_SPEAR, "SPEAR", "Smith_Spear"},
+    {BS_STEEL, "STEEL", "Steel_Tempering"},
+    {BS_SWORD, "SWORD", "Smith_Sword"},
+    {BS_TWOHANDSWORD, "TWOHANDSWORD", "Smith_Two-handed_Sword"},
+    {BS_WEAPONPERFECT, "WEAPONPERFECT", "Weapon_Perfection"},
+    {BS_WEAPONRESEARCH, "WEAPONRESEARCH", "Weaponry_Research"},
+    {CG_ARROWVULCAN, "ARROWVULCAN", "Vulcan_Arrow"},
+    {CG_MARIONETTE, "MARIONETTE", "Marionette_Control"},
+    {CG_MOONLIT, "MOONLIT", "Moonlight_Petals"},
+    {CH_CHAINCRUSH, "CHAINCRUSH", "Chain_Crush_Combo"},
+    {CH_PALMSTRIKE, "PALMSTRIKE", "Palm_Push_Strike"},
+    {CH_SOULCOLLECT, "SOULCOLLECT", "Collect_Soul"},
+    {CH_TIGERFIST, "TIGERFIST", "Tiger_Knuckle_Fist"},
+    {CR_ALCHEMY, "ALCHEMY", "Alchemy"},
+    {CR_AUTOGUARD, "AUTOGUARD", "Guard"},
+    {CR_DEFENDER, "DEFENDER", "Defender"},
+    {CR_DEVOTION, "DEVOTION", "Sacrifice"},
+    {CR_GRANDCROSS, "GRANDCROSS", "Grand_Cross"},
+    {CR_HOLYCROSS, "HOLYCROSS", "Holy_Cross"},
+    {CR_PROVIDENCE, "PROVIDENCE", "Providence"},
+    {CR_REFLECTSHIELD, "REFLECTSHIELD", "Shield_Reflect"},
+    {CR_SHIELDBOOMERANG, "SHIELDBOOMERANG", "Shield_Boomerang"},
+    {CR_SHIELDCHARGE, "SHIELDCHARGE", "Shield_Charge"},
+    {CR_SPEARQUICKEN, "SPEARQUICKEN", "Spear_Quicken"},
+    {CR_SYNTHESISPOTION, "SYNTHESISPOTION", "Potion_Synthesis"},
+    {CR_TRUST, "TRUST", "Faith"},
+    {DC_DANCINGLESSON, "DANCINGLESSON", "Dancing_Lesson"},
+    {DC_DONTFORGETME, "DONTFORGETME", "Don't_Forget_Me"},
+    {DC_FORTUNEKISS, "FORTUNEKISS", "Fortune_Kiss"},
+    {DC_HUMMING, "HUMMING", "Humming"},
+    {DC_SCREAM, "SCREAM", "Scream"},
+    {DC_SERVICEFORYOU, "SERVICEFORYOU", "Prostitute"},
+    {DC_THROWARROW, "THROWARROW", "Throw_Arrow"},
+    {DC_UGLYDANCE, "UGLYDANCE", "Ugly_Dance"},
+    {HP_ASSUMPTIO, "ASSUMPTIO", "Assumptio"},
+    {HP_BASILICA, "BASILICA", "Basilica"},
+    {HP_MEDITATIO, "MEDITATIO", "Meditation"},
+    {HT_ANKLESNARE, "ANKLESNARE", "Ankle_Snare"},
+    {HT_BEASTBANE, "BEASTBANE", "Beast_Bane"},
+    {HT_BLASTMINE, "BLASTMINE", "Blast_Mine"},
+    {HT_BLITZBEAT, "BLITZBEAT", "Blitz_Beat"},
+    {HT_CLAYMORETRAP, "CLAYMORETRAP", "Claymore_Trap"},
+    {HT_DETECTING, "DETECTING", "Detect"},
+    {HT_FALCON, "FALCON", "Falconry_Mastery"},
+    {HT_FLASHER, "FLASHER", "Flasher"},
+    {HT_FREEZINGTRAP, "FREEZINGTRAP", "Freezing_Trap"},
+    {HT_LANDMINE, "LANDMINE", "Land_Mine"},
+    {HT_REMOVETRAP, "REMOVETRAP", "Remove_Trap"},
+    {HT_SANDMAN, "SANDMAN", "Sandman"},
+    {HT_SHOCKWAVE, "SHOCKWAVE", "Shockwave_Trap"},
+    {HT_SKIDTRAP, "SKIDTRAP", "Skid_Trap"},
+    {HT_SPRINGTRAP, "SPRINGTRAP", "Spring_Trap"},
+    {HT_STEELCROW, "STEELCROW", "Steel_Crow"},
+    {HT_TALKIEBOX, "TALKIEBOX", "Talkie_Box"},
+    {HW_MAGICCRASHER, "MAGICCRASHER", "Magic_Crasher"},
+    {HW_MAGICPOWER, "MAGICPOWER", "Magic_Power"},
+    {HW_NAPALMVULCAN, "NAPALMVULCAN", "Napalm_Vulcan"},
+    {HW_SOULDRAIN, "SOULDRAIN", "Soul_Drain"},
+    {KN_AUTOCOUNTER, "AUTOCOUNTER", "Counter_Attack"},
+    {KN_BOWLINGBASH, "BOWLINGBASH", "Bowling_Bash"},
+    {KN_BRANDISHSPEAR, "BRANDISHSPEAR", "Brandish_Spear"},
+    {KN_CAVALIERMASTERY, "CAVALIERMASTERY", "Cavalier_Mastery"},
+    {KN_PIERCE, "PIERCE", "Pierce"},
+    {KN_RIDING, "RIDING", "Peco_Peco_Ride"},
+    {KN_SPEARBOOMERANG, "SPEARBOOMERANG", "Spear_Boomerang"},
+    {KN_SPEARMASTERY, "SPEARMASTERY", "Spear_Mastery"},
+    {KN_SPEARSTAB, "SPEARSTAB", "Spear_Stab"},
+    {KN_TWOHANDQUICKEN, "TWOHANDQUICKEN", "Twohand_Quicken"},
+    {LK_AURABLADE, "AURABLADE", "Aura_Blade"},
+    {LK_BERSERK, "BERSERK", "Berserk"},
+    {LK_CONCENTRATION, "CONCENTRATION", "Concentration"},
+    {LK_FURY, "FURY", "LK_FURY"},
+    {LK_HEADCRUSH, "HEADCRUSH", "Head_Crusher"},
+    {LK_JOINTBEAT, "JOINTBEAT", "Joint_Beat"},
+    {LK_PARRYING, "PARRYING", "Parrying"},
+    {LK_SPIRALPIERCE, "SPIRALPIERCE", "Spiral_Pierce"},
+    {LK_TENSIONRELAX, "TENSIONRELAX", "Tension_Relax"},
+    {MC_CARTREVOLUTION, "CARTREVOLUTION", "Cart_Revolution"},
+    {MC_CHANGECART, "CHANGECART", "Change_Cart"},
+    {MC_DISCOUNT, "DISCOUNT", "Discount"},
+    {MC_IDENTIFY, "IDENTIFY", "Item_Appraisal"},
+    {MC_INCCARRY, "INCCARRY", "Enlarge_Weight_Limit"},
+    {MC_LOUD, "LOUD", "Lord_Exclamation"},
+    {MC_MAMMONITE, "MAMMONITE", "Mammonite"},
+    {MC_OVERCHARGE, "OVERCHARGE", "Overcharge"},
+    {MC_PUSHCART, "PUSHCART", "Pushcart"},
+    {MG_COLDBOLT, "COLDBOLT", "Cold_Bolt"},
+    {MG_ENERGYCOAT, "ENERGYCOAT", "Energy_Coat"},
+    {MG_FIREBALL, "FIREBALL", "Fire_Ball"},
+    {MG_FIREBOLT, "FIREBOLT", "Fire_Bolt"},
+    {MG_FIREWALL, "FIREWALL", "Fire_Wall"},
+    {MG_FROSTDIVER, "FROSTDIVER", "Frost_Diver"},
+    {MG_LIGHTNINGBOLT, "LIGHTNINGBOLT", "Lightening_Bolt"},
+    {MG_NAPALMBEAT, "NAPALMBEAT", "Napalm_Beat"},
+    {MG_SAFETYWALL, "SAFETYWALL", "Safety_Wall"},
+    {MG_SIGHT, "SIGHT", "Sight"},
+    {MG_SOULSTRIKE, "SOULSTRIKE", "Soul_Strike"},
+    {MG_SRECOVERY, "SRECOVERY", "Increase_SP_Recovery"},
+    {MG_STONECURSE, "STONECURSE", "Stone_Curse"},
+    {MG_THUNDERSTORM, "THUNDERSTORM", "Thunderstorm"},
+    {MO_ABSORBSPIRITS, "ABSORBSPIRITS", "Absorb_Spirits"},
+    {MO_BLADESTOP, "BLADESTOP", "Blade_Stop"},
+    {MO_BODYRELOCATION, "BODYRELOCATION", "Body_Relocation"},
+    {MO_CALLSPIRITS, "CALLSPIRITS", "Call_Spirits"},
+    {MO_CHAINCOMBO, "CHAINCOMBO", "Chain_Combo"},
+    {MO_COMBOFINISH, "COMBOFINISH", "Combo_Finish"},
+    {MO_DODGE, "DODGE", "Dodge"},
+    {MO_EXPLOSIONSPIRITS, "EXPLOSIONSPIRITS", "Explosion_Spirits"},
+    {MO_EXTREMITYFIST, "EXTREMITYFIST", "Extremity_Fist"},
+    {MO_FINGEROFFENSIVE, "FINGEROFFENSIVE", "Finger_Offensive"},
+    {MO_INVESTIGATE, "INVESTIGATE", "Investigate"},
+    {MO_IRONHAND, "IRONHAND", "Iron_Hand"},
+    {MO_SPIRITSRECOVERY, "SPIRITSRECOVERY", "Spirit_Recovery"},
+    {MO_STEELBODY, "STEELBODY", "Steel_Body"},
+    {MO_TRIPLEATTACK, "TRIPLEATTACK", "Triple_Blows"},
+    {NPC_ATTRICHANGE, "ATTRICHANGE", "NPC_ATTRICHANGE"},
+    {NPC_BARRIER, "BARRIER", "NPC_BARRIER"},
+    {NPC_BLINDATTACK, "BLINDATTACK", "NPC_BLINDATTACK"},
+    {NPC_BLOODDRAIN, "BLOODDRAIN", "NPC_BLOODDRAIN"},
+    {NPC_CHANGEDARKNESS, "CHANGEDARKNESS", "NPC_CHANGEDARKNESS"},
+    {NPC_CHANGEFIRE, "CHANGEFIRE", "NPC_CHANGEFIRE"},
+    {NPC_CHANGEGROUND, "CHANGEGROUND", "NPC_CHANGEGROUND"},
+    {NPC_CHANGEHOLY, "CHANGEHOLY", "NPC_CHANGEHOLY"},
+    {NPC_CHANGEPOISON, "CHANGEPOISON", "NPC_CHANGEPOISON"},
+    {NPC_CHANGETELEKINESIS, "CHANGETELEKINESIS", "NPC_CHANGETELEKINESIS"},
+    {NPC_CHANGEWATER, "CHANGEWATER", "NPC_CHANGEWATER"},
+    {NPC_CHANGEWIND, "CHANGEWIND", "NPC_CHANGEWIND"},
+    {NPC_COMBOATTACK, "COMBOATTACK", "NPC_COMBOATTACK"},
+    {NPC_CRITICALSLASH, "CRITICALSLASH", "NPC_CRITICALSLASH"},
+    {NPC_CURSEATTACK, "CURSEATTACK", "NPC_CURSEATTACK"},
+    {NPC_DARKBLESSING, "DARKBLESSING", "NPC_DARKBLESSING"},
+    {NPC_DARKBREATH, "DARKBREATH", "NPC_DARKBREATH"},
+    {NPC_DARKCROSS, "DARKCROSS", "NPC_DARKCROSS"},
+    {NPC_DARKNESSATTACK, "DARKNESSATTACK", "NPC_DARKNESSATTACK"},
+    {NPC_DEFENDER, "DEFENDER", "NPC_DEFENDER"},
+    {NPC_EMOTION, "EMOTION", "NPC_EMOTION"},
+    {NPC_ENERGYDRAIN, "ENERGYDRAIN", "NPC_ENERGYDRAIN"},
+    {NPC_FIREATTACK, "FIREATTACK", "NPC_FIREATTACK"},
+    {NPC_GROUNDATTACK, "GROUNDATTACK", "NPC_GROUNDATTACK"},
+    {NPC_GUIDEDATTACK, "GUIDEDATTACK", "NPC_GUIDEDATTACK"},
+    {NPC_HALLUCINATION, "HALLUCINATION", "NPC_HALLUCINATION"},
+    {NPC_HOLYATTACK, "HOLYATTACK", "NPC_HOLYATTACK"},
+    {NPC_KEEPING, "KEEPING", "NPC_KEEPING"},
+    {NPC_LICK, "LICK", "NPC_LICK"},
+    {NPC_MAGICALATTACK, "MAGICALATTACK", "NPC_MAGICALATTACK"},
+    {NPC_MENTALBREAKER, "MENTALBREAKER", "NPC_MENTALBREAKER"},
+    {NPC_METAMORPHOSIS, "METAMORPHOSIS", "NPC_METAMORPHOSIS"},
+    {NPC_PETRIFYATTACK, "PETRIFYATTACK", "NPC_PETRIFYATTACK"},
+    {NPC_PIERCINGATT, "PIERCINGATT", "NPC_PIERCINGATT"},
+    {NPC_POISON, "POISON", "NPC_POISON"},
+    {NPC_POISONATTACK, "POISONATTACK", "NPC_POISONATTACK"},
+    {NPC_RANDOMATTACK, "RANDOMATTACK", "NPC_RANDOMATTACK"},
+    {NPC_RANGEATTACK, "RANGEATTACK", "NPC_RANGEATTACK"},
+    {NPC_REBIRTH, "REBIRTH", "NPC_REBIRTH"},
+    {NPC_SELFDESTRUCTION, "SELFDESTRUCTION", "Kabooooom!"},
+    {NPC_SELFDESTRUCTION2, "SELFDESTRUCTION2", "NPC_SELFDESTRUCTION2"},
+    {NPC_SILENCEATTACK, "SILENCEATTACK", "NPC_SILENCEATTACK"},
+    {NPC_SLEEPATTACK, "SLEEPATTACK", "NPC_SLEEPATTACK"},
+    {NPC_SMOKING, "SMOKING", "NPC_SMOKING"},
+    {NPC_SPLASHATTACK, "SPLASHATTACK", "NPC_SPLASHATTACK"},
+    {NPC_STUNATTACK, "STUNATTACK", "NPC_STUNATTACK"},
+    {NPC_SUICIDE, "SUICIDE", "NPC_SUICIDE"},
+    {NPC_SUMMONMONSTER, "SUMMONMONSTER", "NPC_SUMMONMONSTER"},
+    {NPC_SUMMONSLAVE, "SUMMONSLAVE", "NPC_SUMMONSLAVE"},
+    {NPC_TELEKINESISATTACK, "TELEKINESISATTACK", "NPC_TELEKINESISATTACK"},
+    {NPC_TRANSFORMATION, "TRANSFORMATION", "NPC_TRANSFORMATION"},
+    {NPC_WATERATTACK, "WATERATTACK", "NPC_WATERATTACK"},
+    {NPC_WINDATTACK, "WINDATTACK", "NPC_WINDATTACK"},
+    {NV_EMOTE, "EMOTE", "Emote_Skill"},
+    {NV_TRADE, "TRADE", "Trade_Skill"},
+    {NV_PARTY, "PARTY", "Party_Skill"},
+    {NV_FIRSTAID, "FIRSTAID", "First Aid"},
+    {NV_TRICKDEAD, "TRICKDEAD", "Play_Dead"},
+    {PA_GOSPEL, "GOSPEL", "Gospel"},
+    {PA_PRESSURE, "PRESSURE", "Pressure"},
+    {PA_SACRIFICE, "SACRIFICE", "Sacrificial_Ritual"},
+    {PF_FOGWALL, "FOGWALL", "Wall_of_Fog"},
+    {PF_HPCONVERSION, "HPCONVERSION", "Health_Conversion"},
+    {PF_MEMORIZE, "MEMORIZE", "Memorize"},
+    {PF_MINDBREAKER, "MINDBREAKER", "Mind_Breaker"},
+    {PF_SOULBURN, "SOULBURN", "Soul_Burn"},
+    {PF_SOULCHANGE, "SOULCHANGE", "Soul_Change"},
+    {PF_SPIDERWEB, "SPIDERWEB", "Spider_Web"},
+    {PR_ASPERSIO, "ASPERSIO", "Aspersio"},
+    {PR_BENEDICTIO, "BENEDICTIO", "B.S_Sacramenti"},
+    {PR_GLORIA, "GLORIA", "Gloria"},
+    {PR_IMPOSITIO, "IMPOSITIO", "Impositio_Manus"},
+    {PR_KYRIE, "KYRIE", "Kyrie_Eleison"},
+    {PR_LEXAETERNA, "LEXAETERNA", "Lex_Aeterna"},
+    {PR_LEXDIVINA, "LEXDIVINA", "Lex_Divina"},
+    {PR_MACEMASTERY, "MACEMASTERY", "Mace_Mastery"},
+    {PR_MAGNIFICAT, "MAGNIFICAT", "Magnificat"},
+    {PR_MAGNUS, "MAGNUS", "Magnus_Exorcismus"},
+    {PR_SANCTUARY, "SANCTUARY", "Santuary"},
+    {PR_SLOWPOISON, "SLOWPOISON", "Slow_Poison"},
+    {PR_STRECOVERY, "STRECOVERY", "Status_Recovery"},
+    {PR_SUFFRAGIUM, "SUFFRAGIUM", "Suffragium"},
+    {PR_TURNUNDEAD, "TURNUNDEAD", "Turn_Undead"},
+    {RG_BACKSTAP, "BACKSTAP", "Back_Stab"},
+    {RG_CLEANER, "CLEANER", "Remover"},
+    {RG_COMPULSION, "COMPULSION", "Compulsion_Discount"},
+    {RG_FLAGGRAFFITI, "FLAGGRAFFITI", "Flag_Graffity"},
+    {RG_GANGSTER, "GANGSTER", "Gangster's_Paradise"},
+    {RG_GRAFFITI, "GRAFFITI", "Graffiti"},
+    {RG_INTIMIDATE, "INTIMIDATE", "Intimidate"},
+    {RG_PLAGIARISM, "PLAGIARISM", "Plagiarism"},
+    {RG_RAID, "RAID", "Raid"},
+    {RG_SNATCHER, "SNATCHER", "Snatcher"},
+    {RG_STEALCOIN, "STEALCOIN", "Steal_Coin"},
+    {RG_STRIPARMOR, "STRIPARMOR", "Strip_Armor"},
+    {RG_STRIPHELM, "STRIPHELM", "Strip_Helm"},
+    {RG_STRIPSHIELD, "STRIPSHIELD", "Strip_Shield"},
+    {RG_STRIPWEAPON, "STRIPWEAPON", "Strip_Weapon"},
+    {RG_TUNNELDRIVE, "TUNNELDRIVE", "Tunnel_Drive"},
+    {SA_ABRACADABRA, "ABRACADABRA", "Hocus-pocus"},
+    {SA_ADVANCEDBOOK, "ADVANCEDBOOK", "Advanced_Book"},
+    {SA_AUTOSPELL, "AUTOSPELL", "Auto_Cast"},
+    {SA_CASTCANCEL, "CASTCANCEL", "Cast_Cancel"},
+    {SA_CLASSCHANGE, "CLASSCHANGE", "Class_Change"},
+    {SA_COMA, "COMA", "Coma"},
+    {SA_DEATH, "DEATH", "Death"},
+    {SA_DELUGE, "DELUGE", "Deluge"},
+    {SA_DISPELL, "DISPELL", "Dispel"},
+    {SA_DRAGONOLOGY, "DRAGONOLOGY", "Dragonology"},
+    {SA_FLAMELAUNCHER, "FLAMELAUNCHER", "Flame_Launcher"},
+    {SA_FORTUNE, "FORTUNE", "Fortune"},
+    {SA_FREECAST, "FREECAST", "Cast_Freedom"},
+    {SA_FROSTWEAPON, "FROSTWEAPON", "Frost_Weapon"},
+    {SA_FULLRECOVERY, "FULLRECOVERY", "Full_Recovery"},
+    {SA_GRAVITY, "GRAVITY", "Gravity"},
+    {SA_INSTANTDEATH, "INSTANTDEATH", "Instant_Death"},
+    {SA_LANDPROTECTOR, "LANDPROTECTOR", "Land_Protector"},
+    {SA_LEVELUP, "LEVELUP", "Level_Up"},
+    {SA_LIGHTNINGLOADER, "LIGHTNINGLOADER", "Lightning_Loader"},
+    {SA_MAGICROD, "MAGICROD", "Magic_Rod"},
+    {SA_MONOCELL, "MONOCELL", "Monocell"},
+    {SA_QUESTION, "QUESTION", "Question?"},
+    {SA_REVERSEORCISH, "REVERSEORCISH", "Reverse_Orcish"},
+    {SA_SEISMICWEAPON, "SEISMICWEAPON", "Seismic_Weapon"},
+    {SA_SPELLBREAKER, "SPELLBREAKER", "Break_Spell"},
+    {SA_SUMMONMONSTER, "SUMMONMONSTER", "Summon_Monster"},
+    {SA_VIOLENTGALE, "VIOLENTGALE", "Violent_Gale"},
+    {SA_VOLCANO, "VOLCANO", "Volcano"},
+    {SG_DEVIL, "DEVIL", "Devil"},
+    {SG_FEEL, "FEEL", "Feel"},
+    {SG_FRIEND, "FRIEND", "Friend"},
+    {SG_FUSION, "FUSION", "Fusion"},
+    {SG_HATE, "HATE", "Hate"},
+    {SG_KNOWLEDGE, "KNOWLEDGE", "Knowledge"},
+    {SG_MOON_ANGER, "ANGER", "Moon Anger"},
+    {SG_MOON_BLESS, "BLESS", "Moon Bless"},
+    {SG_MOON_COMFORT, "COMFORT", "Moon Comfort"},
+    {SG_MOON_WARM, "WARM", "Moon Warm"},
+    {SG_STAR_ANGER, "ANGER", "Star Anger"},
+    {SG_STAR_BLESS, "BLESS", "Star Bless"},
+    {SG_STAR_COMFORT, "COMFORT", "Star Comfort"},
+    {SG_STAR_WARM, "WARM", "Star Warm"},
+    {SG_SUN_ANGER, "ANGER", "Sun Anger"},
+    {SG_SUN_BLESS, "BLESS", "Sun Bless"},
+    {SG_SUN_COMFORT, "COMFORT", "Sun Comfort"},
+    {SG_SUN_WARM, "WARM", "Sun Warm"},
+    {SL_ALCHEMIST, "ALCHEMIST", "Alchemist"},
+    {SL_ASSASIN, "ASSASIN", "Assasin"},
+    {SL_BARDDANCER, "BARDDANCER", "Bard Dancer"},
+    {SL_BLACKSMITH, "BLACKSMITH", "Black Smith"},
+    {SL_CRUSADER, "CRUSADER", "Crusader"},
+    {SL_HUNTER, "HUNTER", "Hunter"},
+    {SL_KAAHI, "KAAHI", "Kaahi"},
+    {SL_KAINA, "KAINA", "Kaina"},
+    {SL_KAITE, "KAITE", "Kaite"},
+    {SL_KAIZEL, "KAIZEL", "Kaizel"},
+    {SL_KAUPE, "KAUPE", "Kaupe"},
+    {SL_KNIGHT, "KNIGHT", "Knight"},
+    {SL_MONK, "MONK", "Monk"},
+    {SL_PRIEST, "PRIEST", "Priest"},
+    {SL_ROGUE, "ROGUE", "Rogue"},
+    {SL_SAGE, "SAGE", "Sage"},
+    {SL_SKA, "SKA", "SKA"},
+    {SL_SKE, "SKE", "SKE"},
+    {SL_SMA, "SMA", "SMA"},
+    {SL_SOULLINKER, "SOULLINKER", "Soul Linker"},
+    {SL_STAR, "STAR", "Star"},
+    {SL_STIN, "STIN", "Stin"},
+    {SL_STUN, "STUN", "Stun"},
+    {SL_SUPERNOVICE, "SUPERNOVICE", "Super Novice"},
+    {SL_SWOO, "SWOO", "Swoo"},
+    {SL_WIZARD, "WIZARD", "Wizard"},
+    {SM_AUTOBERSERK, "AUTOBERSERK", "Auto_Berserk"},
+    {SM_BASH, "BASH", "Bash"},
+    {SM_ENDURE, "ENDURE", "Endure"},
+    {SM_FATALBLOW, "FATALBLOW", "Attack_Weak_Point"},
+    {SM_MAGNUM, "MAGNUM", "Magnum_Break"},
+    {SM_MOVINGRECOVERY, "MOVINGRECOVERY", "Moving_HP_Recovery"},
+    {SM_PROVOKE, "PROVOKE", "Provoke"},
+    {SM_RECOVERY, "RECOVERY", "Increase_HP_Recovery"},
+    {SM_SWORD, "SWORD", "Sword_Mastery"},
+    {SM_TWOHAND, "TWOHAND", "Two-Handed_Sword_Mastery"},
+    {SN_FALCONASSAULT, "FALCONASSAULT", "Falcon_Assault"},
+    {SN_SHARPSHOOTING, "SHARPSHOOTING", "Sharpshooting"},
+    {SN_SIGHT, "SIGHT", "True_Sight"},
+    {SN_WINDWALK, "WINDWALK", "Wind_Walk"},
+    {ST_CHASEWALK, "CHASEWALK", "Chase_Walk"},
+    {ST_REJECTSWORD, "REJECTSWORD", "Reject_Sword"},
+    {ST_STEALBACKPACK, "STEALBACKPACK", "Steal_Backpack"},
+    {TF_BACKSLIDING, "BACKSLIDING", "Back_Sliding"},
+    {TF_DETOXIFY, "DETOXIFY", "Detoxify"},
+    {TF_DOUBLE, "DOUBLE", "Double_Attack"},
+    {TF_HIDING, "HIDING", "Hiding"},
+    {TF_MISS, "MISS", "Improve_Dodge"},
+    {TF_PICKSTONE, "PICKSTONE", "Take_Stone"},
+    {TF_POISON, "POISON", "Envenom"},
+    {TF_SPRINKLESAND, "SPRINKLESAND", "Throw_Sand"},
+    {TF_STEAL, "STEAL", "Steal"},
+    {TF_THROWSTONE, "THROWSTONE", "Throw_Stone"},
+    {TK_COUNTER, "COUNTER", "Counter"},
+    {TK_DODGE, "DODGE", "Dodge"},
+    {TK_DOWNKICK, "DOWNKICK", "Down Kick"},
+    {TK_HIGHJUMP, "HIGHJUMP", "High Jump"},
+    {TK_HPTIME, "HPTIME", "HP Time"},
+    {TK_JUMPKICK, "JUMPKICK", "Jump Kick"},
+    {TK_POWER, "POWER", "Power"},
+    {TK_READYCOUNTER, "READYCOUNTER", "Ready Counter"},
+    {TK_READYDOWN, "READYDOWN", "Ready Down"},
+    {TK_READYSTORM, "READYSTORM", "Ready Storm"},
+    {TK_READYTURN, "READYTURN", "Ready Turn"},
+    {TK_RUN, "RUN", "TK_RUN"},
+    {TK_SEVENWIND, "SEVENWIND", "Seven Wind"},
+    {TK_SPTIME, "SPTIME", "SP Time"},
+    {TK_STORMKICK, "STORMKICK", "Storm Kick"},
+    {TK_TURNKICK, "TURNKICK", "Turn Kick"},
+    {WE_BABY, "BABY", "Adopt_Baby"},
+    {WE_CALLBABY, "CALLBABY", "Call_Baby"},
+    {WE_CALLPARENT, "CALLPARENT", "Call_Parent"},
+    {WE_CALLPARTNER, "CALLPARTNER", "I Want to See You"},
+    {WE_FEMALE, "FEMALE", "I Only Look Up to You"},
+    {WE_MALE, "MALE", "I Will Protect You"},
+    {WS_CARTBOOST, "CARTBOOST", "Cart_Boost"},
+    {WS_CREATECOIN, "CREATECOIN", "Create_Coins"},
+    {WS_CREATENUGGET, "CREATENUGGET", "Create_Nuggets"},
+    {WS_MELTDOWN, "MELTDOWN", "Meltdown"},
+    {WS_SYSTEMCREATE, "SYSTEMCREATE", "Create_System_tower"},
+    {WZ_EARTHSPIKE, "EARTHSPIKE", "Earth_Spike"},
+    {WZ_ESTIMATION, "ESTIMATION", "Sense"},
+    {WZ_FIREIVY, "FIREIVY", "Fire_Ivy"},
+    {WZ_FIREPILLAR, "FIREPILLAR", "Fire_Pillar"},
+    {WZ_FROSTNOVA, "FROSTNOVA", "Frost_Nova"},
+    {WZ_HEAVENDRIVE, "HEAVENDRIVE", "Heaven's_Drive"},
+    {WZ_ICEWALL, "ICEWALL", "Ice_Wall"},
+    {WZ_JUPITEL, "JUPITEL", "Jupitel_Thunder"},
+    {WZ_METEOR, "METEOR", "Meteor_Storm"},
+    {WZ_QUAGMIRE, "QUAGMIRE", "Quagmire"},
+    {WZ_SIGHTRASHER, "SIGHTRASHER", "Sightrasher"},
+    {WZ_STORMGUST, "STORMGUST", "Storm_Gust"},
+    {WZ_VERMILION, "VERMILION", "Lord_of_Vermilion"},
+    {WZ_WATERBALL, "WATERBALL", "Water_Ball"},
+    {0, 0, 0}
+};
+
+static const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+static const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+
+static int rdamage;
+
+/* スキルデータベース */
+struct skill_db skill_db[MAX_SKILL_DB];
+
+#define UNARMED_PLAYER_DAMAGE_MIN(bl)	(skill_power_bl((bl), TMW_BRAWLING) >> 4)   // +50 for 200
+#define UNARMED_PLAYER_DAMAGE_MAX(bl)	(skill_power_bl((bl), TMW_BRAWLING))    // +200 for 200
+
+int skill_get_hit (int id)
+{
+    return skill_db[id].hit;
+}
+
+int skill_get_inf (int id)
+{
+    return skill_db[id].inf;
+}
+
+int skill_get_pl (int id)
+{
+    return skill_db[id].pl;
+}
+
+int skill_get_nk (int id)
+{
+    return skill_db[id].nk;
+}
+
+int skill_get_max (int id)
+{
+    return skill_db[id].max;
+}
+
+int skill_get_max_raise (int id)
+{
+    return skill_db[id].max_raise;
+}
+
+int skill_get_range (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].range[lv - 1];
+}
+
+int skill_get_hp (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].hp[lv - 1];
+}
+
+int skill_get_sp (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].sp[lv - 1];
+}
+
+int skill_get_zeny (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].zeny[lv - 1];
+}
+
+int skill_get_num (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].num[lv - 1];
+}
+
+int skill_get_cast (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].cast[lv - 1];
+}
+
+int skill_get_delay (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].delay[lv - 1];
+}
+
+int skill_get_time (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].upkeep_time[lv - 1];
+}
+
+int skill_get_time2 (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].upkeep_time2[lv - 1];
+}
+
+int skill_get_castdef (int id)
+{
+    return skill_db[id].cast_def_rate;
+}
+
+int skill_get_weapontype (int id)
+{
+    return skill_db[id].weapon;
+}
+
+int skill_get_inf2 (int id)
+{
+    return skill_db[id].inf2;
+}
+
+int skill_get_maxcount (int id)
+{
+    return skill_db[id].maxcount;
+}
+
+int skill_get_blewcount (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].blewcount[lv - 1];
+}
+
+int skill_get_mhp (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].mhp[lv - 1];
+}
+
+int skill_get_castnodex (int id, int lv)
+{
+    return (lv <= 0) ? 0 : skill_db[id].castnodex[lv - 1];
+}
+
+/* プロトタイプ */
+struct skill_unit_group *skill_unitsetting (struct block_list *src,
+                                            int skillid, int skilllv, int x,
+                                            int y, int flag);
+int  skill_check_condition (struct map_session_data *sd, int type);
+int  skill_castend_damage_id (struct block_list *src, struct block_list *bl,
+                              int skillid, int skilllv, unsigned int tick,
+                              int flag);
+int  skill_frostjoke_scream (struct block_list *bl, va_list ap);
+int  skill_status_change_timer_sub (struct block_list *bl, va_list ap);
+int  skill_attack_area (struct block_list *bl, va_list ap);
+int  skill_clear_element_field (struct block_list *bl);
+int  skill_landprotector (struct block_list *bl, va_list ap);
+int  skill_trap_splash (struct block_list *bl, va_list ap);
+int  skill_count_target (struct block_list *bl, va_list ap);
+
+// [MouseJstr] - skill ok to cast? and when?
+static int skillnotok (int skillid, struct map_session_data *sd)
+{
+    if (sd == 0)
+        return 0;
+    if (pc_isGM (sd) >= 20)
+        return 0;               // gm's can do anything damn thing they want
+    switch (skillid)
+    {
+        case AL_WARP:
+        case AL_TELEPORT:
+        case MC_IDENTIFY:
+            return 0;           // always allowed
+        default:
+            return (map[sd->bl.m].flag.noskill);
+    }
+}
+
+static int distance (int x0, int y0, int x1, int y1)
+{
+    int  dx, dy;
+
+    dx = abs (x0 - x1);
+    dy = abs (y0 - y1);
+    return dx > dy ? dx : dy;
+}
+
+/* スキルユニットIDを返す(これもデータベースに入れたいな) */
+int skill_get_unit_id (int id, int flag)
+{
+
+    switch (id)
+    {
+        case MG_SAFETYWALL:
+            return 0x7e;        /* セイフティウォール */
+        case MG_FIREWALL:
+            return 0x7f;        /* ファイアーウォール */
+        case AL_WARP:
+            return (flag == 0) ? 0x81 : 0x80;   /* ワープポータル */
+        case PR_BENEDICTIO:
+            return 0x82;        /* 聖体降福 */
+        case PR_SANCTUARY:
+            return 0x83;        /* サンクチュアリ */
+        case PR_MAGNUS:
+            return 0x84;        /* マグヌスエクソシズム */
+        case AL_PNEUMA:
+            return 0x85;        /* ニューマ */
+        case MG_THUNDERSTORM:
+            return 0x86;        /* サンダーストーム */
+        case WZ_HEAVENDRIVE:
+            return 0x86;        /* ヘヴンズドライブ */
+        case WZ_SIGHTRASHER:
+            return 0x86;        /* サイトラッシャー */
+        case WZ_METEOR:
+            return 0x86;        /* メテオストーム */
+        case WZ_VERMILION:
+            return 0x86;        /* ロードオブヴァーミリオン */
+        case WZ_FROSTNOVA:
+            return 0x86;        /* フロストノヴァ */
+        case WZ_STORMGUST:
+            return 0x86;        /* ストームガスト(とりあえずLoVと同じで処理) */
+        case CR_GRANDCROSS:
+            return 0x86;        /* グランドクロス */
+        case WZ_FIREPILLAR:
+            return (flag == 0) ? 0x87 : 0x88;   /* ファイアーピラー */
+        case HT_TALKIEBOX:
+            return 0x99;        /* トーキーボックス */
+        case WZ_ICEWALL:
+            return 0x8d;        /* アイスウォール */
+        case WZ_QUAGMIRE:
+            return 0x8e;        /* クァグマイア */
+        case HT_BLASTMINE:
+            return 0x8f;        /* ブラストマイン */
+        case HT_SKIDTRAP:
+            return 0x90;        /* スキッドトラップ */
+        case HT_ANKLESNARE:
+            return 0x91;        /* アンクルスネア */
+        case AS_VENOMDUST:
+            return 0x92;        /* ベノムダスト */
+        case HT_LANDMINE:
+            return 0x93;        /* ランドマイン */
+        case HT_SHOCKWAVE:
+            return 0x94;        /* ショックウェーブトラップ */
+        case HT_SANDMAN:
+            return 0x95;        /* サンドマン */
+        case HT_FLASHER:
+            return 0x96;        /* フラッシャー */
+        case HT_FREEZINGTRAP:
+            return 0x97;        /* フリージングトラップ */
+        case HT_CLAYMORETRAP:
+            return 0x98;        /* クレイモアートラップ */
+        case SA_VOLCANO:
+            return 0x9a;        /* ボルケーノ */
+        case SA_DELUGE:
+            return 0x9b;        /* デリュージ */
+        case SA_VIOLENTGALE:
+            return 0x9c;        /* バイオレントゲイル */
+        case SA_LANDPROTECTOR:
+            return 0x9d;        /* ランドプロテクター */
+        case BD_LULLABY:
+            return 0x9e;        /* 子守歌 */
+        case BD_RICHMANKIM:
+            return 0x9f;        /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:
+            return 0xa0;        /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:
+            return 0xa1;        /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:
+            return 0xa2;        /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:
+            return 0xa3;        /* ロキの叫び */
+        case BD_INTOABYSS:
+            return 0xa4;        /* 深淵の中に */
+        case BD_SIEGFRIED:
+            return 0xa5;        /* 不死身のジークフリード */
+        case BA_DISSONANCE:
+            return 0xa6;        /* 不協和音 */
+        case BA_WHISTLE:
+            return 0xa7;        /* 口笛 */
+        case BA_ASSASSINCROSS:
+            return 0xa8;        /* 夕陽のアサシンクロス */
+        case BA_POEMBRAGI:
+            return 0xa9;        /* ブラギの詩 */
+        case BA_APPLEIDUN:
+            return 0xaa;        /* イドゥンの林檎 */
+        case DC_UGLYDANCE:
+            return 0xab;        /* 自分勝手なダンス */
+        case DC_HUMMING:
+            return 0xac;        /* ハミング */
+        case DC_DONTFORGETME:
+            return 0xad;        /* 私を忘れないで… */
+        case DC_FORTUNEKISS:
+            return 0xae;        /* 幸運のキス */
+        case DC_SERVICEFORYOU:
+            return 0xaf;        /* サービスフォーユー */
+        case RG_GRAFFITI:
+            return 0xb0;        /* グラフィティ */
+        case AM_DEMONSTRATION:
+            return 0xb1;        /* デモンストレーション */
+        case WE_CALLPARTNER:
+            return 0xb2;        /* あなたに逢いたい */
+        case PA_GOSPEL:
+            return 0xb3;        /* ゴスペル */
+        case HP_BASILICA:
+            return 0xb4;        /* バジリカ */
+        case PF_FOGWALL:
+            return 0xb6;        /* フォグウォール */
+        case PF_SPIDERWEB:
+            return 0xb7;        /* スパイダーウェッブ */
+    }
+    return 0;
+    /*
+     * 0x89,0x8a,0x8b 表示無し
+     * 0x9a 炎属性の詠唱みたいなエフェクト
+     * 0x9b 水属性の詠唱みたいなエフェクト
+     * 0x9c 風属性の詠唱みたいなエフェクト
+     * 0x9d 白い小さなエフェクト
+     * 0xb1 Alchemist Demonstration
+     * 0xb2 = Pink Warp Portal
+     * 0xb3 = Gospel For Paladin
+     * 0xb4 = Basilica
+     * 0xb5 = Empty
+     * 0xb6 = Fog Wall for Professor
+     * 0xb7 = Spider Web for Professor
+     * 0xb8 = Empty
+     * 0xb9 =
+     */
+}
+
+/*==========================================
+ * スキル追加効果
+ *------------------------------------------
+ */
+int skill_additional_effect (struct block_list *src, struct block_list *bl,
+                             int skillid, int skilllv, int attack_type,
+                             unsigned int tick)
+{
+    /* MOB追加効果スキル用 */
+    const int sc[] = {
+        SC_POISON, SC_BLIND, SC_SILENCE, SC_STAN,
+        SC_STONE, SC_CURSE, SC_SLEEP
+    };
+    const int sc2[] = {
+        MG_STONECURSE, MG_FROSTDIVER, NPC_STUNATTACK,
+        NPC_SLEEPATTACK, TF_POISON, NPC_CURSEATTACK,
+        NPC_SILENCEATTACK, 0, NPC_BLINDATTACK
+    };
+
+    struct map_session_data *sd = NULL;
+    struct map_session_data *dstsd = NULL;
+    struct mob_data *md = NULL;
+    struct mob_data *dstmd = NULL;
+
+    int  skill, skill2;
+    int  rate, luk;
+
+    int  sc_def_mdef, sc_def_vit, sc_def_int, sc_def_luk;
+    int  sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2;
+    int  sc_def_phys_shield_spell;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, bl);
+
+    if (skilllv < 0)
+        return 0;
+
+    if (src->type == BL_PC)
+    {
+        nullpo_retr (0, sd = (struct map_session_data *) src);
+    }
+    else if (src->type == BL_MOB)
+    {
+        nullpo_retr (0, md = (struct mob_data *) src);  //未使用?
+    }
+
+    sc_def_phys_shield_spell = 0;
+    if (battle_get_sc_data (bl)[SC_PHYS_SHIELD].timer != -1)
+        sc_def_phys_shield_spell =
+            battle_get_sc_data (bl)[SC_PHYS_SHIELD].val1;
+
+    //対象の耐性
+    luk = battle_get_luk (bl);
+    sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + luk / 3);
+    sc_def_vit = 100 - (3 + battle_get_vit (bl) + luk / 3);
+    sc_def_int = 100 - (3 + battle_get_int (bl) + luk / 3);
+    sc_def_luk = 100 - (3 + luk);
+    //自分の耐性
+    luk = battle_get_luk (src);
+    sc_def_mdef2 = 100 - (3 + battle_get_mdef (src) + luk / 3);
+    sc_def_vit2 = 100 - (3 + battle_get_vit (src) + luk / 3);
+    sc_def_int2 = 100 - (3 + battle_get_int (src) + luk / 3);
+    sc_def_luk2 = 100 - (3 + luk);
+    if (bl->type == BL_PC)
+        dstsd = (struct map_session_data *) bl;
+    else if (bl->type == BL_MOB)
+    {
+        dstmd = (struct mob_data *) bl; //未使用?
+        if (sc_def_mdef > 50)
+            sc_def_mdef = 50;
+        if (sc_def_vit > 50)
+            sc_def_vit = 50;
+        if (sc_def_int > 50)
+            sc_def_int = 50;
+        if (sc_def_luk > 50)
+            sc_def_luk = 50;
+    }
+    if (sc_def_mdef < 0)
+        sc_def_mdef = 0;
+    if (sc_def_vit < 0)
+        sc_def_vit = 0;
+    if (sc_def_int < 0)
+        sc_def_int = 0;
+
+    switch (skillid)
+    {
+        case 0:                /* 通常攻撃 */
+            /* 自動鷹 */
+            if (sd && pc_isfalcon (sd) && sd->status.weapon == 11
+                && (skill = pc_checkskill (sd, HT_BLITZBEAT)) > 0
+                && MRAND (1000) <= sd->paramc[5] * 10 / 3 + 1)
+            {
+                int  lv = (sd->status.job_level + 9) / 10;
+                skill_castend_damage_id (src, bl, HT_BLITZBEAT,
+                                         (skill < lv) ? skill : lv, tick,
+                                         0xf00000);
+            }
+            // スナッチャー
+            if (sd && sd->status.weapon != 11
+                && (skill = pc_checkskill (sd, RG_SNATCHER)) > 0)
+                if ((skill * 15 + 55) +
+                    (skill2 =
+                     pc_checkskill (sd, TF_STEAL)) * 10 > MRAND (1000))
+                {
+                    if (pc_steal_item (sd, bl))
+                        clif_skill_nodamage (src, bl, TF_STEAL, skill2, 1);
+                    else
+                        clif_skill_fail (sd, skillid, 0, 0);
+                }
+            break;
+
+        case SM_BASH:          /* バッシュ(急所攻撃) */
+            if (sd && (skill = pc_checkskill (sd, SM_FATALBLOW)) > 0)
+            {
+                if (MRAND (100) < 6 * (skilllv - 5) * sc_def_vit / 100)
+                    skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                               skill_get_time2 (SM_FATALBLOW,
+                                                                skilllv), 0);
+            }
+            break;
+
+        case TF_POISON:        /* インベナム */
+        case AS_SPLASHER:      /* ベナムスプラッシャー */
+            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_POISON, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            else
+            {
+                if (sd && skillid == TF_POISON)
+                    clif_skill_fail (sd, skillid, 0, 0);
+            }
+            break;
+
+        case AS_SONICBLOW:     /* ソニックブロー */
+            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case HT_FREEZINGTRAP:  /* フリージングトラップ */
+            rate = skilllv * 3 + 35;
+            if (MRAND (100) < rate * sc_def_mdef / 100)
+                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case MG_FROSTDIVER:    /* フロストダイバー */
+        case WZ_FROSTNOVA:     /* フロストノヴァ */
+            rate =
+                (skilllv * 3 + 35) * sc_def_mdef / 100 -
+                (battle_get_int (bl) + battle_get_luk (bl)) / 15;
+            rate = rate <= 5 ? 5 : rate;
+            if (MRAND (100) < rate)
+                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            else if (sd)
+                clif_skill_fail (sd, skillid, 0, 0);
+            break;
+
+        case WZ_STORMGUST:     /* ストームガスト */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            if (sc_data)
+            {
+                sc_data[SC_FREEZE].val3++;
+                if (sc_data[SC_FREEZE].val3 >= 3)
+                    skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0,
+                                               0, skill_get_time2 (skillid,
+                                                                   skilllv),
+                                               0);
+            }
+        }
+            break;
+
+        case HT_LANDMINE:      /* ランドマイン */
+            if (MRAND (100) < (5 * skilllv + 30) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
+            if (map[bl->m].flag.pvp && dstsd)
+            {
+                dstsd->status.sp -=
+                    dstsd->status.sp * (5 + 15 * skilllv) / 100;
+                pc_calcstatus (dstsd, 0);
+            }
+            break;
+        case HT_SANDMAN:       /* サンドマン */
+            if (MRAND (100) < (5 * skilllv + 30) * sc_def_int / 100)
+                skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case TF_SPRINKLESAND:  /* 砂まき */
+            if (MRAND (100) < 15 * sc_def_int / 100)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case TF_THROWSTONE:    /* 石投げ */
+            if (MRAND (100) < 5 * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case CR_HOLYCROSS:     /* ホーリークロス */
+            if (MRAND (100) < 3 * skilllv * sc_def_int / 100)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case CR_GRANDCROSS:    /* グランドクロス */
+        {
+            int  race = battle_get_race (bl);
+            if ((battle_check_undead (race, battle_get_elem_type (bl)) || race == 6) && MRAND (100) < 100000 * sc_def_int / 100)    //強制付与だが完全耐性には無効
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+        }
+            break;
+
+        case CR_SHIELDCHARGE:  /* シールドチャージ */
+            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case RG_RAID:          /* サプライズアタック */
+            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case BA_FROSTJOKE:
+            if (MRAND (100) < (15 + 5 * skilllv) * sc_def_mdef / 100)
+                skill_status_change_start (bl, SC_FREEZE, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case DC_SCREAM:
+            if (MRAND (100) < (25 + 5 * skilllv) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case BD_LULLABY:       /* 子守唄 */
+            if (MRAND (100) < 15 * sc_def_int / 100)
+                skill_status_change_start (bl, SC_SLEEP, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+            /* MOBの追加効果付きスキル */
+
+        case NPC_PETRIFYATTACK:
+            if (MRAND (100) < sc_def_mdef)
+                skill_status_change_start (bl, sc[skillid - NPC_POISON],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case NPC_POISON:
+        case NPC_SILENCEATTACK:
+        case NPC_STUNATTACK:
+            if (MRAND (100) <
+                50 - (sc_def_vit >> 2) - (sc_def_phys_shield_spell) +
+                (skilllv >> 2))
+                skill_status_change_start (bl, sc[skillid - NPC_POISON],
+                                           skilllv, 0, 0, 0, skilllv, 0);
+            break;
+        case NPC_CURSEATTACK:
+            if (MRAND (100) < sc_def_luk)
+                skill_status_change_start (bl, sc[skillid - NPC_POISON],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case NPC_SLEEPATTACK:
+        case NPC_BLINDATTACK:
+            if (MRAND (100) < sc_def_int)
+                skill_status_change_start (bl, sc[skillid - NPC_POISON],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case NPC_MENTALBREAKER:
+            if (dstsd)
+            {
+                int  sp = dstsd->status.max_sp * (10 + skilllv) / 100;
+                if (sp < 1)
+                    sp = 1;
+                pc_heal (dstsd, 0, -sp);
+            }
+            break;
+
+// -- moonsoul (adding status effect chance given to wizard aoe skills meteor and vermillion)
+//
+        case WZ_METEOR:
+            if (MRAND (100) < sc_def_vit)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case WZ_VERMILION:
+            if (MRAND (100) < sc_def_int)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+// -- moonsoul (stun ability of new champion skill tigerfist)
+//
+        case CH_TIGERFIST:
+            if (MRAND (100) < (5 + skilllv * 5) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case LK_SPIRALPIERCE:
+            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case ST_REJECTSWORD:   /* フリージングトラップ */
+            if (MRAND (100) < (10 + skilllv * 5))
+                skill_status_change_start (bl, SC_AUTOCOUNTER, skilllv, 0, 0,
+                                           0, skill_get_time2 (skillid,
+                                                               skilllv), 0);
+            break;
+        case PF_FOGWALL:       /* ホーリークロス */
+            if (MRAND (100) < 3 * skilllv * sc_def_int / 100)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case LK_HEADCRUSH:     /* ヘッドクラッシュ */
+        {                       //条件が良く分からないので適当に
+            int  race = battle_get_race (bl);
+            if (!
+                (battle_check_undead (race, battle_get_elem_type (bl))
+                 || race == 6)
+                && MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_HEADCRUSH, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+        }
+            break;
+        case LK_JOINTBEAT:     /* ジョイントビート */
+            //条件が良く分からないので適当に
+            if (MRAND (100) < (2 * skilllv + 10) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_JOINTBEAT, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case PF_SPIDERWEB:     /* スパイダーウェッブ */
+        {
+            int  sec = skill_get_time2 (skillid, skilllv);
+            if (map[src->m].flag.pvp)   //PvPでは拘束時間半減?
+                sec = sec / 2;
+            battle_stopwalking (bl, 1);
+            skill_status_change_start (bl, SC_SPIDERWEB, skilllv, 0, 0, 0,
+                                       sec, 0);
+        }
+            break;
+        case ASC_METEORASSAULT:    /* メテオアサルト */
+            if (MRAND (100) < (15 + skilllv * 5) * sc_def_vit / 100)    //状態異常は詳細が分からないので適当に
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            if (MRAND (100) < (10 + 3 * skilllv) * sc_def_int / 100)
+                skill_status_change_start (bl, SC_BLIND, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+        case MO_EXTREMITYFIST: /* 阿修羅覇凰拳 */
+            //阿修羅を使うと5分間自然回復しないようになる
+            skill_status_change_start (src, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time2 (skillid, skilllv), 0);
+            break;
+    }
+
+    if (sd && skillid != MC_CARTREVOLUTION && attack_type & BF_WEAPON)
+    {                           /* カードによる追加効果 */
+        int  i;
+        int  sc_def_card = 100;
+
+        for (i = SC_STONE; i <= SC_BLIND; i++)
+        {
+            //対象に状態異常
+            if (i == SC_STONE || i == SC_FREEZE)
+                sc_def_card = sc_def_mdef;
+            else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE)
+                sc_def_card = sc_def_vit;
+            else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND)
+                sc_def_card = sc_def_int;
+            else if (i == SC_CURSE)
+                sc_def_card = sc_def_luk;
+
+            if (!sd->state.arrow_atk)
+            {
+                if (MRAND (10000) <
+                    (sd->addeff[i - SC_STONE]) * sc_def_card / 100)
+                {
+                    if (battle_config.battle_log)
+                        printf
+                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
+                             sd->bl.id, i, sd->addeff[i - SC_STONE]);
+                    skill_status_change_start (bl, i, 7, 0, 0, 0,
+                                               (i ==
+                                                SC_CONFUSION) ? 10000 +
+                                               7000 :
+                                               skill_get_time2 (sc2
+                                                                [i -
+                                                                 SC_STONE],
+                                                                7), 0);
+                }
+            }
+            else
+            {
+                if (MRAND (10000) <
+                    (sd->addeff[i - SC_STONE] +
+                     sd->arrow_addeff[i - SC_STONE]) * sc_def_card / 100)
+                {
+                    if (battle_config.battle_log)
+                        printf
+                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
+                             sd->bl.id, i, sd->addeff[i - SC_STONE]);
+                    skill_status_change_start (bl, i, 7, 0, 0, 0,
+                                               (i ==
+                                                SC_CONFUSION) ? 10000 +
+                                               7000 :
+                                               skill_get_time2 (sc2
+                                                                [i -
+                                                                 SC_STONE],
+                                                                7), 0);
+                }
+            }
+            //自分に状態異常
+            if (i == SC_STONE || i == SC_FREEZE)
+                sc_def_card = sc_def_mdef2;
+            else if (i == SC_STAN || i == SC_POISON || i == SC_SILENCE)
+                sc_def_card = sc_def_vit2;
+            else if (i == SC_SLEEP || i == SC_CONFUSION || i == SC_BLIND)
+                sc_def_card = sc_def_int2;
+            else if (i == SC_CURSE)
+                sc_def_card = sc_def_luk2;
+
+            if (!sd->state.arrow_atk)
+            {
+                if (MRAND (10000) <
+                    (sd->addeff2[i - SC_STONE]) * sc_def_card / 100)
+                {
+                    if (battle_config.battle_log)
+                        printf
+                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
+                             src->id, i, sd->addeff2[i - SC_STONE]);
+                    skill_status_change_start (src, i, 7, 0, 0, 0,
+                                               (i ==
+                                                SC_CONFUSION) ? 10000 +
+                                               7000 :
+                                               skill_get_time2 (sc2
+                                                                [i -
+                                                                 SC_STONE],
+                                                                7), 0);
+                }
+            }
+            else
+            {
+                if (MRAND (10000) <
+                    (sd->addeff2[i - SC_STONE] +
+                     sd->arrow_addeff2[i - SC_STONE]) * sc_def_card / 100)
+                {
+                    if (battle_config.battle_log)
+                        printf
+                            ("PC %d skill_addeff: cardによる異常発動 %d %d\n",
+                             src->id, i, sd->addeff2[i - SC_STONE]);
+                    skill_status_change_start (src, i, 7, 0, 0, 0,
+                                               (i ==
+                                                SC_CONFUSION) ? 10000 +
+                                               7000 :
+                                               skill_get_time2 (sc2
+                                                                [i -
+                                                                 SC_STONE],
+                                                                7), 0);
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+/*=========================================================================
+ スキル攻撃吹き飛ばし処理
+-------------------------------------------------------------------------*/
+int skill_blown (struct block_list *src, struct block_list *target, int count)
+{
+    int  dx = 0, dy = 0, nx, ny;
+    int  x = target->x, y = target->y;
+    int  ret, prev_state = MS_IDLE;
+    int  moveblock;
+    struct map_session_data *sd = NULL;
+    struct mob_data *md = NULL;
+    struct skill_unit *su = NULL;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, target);
+
+    if (target->type == BL_PC)
+    {
+        nullpo_retr (0, sd = (struct map_session_data *) target);
+    }
+    else if (target->type == BL_MOB)
+    {
+        nullpo_retr (0, md = (struct mob_data *) target);
+    }
+    else if (target->type == BL_SKILL)
+    {
+        nullpo_retr (0, su = (struct skill_unit *) target);
+    }
+    else
+        return 0;
+
+    if (!(count & 0x10000 && (sd || md || su)))
+    {                           /* 指定なしなら位置関係から方向を求める */
+        dx = target->x - src->x;
+        dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
+        dy = target->y - src->y;
+        dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
+    }
+    if (dx == 0 && dy == 0)
+    {
+        int  dir = battle_get_dir (target);
+        if (dir >= 0 && dir < 8)
+        {
+            dx = -dirx[dir];
+            dy = -diry[dir];
+        }
+    }
+
+    ret = path_blownpos (target->m, x, y, dx, dy, count & 0xffff);
+    nx = ret >> 16;
+    ny = ret & 0xffff;
+    moveblock = (x / BLOCK_SIZE != nx / BLOCK_SIZE
+                 || y / BLOCK_SIZE != ny / BLOCK_SIZE);
+
+    if (count & 0x20000)
+    {
+        battle_stopwalking (target, 1);
+        if (sd)
+        {
+            sd->to_x = nx;
+            sd->to_y = ny;
+            sd->walktimer = 1;
+            clif_walkok (sd);
+            clif_movechar (sd);
+        }
+        else if (md)
+        {
+            md->to_x = nx;
+            md->to_y = ny;
+            prev_state = md->state.state;
+            md->state.state = MS_WALK;
+            clif_fixmobpos (md);
+        }
+    }
+    else
+        battle_stopwalking (target, 2);
+
+    dx = nx - x;
+    dy = ny - y;
+
+    if (sd)                     /* 画面外に出たので消去 */
+        map_foreachinmovearea (clif_pcoutsight, target->m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               dx, dy, 0, sd);
+    else if (md)
+        map_foreachinmovearea (clif_moboutsight, target->m, x - AREA_SIZE,
+                               y - AREA_SIZE, x + AREA_SIZE, y + AREA_SIZE,
+                               dx, dy, BL_PC, md);
+
+    if (su)
+    {
+        skill_unit_move_unit_group (su->group, target->m, dx, dy);
+    }
+    else
+    {
+//      struct status_change *sc_data=battle_get_sc_data(target);
+        if (moveblock)
+            map_delblock (target);
+        target->x = nx;
+        target->y = ny;
+        if (moveblock)
+            map_addblock (target);
+/*ダンス中にエフェクトは移動しないらしい
+		if(sc_data && sc_data[SC_DANCING].timer!=-1){ //対象がダンス中なのでエフェクトも移動
+			struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2;
+			if(sg)
+				skill_unit_move_unit_group(sg,target->m,dx,dy);
+		}
+*/
+    }
+
+    if (sd)
+    {                           /* 画面内に入ってきたので表示 */
+        map_foreachinmovearea (clif_pcinsight, target->m, nx - AREA_SIZE,
+                               ny - AREA_SIZE, nx + AREA_SIZE, ny + AREA_SIZE,
+                               -dx, -dy, 0, sd);
+        if (count & 0x20000)
+            sd->walktimer = -1;
+    }
+    else if (md)
+    {
+        map_foreachinmovearea (clif_mobinsight, target->m, nx - AREA_SIZE,
+                               ny - AREA_SIZE, nx + AREA_SIZE, ny + AREA_SIZE,
+                               -dx, -dy, BL_PC, md);
+        if (count & 0x20000)
+            md->state.state = prev_state;
+    }
+
+    skill_unit_move (target, gettick (), (count & 0xffff) + 7); /* スキルユニットの判定 */
+
+    return 0;
+}
+
+/*
+ * =========================================================================
+ * スキル攻撃効果処理まとめ
+ * flagの説明。16進図
+ *	00XRTTff
+ *  ff	= magicで計算に渡される)
+ *	TT	= パケットのtype部分(0でデフォルト)
+ *  X   = パケットのスキルLv
+ *  R	= 予約(skill_area_subで使用する)
+ *-------------------------------------------------------------------------
+ */
+
+int skill_attack (int attack_type, struct block_list *src,
+                  struct block_list *dsrc, struct block_list *bl, int skillid,
+                  int skilllv, unsigned int tick, int flag)
+{
+    struct Damage dmg;
+    struct status_change *sc_data;
+    int  type, lv, damage;
+
+    rdamage = 0;
+    nullpo_retr (0, src);
+    nullpo_retr (0, dsrc);
+    nullpo_retr (0, bl);
+
+    sc_data = battle_get_sc_data (bl);
+
+//何もしない判定ここから
+    if (dsrc->m != bl->m)       //対象が同じマップにいなければ何もしない
+        return 0;
+    if (src->prev == NULL || dsrc->prev == NULL || bl->prev == NULL)    //prevよくわからない※
+        return 0;
+    if (src->type == BL_PC && pc_isdead ((struct map_session_data *) src))  //術者?がPCですでに死んでいたら何もしない
+        return 0;
+    if (dsrc->type == BL_PC && pc_isdead ((struct map_session_data *) dsrc))    //術者?がPCですでに死んでいたら何もしない
+        return 0;
+    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))    //対象がPCですでに死んでいたら何もしない
+        return 0;
+    if (skillnotok (skillid, (struct map_session_data *) bl))
+        return 0;               // [MouseJstr]
+    if (sc_data && sc_data[SC_HIDING].timer != -1)
+    {                           //ハイディング状態で
+        if (skill_get_pl (skillid) != 2)    //スキルの属性が地属性でなければ何もしない
+            return 0;
+    }
+    if (sc_data && sc_data[SC_TRICKDEAD].timer != -1)   //死んだふり中は何もしない
+        return 0;
+    if (skillid == WZ_STORMGUST)
+    {                           //使用スキルがストームガストで
+        if (sc_data && sc_data[SC_FREEZE].timer != -1)  //凍結状態なら何もしない
+            return 0;
+    }
+    if (skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y)    //使用スキルがフロストノヴァで、dsrcとblが同じ場所なら何もしない
+        return 0;
+    if (src->type == BL_PC && ((struct map_session_data *) src)->chatID)    //術者がPCでチャット中なら何もしない
+        return 0;
+    if (dsrc->type == BL_PC && ((struct map_session_data *) dsrc)->chatID)  //術者がPCでチャット中なら何もしない
+        return 0;
+    if (src->type == BL_PC && bl
+        && mob_gvmobcheck (((struct map_session_data *) src), bl) == 0)
+        return 0;
+
+//何もしない判定ここまで
+
+    type = -1;
+    lv = (flag >> 20) & 0xf;
+    dmg = battle_calc_attack (attack_type, src, bl, skillid, skilllv, flag & 0xff); //ダメージ計算
+
+//マジックロッド処理ここから
+    if (attack_type & BF_MAGIC && sc_data && sc_data[SC_MAGICROD].timer != -1
+        && src == dsrc)
+    {                           //魔法攻撃でマジックロッド状態でsrc=dsrcなら
+        dmg.damage = dmg.damage2 = 0;   //ダメージ0
+        if (bl->type == BL_PC)
+        {                       //対象がPCの場合
+            int  sp = skill_get_sp (skillid, skilllv);  //使用されたスキルのSPを吸収
+            sp = sp * sc_data[SC_MAGICROD].val2 / 100;  //吸収率計算
+            if (skillid == WZ_WATERBALL && skilllv > 1) //ウォーターボールLv1以上
+                sp = sp / ((skilllv | 1) * (skilllv | 1));  //さらに計算?
+            if (sp > 0x7fff)
+                sp = 0x7fff;    //SP多すぎの場合は理論最大値
+            else if (sp < 1)
+                sp = 1;         //1以下の場合は1
+            if (((struct map_session_data *) bl)->status.sp + sp >
+                ((struct map_session_data *) bl)->status.max_sp)
+            {                   //回復SP+現在のSPがMSPより大きい場合
+                sp = ((struct map_session_data *) bl)->status.max_sp - ((struct map_session_data *) bl)->status.sp; //SPをMSP-現在SPにする
+                ((struct map_session_data *) bl)->status.sp = ((struct map_session_data *) bl)->status.max_sp;  //現在のSPにMSPを代入
+            }
+            else                //回復SP+現在のSPがMSPより小さい場合は回復SPを加算
+                ((struct map_session_data *) bl)->status.sp += sp;
+            clif_heal (((struct map_session_data *) bl)->fd, SP_SP, sp);    //SP回復エフェクトの表示
+            ((struct map_session_data *) bl)->canact_tick = tick + skill_delayfix (bl, skill_get_delay (SA_MAGICROD, sc_data[SC_MAGICROD].val1));   //
+        }
+        clif_skill_nodamage (bl, bl, SA_MAGICROD, sc_data[SC_MAGICROD].val1, 1);    //マジックロッドエフェクトを表示
+    }
+//マジックロッド処理ここまで
+
+    damage = dmg.damage + dmg.damage2;
+
+    if (lv == 15)
+        lv = -1;
+
+    if (flag & 0xff00)
+        type = (flag & 0xff00) >> 8;
+
+    if (damage <= 0 || damage < dmg.div_)   //吹き飛ばし判定?※
+        dmg.blewcount = 0;
+
+    if (skillid == CR_GRANDCROSS)
+    {                           //グランドクロス
+        if (battle_config.gx_disptype)
+            dsrc = src;         // 敵ダメージ白文字表示
+        if (src == bl)
+            type = 4;           // 反動はダメージモーションなし
+    }
+
+//使用者がPCの場合の処理ここから
+    if (src->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) src;
+        nullpo_retr (0, sd);
+//連打掌(MO_CHAINCOMBO)ここから
+        if (skillid == MO_CHAINCOMBO)
+        {
+            int  delay = 1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);    //基本ディレイの計算
+            if (damage < battle_get_hp (bl))
+            {                   //ダメージが対象のHPより小さい場合
+                if (pc_checkskill (sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0)   //猛龍拳(MO_COMBOFINISH)取得&気球保持時は+300ms
+                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
+
+                skill_status_change_start (src, SC_COMBO, MO_CHAINCOMBO, skilllv, 0, 0, delay, 0);  //コンボ状態に
+            }
+            sd->attackabletime = sd->canmove_tick = tick + delay;
+            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
+        }
+//連打掌(MO_CHAINCOMBO)ここまで
+//猛龍拳(MO_COMBOFINISH)ここから
+        else if (skillid == MO_COMBOFINISH)
+        {
+            int  delay =
+                700 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
+            if (damage < battle_get_hp (bl))
+            {
+                //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms
+                //伏虎拳(CH_TIGERFIST)取得時も+300ms
+                if ((pc_checkskill (sd, MO_EXTREMITYFIST) > 0
+                     && sd->spiritball >= 4
+                     && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
+                    || (pc_checkskill (sd, CH_TIGERFIST) > 0
+                        && sd->spiritball > 0)
+                    || (pc_checkskill (sd, CH_CHAINCRUSH) > 0
+                        && sd->spiritball > 1))
+                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
+
+                skill_status_change_start (src, SC_COMBO, MO_COMBOFINISH, skilllv, 0, 0, delay, 0); //コンボ状態に
+            }
+            sd->attackabletime = sd->canmove_tick = tick + delay;
+            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
+        }
+//猛龍拳(MO_COMBOFINISH)ここまで
+//伏虎拳(CH_TIGERFIST)ここから
+        else if (skillid == CH_TIGERFIST)
+        {
+            int  delay =
+                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
+            if (damage < battle_get_hp (bl))
+            {
+                if (pc_checkskill (sd, CH_CHAINCRUSH) > 0)  //連柱崩撃(CH_CHAINCRUSH)取得時は+300ms
+                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
+
+                skill_status_change_start (src, SC_COMBO, CH_TIGERFIST, skilllv, 0, 0, delay, 0);   //コンボ状態に
+            }
+            sd->attackabletime = sd->canmove_tick = tick + delay;
+            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
+        }
+//伏虎拳(CH_TIGERFIST)ここまで
+//連柱崩撃(CH_CHAINCRUSH)ここから
+        else if (skillid == CH_CHAINCRUSH)
+        {
+            int  delay =
+                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
+            if (damage < battle_get_hp (bl))
+            {
+                //阿修羅覇凰拳(MO_EXTREMITYFIST)取得&気球4個保持&爆裂波動(MO_EXPLOSIONSPIRITS)状態時は+300ms
+                if (pc_checkskill (sd, MO_EXTREMITYFIST) > 0
+                    && sd->spiritball >= 4
+                    && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
+                    delay += 300 * battle_config.combo_delay_rate / 100;    //追加ディレイをconfにより調整
+
+                skill_status_change_start (src, SC_COMBO, CH_CHAINCRUSH, skilllv, 0, 0, delay, 0);  //コンボ状態に
+            }
+            sd->attackabletime = sd->canmove_tick = tick + delay;
+            clif_combo_delay (src, delay);  //コンボディレイパケットの送信
+        }
+//連柱崩撃(CH_CHAINCRUSH)ここまで
+    }
+//使用者がPCの場合の処理ここまで
+//武器スキル?ここから
+    //AppleGirl Was Here
+    if (attack_type & BF_MAGIC && damage > 0 && src != bl && src == dsrc)
+    {                           //Blah Blah
+        if (bl->type == BL_PC)
+        {                       //Blah Blah
+            struct map_session_data *tsd = (struct map_session_data *) bl;
+            if (tsd->magic_damage_return > 0)
+            {                   //More Blah
+                rdamage += damage * tsd->magic_damage_return / 100;
+                if (rdamage < 1)
+                    rdamage = 1;
+            }
+        }
+    }
+    //Stop Here
+    if (attack_type & BF_WEAPON && damage > 0 && src != bl && src == dsrc)
+    {                           //武器スキル&ダメージあり&使用者と対象者が違う&src=dsrc
+        if (dmg.flag & BF_SHORT)
+        {                       //近距離攻撃時?※
+            if (bl->type == BL_PC)
+            {                   //対象がPCの時
+                struct map_session_data *tsd = (struct map_session_data *) bl;
+                nullpo_retr (0, tsd);
+                if (tsd->short_weapon_damage_return > 0)
+                {               //近距離攻撃跳ね返し?※
+                    rdamage += damage * tsd->short_weapon_damage_return / 100;
+                    if (rdamage < 1)
+                        rdamage = 1;
+                }
+            }
+            if (sc_data && sc_data[SC_REFLECTSHIELD].timer != -1)
+            {                   //リフレクトシールド時
+                rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100;   //跳ね返し計算
+                if (rdamage < 1)
+                    rdamage = 1;
+            }
+        }
+        else if (dmg.flag & BF_LONG)
+        {                       //遠距離攻撃時?※
+            if (bl->type == BL_PC)
+            {                   //対象がPCの時
+                struct map_session_data *tsd = (struct map_session_data *) bl;
+                nullpo_retr (0, tsd);
+                if (tsd->long_weapon_damage_return > 0)
+                {               //遠距離攻撃跳ね返し?※
+                    rdamage += damage * tsd->long_weapon_damage_return / 100;
+                    if (rdamage < 1)
+                        rdamage = 1;
+                }
+            }
+        }
+        if (rdamage > 0)
+            clif_damage (src, src, tick, dmg.amotion, 0, rdamage, 1, 4, 0);
+    }
+//武器スキル?ここまで
+
+    switch (skillid)
+    {
+        case WZ_SIGHTRASHER:
+            clif_skill_damage (src, bl, tick, dmg.amotion, dmg.dmotion,
+                               damage, dmg.div_, skillid,
+                               (lv != 0) ? lv : skilllv, 5);
+            break;
+        case AS_SPLASHER:
+            clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion,
+                               damage, dmg.div_, skillid, -1, 5);
+            break;
+        case NPC_SELFDESTRUCTION:
+        case NPC_SELFDESTRUCTION2:
+            break;
+        default:
+            clif_skill_damage (dsrc, bl, tick, dmg.amotion, dmg.dmotion,
+                               damage, dmg.div_, skillid,
+                               (lv != 0) ? lv : skilllv,
+                               (skillid == 0) ? 5 : type);
+    }
+    if (dmg.blewcount > 0 && !map[src->m].flag.gvg)
+    {                           /* 吹き飛ばし処理とそのパケット */
+        if (skillid == WZ_SIGHTRASHER)
+            skill_blown (src, bl, dmg.blewcount);
+        else
+            skill_blown (dsrc, bl, dmg.blewcount);
+        if (bl->type == BL_MOB)
+            clif_fixmobpos ((struct mob_data *) bl);
+        else
+            clif_fixpos (bl);
+    }
+
+    map_freeblock_lock ();
+    /* 実際にダメージ処理を行う */
+    if (skillid != KN_BOWLINGBASH || flag)
+        battle_damage (src, bl, damage, 0);
+    if (skillid == RG_INTIMIDATE && damage > 0
+        && !(battle_get_mode (bl) & 0x20) && !map[src->m].flag.gvg)
+    {
+        int  s_lv = battle_get_lv (src), t_lv = battle_get_lv (bl);
+        int  rate = 50 + skilllv * 5;
+        rate = rate + (s_lv - t_lv);
+        if (MRAND (100) < rate)
+            skill_addtimerskill (src, tick + 800, bl->id, 0, 0, skillid,
+                                 skilllv, 0, flag);
+    }
+/*
+	if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM)){
+		struct map_session_data *tsd = (struct map_session_data *)bl;
+		nullpo_retr(0, tsd);
+		if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
+			&& !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
+			//既に盗んでいるスキルがあれば該当スキルを消す
+			if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
+				tsd->status.skill[tsd->cloneskill_id].id=0;
+				tsd->status.skill[tsd->cloneskill_id].lv=0;
+				tsd->status.skill[tsd->cloneskill_id].flag=0;
+			}
+			tsd->cloneskill_id=skillid;
+			tsd->cloneskill_lv=skilllv;
+			tsd->status.skill[skillid].id=skillid;
+			tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
+							skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
+			tsd->status.skill[skillid].flag=13;//cloneskill flag
+			clif_skillinfoblock(tsd);
+		}
+	}
+*/
+    /* ダメージがあるなら追加効果判定 */
+    if (bl->prev != NULL)
+    {
+        struct map_session_data *sd = (struct map_session_data *) bl;
+        nullpo_retr (0, sd);
+        if (bl->type != BL_PC || (sd && !pc_isdead (sd)))
+        {
+            if (damage > 0)
+                skill_additional_effect (src, bl, skillid, skilllv,
+                                         attack_type, tick);
+            if (bl->type == BL_MOB && src != bl)    /* スキル使用条件のMOBスキル */
+            {
+                struct mob_data *md = (struct mob_data *) bl;
+                nullpo_retr (0, md);
+                if (battle_config.mob_changetarget_byskill == 1)
+                {
+                    int  target;
+                    target = md->target_id;
+                    if (src->type == BL_PC)
+                        md->target_id = src->id;
+                    mobskill_use (md, tick, MSC_SKILLUSED | (skillid << 16));
+                    md->target_id = target;
+                }
+                else
+                    mobskill_use (md, tick, MSC_SKILLUSED | (skillid << 16));
+            }
+        }
+    }
+
+    if (src->type == BL_PC && dmg.flag & BF_WEAPON && src != bl && src == dsrc
+        && damage > 0)
+    {
+        struct map_session_data *sd = (struct map_session_data *) src;
+        int  hp = 0, sp = 0;
+        nullpo_retr (0, sd);
+        if (sd->hp_drain_rate && sd->hp_drain_per > 0 && dmg.damage > 0
+            && MRAND (100) < sd->hp_drain_rate)
+        {
+            hp += (dmg.damage * sd->hp_drain_per) / 100;
+            if (sd->hp_drain_rate > 0 && hp < 1)
+                hp = 1;
+            else if (sd->hp_drain_rate < 0 && hp > -1)
+                hp = -1;
+        }
+        if (sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && dmg.damage2 > 0
+            && MRAND (100) < sd->hp_drain_rate_)
+        {
+            hp += (dmg.damage2 * sd->hp_drain_per_) / 100;
+            if (sd->hp_drain_rate_ > 0 && hp < 1)
+                hp = 1;
+            else if (sd->hp_drain_rate_ < 0 && hp > -1)
+                hp = -1;
+        }
+        if (sd->sp_drain_rate > 0 && sd->sp_drain_per > 0 && dmg.damage > 0
+            && MRAND (100) < sd->sp_drain_rate)
+        {
+            sp += (dmg.damage * sd->sp_drain_per) / 100;
+            if (sd->sp_drain_rate > 0 && sp < 1)
+                sp = 1;
+            else if (sd->sp_drain_rate < 0 && sp > -1)
+                sp = -1;
+        }
+        if (sd->sp_drain_rate_ > 0 && sd->sp_drain_per_ > 0 && dmg.damage2 > 0
+            && MRAND (100) < sd->sp_drain_rate_)
+        {
+            sp += (dmg.damage2 * sd->sp_drain_per_) / 100;
+            if (sd->sp_drain_rate_ > 0 && sp < 1)
+                sp = 1;
+            else if (sd->sp_drain_rate_ < 0 && sp > -1)
+                sp = -1;
+        }
+        if (hp || sp)
+            pc_heal (sd, hp, sp);
+    }
+
+    if ((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
+        battle_damage (bl, src, rdamage, 0);
+
+    if (attack_type & BF_WEAPON && sc_data
+        && sc_data[SC_AUTOCOUNTER].timer != -1
+        && sc_data[SC_AUTOCOUNTER].val4 > 0)
+    {
+        if (sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
+            battle_weapon_attack (bl, dsrc, tick,
+                                  0x8000 | sc_data[SC_AUTOCOUNTER].val1);
+        skill_status_change_end (bl, SC_AUTOCOUNTER, -1);
+    }
+
+    map_freeblock_unlock ();
+
+    return (dmg.damage + dmg.damage2);  /* 与ダメを返す */
+}
+
+/*==========================================
+ * スキル範囲攻撃用(map_foreachinareaから呼ばれる)
+ * flagについて:16進図を確認
+ * MSB <- 00fTffff ->LSB
+ *	T	=ターゲット選択用(BCT_*)
+ *  ffff=自由に使用可能
+ *  0	=予約。0に固定
+ *------------------------------------------
+ */
+static int skill_area_temp[8];  /* 一時変数。必要なら使う。 */
+typedef int (*SkillFunc) (struct block_list *, struct block_list *, int, int,
+                          unsigned int, int);
+int skill_area_sub (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    int  skill_id, skill_lv, flag;
+    unsigned int tick;
+    SkillFunc func;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    if (bl->type != BL_PC && bl->type != BL_MOB && bl->type != BL_SKILL)
+        return 0;
+
+    src = va_arg (ap, struct block_list *); //ここではsrcの値を参照していないのでNULLチェックはしない
+    skill_id = va_arg (ap, int);
+    skill_lv = va_arg (ap, int);
+    tick = va_arg (ap, unsigned int);
+    flag = va_arg (ap, int);
+    func = va_arg (ap, SkillFunc);
+
+    if (battle_check_target (src, bl, flag) > 0)
+        func (src, bl, skill_id, skill_lv, tick, flag);
+    return 0;
+}
+
+static int skill_check_unit_range_sub (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    int *c, x, y, range, sx[4], sy[4];
+    int  t_range, tx[4], ty[4];
+    int  i, r_flag, skillid;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, unit = (struct skill_unit *) bl);
+    nullpo_retr (0, c = va_arg (ap, int *));
+
+    if (bl->prev == NULL || bl->type != BL_SKILL)
+        return 0;
+
+    if (!unit->alive)
+        return 0;
+
+    x = va_arg (ap, int);
+    y = va_arg (ap, int);
+    range = va_arg (ap, int);
+    skillid = va_arg (ap, int);
+
+    if (skillid == MG_SAFETYWALL || skillid == AL_PNEUMA)
+    {
+        if (unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
+            return 0;
+    }
+    else if (skillid == AL_WARP)
+    {
+        if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99)
+            && unit->group->unit_id != 0x92)
+            return 0;
+    }
+    else if ((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP)
+             || skillid == HT_TALKIEBOX)
+    {
+        if ((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99)
+            && unit->group->unit_id != 0x92)
+            return 0;
+    }
+    else if (skillid == WZ_FIREPILLAR)
+    {
+        if (unit->group->unit_id != 0x87)
+            return 0;
+    }
+    else
+        return 0;
+    t_range = (unit->range != 0) ? unit->range : unit->group->range;
+    tx[0] = tx[3] = unit->bl.x - t_range;
+    tx[1] = tx[2] = unit->bl.x + t_range;
+    ty[0] = ty[1] = unit->bl.y - t_range;
+    ty[2] = ty[3] = unit->bl.y + t_range;
+    sx[0] = sx[3] = x - range;
+    sx[1] = sx[2] = x + range;
+    sy[0] = sy[1] = y - range;
+    sy[2] = sy[3] = y + range;
+    for (i = r_flag = 0; i < 4; i++)
+    {
+        if (sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0]
+            && sy[i] <= ty[2])
+        {
+            r_flag = 1;
+            break;
+        }
+        if (tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0]
+            && ty[i] <= sy[2])
+        {
+            r_flag = 1;
+            break;
+        }
+    }
+    if (r_flag)
+        (*c)++;
+
+    return 0;
+}
+
+int skill_check_unit_range (int m, int x, int y, int range, int skillid)
+{
+    int  c = 0;
+
+    map_foreachinarea (skill_check_unit_range_sub, m, x - 10, y - 10, x + 10,
+                       y + 10, BL_SKILL, &c, x, y, range, skillid);
+
+    return c;
+}
+
+static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap)
+{
+    int *c;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, c = va_arg (ap, int *));
+
+    if (bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB))
+        return 0;
+
+    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
+        return 0;
+
+    (*c)++;
+
+    return 0;
+}
+
+int skill_check_unit_range2 (int m, int x, int y, int range)
+{
+    int  c = 0;
+
+    map_foreachinarea (skill_check_unit_range2_sub, m, x - range, y - range,
+                       x + range, y + range, 0, &c);
+
+    return c;
+}
+
+/*=========================================================================
+ * 範囲スキル使用処理小分けここから
+ */
+/* 対象の数をカウントする。(skill_area_temp[0]を初期化しておくこと) */
+int skill_area_sub_count (struct block_list *src, struct block_list *target,
+                          int skillid, int skilllv, unsigned int tick,
+                          int flag)
+{
+    if (skill_area_temp[0] < 0xffff)
+        skill_area_temp[0]++;
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static void skill_timerskill (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = NULL;
+    struct mob_data *md = NULL;
+    struct block_list *src = map_id2bl (id), *target;
+    struct skill_timerskill *skl = NULL;
+    int  range;
+
+    nullpo_retv (src);
+
+    if (src->prev == NULL)
+        return;
+
+    if (src->type == BL_PC)
+    {
+        nullpo_retv (sd = (struct map_session_data *) src);
+        skl = &sd->skilltimerskill[data];
+    }
+    else if (src->type == BL_MOB)
+    {
+        nullpo_retv (md = (struct mob_data *) src);
+        skl = &md->skilltimerskill[data];
+    }
+
+    else
+        return;
+
+    nullpo_retv (skl);
+
+    skl->timer = -1;
+    if (skl->target_id)
+    {
+        struct block_list tbl;
+        target = map_id2bl (skl->target_id);
+        if (skl->skill_id == RG_INTIMIDATE)
+        {
+            if (target == NULL)
+            {
+                target = &tbl;  //初期化してないのにアドレス突っ込んでいいのかな?
+                target->type = BL_NUL;
+                target->m = src->m;
+                target->prev = target->next = NULL;
+            }
+        }
+        if (target == NULL)
+            return;
+        if (target->prev == NULL && skl->skill_id != RG_INTIMIDATE)
+            return;
+        if (src->m != target->m)
+            return;
+        if (sd && pc_isdead (sd))
+            return;
+        if (target->type == BL_PC
+            && pc_isdead ((struct map_session_data *) target)
+            && skl->skill_id != RG_INTIMIDATE)
+            return;
+
+        switch (skl->skill_id)
+        {
+            case TF_BACKSLIDING:
+                clif_skill_nodamage (src, src, skl->skill_id, skl->skill_lv,
+                                     1);
+                break;
+            case RG_INTIMIDATE:
+                if (sd && !map[src->m].flag.noteleport)
+                {
+                    int  x, y, i, j, c;
+                    pc_randomwarp (sd, 3);
+                    for (i = 0; i < 16; i++)
+                    {
+                        j = MRAND (8);
+                        x = sd->bl.x + dirx[j];
+                        y = sd->bl.y + diry[j];
+                        if ((c = map_getcell (sd->bl.m, x, y)) != 1 && c != 5)
+                            break;
+                    }
+                    if (i >= 16)
+                    {
+                        x = sd->bl.x;
+                        y = sd->bl.y;
+                    }
+                    if (target->prev != NULL)
+                    {
+                        if (target->type == BL_PC
+                            && !pc_isdead ((struct map_session_data *)
+                                           target))
+                            pc_setpos ((struct map_session_data *) target,
+                                       map[sd->bl.m].name, x, y, 3);
+                        else if (target->type == BL_MOB)
+                            mob_warp ((struct mob_data *) target, -1, x, y,
+                                      3);
+                    }
+                }
+                else if (md && !map[src->m].flag.monster_noteleport)
+                {
+                    int  x, y, i, j, c;
+                    mob_warp (md, -1, -1, -1, 3);
+                    for (i = 0; i < 16; i++)
+                    {
+                        j = MRAND (8);
+                        x = md->bl.x + dirx[j];
+                        y = md->bl.y + diry[j];
+                        if ((c = map_getcell (md->bl.m, x, y)) != 1 && c != 5)
+                            break;
+                    }
+                    if (i >= 16)
+                    {
+                        x = md->bl.x;
+                        y = md->bl.y;
+                    }
+                    if (target->prev != NULL)
+                    {
+                        if (target->type == BL_PC
+                            && !pc_isdead ((struct map_session_data *)
+                                           target))
+                            pc_setpos ((struct map_session_data *) target,
+                                       map[md->bl.m].name, x, y, 3);
+                        else if (target->type == BL_MOB)
+                            mob_warp ((struct mob_data *) target, -1, x, y,
+                                      3);
+                    }
+                }
+                break;
+
+            case BA_FROSTJOKE: /* 寒いジョーク */
+            case DC_SCREAM:    /* スクリーム */
+                range = 15;     //視界全体
+                map_foreachinarea (skill_frostjoke_scream, src->m,
+                                   src->x - range, src->y - range,
+                                   src->x + range, src->y + range, 0, src,
+                                   skl->skill_id, skl->skill_lv, tick);
+                break;
+
+            default:
+                skill_attack (skl->type, src, src, target, skl->skill_id,
+                              skl->skill_lv, tick, skl->flag);
+                break;
+        }
+    }
+    else
+    {
+        if (src->m != skl->map)
+            return;
+        switch (skl->skill_id)
+        {
+            case WZ_METEOR:
+                if (skl->type >= 0)
+                {
+                    skill_unitsetting (src, skl->skill_id, skl->skill_lv,
+                                       skl->type >> 16, skl->type & 0xFFFF,
+                                       0);
+                    clif_skill_poseffect (src, skl->skill_id, skl->skill_lv,
+                                          skl->x, skl->y, tick);
+                }
+                else
+                    skill_unitsetting (src, skl->skill_id, skl->skill_lv,
+                                       skl->x, skl->y, 0);
+                break;
+        }
+    }
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int skill_addtimerskill (struct block_list *src, unsigned int tick,
+                         int target, int x, int y, int skill_id, int skill_lv,
+                         int type, int flag)
+{
+    int  i;
+
+    nullpo_retr (1, src);
+
+    if (src->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) src;
+        nullpo_retr (1, sd);
+        for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
+        {
+            if (sd->skilltimerskill[i].timer == -1)
+            {
+                sd->skilltimerskill[i].timer =
+                    add_timer (tick, skill_timerskill, src->id, i);
+                sd->skilltimerskill[i].src_id = src->id;
+                sd->skilltimerskill[i].target_id = target;
+                sd->skilltimerskill[i].skill_id = skill_id;
+                sd->skilltimerskill[i].skill_lv = skill_lv;
+                sd->skilltimerskill[i].map = src->m;
+                sd->skilltimerskill[i].x = x;
+                sd->skilltimerskill[i].y = y;
+                sd->skilltimerskill[i].type = type;
+                sd->skilltimerskill[i].flag = flag;
+
+                return 0;
+            }
+        }
+        return 1;
+    }
+    else if (src->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) src;
+        nullpo_retr (1, md);
+        for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
+        {
+            if (md->skilltimerskill[i].timer == -1)
+            {
+                md->skilltimerskill[i].timer =
+                    add_timer (tick, skill_timerskill, src->id, i);
+                md->skilltimerskill[i].src_id = src->id;
+                md->skilltimerskill[i].target_id = target;
+                md->skilltimerskill[i].skill_id = skill_id;
+                md->skilltimerskill[i].skill_lv = skill_lv;
+                md->skilltimerskill[i].map = src->m;
+                md->skilltimerskill[i].x = x;
+                md->skilltimerskill[i].y = y;
+                md->skilltimerskill[i].type = type;
+                md->skilltimerskill[i].flag = flag;
+
+                return 0;
+            }
+        }
+        return 1;
+    }
+
+    return 1;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int skill_cleartimerskill (struct block_list *src)
+{
+    int  i;
+
+    nullpo_retr (0, src);
+
+    if (src->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) src;
+        nullpo_retr (0, sd);
+        for (i = 0; i < MAX_SKILLTIMERSKILL; i++)
+        {
+            if (sd->skilltimerskill[i].timer != -1)
+            {
+                delete_timer (sd->skilltimerskill[i].timer, skill_timerskill);
+                sd->skilltimerskill[i].timer = -1;
+            }
+        }
+    }
+    else if (src->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) src;
+        nullpo_retr (0, md);
+        for (i = 0; i < MAX_MOBSKILLTIMERSKILL; i++)
+        {
+            if (md->skilltimerskill[i].timer != -1)
+            {
+                delete_timer (md->skilltimerskill[i].timer, skill_timerskill);
+                md->skilltimerskill[i].timer = -1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+/* 範囲スキル使用処理小分けここまで
+ * -------------------------------------------------------------------------
+ */
+
+/*==========================================
+ * スキル使用(詠唱完了、ID指定攻撃系)
+ * (スパゲッティに向けて1歩前進!(ダメポ))
+ *------------------------------------------
+ */
+int skill_castend_damage_id (struct block_list *src, struct block_list *bl,
+                             int skillid, int skilllv, unsigned int tick,
+                             int flag)
+{
+    struct map_session_data *sd = NULL;
+    int  i;
+
+    nullpo_retr (1, src);
+    nullpo_retr (1, bl);
+
+    if (src->type == BL_PC)
+        sd = (struct map_session_data *) src;
+    if (sd && pc_isdead (sd))
+        return 1;
+
+    if ((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS) && src != bl)
+        bl = src;
+    if (bl->prev == NULL)
+        return 1;
+    if (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl))
+        return 1;
+    map_freeblock_lock ();
+    switch (skillid)
+    {
+            /* 武器攻撃系スキル */
+        case SM_BASH:          /* バッシュ */
+        case MC_MAMMONITE:     /* メマーナイト */
+        case AC_DOUBLE:        /* ダブルストレイフィング */
+        case AS_SONICBLOW:     /* ソニックブロー */
+        case KN_PIERCE:        /* ピアース */
+        case KN_SPEARBOOMERANG:    /* スピアブーメラン */
+        case TF_POISON:        /* インベナム */
+        case TF_SPRINKLESAND:  /* 砂まき */
+        case AC_CHARGEARROW:   /* チャージアロー */
+        case KN_SPEARSTAB:     /* スピアスタブ */
+        case RG_RAID:          /* サプライズアタック */
+        case RG_INTIMIDATE:    /* インティミデイト */
+        case BA_MUSICALSTRIKE: /* ミュージカルストライク */
+        case DC_THROWARROW:    /* 矢撃ち */
+        case BA_DISSONANCE:    /* 不協和音 */
+        case CR_HOLYCROSS:     /* ホーリークロス */
+        case CR_SHIELDCHARGE:
+        case CR_SHIELDBOOMERANG:
+
+            /* 以下MOB専用 */
+            /* 単体攻撃、SP減少攻撃、遠距離攻撃、防御無視攻撃、多段攻撃 */
+        case NPC_PIERCINGATT:
+        case NPC_MENTALBREAKER:
+        case NPC_RANGEATTACK:
+        case NPC_CRITICALSLASH:
+        case NPC_COMBOATTACK:
+            /* 必中攻撃、毒攻撃、暗黒攻撃、沈黙攻撃、スタン攻撃 */
+        case NPC_GUIDEDATTACK:
+        case NPC_POISON:
+        case NPC_BLINDATTACK:
+        case NPC_SILENCEATTACK:
+        case NPC_STUNATTACK:
+            /* 石化攻撃、呪い攻撃、睡眠攻撃、ランダムATK攻撃 */
+        case NPC_PETRIFYATTACK:
+        case NPC_CURSEATTACK:
+        case NPC_SLEEPATTACK:
+        case NPC_RANDOMATTACK:
+            /* 水属性攻撃、地属性攻撃、火属性攻撃、風属性攻撃 */
+        case NPC_WATERATTACK:
+        case NPC_GROUNDATTACK:
+        case NPC_FIREATTACK:
+        case NPC_WINDATTACK:
+            /* 毒属性攻撃、聖属性攻撃、闇属性攻撃、念属性攻撃、SP減少攻撃 */
+        case NPC_POISONATTACK:
+        case NPC_HOLYATTACK:
+        case NPC_DARKNESSATTACK:
+        case NPC_TELEKINESISATTACK:
+        case LK_AURABLADE:     /* オーラブレード */
+        case LK_SPIRALPIERCE:  /* スパイラルピアース */
+        case LK_HEADCRUSH:     /* ヘッドクラッシュ */
+        case LK_JOINTBEAT:     /* ジョイントビート */
+        case PA_PRESSURE:      /* プレッシャー */
+        case PA_SACRIFICE:     /* サクリファイス */
+        case SN_SHARPSHOOTING: /* シャープシューティング */
+        case CG_ARROWVULCAN:   /* アローバルカン */
+        case ASC_BREAKER:      /* ソウルブレーカー */
+        case HW_MAGICCRASHER:  /* マジッククラッシャー */
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+        case NPC_DARKBREATH:
+            clif_emotion (src, 7);
+            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+        case MO_INVESTIGATE:   /* 発勁 */
+        {
+            struct status_change *sc_data = battle_get_sc_data (src);
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            if (sc_data[SC_BLADESTOP].timer != -1)
+                skill_status_change_end (src, SC_BLADESTOP, -1);
+        }
+            break;
+        case SN_FALCONASSAULT: /* ファルコンアサルト */
+            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+        case KN_BRANDISHSPEAR: /* ブランディッシュスピア */
+        {
+            struct mob_data *md = (struct mob_data *) bl;
+            nullpo_retr (1, md);
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            if (md->hp > 0)
+            {
+                skill_blown (src, bl, skill_get_blewcount (skillid, skilllv));
+                if (bl->type == BL_MOB)
+                    clif_fixmobpos ((struct mob_data *) bl);
+                else
+                    clif_fixpos (bl);
+            }
+        }
+            break;
+        case RG_BACKSTAP:      /* バックスタブ */
+        {
+            int  dir = map_calc_dir (src, bl->x, bl->y), t_dir =
+                battle_get_dir (bl);
+            int  dist = distance (src->x, src->y, bl->x, bl->y);
+            if ((dist > 0 && !map_check_dir (dir, t_dir))
+                || bl->type == BL_SKILL)
+            {
+                struct status_change *sc_data = battle_get_sc_data (src);
+                if (sc_data && sc_data[SC_HIDING].timer != -1)
+                    skill_status_change_end (src, SC_HIDING, -1);   // ハイディング解除
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              flag);
+                skill_blown (src, bl, skill_get_blewcount (skillid, skilllv));
+            }
+            else if (src->type == BL_PC)
+                clif_skill_fail (sd, sd->skillid, 0, 0);
+        }
+            break;
+
+        case AM_ACIDTERROR:    /* アシッドテラー */
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            if (bl->type == BL_PC
+                && MRAND (100) < skill_get_time (skillid, skilllv)
+                && battle_config.equipment_breaking)
+                pc_breakarmor ((struct map_session_data *) bl);
+            break;
+        case MO_FINGEROFFENSIVE:   /* 指弾 */
+        {
+            struct status_change *sc_data = battle_get_sc_data (src);
+
+            if (!battle_config.finger_offensive_type)
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              flag);
+            else
+            {
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              flag);
+                if (sd)
+                {
+                    for (i = 1; i < sd->spiritball_old; i++)
+                        skill_addtimerskill (src, tick + i * 200, bl->id, 0,
+                                             0, skillid, skilllv, BF_WEAPON,
+                                             flag);
+                    sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200;
+                }
+            }
+            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+                skill_status_change_end (src, SC_BLADESTOP, -1);
+        }
+            break;
+        case MO_CHAINCOMBO:    /* 連打掌 */
+        {
+            struct status_change *sc_data = battle_get_sc_data (src);
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+                skill_status_change_end (src, SC_BLADESTOP, -1);
+        }
+            break;
+        case MO_COMBOFINISH:   /* 猛龍拳 */
+        case CH_TIGERFIST:     /* 伏虎拳 */
+        case CH_CHAINCRUSH:    /* 連柱崩撃 */
+        case CH_PALMSTRIKE:    /* 猛虎硬派山 */
+            skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+        case MO_EXTREMITYFIST: /* 阿修羅覇鳳拳 */
+        {
+            struct status_change *sc_data = battle_get_sc_data (src);
+
+            if (sd)
+            {
+                struct walkpath_data wpd;
+                int  dx, dy;
+
+                dx = bl->x - sd->bl.x;
+                dy = bl->y - sd->bl.y;
+                if (dx > 0)
+                    dx++;
+                else if (dx < 0)
+                    dx--;
+                if (dy > 0)
+                    dy++;
+                else if (dy < 0)
+                    dy--;
+                if (dx == 0 && dy == 0)
+                    dx++;
+                if (path_search
+                    (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx,
+                     sd->bl.y + dy, 1) == -1)
+                {
+                    dx = bl->x - sd->bl.x;
+                    dy = bl->y - sd->bl.y;
+                    if (path_search
+                        (&wpd, src->m, sd->bl.x, sd->bl.y, sd->bl.x + dx,
+                         sd->bl.y + dy, 1) == -1)
+                    {
+                        clif_skill_fail (sd, sd->skillid, 0, 0);
+                        break;
+                    }
+                }
+                sd->to_x = sd->bl.x + dx;
+                sd->to_y = sd->bl.y + dy;
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              flag);
+                clif_walkok (sd);
+                clif_movechar (sd);
+                if (dx < 0)
+                    dx = -dx;
+                if (dy < 0)
+                    dy = -dy;
+                sd->attackabletime = sd->canmove_tick =
+                    tick + 100 + sd->speed * ((dx > dy) ? dx : dy);
+                if (sd->canact_tick < sd->canmove_tick)
+                    sd->canact_tick = sd->canmove_tick;
+                pc_movepos (sd, sd->to_x, sd->to_y);
+                skill_status_change_end (&sd->bl, SC_COMBO, -1);
+            }
+            else
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              flag);
+            skill_status_change_end (src, SC_EXPLOSIONSPIRITS, -1);
+            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+                skill_status_change_end (src, SC_BLADESTOP, -1);
+        }
+            break;
+            /* 武器系範囲攻撃スキル */
+        case AC_SHOWER:        /* アローシャワー */
+        case SM_MAGNUM:        /* マグナムブレイク */
+        case AS_GRIMTOOTH:     /* グリムトゥース */
+        case MC_CARTREVOLUTION:    /* カートレヴォリューション */
+        case NPC_SPLASHATTACK: /* スプラッシュアタック */
+        case ASC_METEORASSAULT:    /* メテオアサルト */
+        case AS_SPLASHER:      /* [Valaris] */
+            if (flag & 1)
+            {
+                /* 個別にダメージを与える */
+                if (bl->id != skill_area_temp[1])
+                {
+                    int  dist = 0;
+                    if (skillid == SM_MAGNUM)
+                    {           /* マグナムブレイクなら中心からの距離を計算 */
+                        int  dx = abs (bl->x - skill_area_temp[2]);
+                        int  dy = abs (bl->y - skill_area_temp[3]);
+                        dist = ((dx > dy) ? dx : dy);
+                    }
+                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
+                                  tick, 0x0500 | dist);
+                }
+            }
+            else
+            {
+                int  ar = 1;
+                int  x = bl->x, y = bl->y;
+                if (skillid == SM_MAGNUM)
+                {
+                    x = src->x;
+                    y = src->y;
+                }
+                else if (skillid == AC_SHOWER || skillid == ASC_METEORASSAULT)  /* アローシャワー、メテオアサルト範囲5*5 */
+                    ar = 2;
+                else if (skillid == AS_SPLASHER)    /* ベナムスプラッシャー範囲3*3 */
+                    ar = 1;
+                else if (skillid == NPC_SPLASHATTACK)   /* スプラッシュアタックは範囲7*7 */
+                    ar = 3;
+                skill_area_temp[1] = bl->id;
+                skill_area_temp[2] = x;
+                skill_area_temp[3] = y;
+                /* まずターゲットに攻撃を加える */
+                skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv, tick,
+                              0);
+                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, x - ar, y - ar, x + ar, y + ar, 0,
+                                   src, skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+            break;
+
+        case KN_BOWLINGBASH:   /* ボウリングバッシュ */
+            if (flag & 1)
+            {
+                /* 個別にダメージを与える */
+                if (bl->id != skill_area_temp[1])
+                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
+                                  tick, 0x0500);
+            }
+            else
+            {
+                int  damage;
+                map_freeblock_lock ();
+                damage =
+                    skill_attack (BF_WEAPON, src, src, bl, skillid, skilllv,
+                                  tick, 0);
+                if (damage > 0)
+                {
+                    int  i, c;  /* 他人から聞いた動きなので間違ってる可能性大&効率が悪いっす>< */
+                    c = skill_get_blewcount (skillid, skilllv);
+                    if (map[bl->m].flag.gvg)
+                        c = 0;
+                    for (i = 0; i < c; i++)
+                    {
+                        skill_blown (src, bl, 1);
+                        if (bl->type == BL_MOB)
+                            clif_fixmobpos ((struct mob_data *) bl);
+                        else
+                            clif_fixpos (bl);
+                        skill_area_temp[0] = 0;
+                        map_foreachinarea (skill_area_sub,
+                                           bl->m, bl->x - 1, bl->y - 1,
+                                           bl->x + 1, bl->y + 1, 0, src,
+                                           skillid, skilllv, tick,
+                                           flag | BCT_ENEMY,
+                                           skill_area_sub_count);
+                        if (skill_area_temp[0] > 1)
+                            break;
+                    }
+                    skill_area_temp[1] = bl->id;
+                    skill_area_temp[2] = bl->x;
+                    skill_area_temp[3] = bl->y;
+                    /* その後ターゲット以外の範囲内の敵全体に処理を行う */
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
+                                       bl->y + 1, 0, src, skillid, skilllv,
+                                       tick, flag | BCT_ENEMY | 1,
+                                       skill_castend_damage_id);
+                    battle_damage (src, bl, damage, 1);
+                    if (rdamage > 0)
+                        battle_damage (bl, src, rdamage, 0);
+                }
+                map_freeblock_unlock ();
+            }
+            break;
+
+        case ALL_RESURRECTION: /* リザレクション */
+        case PR_TURNUNDEAD:    /* ターンアンデッド */
+            if (bl->type != BL_PC
+                && battle_check_undead (battle_get_race (bl),
+                                        battle_get_elem_type (bl)))
+                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                              flag);
+            else
+            {
+                map_freeblock_unlock ();
+                return 1;
+            }
+            break;
+
+            /* 魔法系スキル */
+        case MG_SOULSTRIKE:    /* ソウルストライク */
+        case MG_COLDBOLT:      /* コールドボルト */
+        case MG_FIREBOLT:      /* ファイアーボルト */
+        case MG_LIGHTNINGBOLT: /* ライトニングボルト */
+        case WZ_EARTHSPIKE:    /* アーススパイク */
+        case AL_HEAL:          /* ヒール */
+        case AL_HOLYLIGHT:     /* ホーリーライト */
+        case MG_FROSTDIVER:    /* フロストダイバー */
+        case WZ_JUPITEL:       /* ユピテルサンダー */
+        case NPC_MAGICALATTACK:    /* MOB:魔法打撃攻撃 */
+        case PR_ASPERSIO:      /* アスペルシオ */
+            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+
+        case WZ_WATERBALL:     /* ウォーターボール */
+            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            if (skilllv > 1)
+                skill_status_change_start (src, SC_WATERBALL, skilllv, bl->id,
+                                           0, 0, 0, 0);
+            break;
+
+        case PR_BENEDICTIO:    /* 聖体降福 */
+            if (battle_get_race (bl) == 1 || battle_get_race (bl) == 6)
+                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                              flag);
+            break;
+
+            /* 魔法系範囲攻撃スキル */
+        case MG_NAPALMBEAT:    /* ナパームビート */
+        case MG_FIREBALL:      /* ファイヤーボール */
+            if (flag & 1)
+            {
+                /* 個別にダメージを与える */
+                if (bl->id != skill_area_temp[1])
+                {
+                    if (skillid == MG_FIREBALL)
+                    {           /* ファイヤーボールなら中心からの距離を計算 */
+                        int  dx = abs (bl->x - skill_area_temp[2]);
+                        int  dy = abs (bl->y - skill_area_temp[3]);
+                        skill_area_temp[0] = ((dx > dy) ? dx : dy);
+                    }
+                    skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv,
+                                  tick, skill_area_temp[0] | 0x0500);
+                }
+            }
+            else
+            {
+                int  ar = (skillid == MG_NAPALMBEAT) ? 1 : 2;
+                skill_area_temp[1] = bl->id;
+                if (skillid == MG_NAPALMBEAT)
+                {               /* ナパームでは先に数える */
+                    skill_area_temp[0] = 0;
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
+                                       bl->y + 1, 0, src, skillid, skilllv,
+                                       tick, flag | BCT_ENEMY,
+                                       skill_area_sub_count);
+                }
+                else
+                {
+                    skill_area_temp[0] = 0;
+                    skill_area_temp[2] = bl->x;
+                    skill_area_temp[3] = bl->y;
+                }
+                /* まずターゲットに攻撃を加える */
+                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                              skill_area_temp[0]);
+                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, bl->x - ar, bl->y - ar, bl->x + ar,
+                                   bl->y + ar, 0, src, skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+            break;
+
+        case HW_NAPALMVULCAN:  // Fixed By SteelViruZ
+            if (flag & 1)
+            {
+                if (bl->id != skill_area_temp[1])
+                {
+                    skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv,
+                                  tick, skill_area_temp[0]);
+                }
+            }
+            else
+            {
+                int  ar = (skillid == HW_NAPALMVULCAN) ? 1 : 2;
+                skill_area_temp[1] = bl->id;
+                if (skillid == HW_NAPALMVULCAN)
+                {
+                    skill_area_temp[0] = 0;
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
+                                       bl->y + 1, 0, src, skillid, skilllv,
+                                       tick, flag | BCT_ENEMY,
+                                       skill_area_sub_count);
+                }
+                else
+                {
+                    skill_area_temp[0] = 0;
+                    skill_area_temp[2] = bl->x;
+                    skill_area_temp[3] = bl->y;
+                }
+                skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                              skill_area_temp[0]);
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, bl->x - ar, bl->y - ar, bl->x + ar,
+                                   bl->y + ar, 0, src, skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+            break;
+
+        case WZ_FROSTNOVA:     /* フロストノヴァ */
+            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
+            skill_attack (BF_MAGIC, src, src, bl, skillid, skilllv, tick,
+                          flag);
+            break;
+
+        case WZ_SIGHTRASHER:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
+            skill_status_change_end (src, SC_SIGHT, -1);
+            break;
+
+            /* その他 */
+        case HT_BLITZBEAT:     /* ブリッツビート */
+            if (flag & 1)
+            {
+                /* 個別にダメージを与える */
+                if (bl->id != skill_area_temp[1])
+                    skill_attack (BF_MISC, src, src, bl, skillid, skilllv,
+                                  tick,
+                                  skill_area_temp[0] | (flag & 0xf00000));
+            }
+            else
+            {
+                skill_area_temp[0] = 0;
+                skill_area_temp[1] = bl->id;
+                if (flag & 0xf00000)
+                    map_foreachinarea (skill_area_sub, bl->m, bl->x - 1,
+                                       bl->y - 1, bl->x + 1, bl->y + 1, 0,
+                                       src, skillid, skilllv, tick,
+                                       flag | BCT_ENEMY,
+                                       skill_area_sub_count);
+                /* まずターゲットに攻撃を加える */
+                skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick,
+                              skill_area_temp[0] | (flag & 0xf00000));
+                /* その後ターゲット以外の範囲内の敵全体に処理を行う */
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, bl->x - 1, bl->y - 1, bl->x + 1,
+                                   bl->y + 1, 0, src, skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+            break;
+
+        case CR_GRANDCROSS:    /* グランドクロス */
+            /* スキルユニット配置 */
+            skill_castend_pos2 (src, bl->x, bl->y, skillid, skilllv, tick, 0);
+            if (sd)
+                sd->canmove_tick = tick + 1000;
+            else if (src->type == BL_MOB)
+                mob_changestate ((struct mob_data *) src, MS_DELAY, 1000);
+            break;
+
+        case TF_THROWSTONE:    /* 石投げ */
+        case NPC_SMOKING:      /* スモーキング */
+            skill_attack (BF_MISC, src, src, bl, skillid, skilllv, tick, 0);
+            break;
+
+        case NPC_SELFDESTRUCTION:  /* 自爆 */
+        case NPC_SELFDESTRUCTION2: /* 自爆2 */
+            if (flag & 1)
+            {
+                /* 個別にダメージを与える */
+                if (src->type == BL_MOB)
+                {
+                    struct mob_data *mb = (struct mob_data *) src;
+                    nullpo_retr (1, mb);
+                    mb->hp = skill_area_temp[2];
+                    if (bl->id != skill_area_temp[1])
+                        skill_attack (BF_MISC, src, src, bl,
+                                      NPC_SELFDESTRUCTION, skilllv, tick,
+                                      flag);
+                    mb->hp = 1;
+                }
+            }
+            else
+            {
+                struct mob_data *md;
+                if ((md = (struct mob_data *) src))
+                {
+                    skill_area_temp[1] = bl->id;
+                    skill_area_temp[2] = battle_get_hp (src);
+                    clif_skill_nodamage (src, src, NPC_SELFDESTRUCTION, -1,
+                                         1);
+                    map_foreachinarea (skill_area_sub, bl->m, bl->x - 5,
+                                       bl->y - 5, bl->x + 5, bl->y + 5, 0,
+                                       src, skillid, skilllv, tick,
+                                       flag | BCT_ENEMY | 1,
+                                       skill_castend_damage_id);
+                    battle_damage (src, src, md->hp, 0);
+                }
+            }
+            break;
+
+            /* HP吸収/HP吸収魔法 */
+        case NPC_BLOODDRAIN:
+        case NPC_ENERGYDRAIN:
+        {
+            int  heal;
+            heal =
+                skill_attack ((skillid ==
+                               NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, src,
+                              src, bl, skillid, skilllv, tick, flag);
+            if (heal > 0)
+            {
+                struct block_list tbl;
+                tbl.id = 0;
+                tbl.m = src->m;
+                tbl.x = src->x;
+                tbl.y = src->y;
+                clif_skill_nodamage (&tbl, src, AL_HEAL, heal, 1);
+                battle_heal (NULL, src, heal, 0, 0);
+            }
+        }
+            break;
+        case 0:
+            if (sd)
+            {
+                if (flag & 3)
+                {
+                    if (bl->id != skill_area_temp[1])
+                        skill_attack (BF_WEAPON, src, src, bl, skillid,
+                                      skilllv, tick, 0x0500);
+                }
+                else
+                {
+                    int  ar = sd->splash_range;
+                    skill_area_temp[1] = bl->id;
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, bl->x - ar, bl->y - ar,
+                                       bl->x + ar, bl->y + ar, 0, src,
+                                       skillid, skilllv, tick,
+                                       flag | BCT_ENEMY | 1,
+                                       skill_castend_damage_id);
+                }
+            }
+            break;
+
+        default:
+            map_freeblock_unlock ();
+            return 1;
+    }
+    map_freeblock_unlock ();
+
+    return 0;
+}
+
+/*==========================================
+ * スキル使用(詠唱完了、ID指定支援系)
+ *------------------------------------------
+ */
+int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl,
+                               int skillid, int skilllv, unsigned int tick,
+                               int flag)
+{
+    struct map_session_data *sd = NULL;
+    struct map_session_data *dstsd = NULL;
+    struct mob_data *md = NULL;
+    struct mob_data *dstmd = NULL;
+    int  i;
+    int  sc_def_vit, sc_def_mdef, strip_fix, strip_time, strip_per;
+    int  sc_dex, sc_luk;
+    //クラスチェンジ用ボスモンスターID
+    int  changeclass[] =
+        { 1038, 1039, 1046, 1059, 1086, 1087, 1112, 1115, 1157, 1159, 1190,
+        1272, 1312, 1373, 1492
+    };
+    int  poringclass[] = { 1002 };
+
+    nullpo_retr (1, src);
+    nullpo_retr (1, bl);
+
+    if (src->type == BL_PC)
+        sd = (struct map_session_data *) src;
+    else if (src->type == BL_MOB)
+        md = (struct mob_data *) src;
+
+    sc_dex = battle_get_mdef (bl);
+    sc_luk = battle_get_luk (bl);
+    sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3);
+    sc_def_vit = 100 - (3 + battle_get_vit (bl) + battle_get_luk (bl) / 3);
+    sc_def_mdef = 100 - (3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3);
+    strip_fix = battle_get_dex (src) - battle_get_dex (bl);
+
+    if (bl->type == BL_PC)
+    {
+        nullpo_retr (1, dstsd = (struct map_session_data *) bl);
+    }
+    else if (bl->type == BL_MOB)
+    {
+        nullpo_retr (1, dstmd = (struct mob_data *) bl);
+        if (sc_def_vit > 50)
+            sc_def_vit = 50;
+        if (sc_def_mdef > 50)
+            sc_def_mdef = 50;
+    }
+    if (sc_def_vit < 0)
+        sc_def_vit = 0;
+    if (sc_def_mdef < 0)
+        sc_def_mdef = 0;
+    if (strip_fix < 0)
+        strip_fix = 0;
+
+    if (bl == NULL || bl->prev == NULL)
+        return 1;
+    if (sd && pc_isdead (sd))
+        return 1;
+    if (dstsd && pc_isdead (dstsd) && skillid != ALL_RESURRECTION)
+        return 1;
+    if (battle_get_class (bl) == 1288)
+        return 1;
+    if (skillnotok (skillid, (struct map_session_data *) bl))   // [MouseJstr]
+        return 0;
+
+    map_freeblock_lock ();
+    switch (skillid)
+    {
+        case AL_HEAL:          /* ヒール */
+        {
+            int  heal = skill_calc_heal (src, skilllv);
+            int  heal_get_jobexp;
+            int  skill;
+            struct pc_base_job s_class;
+
+            if (dstsd && dstsd->special_state.no_magic_damage)
+                heal = 0;       /* 黄金蟲カード(ヒール量0) */
+            if (sd)
+            {
+                s_class = pc_calc_base_job (sd->status.pc_class);
+                if ((skill = pc_checkskill (sd, HP_MEDITATIO)) > 0) // メディテイティオ
+                    heal += heal * (skill * 2 / 100);
+                if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && s_class.job == 23 && sd->status.sex == 0)  //自分も対象もPC、対象が自分のパートナー、自分がスパノビ、自分が♀なら
+                    heal = heal * 2;    //スパノビの嫁が旦那にヒールすると2倍になる
+            }
+
+            clif_skill_nodamage (src, bl, skillid, heal, 1);
+            heal_get_jobexp = battle_heal (NULL, bl, heal, 0, 0);
+
+            // JOB経験値獲得
+            if (src->type == BL_PC && bl->type == BL_PC && heal > 0
+                && src != bl && battle_config.heal_exp > 0)
+            {
+                heal_get_jobexp =
+                    heal_get_jobexp * battle_config.heal_exp / 100;
+                if (heal_get_jobexp <= 0)
+                    heal_get_jobexp = 1;
+                pc_gainexp ((struct map_session_data *) src, 0,
+                            heal_get_jobexp);
+            }
+        }
+            break;
+
+        case ALL_RESURRECTION: /* リザレクション */
+            if (bl->type == BL_PC)
+            {
+                int  per = 0;
+                struct map_session_data *tsd = (struct map_session_data *) bl;
+                nullpo_retr (1, tsd);
+                if ((map[bl->m].flag.pvp) && tsd->pvp_point < 0)
+                    break;      /* PVPで復活不可能状態 */
+
+                if (pc_isdead (tsd))
+                {               /* 死亡判定 */
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                    switch (skilllv)
+                    {
+                        case 1:
+                            per = 10;
+                            break;
+                        case 2:
+                            per = 30;
+                            break;
+                        case 3:
+                            per = 50;
+                            break;
+                        case 4:
+                            per = 80;
+                            break;
+                    }
+                    tsd->status.hp = tsd->status.max_hp * per / 100;
+                    if (tsd->status.hp <= 0)
+                        tsd->status.hp = 1;
+                    if (tsd->special_state.restart_full_recover)
+                    {           /* オシリスカード */
+                        tsd->status.hp = tsd->status.max_hp;
+                        tsd->status.sp = tsd->status.max_sp;
+                    }
+                    pc_setstand (tsd);
+                    if (battle_config.pc_invincible_time > 0)
+                        pc_setinvincibletimer (tsd,
+                                               battle_config.pc_invincible_time);
+                    clif_updatestatus (tsd, SP_HP);
+                    clif_resurrection (&tsd->bl, 1);
+                    if (src != bl && sd && battle_config.resurrection_exp > 0)
+                    {
+                        int  exp = 0, jexp = 0;
+                        int  lv =
+                            tsd->status.base_level - sd->status.base_level,
+                            jlv =
+                            tsd->status.job_level - sd->status.job_level;
+                        if (lv > 0)
+                        {
+                            exp =
+                                (int) ((double) tsd->status.base_exp *
+                                       (double) lv *
+                                       (double) battle_config.resurrection_exp
+                                       / 1000000.);
+                            if (exp < 1)
+                                exp = 1;
+                        }
+                        if (jlv > 0)
+                        {
+                            jexp =
+                                (int) ((double) tsd->status.job_exp *
+                                       (double) lv *
+                                       (double) battle_config.resurrection_exp
+                                       / 1000000.);
+                            if (jexp < 1)
+                                jexp = 1;
+                        }
+                        if (exp > 0 || jexp > 0)
+                            pc_gainexp (sd, exp, jexp);
+                    }
+                }
+            }
+            break;
+
+        case AL_DECAGI:        /* 速度減少 */
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (MRAND (100) <
+                (50 + skilllv * 3 +
+                 (battle_get_lv (src) + battle_get_int (src) / 5) -
+                 sc_def_mdef))
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+            }
+            break;
+
+        case AL_CRUCIS:
+            if (flag & 1)
+            {
+                int  race = battle_get_race (bl), ele =
+                    battle_get_elem_type (bl);
+                if (battle_check_target (src, bl, BCT_ENEMY)
+                    && (race == 6 || battle_check_undead (race, ele)))
+                {
+                    int  slv = battle_get_lv (src), tlv =
+                        battle_get_lv (bl), rate;
+                    rate = 25 + skilllv * 2 + slv - tlv;
+                    if (MRAND (100) < rate)
+                        skill_status_change_start (bl,
+                                                   SkillStatusChangeTable
+                                                   [skillid], skilllv, 0, 0,
+                                                   0, 0, 0);
+                }
+            }
+            else
+            {
+                int  range = 15;
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                map_foreachinarea (skill_area_sub,
+                                   src->m, src->x - range, src->y - range,
+                                   src->x + range, src->y + range, 0, src,
+                                   skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_nodamage_id);
+            }
+            break;
+
+        case PR_LEXDIVINA:     /* レックスディビーナ */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (sc_data && sc_data[SC_DIVINA].timer != -1)
+                skill_status_change_end (bl, SC_DIVINA, -1);
+            else if (MRAND (100) < sc_def_vit)
+            {
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+            }
+        }
+            break;
+        case SA_ABRACADABRA:
+            break;
+        case SA_COMA:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (dstsd)
+            {
+                dstsd->status.hp = 1;
+                dstsd->status.sp = 1;
+                clif_updatestatus (dstsd, SP_HP);
+                clif_updatestatus (dstsd, SP_SP);
+            }
+            if (dstmd)
+                dstmd->hp = 1;
+            break;
+        case SA_FULLRECOVERY:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (dstsd)
+                pc_heal (dstsd, dstsd->status.max_hp, dstsd->status.max_sp);
+            if (dstmd)
+                dstmd->hp = battle_get_max_hp (&dstmd->bl);
+            break;
+        case SA_SUMMONMONSTER:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+                mob_once_spawn (sd, map[sd->bl.m].name, sd->bl.x, sd->bl.y,
+                                "--ja--", -1, 1, "");
+            break;
+        case SA_LEVELUP:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd && pc_nextbaseexp (sd))
+                pc_gainexp (sd, pc_nextbaseexp (sd) * 10 / 100, 0);
+            break;
+
+        case SA_INSTANTDEATH:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+                pc_damage (NULL, sd, sd->status.max_hp);
+            break;
+
+        case SA_QUESTION:
+        case SA_GRAVITY:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            break;
+        case SA_CLASSCHANGE:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (dstmd)
+                mob_class_change (dstmd, changeclass);
+            break;
+        case SA_MONOCELL:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (dstmd)
+                mob_class_change (dstmd, poringclass);
+            break;
+        case SA_DEATH:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (dstsd)
+                pc_damage (NULL, dstsd, dstsd->status.max_hp);
+            if (dstmd)
+                mob_damage (NULL, dstmd, dstmd->hp, 1);
+            break;
+        case SA_REVERSEORCISH:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (dstsd)
+                pc_setoption (dstsd, dstsd->status.option | 0x0800);
+            break;
+        case SA_FORTUNE:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+                pc_getzeny (sd, battle_get_lv (bl) * 100);
+            break;
+        case AL_INCAGI:        /* 速度増加 */
+        case AL_BLESSING:      /* ブレッシング */
+        case PR_SLOWPOISON:
+        case PR_IMPOSITIO:     /* イムポシティオマヌス */
+        case PR_LEXAETERNA:    /* レックスエーテルナ */
+        case PR_SUFFRAGIUM:    /* サフラギウム */
+        case PR_BENEDICTIO:    /* 聖体降福 */
+        case CR_PROVIDENCE:    /* プロヴィデンス */
+        case CG_MARIONETTE:    /* マリオネットコントロール */
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            }
+            else
+            {
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            }
+            break;
+
+        case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
+        case SA_FROSTWEAPON:
+        case SA_LIGHTNINGLOADER:
+        case SA_SEISMICWEAPON:
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+                break;
+            }
+            if (bl->type == BL_PC)
+            {
+                struct map_session_data *sd2 = (struct map_session_data *) bl;
+                if (sd2->status.weapon == 0
+                    || sd2->sc_data[SC_FLAMELAUNCHER].timer != -1
+                    || sd2->sc_data[SC_FROSTWEAPON].timer != -1
+                    || sd2->sc_data[SC_LIGHTNINGLOADER].timer != -1
+                    || sd2->sc_data[SC_SEISMICWEAPON].timer != -1
+                    || sd2->sc_data[SC_ENCPOISON].timer != -1)
+                {
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+                    break;
+                }
+            }
+            if (MRAND (100) > (75 + skilllv * 1) && (skilllv != 5))
+            {
+                clif_skill_fail (sd, skillid, 0, 0);
+                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+                if (bl->type == BL_PC && battle_config.equipment_breaking)
+                {
+                    struct map_session_data *sd2 =
+                        (struct map_session_data *) bl;
+                    if (sd != sd2)
+                        clif_displaymessage (sd->fd,
+                                             "You broke target's weapon");
+                    pc_breakweapon (sd2);
+                }
+                break;
+            }
+            else
+            {
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            }
+            break;
+
+        case PR_ASPERSIO:      /* アスペルシオ */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (bl->type == BL_MOB)
+                break;
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case PR_KYRIE:         /* キリエエレイソン */
+            clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case KN_AUTOCOUNTER:   /* オートカウンター */
+        case KN_TWOHANDQUICKEN:    /* ツーハンドクイッケン */
+        case CR_SPEARQUICKEN:  /* スピアクイッケン */
+        case CR_REFLECTSHIELD:
+        case AS_POISONREACT:   /* ポイズンリアクト */
+        case MC_LOUD:          /* ラウドボイス */
+        case MG_ENERGYCOAT:    /* エナジーコート */
+        case SM_ENDURE:        /* インデュア */
+        case MG_SIGHT:         /* サイト */
+        case AL_RUWACH:        /* ルアフ */
+        case MO_EXPLOSIONSPIRITS:  // 爆裂波動
+        case MO_STEELBODY:     // 金剛
+        case LK_AURABLADE:     /* オーラブレード */
+        case LK_PARRYING:      /* パリイング */
+        case LK_CONCENTRATION: /* コンセントレーション */
+        case LK_BERSERK:       /* バーサーク */
+        case HP_ASSUMPTIO:     /*  */
+        case WS_CARTBOOST:     /* カートブースト */
+        case SN_SIGHT:         /* トゥルーサイト */
+        case WS_MELTDOWN:      /* メルトダウン */
+        case ST_REJECTSWORD:   /* リジェクトソード */
+        case HW_MAGICPOWER:    /* 魔法力増幅 */
+        case PF_MEMORIZE:      /* メモライズ */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case AS_ENCHANTPOISON: // Prevent spamming [Valaris]
+            if (bl->type == BL_PC)
+            {
+                struct map_session_data *sd2 = (struct map_session_data *) bl;
+                if (sd2->sc_data[SC_FLAMELAUNCHER].timer != -1
+                    || sd2->sc_data[SC_FROSTWEAPON].timer != -1
+                    || sd2->sc_data[SC_LIGHTNINGLOADER].timer != -1
+                    || sd2->sc_data[SC_SEISMICWEAPON].timer != -1
+                    || sd2->sc_data[SC_ENCPOISON].timer != -1)
+                {
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    break;
+                }
+            }
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case LK_TENSIONRELAX:  /* テンションリラックス */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            pc_setsit (sd);
+            clif_sitting (sd->fd, sd);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case MC_CHANGECART:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            break;
+        case AC_CONCENTRATION: /* 集中力向上 */
+        {
+            int  range = 1;
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            map_foreachinarea (skill_status_change_timer_sub, src->m,
+                               src->x - range, src->y - range, src->x + range,
+                               src->y + range, 0, src,
+                               SkillStatusChangeTable[skillid], tick);
+        }
+            break;
+        case SM_PROVOKE:       /* プロボック */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+
+            /* MVPmobと不死には効かない */
+            if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl)))   //不死には効かない
+            {
+                map_freeblock_unlock ();
+                return 1;
+            }
+
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+
+            if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel)   // 詠唱妨害
+                skill_castcancel (bl, 0);
+            if (dstsd && dstsd->skilltimer != -1
+                && (!dstsd->special_state.no_castcancel
+                    || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel
+                && !dstsd->special_state.no_castcancel2)
+                skill_castcancel (bl, 0);
+
+            if (sc_data)
+            {
+                if (sc_data[SC_FREEZE].timer != -1)
+                    skill_status_change_end (bl, SC_FREEZE, -1);
+                if (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0)
+                    skill_status_change_end (bl, SC_STONE, -1);
+                if (sc_data[SC_SLEEP].timer != -1)
+                    skill_status_change_end (bl, SC_SLEEP, -1);
+            }
+
+            if (bl->type == BL_MOB)
+            {
+                int  range = skill_get_range (skillid, skilllv);
+                if (range < 0)
+                    range = battle_get_range (src) - (range + 1);
+                mob_target ((struct mob_data *) bl, src, range);
+            }
+        }
+            break;
+
+        case CR_DEVOTION:      /* ディボーション */
+            if (sd && dstsd)
+            {
+                //転生や養子の場合の元の職業を算出する
+
+                int  lv = sd->status.base_level - dstsd->status.base_level;
+                lv = (lv < 0) ? -lv : lv;
+                if ((dstsd->bl.type != BL_PC)   // 相手はPCじゃないとだめ
+                    || (sd->bl.id == dstsd->bl.id)  // 相手が自分はだめ
+                    || (lv > 10)    // レベル差±10まで
+                    || (!sd->status.party_id && !sd->status.guild_id)   // PTにもギルドにも所属無しはだめ
+                    || ((sd->status.party_id != dstsd->status.party_id) // 同じパーティーか、
+                        || (sd->status.guild_id != dstsd->status.guild_id)) // 同じギルドじゃないとだめ
+                    || (dstsd->status.pc_class == 14 || dstsd->status.pc_class == 21
+                        || dstsd->status.pc_class == 4015
+                        || dstsd->status.pc_class == 4022))
+                {               // クルセだめ
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    map_freeblock_unlock ();
+                    return 1;
+                }
+                for (i = 0; i < skilllv; i++)
+                {
+                    if (!sd->dev.val1[i])
+                    {           // 空きがあったら入れる
+                        sd->dev.val1[i] = bl->id;
+                        sd->dev.val2[i] = bl->id;
+                        break;
+                    }
+                    else if (i == skilllv - 1)
+                    {           // 空きがなかった
+                        clif_skill_fail (sd, skillid, 0, 0);
+                        map_freeblock_unlock ();
+                        return 1;
+                    }
+                }
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                clif_devotion (sd, bl->id);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           src->id, 1, 0, 0,
+                                           1000 * (15 + 15 * skilllv), 0);
+            }
+            else
+                clif_skill_fail (sd, skillid, 0, 0);
+            break;
+        case MO_CALLSPIRITS:   // 気功
+            if (sd)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                pc_addspiritball (sd, skill_get_time (skillid, skilllv),
+                                  skilllv);
+            }
+            break;
+        case CH_SOULCOLLECT:   // 狂気功
+            if (sd)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                for (i = 0; i < 5; i++)
+                    pc_addspiritball (sd, skill_get_time (skillid, skilllv),
+                                      5);
+            }
+            break;
+        case MO_BLADESTOP:     // 白刃取り
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (src, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case MO_ABSORBSPIRITS: // 気奪
+            i = 0;
+            if (sd && dstsd)
+            {
+                if (sd == dstsd || map[sd->bl.m].flag.pvp
+                    || map[sd->bl.m].flag.gvg)
+                {
+                    if (dstsd->spiritball > 0)
+                    {
+                        clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                        i = dstsd->spiritball * 7;
+                        pc_delspiritball (dstsd, dstsd->spiritball, 0);
+                        if (i > 0x7FFF)
+                            i = 0x7FFF;
+                        if (sd->status.sp + i > sd->status.max_sp)
+                            i = sd->status.max_sp - sd->status.sp;
+                    }
+                }
+            }
+            else if (sd && dstmd)
+            {                   //対象がモンスターの場合
+                //20%の確率で対象のLv*2のSPを回復する。成功したときはターゲット(σ゚Д゚)σゲッツ!!
+                if (MRAND (100) < 20)
+                {
+                    i = 2 * mob_db[dstmd->mob_class].lv;
+                    mob_target (dstmd, src, 0);
+                }
+            }
+            if (i)
+            {
+                sd->status.sp += i;
+                clif_heal (sd->fd, SP_SP, i);
+            }
+            else
+                clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+            break;
+
+        case AC_MAKINGARROW:   /* 矢作成 */
+/*		if(sd) {
+			clif_arrow_create_list(sd);
+			clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		}*/
+            break;
+
+        case AM_PHARMACY:      /* ポーション作成 */
+/*		if(sd) {
+			clif_skill_produce_mix_list(sd,32);
+			clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		}*/
+            break;
+        case WS_CREATECOIN:    /* クリエイトコイン */
+/*		if(sd) {
+			clif_skill_produce_mix_list(sd,64);
+			clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		}*/
+            break;
+        case WS_CREATENUGGET:  /* 塊製造 */
+/*		if(sd) {
+			clif_skill_produce_mix_list(sd,128);
+			clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		}*/
+            break;
+        case BS_HAMMERFALL:    /* ハンマーフォール */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_weapon_damage)
+                break;
+            if (MRAND (100) < (20 + 10 * skilllv) * sc_def_vit / 100)
+            {
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            }
+            break;
+
+        case RG_RAID:          /* サプライズアタック */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            {
+                int  x = bl->x, y = bl->y;
+                skill_area_temp[1] = bl->id;
+                skill_area_temp[2] = x;
+                skill_area_temp[3] = y;
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, x - 1, y - 1, x + 1, y + 1, 0,
+                                   src, skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+            skill_status_change_end (src, SC_HIDING, -1);   // ハイディング解除
+            break;
+
+        case KN_BRANDISHSPEAR: /*ブランディッシュスピア */
+        {
+            int  c, n = 4, ar;
+            int  dir = map_calc_dir (src, bl->x, bl->y);
+            struct square tc;
+            int  x = bl->x, y = bl->y;
+            ar = skilllv / 3;
+            skill_brandishspear_first (&tc, dir, x, y);
+            skill_brandishspear_dir (&tc, dir, 4);
+            /* 範囲C */
+            if (skilllv == 10)
+            {
+                for (c = 1; c < 4; c++)
+                {
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, tc.val1[c], tc.val2[c],
+                                       tc.val1[c], tc.val2[c], 0, src,
+                                       skillid, skilllv, tick,
+                                       flag | BCT_ENEMY | n,
+                                       skill_castend_damage_id);
+                }
+            }
+            /* 範囲BA */
+            if (skilllv > 6)
+            {
+                skill_brandishspear_dir (&tc, dir, -1);
+                n--;
+            }
+            else
+            {
+                skill_brandishspear_dir (&tc, dir, -2);
+                n -= 2;
+            }
+
+            if (skilllv > 3)
+            {
+                for (c = 0; c < 5; c++)
+                {
+                    map_foreachinarea (skill_area_sub,
+                                       bl->m, tc.val1[c], tc.val2[c],
+                                       tc.val1[c], tc.val2[c], 0, src,
+                                       skillid, skilllv, tick,
+                                       flag | BCT_ENEMY | n,
+                                       skill_castend_damage_id);
+                    if (skilllv > 6 && n == 3 && c == 4)
+                    {
+                        skill_brandishspear_dir (&tc, dir, -1);
+                        n--;
+                        c = -1;
+                    }
+                }
+            }
+            /* 範囲@ */
+            for (c = 0; c < 10; c++)
+            {
+                if (c == 0 || c == 5)
+                    skill_brandishspear_dir (&tc, dir, -1);
+                map_foreachinarea (skill_area_sub,
+                                   bl->m, tc.val1[c % 5], tc.val2[c % 5],
+                                   tc.val1[c % 5], tc.val2[c % 5], 0, src,
+                                   skillid, skilllv, tick,
+                                   flag | BCT_ENEMY | 1,
+                                   skill_castend_damage_id);
+            }
+        }
+            break;
+
+            /* パーティスキル */
+        case AL_ANGELUS:       /* エンジェラス */
+        case PR_MAGNIFICAT:    /* マグニフィカート */
+        case PR_GLORIA:        /* グロリア */
+        case SN_WINDWALK:      /* ウインドウォーク */
+            if (sd == NULL || sd->status.party_id == 0 || (flag & 1))
+            {
+                /* 個別の処理 */
+                clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
+                if (bl->type == BL_PC
+                    && ((struct map_session_data *) bl)->
+                    special_state.no_magic_damage)
+                    break;
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+            }
+            else
+            {
+                /* パーティ全体への処理 */
+                party_foreachsamemap (skill_area_sub,
+                                      sd, 1,
+                                      src, skillid, skilllv, tick,
+                                      flag | BCT_PARTY | 1,
+                                      skill_castend_nodamage_id);
+            }
+            break;
+        case BS_ADRENALINE:    /* アドレナリンラッシュ */
+        case BS_WEAPONPERFECT: /* ウェポンパーフェクション */
+        case BS_OVERTHRUST:    /* オーバートラスト */
+            if (sd == NULL || sd->status.party_id == 0 || (flag & 1))
+            {
+                /* 個別の処理 */
+                clif_skill_nodamage (bl, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, (src == bl) ? 1 : 0, 0, 0,
+                                           skill_get_time (skillid, skilllv),
+                                           0);
+            }
+            else
+            {
+                /* パーティ全体への処理 */
+                party_foreachsamemap (skill_area_sub,
+                                      sd, 1,
+                                      src, skillid, skilllv, tick,
+                                      flag | BCT_PARTY | 1,
+                                      skill_castend_nodamage_id);
+            }
+            break;
+
+            /*(付加と解除が必要) */
+        case BS_MAXIMIZE:      /* マキシマイズパワー */
+        case NV_TRICKDEAD:     /* 死んだふり */
+        case CR_DEFENDER:      /* ディフェンダー */
+        case CR_AUTOGUARD:     /* オートガード */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            int  sc = SkillStatusChangeTable[skillid];
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (tsc_data)
+            {
+                if (tsc_data[sc].timer == -1)
+                    /* 付加する */
+                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
+                                               skill_get_time (skillid,
+                                                               skilllv), 0);
+                else
+                    /* 解除する */
+                    skill_status_change_end (bl, sc, -1);
+            }
+        }
+            break;
+
+        case TF_HIDING:        /* ハイディング */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            int  sc = SkillStatusChangeTable[skillid];
+            clif_skill_nodamage (src, bl, skillid, -1, 1);
+            if (tsc_data)
+            {
+                if (tsc_data[sc].timer == -1)
+                    /* 付加する */
+                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
+                                               skill_get_time (skillid,
+                                                               skilllv), 0);
+                else
+                    /* 解除する */
+                    skill_status_change_end (bl, sc, -1);
+            }
+        }
+            break;
+
+        case AS_CLOAKING:      /* クローキング */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            int  sc = SkillStatusChangeTable[skillid];
+            clif_skill_nodamage (src, bl, skillid, -1, 1);
+            if (tsc_data)
+            {
+                if (tsc_data[sc].timer == -1)
+                    /* 付加する */
+                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
+                                               skill_get_time (skillid,
+                                                               skilllv), 0);
+                else
+                    /* 解除する */
+                    skill_status_change_end (bl, sc, -1);
+            }
+
+            skill_check_cloaking (bl);
+        }
+            break;
+
+        case ST_CHASEWALK:     /* ハイディング */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            int  sc = SkillStatusChangeTable[skillid];
+            clif_skill_nodamage (src, bl, skillid, -1, 1);
+            if (tsc_data)
+            {
+                if (tsc_data[sc].timer == -1)
+                    /* 付加する */
+                    skill_status_change_start (bl, sc, skilllv, 0, 0, 0,
+                                               skill_get_time (skillid,
+                                                               skilllv), 0);
+                else
+                    /* 解除する */
+                    skill_status_change_end (bl, sc, -1);
+            }
+        }
+            break;
+
+            /* 対地スキル */
+        case BD_LULLABY:       /* 子守唄 */
+        case BD_RICHMANKIM:    /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+        case BA_DISSONANCE:    /* 不協和音 */
+        case BA_POEMBRAGI:     /* ブラギの詩 */
+        case BA_WHISTLE:       /* 口笛 */
+        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
+        case BA_APPLEIDUN:     /* イドゥンの林檎 */
+        case DC_UGLYDANCE:     /* 自分勝手なダンス */
+        case DC_HUMMING:       /* ハミング */
+        case DC_DONTFORGETME:  /* 私を忘れないで… */
+        case DC_FORTUNEKISS:   /* 幸運のキス */
+        case DC_SERVICEFORYOU: /* サービスフォーユー */
+        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0);
+            break;
+
+        case HP_BASILICA:      /* バジリカ */
+        case PA_GOSPEL:        /* ゴスペル */
+            skill_clear_unitgroup (src);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_unitsetting (src, skillid, skilllv, src->x, src->y, 0);
+            break;
+
+        case BD_ADAPTATION:    /* アドリブ */
+        {
+            struct status_change *sc_data = battle_get_sc_data (src);
+            if (sc_data && sc_data[SC_DANCING].timer != -1)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_stop_dancing (src, 0);
+            }
+        }
+            break;
+
+        case BA_FROSTJOKE:     /* 寒いジョーク */
+        case DC_SCREAM:        /* スクリーム */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_addtimerskill (src, tick + 3000, bl->id, 0, 0, skillid,
+                                 skilllv, 0, flag);
+            break;
+
+        case TF_STEAL:         // スティール
+            if (sd)
+            {
+                if (pc_steal_item (sd, bl))
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                else
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+            }
+            break;
+
+        case RG_STEALCOIN:     // スティールコイン
+            if (sd)
+            {
+                if (pc_steal_coin (sd, bl))
+                {
+                    int  range = skill_get_range (skillid, skilllv);
+                    if (range < 0)
+                        range = battle_get_range (src) - (range + 1);
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                    mob_target ((struct mob_data *) bl, src, range);
+                }
+                else
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 0);
+            }
+            break;
+
+        case MG_STONECURSE:    /* ストーンカース */
+            if (bl->type == BL_MOB && battle_get_mode (bl) & 0x20)
+            {
+                clif_skill_fail (sd, sd->skillid, 0, 0);
+                break;
+            }
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (MRAND (100) < skilllv * 4 + 20
+                && !battle_check_undead (battle_get_race (bl),
+                                         battle_get_elem_type (bl)))
+                skill_status_change_start (bl, SC_STONE, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            else if (sd)
+                clif_skill_fail (sd, skillid, 0, 0);
+            break;
+
+        case NV_FIRSTAID:      /* 応急手当 */
+            clif_skill_nodamage (src, bl, skillid, 5, 1);
+            battle_heal (NULL, bl, 5, 0, 0);
+            break;
+
+        case AL_CURE:          /* キュアー */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            skill_status_change_end (bl, SC_SILENCE, -1);
+            skill_status_change_end (bl, SC_BLIND, -1);
+            skill_status_change_end (bl, SC_CONFUSION, -1);
+            if (battle_check_undead
+                (battle_get_race (bl), battle_get_elem_type (bl)))
+            {                   //アンデッドなら暗闇効果
+                skill_status_change_start (bl, SC_CONFUSION, 1, 0, 0, 0, 6000,
+                                           0);
+            }
+            break;
+
+        case TF_DETOXIFY:      /* 解毒 */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_end (bl, SC_POISON, -1);
+            break;
+
+        case PR_STRECOVERY:    /* リカバリー */
+        {
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            skill_status_change_end (bl, SC_FREEZE, -1);
+            skill_status_change_end (bl, SC_STONE, -1);
+            skill_status_change_end (bl, SC_SLEEP, -1);
+            skill_status_change_end (bl, SC_STAN, -1);
+            if (battle_check_undead
+                (battle_get_race (bl), battle_get_elem_type (bl)))
+            {                   //アンデッドなら暗闇効果
+                int  blind_time;
+                //blind_time=30-battle_get_vit(bl)/10-battle_get_int/15;
+                blind_time =
+                    30 * (100 -
+                          (battle_get_int (bl) +
+                           battle_get_vit (bl)) / 2) / 100;
+                if (MRAND (100) <
+                    (100 -
+                     (battle_get_int (bl) / 2 + battle_get_vit (bl) / 3 +
+                      battle_get_luk (bl) / 10)))
+                    skill_status_change_start (bl, SC_BLIND, 1, 0, 0, 0,
+                                               blind_time, 0);
+            }
+            if (dstmd)
+            {
+                dstmd->attacked_id = 0;
+                dstmd->target_id = 0;
+                dstmd->state.targettype = NONE_ATTACKABLE;
+                dstmd->state.skillstate = MSS_IDLE;
+                dstmd->next_walktime = tick + MRAND (3000) + 3000;
+            }
+        }
+            break;
+
+        case WZ_ESTIMATION:    /* モンスター情報 */
+            if (src->type == BL_PC)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                clif_skill_estimation ((struct map_session_data *) src, bl);
+            }
+            break;
+
+        case MC_IDENTIFY:      /* アイテム鑑定 */
+            if (sd)
+                clif_item_identify_list (sd);
+            break;
+
+        case BS_REPAIRWEAPON:  /* 武器修理 */
+            if (sd)
+//動作しないのでとりあえずコメントアウト
+//          clif_item_repair_list(sd);
+                break;
+
+        case AL_TELEPORT:      /* テレポート */
+            if (sd)
+            {
+                if (map[sd->bl.m].flag.noteleport)
+                {               /* テレポ禁止 */
+                    clif_skill_teleportmessage (sd, 0);
+                    break;
+                }
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                if (sd->skilllv == 1)
+                    clif_skill_warppoint (sd, sd->skillid, "Random", "", "",
+                                          "");
+                else
+                {
+                    clif_skill_warppoint (sd, sd->skillid, "Random",
+                                          sd->status.save_point.map, "", "");
+                }
+            }
+            else if (bl->type == BL_MOB)
+                mob_warp ((struct mob_data *) bl, -1, -1, -1, 3);
+            break;
+
+        case AL_HOLYWATER:     /* アクアベネディクタ */
+            if (sd)
+            {
+                int  eflag;
+                struct item item_tmp;
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                memset (&item_tmp, 0, sizeof (item_tmp));
+                item_tmp.nameid = 523;
+                item_tmp.identify = 1;
+                if (battle_config.holywater_name_input)
+                {
+                    item_tmp.card[0] = 0xfe;
+                    item_tmp.card[1] = 0;
+                    *((unsigned long *) (&item_tmp.card[2])) = sd->char_id; /* キャラID */
+                }
+                eflag = pc_additem (sd, &item_tmp, 1);
+                if (eflag)
+                {
+                    clif_additem (sd, 0, 0, eflag);
+                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
+                                      sd->bl.y, NULL, NULL, NULL, 0);
+                }
+            }
+            break;
+        case TF_PICKSTONE:
+            if (sd)
+            {
+                int  eflag;
+                struct item item_tmp;
+                struct block_list tbl;
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                memset (&item_tmp, 0, sizeof (item_tmp));
+                memset (&tbl, 0, sizeof (tbl)); // [MouseJstr]
+                item_tmp.nameid = 7049;
+                item_tmp.identify = 1;
+                tbl.id = 0;
+                clif_takeitem (&sd->bl, &tbl);
+                eflag = pc_additem (sd, &item_tmp, 1);
+                if (eflag)
+                {
+                    clif_additem (sd, 0, 0, eflag);
+                    map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
+                                      sd->bl.y, NULL, NULL, NULL, 0);
+                }
+            }
+            break;
+
+        case RG_STRIPWEAPON:   /* ストリップウェポン */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+
+            if (tsc_data && tsc_data[SC_CP_WEAPON].timer != -1)
+                break;
+            strip_per = 5 + 2 * skilllv + strip_fix / 5;
+            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
+            if (MRAND (100) < strip_per)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0, strip_time, 0);
+                if (dstsd)
+                {
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (dstsd->status.inventory[i].equip
+                            && dstsd->status.inventory[i].equip & 0x0002)
+                        {
+                            pc_unequipitem (dstsd, i, 0);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+            break;
+
+        case RG_STRIPSHIELD:   /* ストリップシールド */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+
+            if (tsc_data && tsc_data[SC_CP_SHIELD].timer != -1)
+                break;
+            strip_per = 5 + 2 * skilllv + strip_fix / 5;
+            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
+            if (MRAND (100) < strip_per)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0, strip_time, 0);
+                if (dstsd)
+                {
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (dstsd->status.inventory[i].equip
+                            && dstsd->status.inventory[i].equip & 0x0020)
+                        {
+                            pc_unequipitem (dstsd, i, 0);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+            break;
+
+        case RG_STRIPARMOR:    /* ストリップアーマー */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+
+            if (tsc_data && tsc_data[SC_CP_ARMOR].timer != -1)
+                break;
+            strip_per = 5 + 2 * skilllv + strip_fix / 5;
+            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
+            if (MRAND (100) < strip_per)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0, strip_time, 0);
+                if (dstsd)
+                {
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (dstsd->status.inventory[i].equip
+                            && dstsd->status.inventory[i].equip & 0x0010)
+                        {
+                            pc_unequipitem (dstsd, i, 0);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+            break;
+        case RG_STRIPHELM:     /* ストリップヘルム */
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+
+            if (tsc_data && tsc_data[SC_CP_HELM].timer != -1)
+                break;
+            strip_per = 5 + 2 * skilllv + strip_fix / 5;
+            strip_time = skill_get_time (skillid, skilllv) + strip_fix / 2;
+            if (MRAND (100) < strip_per)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                skill_status_change_start (bl,
+                                           SkillStatusChangeTable[skillid],
+                                           skilllv, 0, 0, 0, strip_time, 0);
+                if (dstsd)
+                {
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (dstsd->status.inventory[i].equip
+                            && dstsd->status.inventory[i].equip & 0x0100)
+                        {
+                            pc_unequipitem (dstsd, i, 0);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+            break;
+            /* PotionPitcher */
+        case AM_POTIONPITCHER: /* ポーションピッチャー */
+        {
+            struct block_list tbl;
+            int  i, x, hp = 0, sp = 0;
+            if (sd)
+            {
+                if (sd == dstsd)
+                {               // cancel use on oneself
+                    map_freeblock_unlock ();
+                    return 1;
+                }
+                x = skilllv % 11 - 1;
+                i = pc_search_inventory (sd, skill_db[skillid].itemid[x]);
+                if (i < 0 || skill_db[skillid].itemid[x] <= 0)
+                {
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    map_freeblock_unlock ();
+                    return 1;
+                }
+                if (sd->inventory_data[i] == NULL
+                    || sd->status.inventory[i].amount <
+                    skill_db[skillid].amount[x])
+                {
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    map_freeblock_unlock ();
+                    return 1;
+                }
+                sd->state.potionpitcher_flag = 1;
+                sd->potion_hp = sd->potion_sp = sd->potion_per_hp =
+                    sd->potion_per_sp = 0;
+                sd->skilltarget = bl->id;
+                run_script (sd->inventory_data[i]->use_script, 0, sd->bl.id,
+                            0);
+                pc_delitem (sd, i, skill_db[skillid].amount[x], 0);
+                sd->state.potionpitcher_flag = 0;
+                if (sd->potion_per_hp > 0 || sd->potion_per_sp > 0)
+                {
+                    hp = battle_get_max_hp (bl) * sd->potion_per_hp / 100;
+                    hp = hp * (100 +
+                               pc_checkskill (sd,
+                                              AM_POTIONPITCHER) * 10 +
+                               pc_checkskill (sd,
+                                              AM_LEARNINGPOTION) * 5) / 100;
+                    if (dstsd)
+                    {
+                        sp = dstsd->status.max_sp * sd->potion_per_sp / 100;
+                        sp = sp * (100 +
+                                   pc_checkskill (sd,
+                                                  AM_POTIONPITCHER) +
+                                   pc_checkskill (sd,
+                                                  AM_LEARNINGPOTION) * 5) /
+                            100;
+                    }
+                }
+                else
+                {
+                    if (sd->potion_hp > 0)
+                    {
+                        hp = sd->potion_hp * (100 +
+                                              pc_checkskill (sd,
+                                                             AM_POTIONPITCHER)
+                                              * 10 + pc_checkskill (sd,
+                                                                    AM_LEARNINGPOTION)
+                                              * 5) / 100;
+                        hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100;
+                        if (dstsd)
+                            hp = hp * (100 +
+                                       pc_checkskill (dstsd,
+                                                      SM_RECOVERY) * 10) /
+                                100;
+                    }
+                    if (sd->potion_sp > 0)
+                    {
+                        sp = sd->potion_sp * (100 +
+                                              pc_checkskill (sd,
+                                                             AM_POTIONPITCHER)
+                                              + pc_checkskill (sd,
+                                                               AM_LEARNINGPOTION)
+                                              * 5) / 100;
+                        sp = sp * (100 + (battle_get_int (bl) << 1)) / 100;
+                        if (dstsd)
+                            sp = sp * (100 +
+                                       pc_checkskill (dstsd,
+                                                      MG_SRECOVERY) * 10) /
+                                100;
+                    }
+                }
+            }
+            else
+            {
+                hp = (1 + MRAND (400)) * (100 + skilllv * 10) / 100;
+                hp = hp * (100 + (battle_get_vit (bl) << 1)) / 100;
+                if (dstsd)
+                    hp = hp * (100 +
+                               pc_checkskill (dstsd, SM_RECOVERY) * 10) / 100;
+            }
+            tbl.id = 0;
+            tbl.m = src->m;
+            tbl.x = src->x;
+            tbl.y = src->y;
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (hp > 0 || (hp <= 0 && sp <= 0))
+                clif_skill_nodamage (&tbl, bl, AL_HEAL, hp, 1);
+            if (sp > 0)
+                clif_skill_nodamage (&tbl, bl, MG_SRECOVERY, sp, 1);
+            battle_heal (src, bl, hp, sp, 0);
+        }
+            break;
+        case AM_CP_WEAPON:
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (tsc_data && tsc_data[SC_STRIPWEAPON].timer != -1)
+                skill_status_change_end (bl, SC_STRIPWEAPON, -1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+        }
+            break;
+        case AM_CP_SHIELD:
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (tsc_data && tsc_data[SC_STRIPSHIELD].timer != -1)
+                skill_status_change_end (bl, SC_STRIPSHIELD, -1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+        }
+            break;
+        case AM_CP_ARMOR:
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (tsc_data && tsc_data[SC_STRIPARMOR].timer != -1)
+                skill_status_change_end (bl, SC_STRIPARMOR, -1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+        }
+            break;
+        case AM_CP_HELM:
+        {
+            struct status_change *tsc_data = battle_get_sc_data (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (tsc_data && tsc_data[SC_STRIPHELM].timer != -1)
+                skill_status_change_end (bl, SC_STRIPHELM, -1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+        }
+            break;
+        case SA_DISPELL:       /* ディスペル */
+        {
+            int  i;
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            for (i = 0; i < 136; i++)
+            {
+                if (i == SC_RIDING || i == SC_FALCON || i == SC_HALLUCINATION
+                    || i == SC_WEIGHT50 || i == SC_WEIGHT90
+                    || i == SC_STRIPWEAPON || i == SC_STRIPSHIELD
+                    || i == SC_STRIPARMOR || i == SC_STRIPHELM
+                    || i == SC_CP_WEAPON || i == SC_CP_SHIELD
+                    || i == SC_CP_ARMOR || i == SC_CP_HELM || i == SC_COMBO)
+                    continue;
+                skill_status_change_end (bl, i, -1);
+            }
+        }
+            break;
+
+        case TF_BACKSLIDING:   /* バックステップ */
+            battle_stopwalking (src, 1);
+            skill_blown (src, bl,
+                         skill_get_blewcount (skillid, skilllv) | 0x10000);
+            if (src->type == BL_MOB)
+                clif_fixmobpos ((struct mob_data *) src);
+            else if (src->type == BL_PC)
+                clif_fixpos (src);
+            skill_addtimerskill (src, tick + 200, src->id, 0, 0, skillid,
+                                 skilllv, 0, flag);
+            break;
+
+        case SA_CASTCANCEL:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_castcancel (src, 1);
+            if (sd)
+            {
+                int  sp = skill_get_sp (sd->skillid_old, sd->skilllv_old);
+                sp = sp * (90 - (skilllv - 1) * 20) / 100;
+                if (sp < 0)
+                    sp = 0;
+                pc_heal (sd, 0, -sp);
+            }
+            break;
+        case SA_SPELLBREAKER:  // スペルブレイカー
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  sp;
+            if (sc_data && sc_data[SC_MAGICROD].timer != -1)
+            {
+                if (dstsd)
+                {
+                    sp = skill_get_sp (skillid, skilllv);
+                    sp = sp * sc_data[SC_MAGICROD].val2 / 100;
+                    if (sp > 0x7fff)
+                        sp = 0x7fff;
+                    else if (sp < 1)
+                        sp = 1;
+                    if (dstsd->status.sp + sp > dstsd->status.max_sp)
+                    {
+                        sp = dstsd->status.max_sp - dstsd->status.sp;
+                        dstsd->status.sp = dstsd->status.max_sp;
+                    }
+                    else
+                        dstsd->status.sp += sp;
+                    clif_heal (dstsd->fd, SP_SP, sp);
+                }
+                clif_skill_nodamage (bl, bl, SA_MAGICROD,
+                                     sc_data[SC_MAGICROD].val1, 1);
+                if (sd)
+                {
+                    sp = sd->status.max_sp / 5;
+                    if (sp < 1)
+                        sp = 1;
+                    pc_heal (sd, 0, -sp);
+                }
+            }
+            else
+            {
+                int  bl_skillid = 0, bl_skilllv = 0;
+                if (bl->type == BL_PC)
+                {
+                    if (dstsd && dstsd->skilltimer != -1)
+                    {
+                        bl_skillid = dstsd->skillid;
+                        bl_skilllv = dstsd->skilllv;
+                    }
+                }
+                else if (bl->type == BL_MOB)
+                {
+                    if (dstmd && dstmd->skilltimer != -1)
+                    {
+                        bl_skillid = dstmd->skillid;
+                        bl_skilllv = dstmd->skilllv;
+                    }
+                }
+                if (bl_skillid > 0
+                    && skill_db[bl_skillid].skill_type == BF_MAGIC)
+                {
+                    clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                    skill_castcancel (bl, 0);
+                    sp = skill_get_sp (bl_skillid, bl_skilllv);
+                    if (dstsd)
+                        pc_heal (dstsd, 0, -sp);
+                    if (sd)
+                    {
+                        sp = sp * (25 * (skilllv - 1)) / 100;
+                        if (skilllv > 1 && sp < 1)
+                            sp = 1;
+                        if (sp > 0x7fff)
+                            sp = 0x7fff;
+                        else if (sp < 1)
+                            sp = 1;
+                        if (sd->status.sp + sp > sd->status.max_sp)
+                        {
+                            sp = sd->status.max_sp - sd->status.sp;
+                            sd->status.sp = sd->status.max_sp;
+                        }
+                        else
+                            sd->status.sp += sp;
+                        clif_heal (sd->fd, SP_SP, sp);
+                    }
+                }
+                else if (sd)
+                    clif_skill_fail (sd, skillid, 0, 0);
+            }
+        }
+            break;
+        case SA_MAGICROD:
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case SA_AUTOSPELL:     /* オートスペル */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+                clif_autospell (sd, skilllv);
+            else
+            {
+                int  maxlv = 1, spellid = 0;
+                static const int spellarray[3] =
+                    { MG_COLDBOLT, MG_FIREBOLT, MG_LIGHTNINGBOLT };
+                if (skilllv >= 10)
+                {
+                    spellid = MG_FROSTDIVER;
+                    maxlv = skilllv - 9;
+                }
+                else if (skilllv >= 8)
+                {
+                    spellid = MG_FIREBALL;
+                    maxlv = skilllv - 7;
+                }
+                else if (skilllv >= 5)
+                {
+                    spellid = MG_SOULSTRIKE;
+                    maxlv = skilllv - 4;
+                }
+                else if (skilllv >= 2)
+                {
+                    int  i = MRAND (3);
+                    spellid = spellarray[i];
+                    maxlv = skilllv - 1;
+                }
+                else if (skilllv > 0)
+                {
+                    spellid = MG_NAPALMBEAT;
+                    maxlv = 3;
+                }
+                if (spellid > 0)
+                    skill_status_change_start (src, SC_AUTOSPELL, skilllv,
+                                               spellid, maxlv, 0,
+                                               skill_get_time (SA_AUTOSPELL,
+                                                               skilllv), 0);
+            }
+            break;
+
+            /* ランダム属性変化、水属性変化、地、火、風 */
+        case NPC_ATTRICHANGE:
+        case NPC_CHANGEWATER:
+        case NPC_CHANGEGROUND:
+        case NPC_CHANGEFIRE:
+        case NPC_CHANGEWIND:
+            /* 毒、聖、念、闇 */
+        case NPC_CHANGEPOISON:
+        case NPC_CHANGEHOLY:
+        case NPC_CHANGEDARKNESS:
+        case NPC_CHANGETELEKINESIS:
+            if (md)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                md->def_ele = skill_get_pl (skillid);
+                if (md->def_ele == 0)   /* ランダム変化、ただし、 */
+                    md->def_ele = MRAND (10);   /* 不死属性は除く */
+                md->def_ele += (1 + MRAND (4)) * 20;    /* 属性レベルはランダム */
+            }
+            break;
+
+        case NPC_HALLUCINATION:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+
+        case NPC_KEEPING:
+        case NPC_BARRIER:
+        {
+            int  skill_time = skill_get_time (skillid, skilllv);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0, skill_time, 0);
+            mob_changestate ((struct mob_data *) src, MS_DELAY, skill_time);
+        }
+            break;
+
+        case NPC_DARKBLESSING:
+        {
+            int  sc_def = 100 - battle_get_mdef (bl);
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (battle_get_elem_type (bl) == 7 || battle_get_race (bl) == 6)
+                break;
+            if (MRAND (100) < sc_def * (50 + skilllv * 5) / 100)
+            {
+                if (dstsd)
+                {
+                    int  hp = battle_get_hp (bl) - 1;
+                    pc_heal (dstsd, -hp, 0);
+                }
+                else if (dstmd)
+                    dstmd->hp = 1;
+            }
+        }
+            break;
+
+        case NPC_SELFDESTRUCTION:  /* 自爆 */
+        case NPC_SELFDESTRUCTION2: /* 自爆2 */
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, skillid, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case NPC_LICK:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_weapon_damage)
+                break;
+            if (dstsd)
+                pc_heal (dstsd, 0, -100);
+            if (MRAND (100) < (skilllv * 5) * sc_def_vit / 100)
+                skill_status_change_start (bl, SC_STAN, skilllv, 0, 0, 0,
+                                           skill_get_time2 (skillid, skilllv),
+                                           0);
+            break;
+
+        case NPC_SUICIDE:      /* 自決 */
+            if (src && bl && md)
+            {
+                clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+                mob_damage (NULL, md, md->hp, 0);
+            }
+            break;
+
+        case NPC_SUMMONSLAVE:  /* 手下召喚 */
+        case NPC_SUMMONMONSTER:    /* MOB召喚 */
+            if (md && !md->master_id)
+            {
+                mob_summonslave (md,
+                                 mob_db[md->mob_class].skill[md->skillidx].val,
+                                 skilllv,
+                                 (skillid == NPC_SUMMONSLAVE) ? 1 : 0);
+            }
+            break;
+
+        case NPC_TRANSFORMATION:
+        case NPC_METAMORPHOSIS:
+            if (md)
+                mob_class_change (md,
+                                  mob_db[md->mob_class].skill[md->skillidx].val);
+            break;
+
+        case NPC_EMOTION:      /* エモーション */
+            if (md)
+                clif_emotion (&md->bl,
+                              mob_db[md->mob_class].skill[md->skillidx].val[0]);
+            break;
+
+        case NPC_DEFENDER:
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            break;
+
+        case WE_MALE:          /* 君だけは護るよ */
+            if (sd && dstsd)
+            {
+                int  hp_rate =
+                    (skilllv <=
+                     0) ? 0 : skill_db[skillid].hp_rate[skilllv - 1];
+                int  gain_hp = sd->status.max_hp * abs (hp_rate) / 100; // 15%
+                clif_skill_nodamage (src, bl, skillid, gain_hp, 1);
+                battle_heal (NULL, bl, gain_hp, 0, 0);
+            }
+            break;
+        case WE_FEMALE:        /* あなたの為に犠牲になります */
+            if (sd && dstsd)
+            {
+                int  sp_rate =
+                    (skilllv <=
+                     0) ? 0 : skill_db[skillid].sp_rate[skilllv - 1];
+                int  gain_sp = sd->status.max_sp * abs (sp_rate) / 100; // 15%
+                clif_skill_nodamage (src, bl, skillid, gain_sp, 1);
+                battle_heal (NULL, bl, 0, gain_sp, 0);
+            }
+            break;
+
+        case WE_CALLPARTNER:   /* あなたに会いたい */
+            if (sd && dstsd)
+            {
+                if (map[sd->bl.m].flag.nomemo)
+                {
+                    clif_skill_teleportmessage (sd, 1);
+                    return 0;
+                }
+                if ((dstsd = pc_get_partner (sd)) == NULL)
+                {
+                    clif_skill_fail (sd, skillid, 0, 0);
+                    return 0;
+                }
+                skill_unitsetting (src, skillid, skilllv, sd->bl.x, sd->bl.y,
+                                   0);
+            }
+            break;
+
+        case PF_HPCONVERSION:  /* ライフ置き換え */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+            {
+                int  conv_hp = 0, conv_sp = 0;
+                conv_hp = sd->status.hp / 10;   //基本はHPの10%
+                sd->status.hp -= conv_hp;   //HPを減らす
+                conv_sp = conv_hp * 20 * skilllv / 100;
+                conv_sp =
+                    (sd->status.sp + conv_sp >
+                     sd->status.max_sp) ? sd->status.max_sp -
+                    sd->status.sp : conv_sp;
+                sd->status.sp += conv_sp;   //SPを増やす
+                pc_heal (sd, -conv_hp, conv_sp);
+                clif_heal (sd->fd, SP_SP, conv_sp);
+            }
+            break;
+        case HT_REMOVETRAP:    /* リムーブトラップ */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            {
+                struct skill_unit *su = NULL;
+                struct item item_tmp;
+                int  flag;
+                if ((bl->type == BL_SKILL) &&
+                    (su = (struct skill_unit *) bl) &&
+                    (su->group->src_id == src->id || map[bl->m].flag.pvp
+                     || map[bl->m].flag.gvg) && (su->group->unit_id >= 0x8f
+                                                 && su->group->unit_id <=
+                                                 0x99)
+                    && (su->group->unit_id != 0x92))
+                {               //罠を取り返す
+                    if (sd)
+                    {
+                        if (battle_config.skill_removetrap_type == 1)
+                        {
+                            for (i = 0; i < 10; i++)
+                            {
+                                if (skill_db[su->group->skill_id].itemid[i] >
+                                    0)
+                                {
+                                    memset (&item_tmp, 0, sizeof (item_tmp));
+                                    item_tmp.nameid =
+                                        skill_db[su->group->
+                                                 skill_id].itemid[i];
+                                    item_tmp.identify = 1;
+                                    if (item_tmp.nameid
+                                        && (flag =
+                                            pc_additem (sd, &item_tmp,
+                                                        skill_db[su->
+                                                                 group->skill_id].amount
+                                                        [i])))
+                                    {
+                                        clif_additem (sd, 0, 0, flag);
+                                        map_addflooritem (&item_tmp,
+                                                          skill_db[su->
+                                                                   group->skill_id].amount
+                                                          [i], sd->bl.m,
+                                                          sd->bl.x, sd->bl.y,
+                                                          NULL, NULL, NULL,
+                                                          0);
+                                    }
+                                }
+                            }
+                        }
+                        else
+                        {
+                            memset (&item_tmp, 0, sizeof (item_tmp));
+                            item_tmp.nameid = 1065;
+                            item_tmp.identify = 1;
+                            if (item_tmp.nameid
+                                && (flag = pc_additem (sd, &item_tmp, 1)))
+                            {
+                                clif_additem (sd, 0, 0, flag);
+                                map_addflooritem (&item_tmp, 1, sd->bl.m,
+                                                  sd->bl.x, sd->bl.y, NULL,
+                                                  NULL, NULL, 0);
+                            }
+                        }
+
+                    }
+                    if (su->group->unit_id == 0x91 && su->group->val2)
+                    {
+                        struct block_list *target =
+                            map_id2bl (su->group->val2);
+                        if (target
+                            && (target->type == BL_PC
+                                || target->type == BL_MOB))
+                            skill_status_change_end (target, SC_ANKLE, -1);
+                    }
+                    skill_delunit (su);
+                }
+            }
+            break;
+        case HT_SPRINGTRAP:    /* スプリングトラップ */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            {
+                struct skill_unit *su = NULL;
+                if ((bl->type == BL_SKILL) && (su = (struct skill_unit *) bl)
+                    && (su->group))
+                {
+                    switch (su->group->unit_id)
+                    {
+                        case 0x8f: /* ブラストマイン */
+                        case 0x90: /* スキッドトラップ */
+                        case 0x93: /* ランドマイン */
+                        case 0x94: /* ショックウェーブトラップ */
+                        case 0x95: /* サンドマン */
+                        case 0x96: /* フラッシャー */
+                        case 0x97: /* フリージングトラップ */
+                        case 0x98: /* クレイモアートラップ */
+                        case 0x99: /* トーキーボックス */
+                            su->group->unit_id = 0x8c;
+                            clif_changelook (bl, LOOK_BASE,
+                                             su->group->unit_id);
+                            su->group->limit =
+                                DIFF_TICK (tick + 1500, su->group->tick);
+                            su->limit =
+                                DIFF_TICK (tick + 1500, su->group->tick);
+                    }
+                }
+            }
+            break;
+        case BD_ENCORE:        /* アンコール */
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            if (sd)
+                skill_use_id (sd, src->id, sd->skillid_dance,
+                              sd->skilllv_dance);
+            break;
+        case AS_SPLASHER:      /* ベナムスプラッシャー */
+            if ((double) battle_get_max_hp (bl) * 2 / 3 < battle_get_hp (bl))   //HPが2/3以上残っていたら失敗
+                return 1;
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, skillid, src->id, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+            break;
+        case PF_MINDBREAKER:   /* プロボック */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+
+            /* MVPmobと不死には効かない */
+            if ((bl->type == BL_MOB && battle_get_mode (bl) & 0x20) || battle_check_undead (battle_get_race (bl), battle_get_elem_type (bl)))   //不死には効かない
+            {
+                map_freeblock_unlock ();
+                return 1;
+            }
+
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            skill_status_change_start (bl, SkillStatusChangeTable[skillid],
+                                       skilllv, 0, 0, 0,
+                                       skill_get_time (skillid, skilllv), 0);
+
+            if (dstmd && dstmd->skilltimer != -1 && dstmd->state.skillcastcancel)   // 詠唱妨害
+                skill_castcancel (bl, 0);
+            if (dstsd && dstsd->skilltimer != -1
+                && (!dstsd->special_state.no_castcancel
+                    || map[bl->m].flag.gvg) && dstsd->state.skillcastcancel
+                && !dstsd->special_state.no_castcancel2)
+                skill_castcancel (bl, 0);
+
+            if (sc_data)
+            {
+                if (sc_data[SC_FREEZE].timer != -1)
+                    skill_status_change_end (bl, SC_FREEZE, -1);
+                if (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0)
+                    skill_status_change_end (bl, SC_STONE, -1);
+                if (sc_data[SC_SLEEP].timer != -1)
+                    skill_status_change_end (bl, SC_SLEEP, -1);
+            }
+
+            if (bl->type == BL_MOB)
+            {
+                int  range = skill_get_range (skillid, skilllv);
+                if (range < 0)
+                    range = battle_get_range (src) - (range + 1);
+                mob_target ((struct mob_data *) bl, src, range);
+            }
+        }
+            break;
+
+        case RG_CLEANER:       //AppleGirl
+            clif_skill_nodamage (src, bl, skillid, skilllv, 1);
+            {
+                struct skill_unit *su = NULL;
+                if ((bl->type == BL_SKILL) &&
+                    (su = (struct skill_unit *) bl) &&
+                    (su->group->src_id == src->id || map[bl->m].flag.pvp
+                     || map[bl->m].flag.gvg) && (su->group->unit_id == 0xb0))
+                {               //罠を取り返す
+                    if (sd)
+                        skill_delunit (su);
+                }
+            }
+            break;
+        default:
+            printf ("Unknown skill used:%d\n", skillid);
+            map_freeblock_unlock ();
+            return 1;
+    }
+
+    map_freeblock_unlock ();
+    return 0;
+}
+
+/*==========================================
+ * スキル使用(詠唱完了、ID指定)
+ *------------------------------------------
+ */
+void skill_castend_id (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ;
+    struct block_list *bl;
+    int  range, inf2;
+
+    nullpo_retv ( sd);
+
+    if (sd->bl.prev == NULL)    //prevが無いのはありなの?
+        return;
+
+    if (sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid)  /* タイマIDの確認 */
+        return;
+    if (sd->skillid != SA_CASTCANCEL && sd->skilltimer != -1
+        && pc_checkskill (sd, SA_FREECAST) > 0)
+    {
+        sd->speed = sd->prev_speed;
+        clif_updatestatus (sd, SP_SPEED);
+    }
+    if (sd->skillid != SA_CASTCANCEL)
+        sd->skilltimer = -1;
+
+    if ((bl = map_id2bl (sd->skilltarget)) == NULL || bl->prev == NULL)
+    {
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+    if (sd->bl.m != bl->m || pc_isdead (sd))
+    {                           //マップが違うか自分が死んでいる
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+
+    if (sd->skillid == PR_LEXAETERNA)
+    {
+        struct status_change *sc_data = battle_get_sc_data (bl);
+        if (sc_data
+            && (sc_data[SC_FREEZE].timer != -1
+                || (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0)))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            sd->skillitem = sd->skillitemlv = -1;
+            return;
+        }
+    }
+    else if (sd->skillid == RG_BACKSTAP)
+    {
+        int  dir = map_calc_dir (&sd->bl, bl->x, bl->y), t_dir =
+            battle_get_dir (bl);
+        int  dist = distance (sd->bl.x, sd->bl.y, bl->x, bl->y);
+        if (bl->type != BL_SKILL && (dist == 0 || map_check_dir (dir, t_dir)))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            sd->skillitem = sd->skillitemlv = -1;
+            return;
+        }
+    }
+
+    inf2 = skill_get_inf2 (sd->skillid);
+    if (((skill_get_inf (sd->skillid) & 1) || inf2 & 4) &&  // 彼我敵対関係チェック
+        battle_check_target (&sd->bl, bl, BCT_ENEMY) <= 0)
+    {
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+    if (inf2 & 0xC00 && sd->bl.id != bl->id)
+    {
+        int  fail_flag = 1;
+        if (inf2 & 0x400 && battle_check_target (&sd->bl, bl, BCT_PARTY) > 0)
+            fail_flag = 0;
+        if (inf2 & 0x800 && sd->status.guild_id > 0
+            && sd->status.guild_id == battle_get_guild_id (bl))
+            fail_flag = 0;
+        if (fail_flag)
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            sd->skillitem = sd->skillitemlv = -1;
+            return;
+        }
+    }
+
+    range = skill_get_range (sd->skillid, sd->skilllv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    range += battle_config.pc_skill_add_range;
+    if ((sd->skillid == MO_EXTREMITYFIST && sd->sc_data[SC_COMBO].timer != -1
+         && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
+        || (sd->skillid == CH_TIGERFIST && sd->sc_data[SC_COMBO].timer != -1
+            && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
+        || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1
+            && sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH)
+        || (sd->skillid == CH_CHAINCRUSH && sd->sc_data[SC_COMBO].timer != -1
+            && sd->sc_data[SC_COMBO].val1 == CH_TIGERFIST))
+        range +=
+            skill_get_blewcount (MO_COMBOFINISH, sd->sc_data[SC_COMBO].val2);
+    if (battle_config.skill_out_range_consume)
+    {                           // changed to allow casting when target walks out of range [Valaris]
+        if (range < distance (sd->bl.x, sd->bl.y, bl->x, bl->y))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            sd->skillitem = sd->skillitemlv = -1;
+            return;
+        }
+    }
+    if (!skill_check_condition (sd, 1))
+    {                           /* 使用条件チェック */
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+    sd->skillitem = sd->skillitemlv = -1;
+    if (battle_config.skill_out_range_consume)
+    {
+        if (range < distance (sd->bl.x, sd->bl.y, bl->x, bl->y))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            return;
+        }
+    }
+
+    if (battle_config.pc_skill_log)
+        printf ("PC %d skill castend skill=%d\n", sd->bl.id, sd->skillid);
+    pc_stop_walking (sd, 0);
+
+    switch (skill_get_nk (sd->skillid))
+    {
+            /* 攻撃系/吹き飛ばし系 */
+        case 0:
+        case 2:
+            skill_castend_damage_id (&sd->bl, bl, sd->skillid, sd->skilllv,
+                                     tick, 0);
+            break;
+        case 1:                /* 支援系 */
+            if ((sd->skillid == AL_HEAL
+                 || (sd->skillid == ALL_RESURRECTION && bl->type != BL_PC)
+                 || sd->skillid == PR_ASPERSIO)
+                && battle_check_undead (battle_get_race (bl),
+                                        battle_get_elem_type (bl)))
+                skill_castend_damage_id (&sd->bl, bl, sd->skillid,
+                                         sd->skilllv, tick, 0);
+            else
+                skill_castend_nodamage_id (&sd->bl, bl, sd->skillid,
+                                           sd->skilllv, tick, 0);
+            break;
+    }
+}
+
+/*==========================================
+ * スキル使用(詠唱完了、場所指定の実際の処理)
+ *------------------------------------------
+ */
+int skill_castend_pos2 (struct block_list *src, int x, int y, int skillid,
+                        int skilllv, unsigned int tick, int flag)
+{
+    struct map_session_data *sd = NULL;
+    int  i, tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
+
+    nullpo_retr (0, src);
+
+    if (src->type == BL_PC)
+    {
+        nullpo_retr (0, sd = (struct map_session_data *) src);
+    }
+    if (skillid != WZ_METEOR &&
+        skillid != WZ_SIGHTRASHER &&
+        skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE)
+        clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
+
+    if (skillnotok (skillid, sd))   // [MouseJstr]
+        return 0;
+
+    switch (skillid)
+    {
+        case PR_BENEDICTIO:    /* 聖体降福 */
+            skill_area_temp[1] = src->id;
+            map_foreachinarea (skill_area_sub,
+                               src->m, x - 1, y - 1, x + 1, y + 1, 0,
+                               src, skillid, skilllv, tick,
+                               flag | BCT_NOENEMY | 1,
+                               skill_castend_nodamage_id);
+            map_foreachinarea (skill_area_sub, src->m, x - 1, y - 1, x + 1,
+                               y + 1, 0, src, skillid, skilllv, tick,
+                               flag | BCT_ENEMY | 1, skill_castend_damage_id);
+            break;
+
+        case BS_HAMMERFALL:    /* ハンマーフォール */
+            skill_area_temp[1] = src->id;
+            skill_area_temp[2] = x;
+            skill_area_temp[3] = y;
+            map_foreachinarea (skill_area_sub,
+                               src->m, x - 2, y - 2, x + 2, y + 2, 0,
+                               src, skillid, skilllv, tick,
+                               flag | BCT_ENEMY | 2,
+                               skill_castend_nodamage_id);
+            break;
+
+        case HT_DETECTING:     /* ディテクティング */
+        {
+            const int range = 7;
+            map_foreachinarea (skill_status_change_timer_sub,
+                               src->m, src->x - range, src->y - range,
+                               src->x + range, src->y + range, 0, src,
+                               SC_SIGHT, tick);
+        }
+            break;
+
+        case MG_SAFETYWALL:    /* セイフティウォール */
+        case MG_FIREWALL:      /* ファイヤーウォール */
+        case MG_THUNDERSTORM:  /* サンダーストーム */
+        case AL_PNEUMA:        /* ニューマ */
+        case WZ_ICEWALL:       /* アイスウォール */
+        case WZ_FIREPILLAR:    /* ファイアピラー */
+        case WZ_SIGHTRASHER:
+        case WZ_QUAGMIRE:      /* クァグマイア */
+        case WZ_VERMILION:     /* ロードオブヴァーミリオン */
+        case WZ_FROSTNOVA:     /* フロストノヴァ */
+        case WZ_STORMGUST:     /* ストームガスト */
+        case WZ_HEAVENDRIVE:   /* ヘヴンズドライブ */
+        case PR_SANCTUARY:     /* サンクチュアリ */
+        case PR_MAGNUS:        /* マグヌスエクソシズム */
+        case CR_GRANDCROSS:    /* グランドクロス */
+        case HT_SKIDTRAP:      /* スキッドトラップ */
+        case HT_LANDMINE:      /* ランドマイン */
+        case HT_ANKLESNARE:    /* アンクルスネア */
+        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
+        case HT_SANDMAN:       /* サンドマン */
+        case HT_FLASHER:       /* フラッシャー */
+        case HT_FREEZINGTRAP:  /* フリージングトラップ */
+        case HT_BLASTMINE:     /* ブラストマイン */
+        case HT_CLAYMORETRAP:  /* クレイモアートラップ */
+        case AS_VENOMDUST:     /* ベノムダスト */
+        case AM_DEMONSTRATION: /* デモンストレーション */
+        case PF_SPIDERWEB:     /* スパイダーウェッブ */
+        case PF_FOGWALL:       /* フォグウォール */
+        case HT_TALKIEBOX:     /* トーキーボックス */
+            skill_unitsetting (src, skillid, skilllv, x, y, 0);
+            break;
+
+        case RG_GRAFFITI:      /* Graffiti [Valaris] */
+            skill_clear_unitgroup (src);
+            skill_unitsetting (src, skillid, skilllv, x, y, 0);
+            break;
+
+        case SA_VOLCANO:       /* ボルケーノ */
+        case SA_DELUGE:        /* デリュージ */
+        case SA_VIOLENTGALE:   /* バイオレントゲイル */
+        case SA_LANDPROTECTOR: /* ランドプロテクター */
+            skill_clear_element_field (src);    //既に自分が発動している属性場をクリア
+            skill_unitsetting (src, skillid, skilllv, x, y, 0);
+            break;
+
+        case WZ_METEOR:        //メテオストーム
+        {
+            int  flag = 0;
+            for (i = 0; i < 2 + (skilllv >> 1); i++)
+            {
+                int  j = 0, c;
+                do
+                {
+                    tmpx = x + (MRAND (7) - 3);
+                    tmpy = y + (MRAND (7) - 3);
+                    if (tmpx < 0)
+                        tmpx = 0;
+                    else if (tmpx >= map[src->m].xs)
+                        tmpx = map[src->m].xs - 1;
+                    if (tmpy < 0)
+                        tmpy = 0;
+                    else if (tmpy >= map[src->m].ys)
+                        tmpy = map[src->m].ys - 1;
+                    j++;
+                }
+                while (((c = map_getcell (src->m, tmpx, tmpy)) == 1 || c == 5)
+                       && j < 100);
+                if (j >= 100)
+                    continue;
+                if (flag == 0)
+                {
+                    clif_skill_poseffect (src, skillid, skilllv, tmpx, tmpy,
+                                          tick);
+                    flag = 1;
+                }
+                if (i > 0)
+                    skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy,
+                                         skillid, skilllv, (x1 << 16) | y1,
+                                         flag);
+                x1 = tmpx;
+                y1 = tmpy;
+            }
+            skill_addtimerskill (src, tick + i * 1000, 0, tmpx, tmpy, skillid,
+                                 skilllv, -1, flag);
+        }
+            break;
+
+        case AL_WARP:          /* ワープポータル */
+            if (sd)
+            {
+                if (map[sd->bl.m].flag.noteleport)  /* テレポ禁止 */
+                    break;
+                clif_skill_warppoint (sd, sd->skillid,
+                                      sd->status.save_point.map,
+                                      (sd->skilllv >
+                                       1) ? sd->status.memo_point[0].map : "",
+                                      (sd->skilllv >
+                                       2) ? sd->status.memo_point[1].map : "",
+                                      (sd->skilllv >
+                                       3) ? sd->status.
+                                      memo_point[2].map : "");
+            }
+            break;
+        case MO_BODYRELOCATION:
+            if (sd)
+            {
+                pc_movepos (sd, x, y);
+            }
+            else if (src->type == BL_MOB)
+                mob_warp ((struct mob_data *) src, -1, x, y, 0);
+            break;
+        case AM_CANNIBALIZE:   // バイオプラント
+            if (sd)
+            {
+                int  mx, my, id = 0;
+                struct mob_data *md;
+
+                mx = x;         // + (rand()%10 - 5);
+                my = y;         // + (rand()%10 - 5);
+                id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1118, 1,
+                                     "");
+                if ((md = (struct mob_data *) map_id2bl (id)) != NULL)
+                {
+                    md->master_id = sd->bl.id;
+                    md->hp = 2210 + skilllv * 200;
+                    md->state.special_mob_ai = 1;
+                    md->deletetimer =
+                        add_timer (gettick () +
+                                   skill_get_time (skillid, skilllv),
+                                   mob_timer_delete, id, 0);
+                }
+                clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
+            }
+            break;
+        case AM_SPHEREMINE:    // スフィアーマイン
+            if (sd)
+            {
+                int  mx, my, id = 0;
+                struct mob_data *md;
+
+                mx = x;         // + (rand()%10 - 5);
+                my = y;         // + (rand()%10 - 5);
+                id = mob_once_spawn (sd, "this", mx, my, "--ja--", 1142, 1,
+                                     "");
+                if ((md = (struct mob_data *) map_id2bl (id)) != NULL)
+                {
+                    md->master_id = sd->bl.id;
+                    md->hp = 1000 + skilllv * 200;
+                    md->state.special_mob_ai = 2;
+                    md->deletetimer =
+                        add_timer (gettick () +
+                                   skill_get_time (skillid, skilllv),
+                                   mob_timer_delete, id, 0);
+                }
+                clif_skill_poseffect (src, skillid, skilllv, x, y, tick);
+            }
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スキル使用(詠唱完了、map指定)
+ *------------------------------------------
+ */
+int skill_castend_map (struct map_session_data *sd, int skill_num,
+                       const char *map)
+{
+    int  x = 0, y = 0;
+
+    nullpo_retr (0, sd);
+    if (sd->bl.prev == NULL || pc_isdead (sd))
+        return 0;
+
+    if (sd->opt1 > 0 || sd->status.option & 2)
+        return 0;
+    //スキルが使えない状態異常中
+    if (sd->sc_data)
+    {
+        if (sd->sc_data[SC_DIVINA].timer != -1 ||
+            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
+            sd->sc_data[SC_AUTOCOUNTER].timer != -1 ||
+            sd->sc_data[SC_STEELBODY].timer != -1 ||
+            sd->sc_data[SC_DANCING].timer != -1 ||
+            sd->sc_data[SC_BERSERK].timer != -1)
+            return 0;
+    }
+
+    if (skill_num != sd->skillid)   /* 不正パケットらしい */
+        return 0;
+
+    pc_stopattack (sd);
+
+    if (battle_config.pc_skill_log)
+        printf ("PC %d skill castend skill =%d map=%s\n", sd->bl.id,
+                skill_num, map);
+    pc_stop_walking (sd, 0);
+
+    if (strcmp (map, "cancel") == 0)
+        return 0;
+
+    switch (skill_num)
+    {
+        case AL_TELEPORT:      /* テレポート */
+            if (strcmp (map, "Random") == 0)
+                pc_randomwarp (sd, 3);
+            else
+                pc_setpos (sd, sd->status.save_point.map,
+                           sd->status.save_point.x, sd->status.save_point.y,
+                           3);
+            break;
+
+        case AL_WARP:          /* ワープポータル */
+        {
+            const struct point *p[] = {
+                &sd->status.save_point, &sd->status.memo_point[0],
+                &sd->status.memo_point[1], &sd->status.memo_point[2],
+            };
+            struct skill_unit_group *group;
+            int  i;
+            int  maxcount = 0;
+
+            if ((maxcount = skill_get_maxcount (sd->skillid)) > 0)
+            {
+                int  c;
+                for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
+                {
+                    if (sd->skillunit[i].alive_count > 0
+                        && sd->skillunit[i].skill_id == sd->skillid)
+                        c++;
+                }
+                if (c >= maxcount)
+                {
+                    clif_skill_fail (sd, sd->skillid, 0, 0);
+                    sd->canact_tick = gettick ();
+                    sd->canmove_tick = gettick ();
+                    sd->skillitem = sd->skillitemlv = -1;
+                    return 0;
+                }
+            }
+
+            for (i = 0; i < sd->skilllv; i++)
+            {
+                if (strcmp (map, p[i]->map) == 0)
+                {
+                    x = p[i]->x;
+                    y = p[i]->y;
+                    break;
+                }
+            }
+            if (x == 0 || y == 0)   /* 不正パケット? */
+                return 0;
+
+            if (!skill_check_condition (sd, 3))
+                return 0;
+            if ((group =
+                 skill_unitsetting (&sd->bl, sd->skillid, sd->skilllv,
+                                    sd->skillx, sd->skilly, 0)) == NULL)
+                return 0;
+            CREATE (group->valstr, char, 24);
+            memcpy (group->valstr, map, 24);
+            group->val2 = (x << 16) | y;
+        }
+            break;
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット設定処理
+ *------------------------------------------
+ */
+struct skill_unit_group *skill_unitsetting (struct block_list *src,
+                                            int skillid, int skilllv, int x,
+                                            int y, int flag)
+{
+    struct skill_unit_group *group;
+    int  i, count = 1, limit = 10000, val1 = 0, val2 = 0;
+    int  target = BCT_ENEMY, interval = 1000, range = 0;
+    int  dir = 0, aoe_diameter = 0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills
+
+    nullpo_retr (0, src);
+
+    switch (skillid)
+    {                           /* 設定 */
+
+        case MG_SAFETYWALL:    /* セイフティウォール */
+            limit = skill_get_time (skillid, skilllv);
+            val2 = skilllv + 1;
+            interval = -1;
+            target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL;
+            break;
+
+        case MG_FIREWALL:      /* ファイヤーウォール */
+            if (src->x == x && src->y == y)
+                dir = 2;
+            else
+                dir = map_calc_dir (src, x, y);
+            if (dir & 1)
+                count = 5;
+            else
+                count = 3;
+            limit = skill_get_time (skillid, skilllv);
+            val2 = 4 + skilllv;
+            interval = 1;
+            break;
+
+        case AL_PNEUMA:        /* ニューマ */
+            limit = skill_get_time (skillid, skilllv);
+            interval = -1;
+            target = (battle_config.defnotenemy) ? BCT_NOENEMY : BCT_ALL;
+            count = 9;
+            break;
+
+        case AL_WARP:          /* ワープポータル */
+            target = BCT_ALL;
+            val1 = skilllv + 6;
+            if (flag == 0)
+                limit = 2000;
+            else
+                limit = skill_get_time (skillid, skilllv);
+            break;
+
+        case PR_SANCTUARY:     /* サンクチュアリ */
+            count = 21;
+            limit = skill_get_time (skillid, skilllv);
+            val1 = skilllv + 3;
+            val2 = (skilllv > 6) ? 777 : skilllv * 100;
+            target = BCT_ALL;
+            range = 1;
+            break;
+
+        case PR_MAGNUS:        /* マグヌスエクソシズム */
+            count = 33;
+            limit = skill_get_time (skillid, skilllv);
+            interval = 3000;
+            break;
+
+        case WZ_FIREPILLAR:    /* ファイアーピラー */
+            if (flag == 0)
+                limit = skill_get_time (skillid, skilllv);
+            else
+                limit = 1000;
+            interval = 2000;
+            val1 = skilllv + 2;
+            range = 1;
+            break;
+
+        case MG_THUNDERSTORM:  /* サンダーストーム */
+            limit = 500;
+            range = 1;
+            break;
+
+        case WZ_FROSTNOVA:     /* フロストノヴァ */
+            limit = 500;
+            range = 5;
+            break;
+        case WZ_HEAVENDRIVE:   /* ヘヴンズドライブ */
+            limit = 500;
+            range = 2;
+            break;
+
+        case WZ_METEOR:        /* メテオストーム */
+            limit = 500;
+            range = 3;
+            break;
+
+        case WZ_SIGHTRASHER:
+            limit = 500;
+            count = 41;
+            break;
+
+        case WZ_VERMILION:     /* ロードオブヴァーミリオン */
+            limit = 4100;
+            interval = 1000;
+            range = 6;
+            break;
+
+        case WZ_ICEWALL:       /* アイスウォール */
+            limit = skill_get_time (skillid, skilllv);
+            count = 5;
+            break;
+
+        case WZ_STORMGUST:     /* ストームガスト */
+            limit = 4600;
+            interval = 450;
+            range = 5;
+            break;
+
+        case WZ_QUAGMIRE:      /* クァグマイア */
+            limit = skill_get_time (skillid, skilllv);
+            interval = 200;
+            count = 25;
+            break;
+
+        case HT_SKIDTRAP:      /* スキッドトラップ */
+        case HT_LANDMINE:      /* ランドマイン */
+        case HT_ANKLESNARE:    /* アンクルスネア */
+        case HT_SANDMAN:       /* サンドマン */
+        case PF_SPIDERWEB:     /* スパイダーウェッブ */
+        case HT_FLASHER:       /* フラッシャー */
+        case HT_FREEZINGTRAP:  /* フリージングトラップ */
+        case HT_BLASTMINE:     /* ブラストマイン */
+        case HT_CLAYMORETRAP:  /* クレイモアートラップ */
+            limit = skill_get_time (skillid, skilllv);
+            range = 1;
+            break;
+
+        case HT_TALKIEBOX:     /* トーキーボックス */
+            limit = skill_get_time (skillid, skilllv);
+            range = 1;
+            target = BCT_ALL;
+            break;
+
+        case HT_SHOCKWAVE:     /* ショックウェーブトラップ */
+            limit = skill_get_time (skillid, skilllv);
+            range = 1;
+            val1 = skilllv * 15 + 10;
+            break;
+
+        case AS_VENOMDUST:     /* ベノムダスト */
+            limit = skill_get_time (skillid, skilllv);
+            interval = 1000;
+            count = 5;
+            break;
+
+        case CR_GRANDCROSS:    /* グランドクロス */
+            count = 29;
+            limit = 1000;
+            interval = 300;
+            break;
+
+        case SA_VOLCANO:       /* ボルケーノ */
+        case SA_DELUGE:        /* デリュージ */
+        case SA_VIOLENTGALE:   /* バイオレントゲイル */
+            limit = skill_get_time (skillid, skilllv);
+            count = skilllv <= 2 ? 25 : (skilllv <= 4 ? 49 : 81);
+            target = BCT_ALL;
+            break;
+
+        case SA_LANDPROTECTOR: /* グランドクロス */
+            limit = skill_get_time (skillid, skilllv);  // changed to get duration from cast_db (moonsoul)
+            val1 = skilllv * 15 + 10;
+            aoe_diameter = skilllv + skilllv % 2 + 5;
+            target = BCT_ALL;
+            count = aoe_diameter * aoe_diameter;    // -- this will not function if changed to ^2 (moonsoul)
+            break;
+
+        case BD_LULLABY:       /* 子守唄 */
+        case BD_ETERNALCHAOS:  /* エターナルカオス */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+            count = 81;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_ALL;
+            break;
+        case BD_RICHMANKIM:
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+            count = 81;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_PARTY;
+            break;
+
+        case BA_WHISTLE:       /* 口笛 */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      BA_MUSICALLESSON) + 1) >> 1;
+            val2 = ((battle_get_agi (src) / 10) & 0xffff) << 16;
+            val2 |= (battle_get_luk (src) / 10) & 0xffff;
+            break;
+        case DC_HUMMING:       /* ハミング */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      DC_DANCINGLESSON) + 1) >> 1;
+            val2 = battle_get_dex (src) / 10;
+            break;
+
+        case BA_DISSONANCE:    /* 不協和音 */
+        case DC_UGLYDANCE:     /* 自分勝手なダンス */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_ENEMY;
+            break;
+
+        case DC_DONTFORGETME:  /* 私を忘れないで… */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_ENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      DC_DANCINGLESSON) + 1) >> 1;
+            val2 = ((battle_get_str (src) / 20) & 0xffff) << 16;
+            val2 |= (battle_get_agi (src) / 10) & 0xffff;
+            break;
+        case BA_POEMBRAGI:     /* ブラギの詩 */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    pc_checkskill ((struct map_session_data *) src,
+                                   BA_MUSICALLESSON);
+            val2 = ((battle_get_dex (src) / 10) & 0xffff) << 16;
+            val2 |= (battle_get_int (src) / 5) & 0xffff;
+            break;
+        case BA_APPLEIDUN:     /* イドゥンの林檎 */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    ((pc_checkskill
+                      ((struct map_session_data *) src,
+                       BA_MUSICALLESSON)) & 0xffff) << 16;
+            else
+                val1 = 0;
+            val1 |= (battle_get_vit (src)) & 0xffff;
+            val2 = 0;           //回復用タイムカウンタ(6秒毎に1増加)
+            break;
+        case DC_SERVICEFORYOU: /* サービスフォーユー */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_PARTY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      DC_DANCINGLESSON) + 1) >> 1;
+            val2 = battle_get_int (src) / 10;
+            break;
+        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      BA_MUSICALLESSON) + 1) >> 1;
+            val2 = battle_get_agi (src) / 20;
+            break;
+        case DC_FORTUNEKISS:   /* 幸運のキス */
+            count = 49;
+            limit = skill_get_time (skillid, skilllv);
+            range = 5;
+            target = BCT_NOENEMY;
+            if (src->type == BL_PC)
+                val1 =
+                    (pc_checkskill
+                     ((struct map_session_data *) src,
+                      DC_DANCINGLESSON) + 1) >> 1;
+            val2 = battle_get_luk (src) / 10;
+            break;
+        case AM_DEMONSTRATION: /* デモンストレーション */
+            limit = skill_get_time (skillid, skilllv);
+            interval = 1000;
+            range = 1;
+            target = BCT_ENEMY;
+            break;
+        case WE_CALLPARTNER:   /* あなたに逢いたい */
+            limit = skill_get_time (skillid, skilllv);
+            range = -1;
+            break;
+
+        case HP_BASILICA:      /* バジリカ */
+            limit = skill_get_time (skillid, skilllv);
+            target = BCT_ALL;
+            range = 3;
+            //Fix to prevent the priest from walking while Basilica is up.
+            battle_stopwalking (src, 1);
+            skill_status_change_start (src, SC_ANKLE, skilllv, 0, 0, 0, limit,
+                                       0);
+            break;
+        case PA_GOSPEL:        /* ゴスペル */
+            count = 49;
+            target = BCT_PARTY;
+            limit = skill_get_time (skillid, skilllv);
+            break;
+        case PF_FOGWALL:       /* フォグウォール */
+            count = 15;
+            limit = skill_get_time (skillid, skilllv);
+            break;
+        case RG_GRAFFITI:      /* Graffiti */
+            count = 1;          // Leave this at 1 [Valaris]
+            limit = 600000;     // Time length [Valaris]
+            break;
+    };
+
+    nullpo_retr (NULL, group =
+                 skill_initunitgroup (src, count, skillid, skilllv,
+                                      skill_get_unit_id (skillid, flag & 1)));
+    group->limit = limit;
+    group->val1 = val1;
+    group->val2 = val2;
+    group->target_flag = target;
+    group->interval = interval;
+    group->range = range;
+    if (skillid == HT_TALKIEBOX || skillid == RG_GRAFFITI)
+    {
+        CREATE (group->valstr, char, 80);
+        memcpy (group->valstr, talkie_mes, 80);
+    }
+    for (i = 0; i < count; i++)
+    {
+        struct skill_unit *unit;
+        int  ux = x, uy = y, val1 = skilllv, val2 = 0, limit =
+            group->limit, alive = 1;
+        int  range = group->range;
+        switch (skillid)
+        {                       /* 設定 */
+            case AL_PNEUMA:    /* ニューマ */
+            {
+                static const int dx[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
+                static const int dy[9] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+            case MG_FIREWALL:  /* ファイヤーウォール */
+            {
+                if (dir & 1)
+                {               /* 斜め配置 */
+                    static const int dx[][5] = {
+                        {1, 1, 0, 0, -1}, {-1, -1, 0, 0, 1},
+                    }, dy[][5] =
+                    {
+                        {
+                        1, 0, 0, -1, -1},
+                        {
+                    1, 0, 0, -1, -1},};
+                    ux += dx[(dir >> 1) & 1][i];
+                    uy += dy[(dir >> 1) & 1][i];
+                }
+                else
+                {               /* 上下配置 */
+                    if (dir % 4 == 0)   /* 上下 */
+                        ux += i - 1;
+                    else        /* 左右 */
+                        uy += i - 1;
+                }
+                val2 = group->val2;
+            }
+                break;
+
+            case PR_SANCTUARY: /* サンクチュアリ */
+            {
+                static const int dx[] = {
+                    -1, 0, 1, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1,
+                    2, -1, 0, 1
+                };
+                static const int dy[] = {
+                    -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+                    1, 2, 2, 2,
+                };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+
+            case PR_MAGNUS:    /* マグヌスエクソシズム */
+            {
+                static const int dx[] =
+                    { -1, 0, 1, -1, 0, 1, -3, -2, -1, 0, 1, 2, 3,
+                    -3, -2, -1, 0, 1, 2, 3, -3, -2, -1, 0, 1, 2, 3, -1, 0, 1,
+                    -1, 0, 1,
+                };
+                static const int dy[] = {
+                    -3, -3, -3, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1,
+                    0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3
+                };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+
+            case WZ_SIGHTRASHER:
+            {
+                static const int dx[] = {
+                    -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5, -4,
+                    -3, -2, -1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3,
+                    0, 3, -4, 0, 4, -5, 0, 5
+                };
+                static const int dy[] = {
+                    -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1,
+                    -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2,
+                    3, 3, 3, 4, 4, 4, 5, 5, 5
+                };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+
+            case WZ_ICEWALL:   /* アイスウォール */
+            {
+                static const int dirx[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
+                static const int diry[8] = { 1, 1, 0, -1, -1, -1, 0, 1 };
+                if (skilllv <= 1)
+                    val1 = 500;
+                else
+                    val1 = 200 + 200 * skilllv;
+                if (src->x == x && src->y == y)
+                    dir = 2;
+                else
+                    dir = map_calc_dir (src, x, y);
+                ux += (2 - i) * diry[dir];
+                uy += (i - 2) * dirx[dir];
+            }
+                break;
+
+            case WZ_QUAGMIRE:  /* クァグマイア */
+                ux += (i % 5 - 2);
+                uy += (i / 5 - 2);
+                if (i == 12)
+                    range = 2;
+                else
+                    range = -1;
+
+                break;
+
+            case AS_VENOMDUST: /* ベノムダスト */
+            {
+                static const int dx[] = { -1, 0, 0, 0, 1 };
+                static const int dy[] = { 0, -1, 0, 1, 0 };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+
+            case CR_GRANDCROSS:    /* グランドクロス */
+            {
+                static const int dx[] = {
+                    0, 0, -1, 0, 1, -2, -1, 0, 1, 2, -4, -3, -2, -1, 0, 1, 2,
+                    3, 4, -2, -1, 0, 1, 2, -1, 0, 1, 0, 0,
+                };
+                static const int dy[] = {
+                    -4, -3, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0,
+                    0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4,
+                };
+                ux += dx[i];
+                uy += dy[i];
+            }
+                break;
+            case SA_VOLCANO:   /* ボルケーノ */
+            case SA_DELUGE:    /* デリュージ */
+            case SA_VIOLENTGALE:   /* バイオレントゲイル */
+            {
+                int  u_range = 0, central = 0;
+                if (skilllv <= 2)
+                {
+                    u_range = 2;
+                    central = 12;
+                }
+                else if (skilllv <= 4)
+                {
+                    u_range = 3;
+                    central = 24;
+                }
+                else if (skilllv >= 5)
+                {
+                    u_range = 4;
+                    central = 40;
+                }
+                ux += (i % (u_range * 2 + 1) - u_range);
+                uy += (i / (u_range * 2 + 1) - u_range);
+
+                if (i == central)
+                    range = u_range;    //中央のユニットの効果範囲は全範囲
+                else
+                    range = -1; //中央以外のユニットは飾り
+            }
+                break;
+            case SA_LANDPROTECTOR: /* ランドプロテクター */
+            {
+                int  u_range = 0;
+
+                if (skilllv <= 2)
+                    u_range = 3;
+                else if (skilllv <= 4)
+                    u_range = 4;
+                else if (skilllv >= 5)
+                    u_range = 5;
+
+                ux += (i % (u_range * 2 + 1) - u_range);
+                uy += (i / (u_range * 2 + 1) - u_range);
+
+                range = 0;
+            }
+                break;
+
+                /* ダンスなど */
+            case BD_LULLABY:   /* 子守歌 */
+            case BD_RICHMANKIM:    /* ニヨルドの宴 */
+            case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+            case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+            case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+            case BD_ROKISWEIL: /* ロキの叫び */
+            case BD_INTOABYSS: /* 深淵の中に */
+            case BD_SIEGFRIED: /* 不死身のジークフリード */
+                ux += (i % 9 - 4);
+                uy += (i / 9 - 4);
+                if (i == 40)
+                    range = 4;  /* 中心の場合は範囲を4にオーバーライド */
+                else
+                    range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */
+                break;
+            case BA_DISSONANCE:    /* 不協和音 */
+            case BA_WHISTLE:   /* 口笛 */
+            case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
+            case BA_POEMBRAGI: /* ブラギの詩 */
+            case BA_APPLEIDUN: /* イドゥンの林檎 */
+            case DC_UGLYDANCE: /* 自分勝手なダンス */
+            case DC_HUMMING:   /* ハミング */
+            case DC_DONTFORGETME:  /* 私を忘れないで… */
+            case DC_FORTUNEKISS:   /* 幸運のキス */
+            case DC_SERVICEFORYOU: /* サービスフォーユー */
+                ux += (i % 7 - 3);
+                uy += (i / 7 - 3);
+                if (i == 40)
+                    range = 4;  /* 中心の場合は範囲を4にオーバーライド */
+                else
+                    range = -1; /* 中心じゃない場合は範囲を-1にオーバーライド */
+                break;
+            case PA_GOSPEL:    /* ゴスペル */
+                ux += (i % 7 - 3);
+                uy += (i / 7 - 3);
+                break;
+            case PF_FOGWALL:   /* フォグウォール */
+                ux += (i % 5 - 2);
+                uy += (i / 5 - 1);
+                break;
+            case RG_GRAFFITI:  /* Graffiti [Valaris] */
+                ux += (i % 5 - 2);
+                uy += (i / 5 - 2);
+                break;
+        }
+        //直上スキルの場合設置座標上にランドプロテクターがないかチェック
+        if (range <= 0)
+            map_foreachinarea (skill_landprotector, src->m, ux, uy, ux, uy,
+                               BL_SKILL, skillid, &alive);
+
+        if (skillid == WZ_ICEWALL && alive)
+        {
+            val2 = map_getcell (src->m, ux, uy);
+            if (val2 == 5 || val2 == 1)
+                alive = 0;
+            else
+            {
+                map_setcell (src->m, ux, uy, 5);
+                clif_changemapcell (src->m, ux, uy, 5, 0);
+            }
+        }
+
+        if (alive)
+        {
+            nullpo_retr (NULL, unit = skill_initunit (group, i, ux, uy));
+            unit->val1 = val1;
+            unit->val2 = val2;
+            unit->limit = limit;
+            unit->range = range;
+        }
+    }
+    return group;
+}
+
+/*==========================================
+ * スキルユニットの発動イベント
+ *------------------------------------------
+ */
+int skill_unit_onplace (struct skill_unit *src, struct block_list *bl,
+                        unsigned int tick)
+{
+    struct skill_unit_group *sg;
+    struct block_list *ss;
+    struct skill_unit_group_tickset *ts;
+    struct map_session_data *srcsd = NULL;
+    int  diff, goflag, splash_count = 0;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, bl);
+
+    if (bl->prev == NULL || !src->alive
+        || (bl->type == BL_PC && pc_isdead ((struct map_session_data *) bl)))
+        return 0;
+
+    nullpo_retr (0, sg = src->group);
+    nullpo_retr (0, ss = map_id2bl (sg->src_id));
+
+    if (ss->type == BL_PC)
+        nullpo_retr (0, srcsd = (struct map_session_data *) ss);
+    if (srcsd && srcsd->chatID)
+        return 0;
+
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+        return 0;
+    nullpo_retr (0, ts = skill_unitgrouptickset_search (bl, sg->group_id));
+    diff = DIFF_TICK (tick, ts->tick);
+    goflag = (diff > sg->interval || diff < 0);
+    if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit)  // 重なっていたら3HITしない
+        goflag = (diff > sg->interval * map_count_oncell (bl->m, bl->x, bl->y)
+                  || diff < 0);
+
+    //対象がLP上に居る場合は無効
+    map_foreachinarea (skill_landprotector, bl->m, bl->x, bl->y, bl->x, bl->y,
+                       BL_SKILL, 0, &goflag);
+
+    if (!goflag)
+        return 0;
+    ts->tick = tick;
+    ts->group_id = sg->group_id;
+
+    switch (sg->unit_id)
+    {
+        case 0x83:             /* サンクチュアリ */
+        {
+            int  race = battle_get_race (bl);
+            int  damage_flag =
+                (battle_check_undead (race, battle_get_elem_type (bl))
+                 || race == 6) ? 1 : 0;
+
+            if (battle_get_hp (bl) >= battle_get_max_hp (bl) && !damage_flag)
+                break;
+
+            if ((sg->val1--) <= 0)
+            {
+                skill_delunitgroup (sg);
+                return 0;
+            }
+            if (!damage_flag)
+            {
+                int  heal = sg->val2;
+                if (bl->type == BL_PC
+                    && ((struct map_session_data *) bl)->
+                    special_state.no_magic_damage)
+                    heal = 0;   /* 黄金蟲カード(ヒール量0) */
+                clif_skill_nodamage (&src->bl, bl, AL_HEAL, heal, 1);
+                battle_heal (NULL, bl, heal, 0, 0);
+            }
+            else
+                skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
+                              sg->skill_lv, tick, 0);
+        }
+            break;
+
+        case 0x84:             /* マグヌスエクソシズム */
+        {
+            int  race = battle_get_race (bl);
+            int  damage_flag =
+                (battle_check_undead (race, battle_get_elem_type (bl))
+                 || race == 6) ? 1 : 0;
+
+            if (!damage_flag)
+                return 0;
+            skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
+                          sg->skill_lv, tick, 0);
+        }
+            break;
+
+        case 0x85:             /* ニューマ */
+        {
+            struct skill_unit *unit2;
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SC_PNEUMA;
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
+                                           0, 0, 0, 0);
+            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
+                     && unit2 != src)
+            {
+                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
+                    skill_status_change_start (bl, type, sg->skill_lv,
+                                               (int) src, 0, 0, 0, 0);
+                ts->tick -= sg->interval;
+            }
+        }
+            break;
+        case 0x7e:             /* セイフティウォール */
+        {
+            struct skill_unit *unit2;
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SC_SAFETYWALL;
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
+                                           0, 0, 0, 0);
+            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
+                     && unit2 != src)
+            {
+                if (sg->val1 < unit2->group->val1)
+                    skill_status_change_start (bl, type, sg->skill_lv,
+                                               (int) src, 0, 0, 0, 0);
+                ts->tick -= sg->interval;
+            }
+        }
+            break;
+
+        case 0x86:             /* ロードオブヴァーミリオン(&ストームガスト &グランドクロス) */
+            skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
+                          sg->skill_lv, tick, 0);
+            break;
+
+        case 0x7f:             /* ファイヤーウォール */
+            if ((src->val2--) > 0)
+                skill_attack (BF_MAGIC, ss, &src->bl, bl,
+                              sg->skill_id, sg->skill_lv, tick, 0);
+            if (src->val2 <= 0)
+                skill_delunit (src);
+            break;
+
+        case 0x87:             /* ファイアーピラー(発動前) */
+            skill_delunit (src);
+            skill_unitsetting (ss, sg->skill_id, sg->skill_lv, src->bl.x,
+                               src->bl.y, 1);
+            break;
+
+        case 0x88:             /* ファイアーピラー(発動後) */
+            if (DIFF_TICK (tick, sg->tick) < 150)
+                skill_attack (BF_MAGIC, ss, &src->bl, bl, sg->skill_id,
+                              sg->skill_lv, tick, 0);
+            break;
+
+        case 0x90:             /* スキッドトラップ */
+        {
+            int  i, c = skill_get_blewcount (sg->skill_id, sg->skill_lv);
+            if (map[bl->m].flag.gvg)
+                c = 0;
+            for (i = 0; i < c; i++)
+                skill_blown (&src->bl, bl, 1 | 0x30000);
+            sg->unit_id = 0x8c;
+            clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
+        }
+            break;
+
+        case 0x93:             /* ランドマイン */
+            skill_attack (BF_MISC, ss, &src->bl, bl, sg->skill_id,
+                          sg->skill_lv, tick, 0);
+            sg->unit_id = 0x8c;
+            clif_changelook (&src->bl, LOOK_BASE, 0x88);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
+            break;
+
+        case 0x8f:             /* ブラストマイン */
+        case 0x94:             /* ショックウェーブトラップ */
+        case 0x95:             /* サンドマン */
+        case 0x96:             /* フラッシャー */
+        case 0x97:             /* フリージングトラップ */
+        case 0x98:             /* クレイモアートラップ */
+            map_foreachinarea (skill_count_target, src->bl.m,
+                               src->bl.x - src->range, src->bl.y - src->range,
+                               src->bl.x + src->range, src->bl.y + src->range,
+                               0, &src->bl, &splash_count);
+            map_foreachinarea (skill_trap_splash, src->bl.m,
+                               src->bl.x - src->range, src->bl.y - src->range,
+                               src->bl.x + src->range, src->bl.y + src->range,
+                               0, &src->bl, tick, splash_count);
+            sg->unit_id = 0x8c;
+            clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1500;
+            break;
+
+        case 0x91:             /* アンクルスネア */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            if (sg->val2 == 0 && sc_data && sc_data[SC_ANKLE].timer == -1)
+            {
+                int  moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE
+                                  || bl->y / BLOCK_SIZE !=
+                                  src->bl.y / BLOCK_SIZE);
+                int  sec = skill_get_time2 (sg->skill_id,
+                                            sg->skill_lv) -
+                    (double) battle_get_agi (bl) * 0.1;
+                if (battle_get_mode (bl) & 0x20)
+                    sec = sec / 5;
+                battle_stopwalking (bl, 1);
+                skill_status_change_start (bl, SC_ANKLE, sg->skill_lv, 0, 0,
+                                           0, sec, 0);
+
+                if (moveblock)
+                    map_delblock (bl);
+                bl->x = src->bl.x;
+                bl->y = src->bl.y;
+                if (moveblock)
+                    map_addblock (bl);
+                if (bl->type == BL_MOB)
+                    clif_fixmobpos ((struct mob_data *) bl);
+                else
+                    clif_fixpos (bl);
+                clif_01ac (&src->bl);
+                sg->limit = DIFF_TICK (tick, sg->tick) + sec;
+                sg->val2 = bl->id;
+            }
+        }
+            break;
+
+        case 0x80:             /* ワープポータル(発動後) */
+            if (bl->type == BL_PC)
+            {
+                struct map_session_data *sd = (struct map_session_data *) bl;
+                if (sd && src->bl.m == bl->m && src->bl.x == bl->x
+                    && src->bl.y == bl->y && src->bl.x == sd->to_x
+                    && src->bl.y == sd->to_y)
+                {
+                    if (battle_config.chat_warpportal || !sd->chatID)
+                    {
+                        if ((sg->val1--) > 0)
+                        {
+                            pc_setpos (sd, sg->valstr, sg->val2 >> 16,
+                                       sg->val2 & 0xffff, 3);
+                            if (sg->src_id == bl->id
+                                || (strcmp (map[src->bl.m].name, sg->valstr)
+                                    == 0 && src->bl.x == (sg->val2 >> 16)
+                                    && src->bl.y == (sg->val2 & 0xffff)))
+                                skill_delunitgroup (sg);
+                        }
+                        else
+                            skill_delunitgroup (sg);
+                    }
+                }
+            }
+            else if (bl->type == BL_MOB && battle_config.mob_warpportal)
+            {
+                int  m = map_mapname2mapid (sg->valstr);
+                struct mob_data *md;
+                md = (struct mob_data *) bl;
+                mob_warp ((struct mob_data *) bl, m, sg->val2 >> 16,
+                          sg->val2 & 0xffff, 3);
+            }
+            break;
+
+        case 0x8e:             /* クァグマイア */
+        {
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (bl->type == BL_PC
+                && ((struct map_session_data *) bl)->
+                special_state.no_magic_damage)
+                break;
+            if (battle_get_sc_data (bl)[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
+                                           0, 0,
+                                           skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv), 0);
+        }
+            break;
+        case 0x92:             /* ベノムダスト */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
+                                           0, 0,
+                                           skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv), 0);
+        }
+            break;
+        case 0x9a:             /* ボルケーノ */
+        case 0x9b:             /* デリュージ */
+        case 0x9c:             /* バイオレントゲイル */
+        {
+            struct skill_unit *unit2;
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, (int) src,
+                                           0, 0,
+                                           skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv), 0);
+            else if ((unit2 = (struct skill_unit *) sc_data[type].val2)
+                     && unit2 != src)
+            {
+                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
+                    skill_status_change_start (bl, type, sg->skill_lv,
+                                               (int) src, 0, 0,
+                                               skill_get_time2 (sg->skill_id,
+                                                                sg->skill_lv),
+                                               0);
+                ts->tick -= sg->interval;
+            }
+        } break;
+
+        case 0x9e:             /* 子守唄 */
+        case 0x9f:             /* ニヨルドの宴 */
+        case 0xa0:             /* 永遠の混沌 */
+        case 0xa1:             /* 戦太鼓の響き */
+        case 0xa2:             /* ニーベルングの指輪 */
+        case 0xa3:             /* ロキの叫び */
+        case 0xa4:             /* 深淵の中に */
+        case 0xa5:             /* 不死身のジークフリード */
+        case 0xa6:             /* 不協和音 */
+        case 0xa7:             /* 口笛 */
+        case 0xa8:             /* 夕陽のアサシンクロス */
+        case 0xa9:             /* ブラギの詩 */
+        case 0xab:             /* 自分勝手なダンス */
+        case 0xac:             /* ハミング */
+        case 0xad:             /* 私を忘れないで… */
+        case 0xae:             /* 幸運のキス */
+        case 0xaf:             /* サービスフォーユー */
+        case 0xb4:
+        {
+            struct skill_unit *unit2;
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sg->src_id == bl->id)
+                break;
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv, sg->val1,
+                                           sg->val2, (int) src,
+                                           skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv), 0);
+            else if ((unit2 = (struct skill_unit *) sc_data[type].val4)
+                     && unit2 != src)
+            {
+                if (unit2->group
+                    && DIFF_TICK (sg->tick, unit2->group->tick) > 0)
+                    skill_status_change_start (bl, type, sg->skill_lv,
+                                               sg->val1, sg->val2, (int) src,
+                                               skill_get_time2 (sg->skill_id,
+                                                                sg->skill_lv),
+                                               0);
+                ts->tick -= sg->interval;
+            }
+        } break;
+
+        case 0xaa:             /* イドゥンの林檎 */
+        {
+            struct skill_unit *unit2;
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sg->src_id == bl->id)
+                break;
+            if (sc_data && sc_data[type].timer == -1)
+                skill_status_change_start (bl, type, sg->skill_lv,
+                                           (sg->val1) >> 16,
+                                           (sg->val1) & 0xffff, (int) src,
+                                           skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv), 0);
+            else if ((unit2 = (struct skill_unit *) sc_data[type].val4)
+                     && unit2 != src)
+            {
+                if (DIFF_TICK (sg->tick, unit2->group->tick) > 0)
+                    skill_status_change_start (bl, type, sg->skill_lv,
+                                               (sg->val1) >> 16,
+                                               (sg->val1) & 0xffff, (int) src,
+                                               skill_get_time2 (sg->skill_id,
+                                                                sg->skill_lv),
+                                               0);
+                ts->tick -= sg->interval;
+            }
+        } break;
+
+        case 0xb1:             /* デモンストレーション */
+            skill_attack (BF_WEAPON, ss, &src->bl, bl, sg->skill_id,
+                          sg->skill_lv, tick, 0);
+            if (bl->type == BL_PC && MRAND (100) < sg->skill_lv
+                && battle_config.equipment_breaking)
+                pc_breakweapon ((struct map_session_data *) bl);
+            break;
+        case 0x99:             /* トーキーボックス */
+            if (sg->src_id == bl->id)   //自分が踏んでも発動しない
+                break;
+            if (sg->val2 == 0)
+            {
+                clif_talkiebox (&src->bl, sg->valstr);
+                sg->unit_id = 0x8c;
+                clif_changelook (&src->bl, LOOK_BASE, sg->unit_id);
+                sg->limit = DIFF_TICK (tick, sg->tick) + 5000;
+                sg->val2 = -1;  //踏んだ
+            }
+            break;
+        case 0xb2:             /* あなたを_会いたいです */
+        case 0xb3:             /* ゴスペル */
+        case 0xb6:             /* フォグウォール */
+            //とりあえず何もしない
+            break;
+
+        case 0xb7:             /* スパイダーウェッブ */
+            if (sg->val2 == 0)
+            {
+                int  moveblock = (bl->x / BLOCK_SIZE != src->bl.x / BLOCK_SIZE
+                                  || bl->y / BLOCK_SIZE !=
+                                  src->bl.y / BLOCK_SIZE);
+                skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv,
+                                         BF_MISC, tick);
+                if (moveblock)
+                    map_delblock (bl);
+                bl->x = (&src->bl)->x;
+                bl->y = (&src->bl)->y;
+                if (moveblock)
+                    map_addblock (bl);
+                if (bl->type == BL_MOB)
+                    clif_fixmobpos ((struct mob_data *) bl);
+                else
+                    clif_fixpos (bl);
+                clif_01ac (&src->bl);
+                sg->limit =
+                    DIFF_TICK (tick,
+                               sg->tick) + skill_get_time2 (sg->skill_id,
+                                                            sg->skill_lv);
+                sg->val2 = bl->id;
+            }
+            break;
+
+/*	default:
+		if(battle_config.error_log)
+			printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
+		break;*/
+    }
+    if (bl->type == BL_MOB && ss != bl) /* スキル使用条件のMOBスキル */
+    {
+        if (battle_config.mob_changetarget_byskill == 1)
+        {
+            int  target = ((struct mob_data *) bl)->target_id;
+            if (ss->type == BL_PC)
+                ((struct mob_data *) bl)->target_id = ss->id;
+            mobskill_use ((struct mob_data *) bl, tick,
+                          MSC_SKILLUSED | (sg->skill_id << 16));
+            ((struct mob_data *) bl)->target_id = target;
+        }
+        else
+            mobskill_use ((struct mob_data *) bl, tick,
+                          MSC_SKILLUSED | (sg->skill_id << 16));
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットから離脱する(もしくはしている)場合
+ *------------------------------------------
+ */
+int skill_unit_onout (struct skill_unit *src, struct block_list *bl,
+                      unsigned int tick)
+{
+    struct skill_unit_group *sg;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, bl);
+    nullpo_retr (0, sg = src->group);
+
+    if (bl->prev == NULL || !src->alive)
+        return 0;
+
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+        return 0;
+
+    switch (sg->unit_id)
+    {
+        case 0x7e:             /* セイフティウォール */
+        case 0x85:             /* ニューマ */
+        case 0x8e:             /* クァグマイア */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            int  type =
+                (sg->unit_id == 0x85) ? SC_PNEUMA :
+                ((sg->unit_id == 0x7e) ? SC_SAFETYWALL : SC_QUAGMIRE);
+            if ((type != SC_QUAGMIRE || bl->type != BL_MOB) &&
+                sc_data && sc_data[type].timer != -1
+                && ((struct skill_unit *) sc_data[type].val2) == src)
+            {
+                skill_status_change_end (bl, type, -1);
+            }
+        } break;
+
+        case 0x91:             /* アンクルスネア */
+        {
+            struct block_list *target = map_id2bl (sg->val2);
+            if (target && target == bl)
+            {
+                skill_status_change_end (bl, SC_ANKLE, -1);
+                sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
+            }
+        }
+            break;
+        case 0xb5:
+        case 0xb8:
+        {
+            struct block_list *target = map_id2bl (sg->val2);
+            if (target == bl)
+                skill_status_change_end (bl, SC_SPIDERWEB, -1);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
+        }
+            break;
+        case 0xb6:
+        {
+            struct block_list *target = map_id2bl (sg->val2);
+            if (target == bl)
+                skill_status_change_end (bl, SC_FOGWALL, -1);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
+        }
+            break;
+        case 0x9a:             /* ボルケーノ */
+        case 0x9b:             /* デリュージ */
+        case 0x9c:             /* バイオレントゲイル */
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            struct skill_unit *su;
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sc_data && sc_data[type].timer != -1
+                && (su = ((struct skill_unit *) sc_data[type].val2))
+                && su == src)
+            {
+                skill_status_change_end (bl, type, -1);
+            }
+        }
+            break;
+
+        case 0x9e:             /* 子守唄 */
+        case 0x9f:             /* ニヨルドの宴 */
+        case 0xa0:             /* 永遠の混沌 */
+        case 0xa1:             /* 戦太鼓の響き */
+        case 0xa2:             /* ニーベルングの指輪 */
+        case 0xa3:             /* ロキの叫び */
+        case 0xa4:             /* 深淵の中に */
+        case 0xa5:             /* 不死身のジークフリード */
+        case 0xa6:             /* 不協和音 */
+        case 0xa7:             /* 口笛 */
+        case 0xa8:             /* 夕陽のアサシンクロス */
+        case 0xa9:             /* ブラギの詩 */
+        case 0xaa:             /* イドゥンの林檎 */
+        case 0xab:             /* 自分勝手なダンス */
+        case 0xac:             /* ハミング */
+        case 0xad:             /* 私を忘れないで… */
+        case 0xae:             /* 幸運のキス */
+        case 0xaf:             /* サービスフォーユー */
+        case 0xb4:
+        {
+            struct status_change *sc_data = battle_get_sc_data (bl);
+            struct skill_unit *su;
+            int  type = SkillStatusChangeTable[sg->skill_id];
+            if (sc_data && sc_data[type].timer != -1
+                && (su = ((struct skill_unit *) sc_data[type].val4))
+                && su == src)
+            {
+                skill_status_change_end (bl, type, -1);
+            }
+        }
+            break;
+        case 0xb7:             /* スパイダーウェッブ */
+        {
+            struct block_list *target = map_id2bl (sg->val2);
+            if (target && target == bl)
+                skill_status_change_end (bl, SC_SPIDERWEB, -1);
+            sg->limit = DIFF_TICK (tick, sg->tick) + 1000;
+        }
+            break;
+
+/*	default:
+		if(battle_config.error_log)
+			printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
+		break;*/
+    }
+    skill_unitgrouptickset_delete (bl, sg->group_id);
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットの削除イベント
+ *------------------------------------------
+ */
+int skill_unit_ondelete (struct skill_unit *src, struct block_list *bl,
+                         unsigned int tick)
+{
+    struct skill_unit_group *sg;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, bl);
+    nullpo_retr (0, sg = src->group);
+
+    if (bl->prev == NULL || !src->alive)
+        return 0;
+
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+        return 0;
+
+    switch (sg->unit_id)
+    {
+        case 0x85:             /* ニューマ */
+        case 0x7e:             /* セイフティウォール */
+        case 0x8e:             /* クァグマイヤ */
+        case 0x9a:             /* ボルケーノ */
+        case 0x9b:             /* デリュージ */
+        case 0x9c:             /* バイオレントゲイル */
+        case 0x9e:             /* 子守唄 */
+        case 0x9f:             /* ニヨルドの宴 */
+        case 0xa0:             /* 永遠の混沌 */
+        case 0xa1:             /* 戦太鼓の響き */
+        case 0xa2:             /* ニーベルングの指輪 */
+        case 0xa3:             /* ロキの叫び */
+        case 0xa4:             /* 深淵の中に */
+        case 0xa5:             /* 不死身のジークフリード */
+        case 0xa6:             /* 不協和音 */
+        case 0xa7:             /* 口笛 */
+        case 0xa8:             /* 夕陽のアサシンクロス */
+        case 0xa9:             /* ブラギの詩 */
+        case 0xaa:             /* イドゥンの林檎 */
+        case 0xab:             /* 自分勝手なダンス */
+        case 0xac:             /* ハミング */
+        case 0xad:             /* 私を忘れないで… */
+        case 0xae:             /* 幸運のキス */
+        case 0xaf:             /* サービスフォーユー */
+        case 0xb4:
+            return skill_unit_onout (src, bl, tick);
+
+/*	default:
+		if(battle_config.error_log)
+			printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id);
+		break;*/
+    }
+    skill_unitgrouptickset_delete (bl, sg->group_id);
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットの限界イベント
+ *------------------------------------------
+ */
+int skill_unit_onlimit (struct skill_unit *src, unsigned int tick)
+{
+    struct skill_unit_group *sg;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, sg = src->group);
+
+    switch (sg->unit_id)
+    {
+        case 0x81:             /* ワープポータル(発動前) */
+        {
+            struct skill_unit_group *group =
+                skill_unitsetting (map_id2bl (sg->src_id), sg->skill_id,
+                                   sg->skill_lv,
+                                   src->bl.x, src->bl.y, 1);
+            if (group == NULL)
+                return 0;
+            CREATE (group->valstr, char, 24);
+            memcpy (group->valstr, sg->valstr, 24);
+            group->val2 = sg->val2;
+        }
+            break;
+
+        case 0x8d:             /* アイスウォール */
+            map_setcell (src->bl.m, src->bl.x, src->bl.y, src->val2);
+            clif_changemapcell (src->bl.m, src->bl.x, src->bl.y, src->val2,
+                                1);
+            break;
+        case 0xb2:             /* あなたに会いたい */
+        {
+            struct map_session_data *sd = NULL;
+            struct map_session_data *p_sd = NULL;
+            if ((sd =
+                 (struct map_session_data *) (map_id2bl (sg->src_id))) ==
+                NULL)
+                return 0;
+            if ((p_sd = pc_get_partner (sd)) == NULL)
+                return 0;
+
+            pc_setpos (p_sd, map[src->bl.m].name, src->bl.x, src->bl.y, 3);
+        }
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットのダメージイベント
+ *------------------------------------------
+ */
+int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl,
+                          int damage, unsigned int tick)
+{
+    struct skill_unit_group *sg;
+
+    nullpo_retr (0, src);
+    nullpo_retr (0, sg = src->group);
+
+    switch (sg->unit_id)
+    {
+        case 0x8d:             /* アイスウォール */
+            src->val1 -= damage;
+            break;
+        case 0x8f:             /* ブラストマイン */
+        case 0x98:             /* クレイモアートラップ */
+            skill_blown (bl, &src->bl, 2);  //吹き飛ばしてみる
+            break;
+        default:
+            damage = 0;
+            break;
+    }
+    return damage;
+}
+
+/*---------------------------------------------------------------------------- */
+
+/*==========================================
+ * スキル使用(詠唱完了、場所指定)
+ *------------------------------------------
+ */
+void skill_castend_pos (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    struct map_session_data *sd = map_id2sd (id) /*,*target_sd=NULL */ ;
+    int  range, maxcount;
+
+    nullpo_retv (sd);
+
+    if (sd->bl.prev == NULL)
+        return;
+    if (sd->skilltimer != tid)  /* タイマIDの確認 */
+        return;
+    if (sd->skilltimer != -1 && pc_checkskill (sd, SA_FREECAST) > 0)
+    {
+        sd->speed = sd->prev_speed;
+        clif_updatestatus (sd, SP_SPEED);
+    }
+    sd->skilltimer = -1;
+    if (pc_isdead (sd))
+    {
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+
+    if (battle_config.pc_skill_reiteration == 0)
+    {
+        range = -1;
+        switch (sd->skillid)
+        {
+            case MG_SAFETYWALL:
+            case WZ_FIREPILLAR:
+            case HT_SKIDTRAP:
+            case HT_LANDMINE:
+            case HT_ANKLESNARE:
+            case HT_SHOCKWAVE:
+            case HT_SANDMAN:
+            case HT_FLASHER:
+            case HT_FREEZINGTRAP:
+            case HT_BLASTMINE:
+            case HT_CLAYMORETRAP:
+            case HT_TALKIEBOX:
+            case AL_WARP:
+            case PF_SPIDERWEB: /* スパイダーウェッブ */
+            case RG_GRAFFITI:  /* グラフィティ */
+                range = 0;
+                break;
+            case AL_PNEUMA:
+                range = 1;
+                break;
+        }
+        if (range >= 0)
+        {
+            if (skill_check_unit_range
+                (sd->bl.m, sd->skillx, sd->skilly, range, sd->skillid) > 0)
+            {
+                clif_skill_fail (sd, sd->skillid, 0, 0);
+                sd->canact_tick = tick;
+                sd->canmove_tick = tick;
+                sd->skillitem = sd->skillitemlv = -1;
+                return;
+            }
+        }
+    }
+    if (battle_config.pc_skill_nofootset)
+    {
+        range = -1;
+        switch (sd->skillid)
+        {
+            case WZ_FIREPILLAR:
+            case HT_SKIDTRAP:
+            case HT_LANDMINE:
+            case HT_ANKLESNARE:
+            case HT_SHOCKWAVE:
+            case HT_SANDMAN:
+            case HT_FLASHER:
+            case HT_FREEZINGTRAP:
+            case HT_BLASTMINE:
+            case HT_CLAYMORETRAP:
+            case HT_TALKIEBOX:
+            case PF_SPIDERWEB: /* スパイダーウェッブ */
+            case WZ_ICEWALL:
+                range = 1;
+                break;
+            case AL_WARP:
+                range = 0;
+                break;
+        }
+        if (range >= 0)
+        {
+            if (skill_check_unit_range2
+                (sd->bl.m, sd->skillx, sd->skilly, range) > 0)
+            {
+                clif_skill_fail (sd, sd->skillid, 0, 0);
+                sd->canact_tick = tick;
+                sd->canmove_tick = tick;
+                sd->skillitem = sd->skillitemlv = -1;
+                return;
+            }
+        }
+    }
+
+    if (battle_config.pc_land_skill_limit)
+    {
+        maxcount = skill_get_maxcount (sd->skillid);
+        if (maxcount > 0)
+        {
+            int  i, c;
+            for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
+            {
+                if (sd->skillunit[i].alive_count > 0
+                    && sd->skillunit[i].skill_id == sd->skillid)
+                    c++;
+            }
+            if (c >= maxcount)
+            {
+                clif_skill_fail (sd, sd->skillid, 0, 0);
+                sd->canact_tick = tick;
+                sd->canmove_tick = tick;
+                sd->skillitem = sd->skillitemlv = -1;
+                return;
+            }
+        }
+    }
+
+    range = skill_get_range (sd->skillid, sd->skilllv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    range += battle_config.pc_skill_add_range;
+    if (battle_config.skill_out_range_consume)
+    {                           // changed to allow casting when target walks out of range [Valaris]
+        if (range < distance (sd->bl.x, sd->bl.y, sd->skillx, sd->skilly))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            sd->skillitem = sd->skillitemlv = -1;
+            return;
+        }
+    }
+    if (!skill_check_condition (sd, 1))
+    {                           /* 使用条件チェック */
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        sd->skillitem = sd->skillitemlv = -1;
+        return;
+    }
+    sd->skillitem = sd->skillitemlv = -1;
+    if (battle_config.skill_out_range_consume)
+    {
+        if (range < distance (sd->bl.x, sd->bl.y, sd->skillx, sd->skilly))
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            sd->canact_tick = tick;
+            sd->canmove_tick = tick;
+            return;
+        }
+    }
+
+    if (battle_config.pc_skill_log)
+        printf ("PC %d skill castend skill=%d\n", sd->bl.id, sd->skillid);
+    pc_stop_walking (sd, 0);
+
+    skill_castend_pos2 (&sd->bl, sd->skillx, sd->skilly, sd->skillid,
+                        sd->skilllv, tick, 0);
+}
+
+/*==========================================
+ * 範囲内キャラ存在確認判定処理(foreachinarea)
+ *------------------------------------------
+ */
+
+static int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
+{
+    int *c;
+    struct block_list *src;
+    struct map_session_data *sd;
+    struct map_session_data *ssd;
+    struct pc_base_job s_class;
+    struct pc_base_job ss_class;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = (struct map_session_data *) bl);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    nullpo_retr (0, c = va_arg (ap, int *));
+    nullpo_retr (0, ssd = (struct map_session_data *) src);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+    //チェックしない設定ならcにありえない大きな数字を返して終了
+    if (!battle_config.player_skill_partner_check)
+    {                           //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
+        (*c) = 99;
+        return 0;
+    }
+
+    ;
+    ss_class = pc_calc_base_job (ssd->status.pc_class);
+
+    switch (ssd->skillid)
+    {
+        case PR_BENEDICTIO:    /* 聖体降福 */
+            if (sd != ssd
+                && (sd->status.pc_class == 4 || sd->status.pc_class == 8
+                    || sd->status.pc_class == 15 || sd->status.pc_class == 4005
+                    || sd->status.pc_class == 4009 || sd->status.pc_class == 4016)
+                && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1)
+                && sd->status.sp >= 10)
+                (*c)++;
+            break;
+        case BD_LULLABY:       /* 子守歌 */
+        case BD_RICHMANKIM:    /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+        case BD_RAGNAROK:      /* 神々の黄昏 */
+        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
+            if (sd != ssd &&
+                ((ssd->status.pc_class == 19 && sd->status.pc_class == 20) ||
+                 (ssd->status.pc_class == 20 && sd->status.pc_class == 19) ||
+                 (ssd->status.pc_class == 4020 && sd->status.pc_class == 4021) ||
+                 (ssd->status.pc_class == 4021 && sd->status.pc_class == 4020) ||
+                 (ssd->status.pc_class == 20 && sd->status.pc_class == 4020) ||
+                 (ssd->status.pc_class == 19 && sd->status.pc_class == 4021)) &&
+                pc_checkskill (sd, ssd->skillid) > 0 &&
+                (*c) == 0 &&
+                sd->status.party_id == ssd->status.party_id &&
+                !pc_issit (sd) && sd->sc_data[SC_DANCING].timer == -1)
+                (*c) = pc_checkskill (sd, ssd->skillid);
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 範囲内キャラ存在確認判定後スキル使用処理(foreachinarea)
+ *------------------------------------------
+ */
+
+static int skill_check_condition_use_sub (struct block_list *bl, va_list ap)
+{
+    int *c;
+    struct block_list *src;
+    struct map_session_data *sd;
+    struct map_session_data *ssd;
+    struct pc_base_job s_class;
+    struct pc_base_job ss_class;
+    int  skillid, skilllv;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, sd = (struct map_session_data *) bl);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    nullpo_retr (0, c = va_arg (ap, int *));
+    nullpo_retr (0, ssd = (struct map_session_data *) src);
+
+    s_class = pc_calc_base_job (sd->status.pc_class);
+
+    //チェックしない設定ならcにありえない大きな数字を返して終了
+    if (!battle_config.player_skill_partner_check)
+    {                           //本当はforeachの前にやりたいけど設定適用箇所をまとめるためにここへ
+        (*c) = 99;
+        return 0;
+    }
+
+    ss_class = pc_calc_base_job (ssd->status.pc_class);
+    skillid = ssd->skillid;
+    skilllv = ssd->skilllv;
+    switch (skillid)
+    {
+        case PR_BENEDICTIO:    /* 聖体降福 */
+            if (sd != ssd
+                && (sd->status.pc_class == 4 || sd->status.pc_class == 8
+                    || sd->status.pc_class == 15 || sd->status.pc_class == 4005
+                    || sd->status.pc_class == 4009 || sd->status.pc_class == 4016)
+                && (sd->bl.x == ssd->bl.x - 1 || sd->bl.x == ssd->bl.x + 1)
+                && sd->status.sp >= 10)
+            {
+                sd->status.sp -= 10;
+                pc_calcstatus (sd, 0);
+                (*c)++;
+            }
+            break;
+        case BD_LULLABY:       /* 子守歌 */
+        case BD_RICHMANKIM:    /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+        case BD_RAGNAROK:      /* 神々の黄昏 */
+        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
+            if (sd != ssd &&    //本人以外で
+                ((ssd->status.pc_class == 19 && sd->status.pc_class == 20) ||
+                (ssd->status.pc_class == 20 && sd->status.pc_class == 19) ||
+                (ssd->status.pc_class == 4020 && sd->status.pc_class == 4021) ||
+                (ssd->status.pc_class == 4021 && sd->status.pc_class == 4020) ||
+                (ssd->status.pc_class == 20 && sd->status.pc_class == 4020) ||
+                (ssd->status.pc_class == 19 && sd->status.pc_class == 4021)) && //自分がダンサーならバードで
+                pc_checkskill (sd, skillid) > 0 &&  //スキルを持っていて
+                (*c) == 0 &&    //最初の一人で
+                sd->status.party_id == ssd->status.party_id &&  //パーティーが同じで
+                !pc_issit (sd) &&   //座ってない
+                sd->sc_data[SC_DANCING].timer == -1 //ダンス中じゃない
+                )
+            {
+                ssd->sc_data[SC_DANCING].val4 = bl->id;
+                clif_skill_nodamage (bl, src, skillid, skilllv, 1);
+                skill_status_change_start (bl, SC_DANCING, skillid,
+                                           ssd->sc_data[SC_DANCING].val2, 0,
+                                           src->id, skill_get_time (skillid,
+                                                                    skilllv) +
+                                           1000, 0);
+                sd->skillid_dance = sd->skillid = skillid;
+                sd->skilllv_dance = sd->skilllv = skilllv;
+                (*c)++;
+            }
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 範囲内バイオプラント、スフィアマイン用Mob存在確認判定処理(foreachinarea)
+ *------------------------------------------
+ */
+
+static int skill_check_condition_mob_master_sub (struct block_list *bl,
+                                                 va_list ap)
+{
+    int *c, src_id = 0, mob_class = 0;
+    struct mob_data *md;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, md = (struct mob_data *) bl);
+
+    if (!(src_id = va_arg (ap, int)))
+        return 0;
+    if (!(mob_class = va_arg (ap, int)))
+        return 0;
+    nullpo_retr (0, c = va_arg (ap, int *));
+
+    if (md->mob_class == mob_class && md->master_id == src_id)
+        (*c)++;
+    return 0;
+}
+
+/*==========================================
+ * スキル使用条件(偽で使用失敗)
+ *------------------------------------------
+ */
+int skill_check_condition (struct map_session_data *sd, int type)
+{
+    int  i, hp, sp, hp_rate, sp_rate, zeny, weapon, state, spiritball, skill,
+        lv, mhp;
+    int  index[10], itemid[10], amount[10];
+
+    nullpo_retr (0, sd);
+
+    if (battle_config.gm_skilluncond > 0
+        && pc_isGM (sd) >= battle_config.gm_skilluncond)
+    {
+        sd->skillitem = sd->skillitemlv = -1;
+        return 1;
+    }
+
+    if (sd->opt1 > 0)
+    {
+        clif_skill_fail (sd, sd->skillid, 0, 0);
+        sd->skillitem = sd->skillitemlv = -1;
+        return 0;
+    }
+    if (pc_is90overweight (sd))
+    {
+        clif_skill_fail (sd, sd->skillid, 9, 0);
+        sd->skillitem = sd->skillitemlv = -1;
+        return 0;
+    }
+
+    if (sd->skillid == AC_MAKINGARROW && sd->state.make_arrow_flag == 1)
+    {
+        sd->skillitem = sd->skillitemlv = -1;
+        return 0;
+    }
+    /*if(sd->skillid == AM_PHARMACY &&  sd->state.produce_flag == 1) {
+     * sd->skillitem = sd->skillitemlv = -1;
+     * return 0;
+     * } */
+
+    if (sd->skillitem == sd->skillid)
+    {                           /* アイテムの場合無条件成功 */
+        if (type & 1)
+            sd->skillitem = sd->skillitemlv = -1;
+        return 1;
+    }
+    if (sd->opt1 > 0)
+    {
+        clif_skill_fail (sd, sd->skillid, 0, 0);
+        return 0;
+    }
+    if (sd->sc_data)
+    {
+        if (sd->sc_data[SC_DIVINA].timer != -1 ||
+            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
+            (sd->sc_data[SC_AUTOCOUNTER].timer != -1
+             && sd->skillid != KN_AUTOCOUNTER)
+            || sd->sc_data[SC_STEELBODY].timer != -1
+            || sd->sc_data[SC_BERSERK].timer != -1)
+        {
+            clif_skill_fail (sd, sd->skillid, 0, 0);
+            return 0;           /* 状態異常や沈黙など */
+        }
+    }
+    skill = sd->skillid;
+    lv = sd->skilllv;
+    hp = skill_get_hp (skill, lv);  /* 消費HP */
+    sp = skill_get_sp (skill, lv);  /* 消費SP */
+    if ((sd->skillid_old == BD_ENCORE) && skill == sd->skillid_dance)
+        sp = sp / 2;            //アンコール時はSP消費が半分
+    hp_rate = (lv <= 0) ? 0 : skill_db[skill].hp_rate[lv - 1];
+    sp_rate = (lv <= 0) ? 0 : skill_db[skill].sp_rate[lv - 1];
+    zeny = skill_get_zeny (skill, lv);
+    weapon = skill_db[skill].weapon;
+    state = skill_db[skill].state;
+    spiritball = (lv <= 0) ? 0 : skill_db[skill].spiritball[lv - 1];
+    mhp = skill_get_mhp (skill, lv);    /* 消費HP */
+    for (i = 0; i < 10; i++)
+    {
+        itemid[i] = skill_db[skill].itemid[i];
+        amount[i] = skill_db[skill].amount[i];
+    }
+    if (mhp > 0)
+        hp += (sd->status.max_hp * mhp) / 100;
+    if (hp_rate > 0)
+        hp += (sd->status.hp * hp_rate) / 100;
+    else
+        hp += (sd->status.max_hp * abs (hp_rate)) / 100;
+    if (sp_rate > 0)
+        sp += (sd->status.sp * sp_rate) / 100;
+    else
+        sp += (sd->status.max_sp * abs (sp_rate)) / 100;
+    if (sd->dsprate != 100)
+        sp = sp * sd->dsprate / 100;    /* 消費SP修正 */
+
+    switch (skill)
+    {
+        case SA_CASTCANCEL:
+            if (sd->skilltimer == -1)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case BS_MAXIMIZE:      /* マキシマイズパワー */
+        case NV_TRICKDEAD:     /* 死んだふり */
+        case TF_HIDING:        /* ハイディング */
+        case AS_CLOAKING:      /* クローキング */
+        case CR_AUTOGUARD:     /* オートガード */
+        case CR_DEFENDER:      /* ディフェンダー */
+        case ST_CHASEWALK:
+            if (sd->sc_data[SkillStatusChangeTable[skill]].timer != -1)
+                return 1;       /* 解除する場合はSP消費しない */
+            break;
+        case AL_TELEPORT:
+        case AL_WARP:
+            if (map[sd->bl.m].flag.noteleport)
+            {
+                clif_skill_teleportmessage (sd, 0);
+                return 0;
+            }
+            break;
+        case MO_CALLSPIRITS:   /* 気功 */
+            if (sd->spiritball >= lv)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case CH_SOULCOLLECT:   /* 狂気功 */
+            if (sd->spiritball >= 5)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case MO_FINGEROFFENSIVE:   //指弾
+            if (sd->spiritball > 0 && sd->spiritball < spiritball)
+            {
+                spiritball = sd->spiritball;
+                sd->spiritball_old = sd->spiritball;
+            }
+            else
+                sd->spiritball_old = lv;
+            break;
+        case MO_CHAINCOMBO:    //連打掌
+            if (sd->sc_data[SC_BLADESTOP].timer == -1)
+            {
+                if (sd->sc_data[SC_COMBO].timer == -1
+                    || sd->sc_data[SC_COMBO].val1 != MO_TRIPLEATTACK)
+                    return 0;
+            }
+            break;
+        case MO_COMBOFINISH:   //猛龍拳
+            if (sd->sc_data[SC_COMBO].timer == -1
+                || sd->sc_data[SC_COMBO].val1 != MO_CHAINCOMBO)
+                return 0;
+            break;
+        case CH_TIGERFIST:     //伏虎拳
+            if (sd->sc_data[SC_COMBO].timer == -1
+                || sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH)
+                return 0;
+            break;
+        case CH_CHAINCRUSH:    //連柱崩撃
+            if (sd->sc_data[SC_COMBO].timer == -1)
+                return 0;
+            if (sd->sc_data[SC_COMBO].val1 != MO_COMBOFINISH
+                && sd->sc_data[SC_COMBO].val1 != CH_TIGERFIST)
+                return 0;
+            break;
+        case MO_EXTREMITYFIST: // 阿修羅覇鳳拳
+            if ((sd->sc_data[SC_COMBO].timer != -1
+                 && (sd->sc_data[SC_COMBO].val1 == MO_COMBOFINISH
+                     || sd->sc_data[SC_COMBO].val1 == CH_CHAINCRUSH))
+                || sd->sc_data[SC_BLADESTOP].timer != -1)
+                spiritball--;
+            break;
+        case BD_ADAPTATION:    /* アドリブ */
+        {
+            struct skill_unit_group *group = NULL;
+            if (sd->sc_data[SC_DANCING].timer == -1
+                ||
+                ((group =
+                  (struct skill_unit_group *) sd->sc_data[SC_DANCING].val2)
+                 &&
+                 (skill_get_time
+                  (sd->sc_data[SC_DANCING].val1,
+                   group->skill_lv) - sd->sc_data[SC_DANCING].val3 * 1000) <=
+                 skill_get_time2 (skill, lv)))
+            {                   //ダンス中で使用後5秒以上のみ?
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+        }
+            break;
+        case PR_BENEDICTIO:    /* 聖体降福 */
+        {
+            int  range = 1;
+            int  c = 0;
+            if (!(type & 1))
+            {
+                map_foreachinarea (skill_check_condition_char_sub, sd->bl.m,
+                                   sd->bl.x - range, sd->bl.y - range,
+                                   sd->bl.x + range, sd->bl.y + range, BL_PC,
+                                   &sd->bl, &c);
+                if (c < 2)
+                {
+                    clif_skill_fail (sd, skill, 0, 0);
+                    return 0;
+                }
+            }
+            else
+            {
+                map_foreachinarea (skill_check_condition_use_sub, sd->bl.m,
+                                   sd->bl.x - range, sd->bl.y - range,
+                                   sd->bl.x + range, sd->bl.y + range, BL_PC,
+                                   &sd->bl, &c);
+            }
+        }
+            break;
+        case WE_CALLPARTNER:   /* あなたに逢いたい */
+            if (!sd->status.partner_id)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case AM_CANNIBALIZE:   /* バイオプラント */
+        case AM_SPHEREMINE:    /* スフィアーマイン */
+            if (type & 1)
+            {
+                int  c = 0;
+                int  maxcount = skill_get_maxcount (skill);
+                int  mob_class = (skill == AM_CANNIBALIZE) ? 1118 : 1142;
+                if (battle_config.pc_land_skill_limit && maxcount > 0)
+                {
+                    map_foreachinarea (skill_check_condition_mob_master_sub,
+                                       sd->bl.m, 0, 0, map[sd->bl.m].xs,
+                                       map[sd->bl.m].ys, BL_MOB, sd->bl.id,
+                                       mob_class, &c);
+                    if (c >= maxcount)
+                    {
+                        clif_skill_fail (sd, skill, 0, 0);
+                        return 0;
+                    }
+                }
+            }
+            break;
+        case MG_FIREWALL:      /* ファイアーウォール */
+            /* 数制限 */
+            if (battle_config.pc_land_skill_limit)
+            {
+                int  maxcount = skill_get_maxcount (skill);
+                if (maxcount > 0)
+                {
+                    int  i, c;
+                    for (i = c = 0; i < MAX_SKILLUNITGROUP; i++)
+                    {
+                        if (sd->skillunit[i].alive_count > 0
+                            && sd->skillunit[i].skill_id == skill)
+                            c++;
+                    }
+                    if (c >= maxcount)
+                    {
+                        clif_skill_fail (sd, skill, 0, 0);
+                        return 0;
+                    }
+                }
+            }
+            break;
+    }
+
+    if (!(type & 2))
+    {
+        if (hp > 0 && sd->status.hp < hp)
+        {                       /* HPチェック */
+            clif_skill_fail (sd, skill, 2, 0);  /* HP不足:失敗通知 */
+            return 0;
+        }
+        if (sp > 0 && sd->status.sp < sp)
+        {                       /* SPチェック */
+            clif_skill_fail (sd, skill, 1, 0);  /* SP不足:失敗通知 */
+            return 0;
+        }
+        if (zeny > 0 && sd->status.zeny < zeny)
+        {
+            clif_skill_fail (sd, skill, 5, 0);
+            return 0;
+        }
+        if (!(weapon & (1 << sd->status.weapon)))
+        {
+            clif_skill_fail (sd, skill, 6, 0);
+            return 0;
+        }
+        if (spiritball > 0 && sd->spiritball < spiritball)
+        {
+            clif_skill_fail (sd, skill, 0, 0);  // 氣球不足
+            return 0;
+        }
+    }
+
+    switch (state)
+    {
+        case ST_HIDING:
+            if (!(sd->status.option & 2))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_CLOAKING:
+            if (!(sd->status.option & 4))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_HIDDEN:
+            if (!pc_ishiding (sd))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_RIDING:
+            if (!pc_isriding (sd))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_FALCON:
+            if (!pc_isfalcon (sd))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_CART:
+            if (!pc_iscarton (sd))
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_SHIELD:
+            if (sd->status.shield <= 0)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_SIGHT:
+            if (sd->sc_data[SC_SIGHT].timer == -1 && type & 1)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_EXPLOSIONSPIRITS:
+            if (sd->sc_data[SC_EXPLOSIONSPIRITS].timer == -1)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_RECOV_WEIGHT_RATE:
+            if (battle_config.natural_heal_weight_rate <= 100
+                && sd->weight * 100 / sd->max_weight >=
+                battle_config.natural_heal_weight_rate)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+        case ST_MOVE_ENABLE:
+        {
+            struct walkpath_data wpd;
+            if (path_search
+                (&wpd, sd->bl.m, sd->bl.x, sd->bl.y, sd->skillx, sd->skilly,
+                 1) == -1)
+            {
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+        }
+            break;
+        case ST_WATER:
+            if (map_getcell (sd->bl.m, sd->bl.x, sd->bl.y) != 3
+                && (sd->sc_data[SC_DELUGE].timer == -1))
+            {                   //水場判定
+                clif_skill_fail (sd, skill, 0, 0);
+                return 0;
+            }
+            break;
+    }
+
+    for (i = 0; i < 10; i++)
+    {
+        int  x = lv % 11 - 1;
+        index[i] = -1;
+        if (itemid[i] <= 0)
+            continue;
+        if (itemid[i] >= 715 && itemid[i] <= 717
+            && sd->special_state.no_gemstone)
+            continue;
+        if (((itemid[i] >= 715 && itemid[i] <= 717) || itemid[i] == 1065)
+            && sd->sc_data[SC_INTOABYSS].timer != -1)
+            continue;
+        if (skill == AM_POTIONPITCHER && i != x)
+            continue;
+
+        index[i] = pc_search_inventory (sd, itemid[i]);
+        if (index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i])
+        {
+            if (itemid[i] == 716 || itemid[i] == 717)
+                clif_skill_fail (sd, skill, (7 + (itemid[i] - 716)), 0);
+            else
+                clif_skill_fail (sd, skill, 0, 0);
+            return 0;
+        }
+    }
+
+    if (!(type & 1))
+        return 1;
+
+    if (skill != AM_POTIONPITCHER)
+    {
+        if (skill == AL_WARP && !(type & 2))
+            return 1;
+        for (i = 0; i < 10; i++)
+        {
+            if (index[i] >= 0)
+                pc_delitem (sd, index[i], amount[i], 0);    // アイテム消費
+        }
+    }
+
+    if (type & 2)
+        return 1;
+
+    pc_heal (sd, -sp, -hp);     // [Fate] This might suppress some dupe messages
+
+/* 	if(sp > 0) {					// SP消費 */
+/* 		sd->status.sp-=sp; */
+/* 		clif_updatestatus(sd,SP_SP); */
+/* 	} */
+/* 	if(hp > 0) {					// HP消費 */
+/* 		sd->status.hp-=hp; */
+/* 		clif_updatestatus(sd,SP_HP); */
+/* 	} */
+    if (zeny > 0)               // Zeny消費
+        pc_payzeny (sd, zeny);
+    if (spiritball > 0)         // 氣球消費
+        pc_delspiritball (sd, spiritball, 0);
+
+    return 1;
+}
+
+/*==========================================
+ * 詠唱時間計算
+ *------------------------------------------
+ */
+int skill_castfix (struct block_list *bl, int time)
+{
+    struct map_session_data *sd;
+    struct mob_data *md;        // [Valaris]
+    struct status_change *sc_data;
+    int  dex;
+    int  castrate = 100;
+    int  skill, lv, castnodex;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_MOB)
+    {                           // Crash fix [Valaris]
+        md = (struct mob_data *) bl;
+        skill = md->skillid;
+        lv = md->skilllv;
+    }
+
+    else
+    {
+        sd = (struct map_session_data *) bl;
+        skill = sd->skillid;
+        lv = sd->skilllv;
+    }
+
+    sc_data = battle_get_sc_data (bl);
+    dex = battle_get_dex (bl);
+
+    if (skill > MAX_SKILL_DB || skill < 0)
+        return 0;
+
+    castnodex = skill_get_castnodex (skill, lv);
+
+    if (time == 0)
+        return 0;
+    if (castnodex > 0 && bl->type == BL_PC)
+        castrate = ((struct map_session_data *) bl)->castrate;
+    else if (castnodex <= 0 && bl->type == BL_PC)
+    {
+        castrate = ((struct map_session_data *) bl)->castrate;
+        time =
+            time * castrate * (battle_config.castrate_dex_scale -
+                               dex) / (battle_config.castrate_dex_scale *
+                                       100);
+        time = time * battle_config.cast_rate / 100;
+    }
+
+    /* サフラギウム */
+    if (sc_data && sc_data[SC_SUFFRAGIUM].timer != -1)
+    {
+        time = time * (100 - sc_data[SC_SUFFRAGIUM].val1 * 15) / 100;
+        skill_status_change_end (bl, SC_SUFFRAGIUM, -1);
+    }
+    /* ブラギの詩 */
+    if (sc_data && sc_data[SC_POEMBRAGI].timer != -1)
+        time =
+            time * (100 -
+                    (sc_data[SC_POEMBRAGI].val1 * 3 +
+                     sc_data[SC_POEMBRAGI].val2 +
+                     (sc_data[SC_POEMBRAGI].val3 >> 16))) / 100;
+
+    return (time > 0) ? time : 0;
+}
+
+/*==========================================
+ * ディレイ計算
+ *------------------------------------------
+ */
+int skill_delayfix (struct block_list *bl, int time)
+{
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+
+    sc_data = battle_get_sc_data (bl);
+    if (time <= 0)
+        return 0;
+
+    if (bl->type == BL_PC)
+    {
+        if (battle_config.delay_dependon_dex)   /* dexの影響を計算する */
+            time =
+                time * (battle_config.castrate_dex_scale -
+                        battle_get_dex (bl)) /
+                battle_config.castrate_dex_scale;
+        time = time * battle_config.delay_rate / 100;
+    }
+
+    /* ブラギの詩 */
+    if (sc_data && sc_data[SC_POEMBRAGI].timer != -1)
+        time =
+            time * (100 -
+                    (sc_data[SC_POEMBRAGI].val1 * 3 +
+                     sc_data[SC_POEMBRAGI].val2 +
+                     (sc_data[SC_POEMBRAGI].val3 & 0xffff))) / 100;
+
+    return (time > 0) ? time : 0;
+}
+
+/*==========================================
+ * スキル使用(ID指定)
+ *------------------------------------------
+ */
+int skill_use_id (struct map_session_data *sd, int target_id,
+                  int skill_num, int skill_lv)
+{
+    unsigned int tick;
+    int  casttime = 0, delay = 0, skill, range;
+    struct map_session_data *target_sd = NULL;
+    int  forcecast = 0;
+    struct block_list *bl;
+    struct status_change *sc_data;
+    tick = gettick ();
+
+    nullpo_retr (0, sd);
+
+    if ((bl = map_id2bl (target_id)) == NULL)
+    {
+/*		if(battle_config.error_log)
+			printf("skill target not found %d\n",target_id); */
+        return 0;
+    }
+    if (sd->bl.m != bl->m || pc_isdead (sd))
+        return 0;
+
+    if (skillnotok (skill_num, sd)) // [MouseJstr]
+        return 0;
+
+    if (sd->skillid == WZ_ICEWALL && map[sd->bl.m].flag.noicewall
+        && !map[sd->bl.m].flag.pvp)
+    {                           // noicewall flag [Valaris]
+        clif_skill_fail (sd, sd->skillid, 0, 0);
+        return 0;
+    }
+    sc_data = sd->sc_data;
+
+    /* 沈黙や異常(ただし、グリムなどの判定をする) */
+    if (sd->opt1 > 0)
+        return 0;
+    if (sd->sc_data)
+    {
+        if (sc_data[SC_CHASEWALK].timer != -1)
+            return 0;
+        if (sc_data[SC_VOLCANO].timer != -1)
+        {
+            if (skill_num == WZ_ICEWALL)
+                return 0;
+        }
+        if (sc_data[SC_ROKISWEIL].timer != -1)
+        {
+            if (skill_num == BD_ADAPTATION)
+                return 0;
+        }
+        if (sd->sc_data[SC_DIVINA].timer != -1 ||
+            sd->sc_data[SC_ROKISWEIL].timer != -1 ||
+            (sd->sc_data[SC_AUTOCOUNTER].timer != -1
+             && sd->skillid != KN_AUTOCOUNTER)
+            || sd->sc_data[SC_STEELBODY].timer != -1
+            || sd->sc_data[SC_BERSERK].timer != -1)
+        {
+            return 0;           /* 状態異常や沈黙など */
+        }
+
+        if (sc_data[SC_BLADESTOP].timer != -1)
+        {
+            int  lv = sc_data[SC_BLADESTOP].val1;
+            if (sc_data[SC_BLADESTOP].val2 == 1)
+                return 0;       //白羽された側なのでダメ
+            if (lv == 1)
+                return 0;
+            if (lv == 2 && skill_num != MO_FINGEROFFENSIVE)
+                return 0;
+            if (lv == 3 && skill_num != MO_FINGEROFFENSIVE
+                && skill_num != MO_INVESTIGATE)
+                return 0;
+            if (lv == 4 && skill_num != MO_FINGEROFFENSIVE
+                && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO)
+                return 0;
+            if (lv == 5 && skill_num != MO_FINGEROFFENSIVE
+                && skill_num != MO_INVESTIGATE && skill_num != MO_CHAINCOMBO
+                && skill_num != MO_EXTREMITYFIST)
+                return 0;
+        }
+    }
+
+    if (sd->status.option & 4 && skill_num == TF_HIDING)
+        return 0;
+    if (sd->status.option & 2 && skill_num != TF_HIDING
+        && skill_num != AS_GRIMTOOTH && skill_num != RG_BACKSTAP
+        && skill_num != RG_RAID)
+        return 0;
+
+    if (map[sd->bl.m].flag.gvg)
+    {                           //GvGで使用できないスキル
+        switch (skill_num)
+        {
+            case SM_ENDURE:
+            case AL_TELEPORT:
+            case AL_WARP:
+            case WZ_ICEWALL:
+            case TF_BACKSLIDING:
+            case LK_BERSERK:
+            case HP_BASILICA:
+            case ST_CHASEWALK:
+                return 0;
+        }
+    }
+
+    /* 演奏/ダンス中 */
+    if (sc_data && sc_data[SC_DANCING].timer != -1)
+    {
+//      if(battle_config.pc_skill_log)
+//          printf("dancing! %d\n",skill_num);
+        if (sc_data[SC_DANCING].val4 && skill_num != BD_ADAPTATION) //合奏中はアドリブ以外不可
+            return 0;
+        if (skill_num != BD_ADAPTATION && skill_num != BA_MUSICALSTRIKE
+            && skill_num != DC_THROWARROW)
+        {
+            return 0;
+        }
+    }
+
+    if (skill_get_inf2 (skill_num) & 0x200 && sd->bl.id == target_id)
+        return 0;
+    //直前のスキルが何か覚える必要のあるスキル
+    switch (skill_num)
+    {
+        case SA_CASTCANCEL:
+            if (sd->skillid != skill_num)
+            {                   //キャストキャンセル自体は覚えない
+                sd->skillid_old = sd->skillid;
+                sd->skilllv_old = sd->skilllv;
+                break;
+            }
+        case BD_ENCORE:        /* アンコール */
+            if (!sd->skillid_dance)
+            {                   //前回使用した踊りがないとだめ
+                clif_skill_fail (sd, skill_num, 0, 0);
+                return 0;
+            }
+            else
+            {
+                sd->skillid_old = skill_num;
+            }
+            break;
+    }
+
+    sd->skillid = skill_num;
+    sd->skilllv = skill_lv;
+
+    switch (skill_num)
+    {                           //事前にレベルが変わったりするスキル
+        case BD_LULLABY:       /* 子守歌 */
+        case BD_RICHMANKIM:    /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+        case BD_RAGNAROK:      /* 神々の黄昏 */
+        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
+        {
+            int  range = 1;
+            int  c = 0;
+            map_foreachinarea (skill_check_condition_char_sub, sd->bl.m,
+                               sd->bl.x - range, sd->bl.y - range,
+                               sd->bl.x + range, sd->bl.y + range, BL_PC,
+                               &sd->bl, &c);
+            if (c < 1)
+            {
+                clif_skill_fail (sd, skill_num, 0, 0);
+                return 0;
+            }
+            else if (c == 99)
+            {                   //相方不要設定だった
+                ;
+            }
+            else
+            {
+                sd->skilllv = (c + skill_lv) / 2;
+            }
+        }
+            break;
+    }
+
+    if (!skill_check_condition (sd, 0))
+        return 0;
+
+    /* 射程と障害物チェック */
+    range = skill_get_range (skill_num, skill_lv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    if (!battle_check_range (&sd->bl, bl, range))
+        return 0;
+
+    if (bl->type == BL_PC)
+    {
+        target_sd = (struct map_session_data *) bl;
+        if (target_sd && skill_num == ALL_RESURRECTION
+            && !pc_isdead (target_sd))
+            return 0;
+    }
+    if ((skill_num != MO_CHAINCOMBO &&
+         skill_num != MO_COMBOFINISH &&
+         skill_num != MO_EXTREMITYFIST &&
+         skill_num != CH_TIGERFIST &&
+         skill_num != CH_CHAINCRUSH) ||
+        (skill_num == MO_EXTREMITYFIST && sd->state.skill_flag))
+        pc_stopattack (sd);
+
+    casttime = skill_castfix (&sd->bl, skill_get_cast (skill_num, skill_lv));
+    if (skill_num != SA_MAGICROD)
+        delay =
+            skill_delayfix (&sd->bl, skill_get_delay (skill_num, skill_lv));
+    sd->state.skillcastcancel = skill_db[skill_num].castcancel;
+
+    switch (skill_num)
+    {                           /* 何か特殊な処理が必要 */
+//  case AL_HEAL:   /* ヒール */
+//      if(battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
+//          forcecast=1;    /* ヒールアタックなら詠唱エフェクト有り */
+//      break;
+        case ALL_RESURRECTION: /* リザレクション */
+            if (bl->type != BL_PC
+                && battle_check_undead (battle_get_race (bl),
+                                        battle_get_elem_type (bl)))
+            {                   /* 敵がアンデッドなら */
+                forcecast = 1;  /* ターンアンデットと同じ詠唱時間 */
+                casttime =
+                    skill_castfix (&sd->bl,
+                                   skill_get_cast (PR_TURNUNDEAD, skill_lv));
+            }
+            break;
+        case MO_FINGEROFFENSIVE:   /* 指弾 */
+            casttime +=
+                casttime *
+                ((skill_lv > sd->spiritball) ? sd->spiritball : skill_lv);
+            break;
+        case MO_CHAINCOMBO:    /*連打掌 */
+            target_id = sd->attacktarget;
+            if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
+            {
+                struct block_list *tbl;
+                if ((tbl = (struct block_list *) sc_data[SC_BLADESTOP].val4) == NULL)   //ターゲットがいない?
+                    return 0;
+                target_id = tbl->id;
+            }
+            break;
+        case MO_COMBOFINISH:   /*猛龍拳 */
+        case CH_TIGERFIST:     /* 伏虎拳 */
+        case CH_CHAINCRUSH:    /* 連柱崩撃 */
+            target_id = sd->attacktarget;
+            break;
+
+// -- moonsoul  (altered to allow proper usage of extremity from new champion combos)
+//
+        case MO_EXTREMITYFIST: /*阿修羅覇鳳拳 */
+            if (sc_data && sc_data[SC_COMBO].timer != -1
+                && (sc_data[SC_COMBO].val1 == MO_COMBOFINISH
+                    || sc_data[SC_COMBO].val1 == CH_CHAINCRUSH))
+            {
+                casttime = 0;
+                target_id = sd->attacktarget;
+            }
+            forcecast = 1;
+            break;
+        case SA_MAGICROD:
+        case SA_SPELLBREAKER:
+            forcecast = 1;
+            break;
+        case WE_MALE:
+        case WE_FEMALE:
+        {
+            struct map_session_data *p_sd = NULL;
+            if ((p_sd = pc_get_partner (sd)) == NULL)
+                return 0;
+            target_id = p_sd->bl.id;
+            //rangeをもう1回検査
+            range = skill_get_range (skill_num, skill_lv);
+            if (range < 0)
+                range = battle_get_range (&sd->bl) - (range + 1);
+            if (!battle_check_range (&sd->bl, &p_sd->bl, range))
+            {
+                return 0;
+            }
+        }
+            break;
+        case AS_SPLASHER:      /* ベナムスプラッシャー */
+        {
+            struct status_change *t_sc_data = battle_get_sc_data (bl);
+            if (t_sc_data && t_sc_data[SC_POISON].timer == -1)
+            {
+                clif_skill_fail (sd, skill_num, 0, 10);
+                return 0;
+            }
+        }
+            break;
+        case PF_MEMORIZE:      /* メモライズ */
+            casttime = 12000;
+            break;
+
+    }
+
+    //メモライズ状態ならキャストタイムが1/3
+    if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0)
+    {
+        casttime = casttime / 3;
+        if ((--sc_data[SC_MEMORIZE].val2) <= 0)
+            skill_status_change_end (&sd->bl, SC_MEMORIZE, -1);
+    }
+
+    if (battle_config.pc_skill_log)
+        printf ("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",
+                sd->bl.id, target_id, skill_num, skill_lv, casttime);
+
+//  if(sd->skillitem == skill_num)
+//      casttime = delay = 0;
+
+    if (casttime > 0 || forcecast)
+    {                           /* 詠唱が必要 */
+        struct mob_data *md;
+        clif_skillcasting (&sd->bl,
+                           sd->bl.id, target_id, 0, 0, skill_num, casttime);
+
+        /* 詠唱反応モンスター */
+        if (bl->type == BL_MOB && (md = (struct mob_data *) bl)
+            && mob_db[md->mob_class].mode & 0x10 && md->state.state != MS_ATTACK
+            && sd->invincible_timer == -1)
+        {
+            md->target_id = sd->bl.id;
+            md->state.targettype = ATTACKABLE;
+            md->min_chase = 13;
+        }
+    }
+
+    if (casttime <= 0)          /* 詠唱の無いものはキャンセルされない */
+        sd->state.skillcastcancel = 0;
+
+    sd->skilltarget = target_id;
+/*	sd->cast_target_bl	= bl; */
+    sd->skillx = 0;
+    sd->skilly = 0;
+    sd->canact_tick = tick + casttime + delay;
+    sd->canmove_tick = tick;
+    if (!(battle_config.pc_cloak_check_type & 2) && sc_data
+        && sc_data[SC_CLOAKING].timer != -1 && sd->skillid != AS_CLOAKING)
+        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
+    if (casttime > 0)
+    {
+        sd->skilltimer =
+            add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0);
+        if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0)
+        {
+            sd->prev_speed = sd->speed;
+            sd->speed = sd->speed * (175 - skill * 5) / 100;
+            clif_updatestatus (sd, SP_SPEED);
+        }
+        else
+            pc_stop_walking (sd, 0);
+    }
+    else
+    {
+        if (skill_num != SA_CASTCANCEL)
+            sd->skilltimer = -1;
+        skill_castend_id (sd->skilltimer, tick, sd->bl.id, 0);
+    }
+
+    //マジックパワーの効果終了
+    if (sc_data && sc_data[SC_MAGICPOWER].timer != -1
+        && skill_num != HW_MAGICPOWER)
+        skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル使用(場所指定)
+ *------------------------------------------
+ */
+int skill_use_pos (struct map_session_data *sd,
+                   int skill_x, int skill_y, int skill_num, int skill_lv)
+{
+    struct block_list bl;
+    struct status_change *sc_data;
+    unsigned int tick;
+    int  casttime = 0, delay = 0, skill, range;
+
+    nullpo_retr (0, sd);
+
+    if (pc_isdead (sd))
+        return 0;
+
+    if (skillnotok (skill_num, sd)) // [MoueJstr]
+        return 0;
+
+    sc_data = sd->sc_data;
+
+    if (sd->opt1 > 0)
+        return 0;
+    if (sc_data)
+    {
+        if (sc_data[SC_DIVINA].timer != -1 ||
+            sc_data[SC_ROKISWEIL].timer != -1 ||
+            sc_data[SC_AUTOCOUNTER].timer != -1 ||
+            sc_data[SC_STEELBODY].timer != -1 ||
+            sc_data[SC_DANCING].timer != -1 ||
+            sc_data[SC_BERSERK].timer != -1)
+            return 0;           /* 状態異常や沈黙など */
+    }
+
+    if (sd->status.option & 2)
+        return 0;
+
+    if (map[sd->bl.m].flag.gvg
+        && (skill_num == SM_ENDURE || skill_num == AL_TELEPORT
+            || skill_num == AL_WARP || skill_num == WZ_ICEWALL
+            || skill_num == TF_BACKSLIDING))
+        return 0;
+
+    sd->skillid = skill_num;
+    sd->skilllv = skill_lv;
+    sd->skillx = skill_x;
+    sd->skilly = skill_y;
+    if (!skill_check_condition (sd, 0))
+        return 0;
+
+    /* 射程と障害物チェック */
+    bl.type = BL_NUL;
+    bl.m = sd->bl.m;
+    bl.x = skill_x;
+    bl.y = skill_y;
+    range = skill_get_range (skill_num, skill_lv);
+    if (range < 0)
+        range = battle_get_range (&sd->bl) - (range + 1);
+    if (!battle_check_range (&sd->bl, &bl, range))
+        return 0;
+
+    pc_stopattack (sd);
+
+    casttime = skill_castfix (&sd->bl, skill_get_cast (skill_num, skill_lv));
+    delay = skill_delayfix (&sd->bl, skill_get_delay (skill_num, skill_lv));
+    sd->state.skillcastcancel = skill_db[skill_num].castcancel;
+
+    if (battle_config.pc_skill_log)
+        printf ("PC %d skill use target_pos=(%d,%d) skill=%d lv=%d cast=%d\n",
+                sd->bl.id, skill_x, skill_y, skill_num, skill_lv, casttime);
+
+//  if(sd->skillitem == skill_num)
+//      casttime = delay = 0;
+    //メモライズ状態ならキャストタイムが1/3
+    if (sc_data && sc_data[SC_MEMORIZE].timer != -1 && casttime > 0)
+    {
+        casttime = casttime / 3;
+        if ((--sc_data[SC_MEMORIZE].val2) <= 0)
+            skill_status_change_end (&sd->bl, SC_MEMORIZE, -1);
+    }
+
+    if (casttime > 0)           /* 詠唱が必要 */
+        clif_skillcasting (&sd->bl,
+                           sd->bl.id, 0, skill_x, skill_y, skill_num,
+                           casttime);
+
+    if (casttime <= 0)          /* 詠唱の無いものはキャンセルされない */
+        sd->state.skillcastcancel = 0;
+
+    sd->skilltarget = 0;
+/*	sd->cast_target_bl	= NULL; */
+    tick = gettick ();
+    sd->canact_tick = tick + casttime + delay;
+    sd->canmove_tick = tick;
+    if (!(battle_config.pc_cloak_check_type & 2) && sc_data
+        && sc_data[SC_CLOAKING].timer != -1)
+        skill_status_change_end (&sd->bl, SC_CLOAKING, -1);
+    if (casttime > 0)
+    {
+        sd->skilltimer =
+            add_timer (tick + casttime, skill_castend_pos, sd->bl.id, 0);
+        if ((skill = pc_checkskill (sd, SA_FREECAST)) > 0)
+        {
+            sd->prev_speed = sd->speed;
+            sd->speed = sd->speed * (175 - skill * 5) / 100;
+            clif_updatestatus (sd, SP_SPEED);
+        }
+        else
+            pc_stop_walking (sd, 0);
+    }
+    else
+    {
+        sd->skilltimer = -1;
+        skill_castend_pos (sd->skilltimer, tick, sd->bl.id, 0);
+    }
+    //マジックパワーの効果終了
+    if (sc_data && sc_data[SC_MAGICPOWER].timer != -1
+        && skill_num != HW_MAGICPOWER)
+        skill_status_change_end (&sd->bl, SC_MAGICPOWER, -1);
+
+    return 0;
+}
+
+/*==========================================
+ * スキル詠唱キャンセル
+ *------------------------------------------
+ */
+int skill_castcancel (struct block_list *bl, int type)
+{
+    int  inf;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+    {
+        struct map_session_data *sd = (struct map_session_data *) bl;
+        unsigned long tick = gettick ();
+        nullpo_retr (0, sd);
+        sd->canact_tick = tick;
+        sd->canmove_tick = tick;
+        if (sd->skilltimer != -1)
+        {
+            if (pc_checkskill (sd, SA_FREECAST) > 0)
+            {
+                sd->speed = sd->prev_speed;
+                clif_updatestatus (sd, SP_SPEED);
+            }
+            if (!type)
+            {
+                if ((inf = skill_get_inf (sd->skillid)) == 2 || inf == 32)
+                    delete_timer (sd->skilltimer, skill_castend_pos);
+                else
+                    delete_timer (sd->skilltimer, skill_castend_id);
+            }
+            else
+            {
+                if ((inf = skill_get_inf (sd->skillid_old)) == 2 || inf == 32)
+                    delete_timer (sd->skilltimer, skill_castend_pos);
+                else
+                    delete_timer (sd->skilltimer, skill_castend_id);
+            }
+            sd->skilltimer = -1;
+            clif_skillcastcancel (bl);
+        }
+
+        return 0;
+    }
+    else if (bl->type == BL_MOB)
+    {
+        struct mob_data *md = (struct mob_data *) bl;
+        nullpo_retr (0, md);
+        if (md->skilltimer != -1)
+        {
+            if ((inf = skill_get_inf (md->skillid)) == 2 || inf == 32)
+                delete_timer (md->skilltimer, mobskill_castend_pos);
+            else
+                delete_timer (md->skilltimer, mobskill_castend_id);
+            md->skilltimer = -1;
+            clif_skillcastcancel (bl);
+        }
+        return 0;
+    }
+    return 1;
+}
+
+/*=========================================
+ * ブランディッシュスピア 初期範囲決定
+ *----------------------------------------
+ */
+void skill_brandishspear_first (struct square *tc, int dir, int x, int y)
+{
+
+    nullpo_retv (tc);
+
+    if (dir == 0)
+    {
+        tc->val1[0] = x - 2;
+        tc->val1[1] = x - 1;
+        tc->val1[2] = x;
+        tc->val1[3] = x + 1;
+        tc->val1[4] = x + 2;
+        tc->val2[0] =
+            tc->val2[1] = tc->val2[2] = tc->val2[3] = tc->val2[4] = y - 1;
+    }
+    else if (dir == 2)
+    {
+        tc->val1[0] =
+            tc->val1[1] = tc->val1[2] = tc->val1[3] = tc->val1[4] = x + 1;
+        tc->val2[0] = y + 2;
+        tc->val2[1] = y + 1;
+        tc->val2[2] = y;
+        tc->val2[3] = y - 1;
+        tc->val2[4] = y - 2;
+    }
+    else if (dir == 4)
+    {
+        tc->val1[0] = x - 2;
+        tc->val1[1] = x - 1;
+        tc->val1[2] = x;
+        tc->val1[3] = x + 1;
+        tc->val1[4] = x + 2;
+        tc->val2[0] =
+            tc->val2[1] = tc->val2[2] = tc->val2[3] = tc->val2[4] = y + 1;
+    }
+    else if (dir == 6)
+    {
+        tc->val1[0] =
+            tc->val1[1] = tc->val1[2] = tc->val1[3] = tc->val1[4] = x - 1;
+        tc->val2[0] = y + 2;
+        tc->val2[1] = y + 1;
+        tc->val2[2] = y;
+        tc->val2[3] = y - 1;
+        tc->val2[4] = y - 2;
+    }
+    else if (dir == 1)
+    {
+        tc->val1[0] = x - 1;
+        tc->val1[1] = x;
+        tc->val1[2] = x + 1;
+        tc->val1[3] = x + 2;
+        tc->val1[4] = x + 3;
+        tc->val2[0] = y - 4;
+        tc->val2[1] = y - 3;
+        tc->val2[2] = y - 1;
+        tc->val2[3] = y;
+        tc->val2[4] = y + 1;
+    }
+    else if (dir == 3)
+    {
+        tc->val1[0] = x + 3;
+        tc->val1[1] = x + 2;
+        tc->val1[2] = x + 1;
+        tc->val1[3] = x;
+        tc->val1[4] = x - 1;
+        tc->val2[0] = y - 1;
+        tc->val2[1] = y;
+        tc->val2[2] = y + 1;
+        tc->val2[3] = y + 2;
+        tc->val2[4] = y + 3;
+    }
+    else if (dir == 5)
+    {
+        tc->val1[0] = x + 1;
+        tc->val1[1] = x;
+        tc->val1[2] = x - 1;
+        tc->val1[3] = x - 2;
+        tc->val1[4] = x - 3;
+        tc->val2[0] = y + 3;
+        tc->val2[1] = y + 2;
+        tc->val2[2] = y + 1;
+        tc->val2[3] = y;
+        tc->val2[4] = y - 1;
+    }
+    else if (dir == 7)
+    {
+        tc->val1[0] = x - 3;
+        tc->val1[1] = x - 2;
+        tc->val1[2] = x - 1;
+        tc->val1[3] = x;
+        tc->val1[4] = x + 1;
+        tc->val2[1] = y;
+        tc->val2[0] = y + 1;
+        tc->val2[2] = y - 1;
+        tc->val2[3] = y - 2;
+        tc->val2[4] = y - 3;
+    }
+
+}
+
+/*=========================================
+ * ブランディッシュスピア 方向判定 範囲拡張
+ *-----------------------------------------
+ */
+void skill_brandishspear_dir (struct square *tc, int dir, int are)
+{
+
+    int  c;
+
+    nullpo_retv (tc);
+
+    for (c = 0; c < 5; c++)
+    {
+        if (dir == 0)
+        {
+            tc->val2[c] += are;
+        }
+        else if (dir == 1)
+        {
+            tc->val1[c] -= are;
+            tc->val2[c] += are;
+        }
+        else if (dir == 2)
+        {
+            tc->val1[c] -= are;
+        }
+        else if (dir == 3)
+        {
+            tc->val1[c] -= are;
+            tc->val2[c] -= are;
+        }
+        else if (dir == 4)
+        {
+            tc->val2[c] -= are;
+        }
+        else if (dir == 5)
+        {
+            tc->val1[c] += are;
+            tc->val2[c] -= are;
+        }
+        else if (dir == 6)
+        {
+            tc->val1[c] += are;
+        }
+        else if (dir == 7)
+        {
+            tc->val1[c] += are;
+            tc->val2[c] += are;
+        }
+    }
+}
+
+/*==========================================
+ * ディボーション 有効確認
+ *------------------------------------------
+ */
+void skill_devotion (struct map_session_data *md, int target)
+{
+    // 総確認
+    int  n;
+
+    nullpo_retv (md);
+
+    for (n = 0; n < 5; n++)
+    {
+        if (md->dev.val1[n])
+        {
+            struct map_session_data *sd = map_id2sd (md->dev.val1[n]);
+            // 相手が見つからない // 相手をディボしてるのが自分じゃない // 距離が離れてる
+            if (sd == NULL
+                || (sd->sc_data
+                    && (md->bl.id != sd->sc_data[SC_DEVOTION].val1))
+                || skill_devotion3 (&md->bl, md->dev.val1[n]))
+            {
+                skill_devotion_end (md, sd, n);
+            }
+        }
+    }
+}
+
+void skill_devotion2 (struct block_list *bl, int crusader)
+{
+    // 被ディボーションが歩いた時の距離チェック
+    struct map_session_data *sd = map_id2sd (crusader);
+
+    nullpo_retv (bl);
+
+    if (sd)
+        skill_devotion3 (&sd->bl, bl->id);
+}
+
+int skill_devotion3 (struct block_list *bl, int target)
+{
+    // クルセが歩いた時の距離チェック
+    struct map_session_data *md;
+    struct map_session_data *sd;
+    int  n, r = 0;
+
+    nullpo_retr (1, bl);
+
+    if ((md = (struct map_session_data *) bl) == NULL
+        || (sd = map_id2sd (target)) == NULL)
+        return 1;
+    else
+        r = distance (bl->x, bl->y, sd->bl.x, sd->bl.y);
+
+    if (pc_checkskill (sd, CR_DEVOTION) + 6 < r)
+    {                           // 許容範囲を超えてた
+        for (n = 0; n < 5; n++)
+            if (md->dev.val1[n] == target)
+                md->dev.val2[n] = 0;    // 離れた時は、糸を切るだけ
+        clif_devotion (md, sd->bl.id);
+        return 1;
+    }
+    return 0;
+}
+
+void skill_devotion_end (struct map_session_data *md,
+                         struct map_session_data *sd, int target)
+{
+    // クルセと被ディボキャラのリセット
+    nullpo_retv (md);
+    nullpo_retv (sd);
+
+    md->dev.val1[target] = md->dev.val2[target] = 0;
+    if (sd && sd->sc_data)
+    {
+        //  skill_status_change_end(sd->bl,SC_DEVOTION,-1);
+        sd->sc_data[SC_DEVOTION].val1 = 0;
+        sd->sc_data[SC_DEVOTION].val2 = 0;
+        clif_status_change (&sd->bl, SC_DEVOTION, 0);
+        clif_devotion (md, sd->bl.id);
+    }
+}
+
+/*==========================================
+ * オートスペル
+ *------------------------------------------
+ */
+int skill_autospell (struct map_session_data *sd, int skillid)
+{
+    int  skilllv;
+    int  maxlv = 1, lv;
+
+    nullpo_retr (0, sd);
+
+    skilllv = pc_checkskill (sd, SA_AUTOSPELL);
+
+    if (skillid == MG_NAPALMBEAT)
+        maxlv = 3;
+    else if (skillid == MG_COLDBOLT || skillid == MG_FIREBOLT
+             || skillid == MG_LIGHTNINGBOLT)
+    {
+        if (skilllv == 2)
+            maxlv = 1;
+        else if (skilllv == 3)
+            maxlv = 2;
+        else if (skilllv >= 4)
+            maxlv = 3;
+    }
+    else if (skillid == MG_SOULSTRIKE)
+    {
+        if (skilllv == 5)
+            maxlv = 1;
+        else if (skilllv == 6)
+            maxlv = 2;
+        else if (skilllv >= 7)
+            maxlv = 3;
+    }
+    else if (skillid == MG_FIREBALL)
+    {
+        if (skilllv == 8)
+            maxlv = 1;
+        else if (skilllv >= 9)
+            maxlv = 2;
+    }
+    else if (skillid == MG_FROSTDIVER)
+        maxlv = 1;
+    else
+        return 0;
+
+    if (maxlv > (lv = pc_checkskill (sd, skillid)))
+        maxlv = lv;
+
+    skill_status_change_start (&sd->bl, SC_AUTOSPELL, skilllv, skillid, maxlv, 0,   // val1:スキルID val2:使用最大Lv
+                               skill_get_time (SA_AUTOSPELL, skilllv), 0);  // にしてみたけどbscriptが書き易い・・・?
+    return 0;
+}
+
+/*==========================================
+ * ギャングスターパラダイス判定処理(foreachinarea)
+ *------------------------------------------
+ */
+
+static int skill_gangster_count (struct block_list *bl, va_list ap)
+{
+    int *c;
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    sd = (struct map_session_data *) bl;
+    c = va_arg (ap, int *);
+
+    if (sd && c && pc_issit (sd) && pc_checkskill (sd, RG_GANGSTER) > 0)
+        (*c)++;
+    return 0;
+}
+
+static int skill_gangster_in (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    sd = (struct map_session_data *) bl;
+    if (sd && pc_issit (sd) && pc_checkskill (sd, RG_GANGSTER) > 0)
+        sd->state.gangsterparadise = 1;
+    return 0;
+}
+
+static int skill_gangster_out (struct block_list *bl, va_list ap)
+{
+    struct map_session_data *sd;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    sd = (struct map_session_data *) bl;
+    if (sd && sd->state.gangsterparadise)
+        sd->state.gangsterparadise = 0;
+    return 0;
+}
+
+int skill_gangsterparadise (struct map_session_data *sd, int type)
+{
+    int  range = 1;
+    int  c = 0;
+
+    nullpo_retr (0, sd);
+
+    if (pc_checkskill (sd, RG_GANGSTER) <= 0)
+        return 0;
+
+    if (type == 1)
+    {                           /* 座った時の処理 */
+        map_foreachinarea (skill_gangster_count, sd->bl.m,
+                           sd->bl.x - range, sd->bl.y - range,
+                           sd->bl.x + range, sd->bl.y + range, BL_PC, &c);
+        if (c > 0)
+        {                       /*ギャングスター成功したら自分にもギャングスター属性付与 */
+            map_foreachinarea (skill_gangster_in, sd->bl.m,
+                               sd->bl.x - range, sd->bl.y - range,
+                               sd->bl.x + range, sd->bl.y + range, BL_PC);
+            sd->state.gangsterparadise = 1;
+        }
+        return 0;
+    }
+    else if (type == 0)
+    {                           /* 立ち上がったときの処理 */
+        map_foreachinarea (skill_gangster_count, sd->bl.m,
+                           sd->bl.x - range, sd->bl.y - range,
+                           sd->bl.x + range, sd->bl.y + range, BL_PC, &c);
+        if (c < 1)
+            map_foreachinarea (skill_gangster_out, sd->bl.m,
+                               sd->bl.x - range, sd->bl.y - range,
+                               sd->bl.x + range, sd->bl.y + range, BL_PC);
+        sd->state.gangsterparadise = 0;
+        return 0;
+    }
+    return 0;
+}
+
+/*==========================================
+ * 寒いジョーク・スクリーム判定処理(foreachinarea)
+ *------------------------------------------
+ */
+int skill_frostjoke_scream (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    int  skillnum, skilllv;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+
+    skillnum = va_arg (ap, int);
+    skilllv = va_arg (ap, int);
+    tick = va_arg (ap, unsigned int);
+
+    if (src == bl)              //自分には効かない
+        return 0;
+
+    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
+        skill_additional_effect (src, bl, skillnum, skilllv, BF_MISC, tick);
+    else if (battle_check_target (src, bl, BCT_PARTY) > 0)
+    {
+        if (MRAND (100) < 10)   //PTメンバにも低確率でかかる(とりあえず10%)
+            skill_additional_effect (src, bl, skillnum, skilllv, BF_MISC,
+                                     tick);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int skill_attack_area (struct block_list *bl, va_list ap)
+{
+    struct block_list *src, *dsrc;
+    int  atk_type, skillid, skilllv, flag, type;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    atk_type = va_arg (ap, int);
+    if ((src = va_arg (ap, struct block_list *)) == NULL)
+        return 0;
+    if ((dsrc = va_arg (ap, struct block_list *)) == NULL)
+        return 0;
+    skillid = va_arg (ap, int);
+    skilllv = va_arg (ap, int);
+    tick = va_arg (ap, unsigned int);
+    flag = va_arg (ap, int);
+    type = va_arg (ap, int);
+
+    if (battle_check_target (dsrc, bl, type) > 0)
+        skill_attack (atk_type, src, dsrc, bl, skillid, skilllv, tick, flag);
+
+    return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int skill_clear_element_field (struct block_list *bl)
+{
+    struct mob_data *md = NULL;
+    struct map_session_data *sd = NULL;
+    int  i, skillid;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_MOB)
+        md = (struct mob_data *) bl;
+    if (bl->type == BL_PC)
+        sd = (struct map_session_data *) bl;
+
+    for (i = 0; i < MAX_MOBSKILLUNITGROUP; i++)
+    {
+        if (sd)
+        {
+            skillid = sd->skillunit[i].skill_id;
+            if (skillid == SA_DELUGE || skillid == SA_VOLCANO
+                || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR)
+                skill_delunitgroup (&sd->skillunit[i]);
+        }
+        else if (md)
+        {
+            skillid = md->skillunit[i].skill_id;
+            if (skillid == SA_DELUGE || skillid == SA_VOLCANO
+                || skillid == SA_VIOLENTGALE || skillid == SA_LANDPROTECTOR)
+                skill_delunitgroup (&md->skillunit[i]);
+        }
+    }
+    return 0;
+}
+
+/*==========================================
+ * ランドプロテクターチェック(foreachinarea)
+ *------------------------------------------
+ */
+int skill_landprotector (struct block_list *bl, va_list ap)
+{
+    int  skillid;
+    int *alive;
+    struct skill_unit *unit;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    skillid = va_arg (ap, int);
+    alive = va_arg (ap, int *);
+    if ((unit = (struct skill_unit *) bl) == NULL)
+        return 0;
+
+    if (skillid == SA_LANDPROTECTOR)
+    {
+        skill_delunit (unit);
+    }
+    else
+    {
+        if (alive && unit->group->skill_id == SA_LANDPROTECTOR)
+            (*alive) = 0;
+    }
+    return 0;
+}
+
+/*==========================================
+ * イドゥンの林檎の回復処理(foreachinarea)
+ *------------------------------------------
+ */
+int skill_idun_heal (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    struct skill_unit_group *sg;
+    int  heal;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, unit = va_arg (ap, struct skill_unit *));
+    nullpo_retr (0, sg = unit->group);
+
+    heal =
+        30 + sg->skill_lv * 5 + ((sg->val1) >> 16) * 5 +
+        ((sg->val1) & 0xfff) / 2;
+
+    if (bl->type == BL_SKILL || bl->id == sg->src_id)
+        return 0;
+
+    if (bl->type == BL_PC || bl->type == BL_MOB)
+    {
+        clif_skill_nodamage (&unit->bl, bl, AL_HEAL, heal, 1);
+        battle_heal (NULL, bl, heal, 0, 0);
+    }
+    return 0;
+}
+
+/*==========================================
+ * 指定範囲内でsrcに対して有効なターゲットのblの数を数える(foreachinarea)
+ *------------------------------------------
+ */
+int skill_count_target (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    int *c;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+
+    if ((src = va_arg (ap, struct block_list *)) == NULL)
+        return 0;
+    if ((c = va_arg (ap, int *)) == NULL)
+        return 0;
+    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
+        (*c)++;
+    return 0;
+}
+
+/*==========================================
+ * トラップ範囲処理(foreachinarea)
+ *------------------------------------------
+ */
+int skill_trap_splash (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    int  tick;
+    int  splash_count;
+    struct skill_unit *unit;
+    struct skill_unit_group *sg;
+    struct block_list *ss;
+    int  i;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    nullpo_retr (0, unit = (struct skill_unit *) src);
+    nullpo_retr (0, sg = unit->group);
+    nullpo_retr (0, ss = map_id2bl (sg->src_id));
+
+    tick = va_arg (ap, int);
+    splash_count = va_arg (ap, int);
+
+    if (battle_check_target (src, bl, BCT_ENEMY) > 0)
+    {
+        switch (sg->unit_id)
+        {
+            case 0x95:         /* サンドマン */
+            case 0x96:         /* フラッシャー */
+            case 0x94:         /* ショックウェーブトラップ */
+                skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv,
+                                         BF_MISC, tick);
+                break;
+            case 0x8f:         /* ブラストマイン */
+            case 0x98:         /* クレイモアートラップ */
+                for (i = 0; i < splash_count; i++)
+                {
+                    skill_attack (BF_MISC, ss, src, bl, sg->skill_id,
+                                  sg->skill_lv, tick,
+                                  (sg->val2) ? 0x0500 : 0);
+                }
+            case 0x97:         /* フリージングトラップ */
+                skill_attack (BF_WEAPON, ss, src, bl, sg->skill_id,
+                              sg->skill_lv, tick, (sg->val2) ? 0x0500 : 0);
+                break;
+            default:
+                break;
+        }
+    }
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * ステータス異常
+ *----------------------------------------------------------------------------
+ */
+
+/*==========================================
+ * ステータス異常タイマー範囲処理
+ *------------------------------------------
+ */
+int skill_status_change_timer_sub (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    int  type;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    type = va_arg (ap, int);
+    tick = va_arg (ap, unsigned int);
+
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+        return 0;
+
+    switch (type)
+    {
+        case SC_SIGHT:         /* サイト */
+        case SC_CONCENTRATE:
+            if ((*battle_get_option (bl)) & 6)
+            {
+                skill_status_change_end (bl, SC_HIDING, -1);
+                skill_status_change_end (bl, SC_CLOAKING, -1);
+            }
+            break;
+        case SC_RUWACH:        /* ルアフ */
+            if ((*battle_get_option (bl)) & 6)
+            {
+                skill_status_change_end (bl, SC_HIDING, -1);
+                skill_status_change_end (bl, SC_CLOAKING, -1);
+                if (battle_check_target (src, bl, BCT_ENEMY) > 0)
+                {
+                    struct status_change *sc_data = battle_get_sc_data (bl);
+                    skill_attack (BF_MAGIC, src, src, bl, AL_RUWACH,
+                                  sc_data[type].val1, tick, 0);
+                }
+            }
+            break;
+    }
+    return 0;
+}
+
+/*==========================================
+ * ステータス異常終了
+ *------------------------------------------
+ */
+int skill_status_change_active (struct block_list *bl, int type)
+{
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+    {
+        if (battle_config.error_log)
+            printf ("skill_status_change_active: neither MOB nor PC !\n");
+        return 0;
+    }
+
+    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
+
+    return sc_data[type].timer != -1;
+}
+
+int skill_status_change_end (struct block_list *bl, int type, int tid)
+{
+    struct status_change *sc_data;
+    int  opt_flag = 0, calc_flag = 0;
+    short *sc_count, *option, *opt1, *opt2, *opt3;
+
+    nullpo_retr (0, bl);
+    if (bl->type != BL_PC && bl->type != BL_MOB)
+    {
+        if (battle_config.error_log)
+            printf ("skill_status_change_end: neither MOB nor PC !\n");
+        return 0;
+    }
+    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
+    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
+    nullpo_retr (0, option = battle_get_option (bl));
+    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
+    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
+    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
+
+    if ((*sc_count) > 0 && sc_data[type].timer != -1
+        && (sc_data[type].timer == tid || tid == -1))
+    {
+
+        if (tid == -1)          // タイマから呼ばれていないならタイマ削除をする
+            delete_timer (sc_data[type].timer, skill_status_change_timer);
+
+        /* 該当の異常を正常に戻す */
+        sc_data[type].timer = -1;
+        (*sc_count)--;
+
+        switch (type)
+        {                       /* 異常の種類ごとの処理 */
+            case SC_PROVOKE:   /* プロボック */
+            case SC_CONCENTRATE:   /* 集中力向上 */
+            case SC_BLESSING:  /* ブレッシング */
+            case SC_ANGELUS:   /* アンゼルス */
+            case SC_INCREASEAGI:   /* 速度上昇 */
+            case SC_DECREASEAGI:   /* 速度減少 */
+            case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
+            case SC_HIDING:
+            case SC_TWOHANDQUICKEN:    /* 2HQ */
+            case SC_ADRENALINE:    /* アドレナリンラッシュ */
+            case SC_ENCPOISON: /* エンチャントポイズン */
+            case SC_IMPOSITIO: /* インポシティオマヌス */
+            case SC_GLORIA:    /* グロリア */
+            case SC_LOUD:      /* ラウドボイス */
+            case SC_QUAGMIRE:  /* クァグマイア */
+            case SC_PROVIDENCE:    /* プロヴィデンス */
+            case SC_SPEARSQUICKEN: /* スピアクイッケン */
+            case SC_VOLCANO:
+            case SC_DELUGE:
+            case SC_VIOLENTGALE:
+            case SC_ETERNALCHAOS:  /* エターナルカオス */
+            case SC_DRUMBATTLE:    /* 戦太鼓の響き */
+            case SC_NIBELUNGEN:    /* ニーベルングの指輪 */
+            case SC_SIEGFRIED: /* 不死身のジークフリード */
+            case SC_WHISTLE:   /* 口笛 */
+            case SC_ASSNCROS:  /* 夕陽のアサシンクロス */
+            case SC_HUMMING:   /* ハミング */
+            case SC_DONTFORGETME:  /* 私を忘れないで */
+            case SC_FORTUNE:   /* 幸運のキス */
+            case SC_SERVICE4U: /* サービスフォーユー */
+            case SC_EXPLOSIONSPIRITS:  // 爆裂波動
+            case SC_STEELBODY: // 金剛
+            case SC_DEFENDER:
+            case SC_SPEEDPOTION0:  /* 増速ポーション */
+            case SC_SPEEDPOTION1:
+            case SC_SPEEDPOTION2:
+            case SC_APPLEIDUN: /* イドゥンの林檎 */
+            case SC_RIDING:
+            case SC_BLADESTOP_WAIT:
+            case SC_AURABLADE: /* オーラブレード */
+            case SC_PARRYING:  /* パリイング */
+            case SC_CONCENTRATION: /* コンセントレーション */
+            case SC_TENSIONRELAX:  /* テンションリラックス */
+            case SC_ASSUMPTIO: /* アシャンプティオ */
+            case SC_WINDWALK:  /* ウインドウォーク */
+            case SC_TRUESIGHT: /* トゥルーサイト */
+            case SC_SPIDERWEB: /* スパイダーウェッブ */
+            case SC_MAGICPOWER:    /* 魔法力増幅 */
+            case SC_CHASEWALK:
+            case SC_ATKPOT:    /* attack potion [Valaris] */
+            case SC_MATKPOT:   /* magic attack potion [Valaris] */
+            case SC_WEDDING:   //結婚用(結婚衣裳になって歩くのが遅いとか)
+            case SC_MELTDOWN:  /* メルトダウン */
+            case SC_PHYS_SHIELD:
+            case SC_HASTE:
+                calc_flag = 1;
+                break;
+            case SC_BERSERK:   /* バーサーク */
+                calc_flag = 1;
+                clif_status_change (bl, SC_INCREASEAGI, 0); /* アイコン消去 */
+                break;
+            case SC_DEVOTION:  /* ディボーション */
+            {
+                struct map_session_data *md = map_id2sd (sc_data[type].val1);
+                sc_data[type].val1 = sc_data[type].val2 = 0;
+                skill_devotion (md, bl->id);
+                calc_flag = 1;
+            }
+                break;
+            case SC_BLADESTOP:
+            {
+                struct status_change *t_sc_data =
+                    battle_get_sc_data ((struct block_list *)
+                                        sc_data[type].val4);
+                //片方が切れたので相手の白刃状態が切れてないのなら解除
+                if (t_sc_data && t_sc_data[SC_BLADESTOP].timer != -1)
+                    skill_status_change_end ((struct block_list *)
+                                             sc_data[type].val4, SC_BLADESTOP,
+                                             -1);
+
+                if (sc_data[type].val2 == 2)
+                    clif_bladestop ((struct block_list *) sc_data[type].val3,
+                                    (struct block_list *) sc_data[type].val4,
+                                    0);
+            }
+                break;
+            case SC_DANCING:
+            {
+                struct map_session_data *dsd;
+                struct status_change *d_sc_data;
+                if (sc_data[type].val4
+                    && (dsd = map_id2sd (sc_data[type].val4)))
+                {
+                    d_sc_data = dsd->sc_data;
+                    //合奏で相手がいる場合相手のval4を0にする
+                    if (d_sc_data && d_sc_data[type].timer != -1)
+                        d_sc_data[type].val4 = 0;
+                }
+            }
+                calc_flag = 1;
+                break;
+            case SC_GRAFFITI:
+            {
+                struct skill_unit_group *sg = (struct skill_unit_group *) sc_data[type].val4;   //val4がグラフィティのgroup_id
+                if (sg)
+                    skill_delunitgroup (sg);
+            }
+                break;
+            case SC_NOCHAT:    //チャット禁止状態
+            {
+                struct map_session_data *sd = NULL;
+                if (bl->type == BL_PC
+                    && (sd = (struct map_session_data *) bl))
+                {
+                    sd->status.manner = 0;
+                    clif_updatestatus (sd, SP_MANNER);
+                }
+            }
+                break;
+            case SC_SPLASHER:  /* ベナムスプラッシャー */
+            {
+                struct block_list *src = map_id2bl (sc_data[type].val3);
+                if (src && tid != -1)
+                {
+                    //自分にダメージ&周囲3*3にダメージ
+                    skill_castend_damage_id (src, bl, sc_data[type].val2,
+                                             sc_data[type].val1, gettick (),
+                                             0);
+                }
+            }
+                break;
+            case SC_SELFDESTRUCTION:   /* 自爆 */
+            {
+                //自分のダメージは0にして
+                struct mob_data *md = NULL;
+                if (bl->type == BL_MOB && (md = (struct mob_data *) bl))
+                    skill_castend_damage_id (bl, bl, sc_data[type].val2,
+                                             sc_data[type].val1, gettick (),
+                                             0);
+            }
+                break;
+                /* option1 */
+            case SC_FREEZE:
+                sc_data[type].val3 = 0;
+                break;
+
+                /* option2 */
+            case SC_POISON:    /* 毒 */
+            case SC_BLIND:     /* 暗黒 */
+            case SC_CURSE:
+                calc_flag = 1;
+                break;
+        }
+
+        if (bl->type == BL_PC && type < SC_SENDMAX)
+            clif_status_change (bl, type, 0);   /* アイコン消去 */
+
+        switch (type)
+        {                       /* 正常に戻るときなにか処理が必要 */
+            case SC_STONE:
+            case SC_FREEZE:
+            case SC_STAN:
+            case SC_SLEEP:
+                *opt1 = 0;
+                opt_flag = 1;
+                break;
+
+            case SC_POISON:
+            case SC_CURSE:
+            case SC_SILENCE:
+            case SC_BLIND:
+                *opt2 &= ~(1 << (type - SC_POISON));
+                opt_flag = 1;
+                break;
+
+            case SC_SLOWPOISON:
+                if (sc_data[SC_POISON].timer != -1)
+                    *opt2 |= 0x1;
+                *opt2 &= ~0x200;
+                opt_flag = 1;
+                break;
+
+            case SC_SIGNUMCRUCIS:
+                *opt2 &= ~0x40;
+                opt_flag = 1;
+                break;
+
+            case SC_SPEEDPOTION0:
+                *opt2 &= ~0x20;
+                opt_flag = 1;
+                break;
+
+            case SC_ATKPOT:
+                *opt2 &= ~0x80;
+                opt_flag = 1;
+                break;
+
+            case SC_HIDING:
+            case SC_CLOAKING:
+                *option &= ~((type == SC_HIDING) ? 2 : 4);
+                opt_flag = 1;
+                break;
+
+            case SC_CHASEWALK:
+                *option &= ~16388;
+                opt_flag = 1;
+                break;
+
+            case SC_SIGHT:
+                *option &= ~1;
+                opt_flag = 1;
+                break;
+            case SC_WEDDING:   //結婚用(結婚衣裳になって歩くのが遅いとか)
+                *option &= ~4096;
+                opt_flag = 1;
+                break;
+            case SC_RUWACH:
+                *option &= ~8192;
+                opt_flag = 1;
+                break;
+
+                //opt3
+            case SC_TWOHANDQUICKEN:    /* 2HQ */
+            case SC_SPEARSQUICKEN: /* スピアクイッケン */
+            case SC_CONCENTRATION: /* コンセントレーション */
+                *opt3 &= ~1;
+                break;
+            case SC_OVERTHRUST:    /* オーバースラスト */
+                *opt3 &= ~2;
+                break;
+            case SC_ENERGYCOAT:    /* エナジーコート */
+                *opt3 &= ~4;
+                break;
+            case SC_EXPLOSIONSPIRITS:  // 爆裂波動
+                *opt3 &= ~8;
+                break;
+            case SC_STEELBODY: // 金剛
+                *opt3 &= ~16;
+                break;
+            case SC_BLADESTOP: /* 白刃取り */
+                *opt3 &= ~32;
+                break;
+            case SC_BERSERK:   /* バーサーク */
+                *opt3 &= ~128;
+                break;
+            case SC_MARIONETTE:    /* マリオネットコントロール */
+                *opt3 &= ~1024;
+                break;
+            case SC_ASSUMPTIO: /* アスムプティオ */
+                *opt3 &= ~2048;
+                break;
+        }
+
+        if (night_flag == 1 && (*opt2 & STATE_BLIND) == 0
+            && bl->type == BL_PC)
+        {                       // by [Yor]
+            *opt2 |= STATE_BLIND;
+            opt_flag = 1;
+        }
+
+        if (opt_flag)           /* optionの変更を伝える */
+            clif_changeoption (bl);
+
+        if (bl->type == BL_PC && calc_flag)
+            pc_calcstatus ((struct map_session_data *) bl, 0);  /* ステータス再計算 */
+    }
+
+    return 0;
+}
+
+int skill_update_heal_animation (struct map_session_data *sd)
+{
+    const int mask = 0x100;
+    int  was_active;
+    int  is_active;
+
+    nullpo_retr (0, sd);
+    was_active = sd->opt2 & mask;
+    is_active = sd->quick_regeneration_hp.amount > 0;
+
+    if ((was_active && is_active) || (!was_active && !is_active))
+        return 0;               // no update
+
+    if (is_active)
+        sd->opt2 |= mask;
+    else
+        sd->opt2 &= ~mask;
+
+    return clif_changeoption (&sd->bl);
+}
+
+/*==========================================
+ * ステータス異常終了タイマー
+ *------------------------------------------
+ */
+void skill_status_change_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    int  type = data;
+    struct block_list *bl;
+    struct map_session_data *sd = NULL;
+    struct status_change *sc_data;
+    //short *sc_count; //使ってない?
+
+    if ((bl = map_id2bl (id)) == NULL)
+        return;               //該当IDがすでに消滅しているというのはいかにもありそうなのでスルーしてみる
+    nullpo_retv (sc_data = battle_get_sc_data (bl));
+
+    if (bl->type == BL_PC)
+        sd = (struct map_session_data *) bl;
+
+    //sc_count=battle_get_sc_count(bl); //使ってない?
+
+    if (sc_data[type].timer != tid)
+    {
+        if (battle_config.error_log)
+            printf ("skill_status_change_timer %d != %d\n", tid,
+                    sc_data[type].timer);
+    }
+
+    if (sc_data[type].spell_invocation)
+    {                           // Must report termination
+        spell_effect_report_termination (sc_data[type].spell_invocation,
+                                         bl->id, type, 0);
+        sc_data[type].spell_invocation = 0;
+    }
+
+    switch (type)
+    {                           /* 特殊な処理になる場合 */
+        case SC_MAXIMIZEPOWER: /* マキシマイズパワー */
+        case SC_CLOAKING:      /* クローキング */
+        case SC_CHASEWALK:
+            if (sd)
+            {
+                if (sd->status.sp > 0)
+                {               /* SP切れるまで持続 */
+                    sd->status.sp--;
+                    clif_updatestatus (sd, SP_SP);
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        sc_data[type].val2 +
+                                                        tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+            break;
+
+        case SC_HIDING:        /* ハイディング */
+            if (sd)
+            {                   /* SPがあって、時間制限の間は持続 */
+                if (sd->status.sp > 0 && (--sc_data[type].val2) > 0)
+                {
+                    if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0)
+                    {
+                        sd->status.sp--;
+                        clif_updatestatus (sd, SP_SP);
+                    }
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        1000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+            break;
+
+        case SC_SIGHT:         /* サイト */
+        {
+            const int range = 7;
+            map_foreachinarea (skill_status_change_timer_sub,
+                               bl->m, bl->x - range, bl->y - range,
+                               bl->x + range, bl->y + range, 0, bl, type,
+                               tick);
+
+            if ((--sc_data[type].val2) > 0)
+            {
+                sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                    250 + tick,
+                                                    skill_status_change_timer,
+                                                    bl->id, data);
+                return;
+            }
+        }
+            break;
+        case SC_RUWACH:        /* ルアフ */
+        {
+            const int range = 5;
+            map_foreachinarea (skill_status_change_timer_sub,
+                               bl->m, bl->x - range, bl->y - range,
+                               bl->x + range, bl->y + range, 0, bl, type,
+                               tick);
+
+            if ((--sc_data[type].val2) > 0)
+            {
+                sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                    250 + tick,
+                                                    skill_status_change_timer,
+                                                    bl->id, data);
+                return;
+            }
+        }
+            break;
+
+        case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
+        {
+            int  race = battle_get_race (bl);
+            if (race == 6
+                || battle_check_undead (race, battle_get_elem_type (bl)))
+            {
+                sc_data[type].timer =
+                    add_timer (1000 * 600 + tick, skill_status_change_timer,
+                               bl->id, data);
+                return;
+            }
+        }
+            break;
+
+        case SC_PROVOKE:       /* プロボック/オートバーサーク */
+            if (sc_data[type].val2 != 0)
+            {                   /* オートバーサーク(1秒ごとにHPチェック) */
+                if (sd && sd->status.hp > sd->status.max_hp >> 2)   /* 停止 */
+                    break;
+                sc_data[type].timer =
+                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
+                               data);
+                return;
+            }
+            break;
+
+        case SC_WATERBALL:     /* ウォーターボール */
+        {
+            struct block_list *target = map_id2bl (sc_data[type].val2);
+            if (target == NULL || target->prev == NULL)
+                break;
+            skill_attack (BF_MAGIC, bl, bl, target, WZ_WATERBALL,
+                          sc_data[type].val1, tick, 0);
+            if ((--sc_data[type].val3) > 0)
+            {
+                sc_data[type].timer =
+                    add_timer (150 + tick, skill_status_change_timer, bl->id,
+                               data);
+                return;
+            }
+        }
+            break;
+
+        case SC_ENDURE:        /* インデュア */
+            if (sd && sd->special_state.infinite_endure)
+            {
+                sc_data[type].timer =
+                    add_timer (1000 * 600 + tick, skill_status_change_timer,
+                               bl->id, data);
+                sc_data[type].val2 = 1;
+                return;
+            }
+            break;
+
+        case SC_DISSONANCE:    /* 不協和音 */
+            if ((--sc_data[type].val2) > 0)
+            {
+                struct skill_unit *unit =
+                    (struct skill_unit *) sc_data[type].val4;
+                struct block_list *src;
+
+                if (!unit || !unit->group)
+                    break;
+                src = map_id2bl (unit->group->src_id);
+                if (!src)
+                    break;
+                skill_attack (BF_MISC, src, &unit->bl, bl,
+                              unit->group->skill_id, sc_data[type].val1, tick,
+                              0);
+                sc_data[type].timer =
+                    add_timer (skill_get_time2
+                               (unit->group->skill_id,
+                                unit->group->skill_lv) + tick,
+                               skill_status_change_timer, bl->id, data);
+                return;
+            }
+            break;
+
+        case SC_LULLABY:       /* 子守唄 */
+            if ((--sc_data[type].val2) > 0)
+            {
+                struct skill_unit *unit =
+                    (struct skill_unit *) sc_data[type].val4;
+                if (!unit || !unit->group || unit->group->src_id == bl->id)
+                    break;
+                skill_additional_effect (bl, bl, unit->group->skill_id,
+                                         sc_data[type].val1,
+                                         BF_LONG | BF_SKILL | BF_MISC, tick);
+                sc_data[type].timer =
+                    add_timer (skill_get_time
+                               (unit->group->skill_id,
+                                unit->group->skill_lv) / 10 + tick,
+                               skill_status_change_timer, bl->id, data);
+                return;
+            }
+            break;
+
+        case SC_STONE:
+            if (sc_data[type].val2 != 0)
+            {
+                short *opt1 = battle_get_opt1 (bl);
+                sc_data[type].val2 = 0;
+                sc_data[type].val4 = 0;
+                battle_stopwalking (bl, 1);
+                if (opt1)
+                {
+                    *opt1 = 1;
+                    clif_changeoption (bl);
+                }
+                sc_data[type].timer =
+                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
+                               data);
+                return;
+            }
+            else if ((--sc_data[type].val3) > 0)
+            {
+                int  hp = battle_get_max_hp (bl);
+                if ((++sc_data[type].val4) % 5 == 0
+                    && battle_get_hp (bl) > hp >> 2)
+                {
+                    hp = hp / 100;
+                    if (hp < 1)
+                        hp = 1;
+                    if (bl->type == BL_PC)
+                        pc_heal ((struct map_session_data *) bl, -hp, 0);
+                    else if (bl->type == BL_MOB)
+                    {
+                        struct mob_data *md;
+                        if ((md = ((struct mob_data *) bl)) == NULL)
+                            break;
+                        md->hp -= hp;
+                    }
+                }
+                sc_data[type].timer =
+                    add_timer (1000 + tick, skill_status_change_timer, bl->id,
+                               data);
+                return;
+            }
+            break;
+        case SC_POISON:
+            if (sc_data[SC_SLOWPOISON].timer == -1)
+            {
+                const int resist_poison =
+                    skill_power_bl (bl, TMW_RESIST_POISON) >> 3;
+                if (resist_poison)
+                    sc_data[type].val1 -= MRAND (resist_poison + 1);
+
+                if ((--sc_data[type].val1) > 0)
+                {
+
+                    int  hp = battle_get_max_hp (bl);
+                    if (battle_get_hp (bl) > hp >> 4)
+                    {
+                        if (bl->type == BL_PC)
+                        {
+                            hp = 3 + hp * 3 / 200;
+                            pc_heal ((struct map_session_data *) bl, -hp, 0);
+                        }
+                        else if (bl->type == BL_MOB)
+                        {
+                            struct mob_data *md;
+                            if ((md = ((struct mob_data *) bl)) == NULL)
+                                break;
+                            hp = 3 + hp / 200;
+                            md->hp -= hp;
+                        }
+                    }
+                    sc_data[type].timer =
+                        add_timer (1000 + tick, skill_status_change_timer,
+                                   bl->id, data);
+                }
+            }
+            else
+                sc_data[type].timer =
+                    add_timer (2000 + tick, skill_status_change_timer, bl->id,
+                               data);
+            break;
+
+        case SC_TENSIONRELAX:  /* テンションリラックス */
+            if (sd)
+            {                   /* SPがあって、HPが満タンでなければ継続 */
+                if (sd->status.sp > 12 && sd->status.max_hp > sd->status.hp)
+                {
+                    if (sc_data[type].val2 % (sc_data[type].val1 + 3) == 0)
+                    {
+                        sd->status.sp -= 12;
+                        clif_updatestatus (sd, SP_SP);
+                    }
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        10000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+                if (sd->status.max_hp <= sd->status.hp)
+                    skill_status_change_end (&sd->bl, SC_TENSIONRELAX, -1);
+            }
+            break;
+
+            /* 時間切れ無し?? */
+        case SC_AETERNA:
+        case SC_TRICKDEAD:
+        case SC_RIDING:
+        case SC_FALCON:
+        case SC_WEIGHT50:
+        case SC_WEIGHT90:
+        case SC_MAGICPOWER:    /* 魔法力増幅 */
+        case SC_REJECTSWORD:   /* リジェクトソード */
+        case SC_MEMORIZE:      /* メモライズ */
+        case SC_BROKNWEAPON:
+        case SC_BROKNARMOR:
+            if (sc_data[type].timer == tid)
+                sc_data[type].timer =
+                    add_timer (1000 * 600 + tick, skill_status_change_timer,
+                               bl->id, data);
+            return;
+
+        case SC_DANCING:       //ダンススキルの時間SP消費
+        {
+            int  s = 0;
+            if (sd)
+            {
+                if (sd->status.sp > 0 && (--sc_data[type].val3) > 0)
+                {
+                    switch (sc_data[type].val1)
+                    {
+                        case BD_RICHMANKIM:    /* ニヨルドの宴 3秒にSP1 */
+                        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き 3秒にSP1 */
+                        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 3秒にSP1 */
+                        case BD_SIEGFRIED: /* 不死身のジークフリード 3秒にSP1 */
+                        case BA_DISSONANCE:    /* 不協和音 3秒でSP1 */
+                        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス 3秒でSP1 */
+                        case DC_UGLYDANCE: /* 自分勝手なダンス 3秒でSP1 */
+                            s = 3;
+                            break;
+                        case BD_LULLABY:   /* 子守歌 4秒にSP1 */
+                        case BD_ETERNALCHAOS:  /* 永遠の混沌 4秒にSP1 */
+                        case BD_ROKISWEIL: /* ロキの叫び 4秒にSP1 */
+                        case DC_FORTUNEKISS:   /* 幸運のキス 4秒でSP1 */
+                            s = 4;
+                            break;
+                        case BD_INTOABYSS: /* 深淵の中に 5秒にSP1 */
+                        case BA_WHISTLE:   /* 口笛 5秒でSP1 */
+                        case DC_HUMMING:   /* ハミング 5秒でSP1 */
+                        case BA_POEMBRAGI: /* ブラギの詩 5秒でSP1 */
+                        case DC_SERVICEFORYOU: /* サービスフォーユー 5秒でSP1 */
+                            s = 5;
+                            break;
+                        case BA_APPLEIDUN: /* イドゥンの林檎 6秒でSP1 */
+                            s = 6;
+                            break;
+                        case DC_DONTFORGETME:  /* 私を忘れないで… 10秒でSP1 */
+                        case CG_MOONLIT:   /* 月明りの泉に落ちる花びら 10秒でSP1? */
+                            s = 10;
+                            break;
+                    }
+                    if (s && ((sc_data[type].val3 % s) == 0))
+                    {
+                        sd->status.sp--;
+                        clif_updatestatus (sd, SP_SP);
+                    }
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        1000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+        }
+            break;
+        case SC_BERSERK:       /* バーサーク */
+            if (sd)
+            {                   /* HPが100以上なら継続 */
+                if ((sd->status.hp - sd->status.hp / 100) > 100)
+                {
+                    sd->status.hp -= sd->status.hp / 100;
+                    clif_updatestatus (sd, SP_HP);
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        15000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+            break;
+        case SC_WEDDING:       //結婚用(結婚衣裳になって歩くのが遅いとか)
+            if (sd)
+            {
+                time_t timer;
+                if (time (&timer) < ((sc_data[type].val2) + 3600))
+                {               //1時間たっていないので継続
+                    sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                        10000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+            break;
+        case SC_NOCHAT:        //チャット禁止状態
+            if (sd && battle_config.muting_players)
+            {
+                time_t timer;
+                if ((++sd->status.manner)
+                    && time (&timer) <
+                    ((sc_data[type].val2) + 60 * (0 - sd->status.manner)))
+                {               //開始からstatus.manner分経ってないので継続
+                    clif_updatestatus (sd, SP_MANNER);
+                    sc_data[type].timer = add_timer (   /* タイマー再設定(60秒) */
+                                                        60000 + tick,
+                                                        skill_status_change_timer,
+                                                        bl->id, data);
+                    return;
+                }
+            }
+            break;
+        case SC_SELFDESTRUCTION:   /* 自爆 */
+            if (--sc_data[type].val3 > 0)
+            {
+                struct mob_data *md;
+                if (bl->type == BL_MOB && (md = (struct mob_data *) bl)
+                    && md->stats[MOB_SPEED] > 250)
+                {
+                    md->stats[MOB_SPEED] -= 250;
+                    md->next_walktime = tick;
+                }
+                sc_data[type].timer = add_timer (   /* タイマー再設定 */
+                                                    1000 + tick,
+                                                    skill_status_change_timer,
+                                                    bl->id, data);
+                return;
+            }
+            break;
+
+        case SC_FLYING_BACKPACK:
+            clif_updatestatus (sd, SP_WEIGHT);
+            break;
+
+    }
+
+    skill_status_change_end (bl, type, tid);
+}
+
+/*==========================================
+ * ステータス異常終了
+ *------------------------------------------
+ */
+int skill_encchant_eremental_end (struct block_list *bl, int type)
+{
+    struct status_change *sc_data;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
+
+    if (type != SC_ENCPOISON && sc_data[SC_ENCPOISON].timer != -1)  /* エンチャントポイズン解除 */
+        skill_status_change_end (bl, SC_ENCPOISON, -1);
+    if (type != SC_ASPERSIO && sc_data[SC_ASPERSIO].timer != -1)    /* アスペルシオ解除 */
+        skill_status_change_end (bl, SC_ASPERSIO, -1);
+    if (type != SC_FLAMELAUNCHER && sc_data[SC_FLAMELAUNCHER].timer != -1)  /* フレイムランチャ解除 */
+        skill_status_change_end (bl, SC_FLAMELAUNCHER, -1);
+    if (type != SC_FROSTWEAPON && sc_data[SC_FROSTWEAPON].timer != -1)  /* フロストウェポン解除 */
+        skill_status_change_end (bl, SC_FROSTWEAPON, -1);
+    if (type != SC_LIGHTNINGLOADER && sc_data[SC_LIGHTNINGLOADER].timer != -1)  /* ライトニングローダー解除 */
+        skill_status_change_end (bl, SC_LIGHTNINGLOADER, -1);
+    if (type != SC_SEISMICWEAPON && sc_data[SC_SEISMICWEAPON].timer != -1)  /* サイスミックウェポン解除 */
+        skill_status_change_end (bl, SC_SEISMICWEAPON, -1);
+
+    return 0;
+}
+
+/*==========================================
+ * ステータス異常開始
+ *------------------------------------------
+ */
+int skill_status_change_start (struct block_list *bl, int type, int val1,
+                               int val2, int val3, int val4, int tick,
+                               int flag)
+{
+    return skill_status_effect (bl, type, val1, val2, val3, val4, tick, flag,
+                                0);
+}
+
+int skill_status_effect (struct block_list *bl, int type, int val1, int val2,
+                         int val3, int val4, int tick, int flag,
+                         int spell_invocation)
+{
+    struct map_session_data *sd = NULL;
+    struct status_change *sc_data;
+    short *sc_count, *option, *opt1, *opt2, *opt3;
+    int  opt_flag = 0, calc_flag = 0, updateflag =
+        0, race, mode, elem, undead_flag;
+    int  scdef = 0;
+
+    nullpo_retr (0, bl);
+    if (bl->type == BL_SKILL)
+        return 0;
+    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
+    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
+    nullpo_retr (0, option = battle_get_option (bl));
+    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
+    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
+    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
+
+    race = battle_get_race (bl);
+    mode = battle_get_mode (bl);
+    elem = battle_get_elem_type (bl);
+    undead_flag = battle_check_undead (race, elem);
+
+    if (type == SC_AETERNA
+        && (sc_data[SC_STONE].timer != -1 || sc_data[SC_FREEZE].timer != -1))
+        return 0;
+
+    switch (type)
+    {
+        case SC_STONE:
+        case SC_FREEZE:
+            scdef = 3 + battle_get_mdef (bl) + battle_get_luk (bl) / 3;
+            break;
+        case SC_STAN:
+        case SC_SILENCE:
+        case SC_POISON:
+            scdef = 3 + battle_get_vit (bl) + battle_get_luk (bl) / 3;
+            break;
+        case SC_SLEEP:
+        case SC_BLIND:
+            scdef = 3 + battle_get_int (bl) + battle_get_luk (bl) / 3;
+            break;
+        case SC_CURSE:
+            scdef = 3 + battle_get_luk (bl);
+            break;
+
+//      case SC_CONFUSION:
+        default:
+            scdef = 0;
+    }
+    if (scdef >= 100)
+        return 0;
+    if (bl->type == BL_PC)
+    {
+        sd = (struct map_session_data *) bl;
+        if (sd && type == SC_ADRENALINE
+            && !(skill_get_weapontype (BS_ADRENALINE) &
+                 (1 << sd->status.weapon)))
+            return 0;
+
+        if (SC_STONE <= type && type <= SC_BLIND)
+        {                       /* カードによる耐性 */
+            if (sd && sd->reseff[type - SC_STONE] > 0
+                && MRAND (10000) < sd->reseff[type - SC_STONE])
+            {
+                if (battle_config.battle_log)
+                    printf ("PC %d skill_sc_start: cardによる異常耐性発動\n",
+                            sd->bl.id);
+                return 0;
+            }
+        }
+    }
+    else if (bl->type == BL_MOB)
+    {
+    }
+    else
+    {
+        if (battle_config.error_log)
+            printf ("skill_status_change_start: neither MOB nor PC !\n");
+        return 0;
+    }
+
+    if (type == SC_FREEZE && undead_flag && !(flag & 1))
+        return 0;
+
+    if ((type == SC_ADRENALINE || type == SC_WEAPONPERFECTION
+         || type == SC_OVERTHRUST) && sc_data[type].timer != -1
+        && sc_data[type].val2 && !val2)
+        return 0;
+
+    if (mode & 0x20 && (type == SC_STONE || type == SC_FREEZE ||
+                        type == SC_STAN || type == SC_SLEEP
+                        || type == SC_SILENCE || type == SC_QUAGMIRE
+                        || type == SC_DECREASEAGI || type == SC_SIGNUMCRUCIS
+                        || type == SC_PROVOKE || (type == SC_BLESSING
+                                                  && (undead_flag
+                                                      || race == 6)))
+        && !(flag & 1))
+    {
+        /* ボスには効かない(ただしカードによる効果は適用される) */
+        return 0;
+    }
+    if (type == SC_FREEZE || type == SC_STAN || type == SC_SLEEP)
+        battle_stopwalking (bl, 1);
+
+    if (sc_data[type].timer != -1)
+    {                           /* すでに同じ異常になっている場合タイマ解除 */
+        if (sc_data[type].val1 > val1 && type != SC_COMBO && type != SC_DANCING && type != SC_DEVOTION && type != SC_SPEEDPOTION0 && type != SC_SPEEDPOTION1 && type != SC_SPEEDPOTION2 && type != SC_ATKPOT && type != SC_MATKPOT) // added atk and matk potions [Valaris]
+            return 0;
+        if (type >= SC_STAN && type <= SC_BLIND)
+            return 0;           /* 継ぎ足しができない状態異常である時は状態異常を行わない */
+        if (type == SC_GRAFFITI)
+        {                       //異常中にもう一度状態異常になった時に解除してから再度かかる
+            skill_status_change_end (bl, type, -1);
+        }
+        else
+        {
+            (*sc_count)--;
+            delete_timer (sc_data[type].timer, skill_status_change_timer);
+            sc_data[type].timer = -1;
+        }
+    }
+
+    switch (type)
+    {                           /* 異常の種類ごとの処理 */
+        case SC_PROVOKE:       /* プロボック */
+            calc_flag = 1;
+            if (tick <= 0)
+                tick = 1000;    /* (オートバーサーク) */
+            break;
+        case SC_ENDURE:        /* インデュア */
+            if (tick <= 0)
+                tick = 1000 * 60;
+            break;
+        case SC_CONCENTRATE:   /* 集中力向上 */
+            calc_flag = 1;
+            break;
+        case SC_BLESSING:      /* ブレッシング */
+        {
+            if (bl->type == BL_PC || (!undead_flag && race != 6))
+            {
+                if (sc_data[SC_CURSE].timer != -1)
+                    skill_status_change_end (bl, SC_CURSE, -1);
+                if (sc_data[SC_STONE].timer != -1
+                    && sc_data[SC_STONE].val2 == 0)
+                    skill_status_change_end (bl, SC_STONE, -1);
+            }
+            calc_flag = 1;
+        }
+            break;
+        case SC_ANGELUS:       /* アンゼルス */
+            calc_flag = 1;
+            break;
+        case SC_INCREASEAGI:   /* 速度上昇 */
+            calc_flag = 1;
+            if (sc_data[SC_DECREASEAGI].timer != -1)
+                skill_status_change_end (bl, SC_DECREASEAGI, -1);
+            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
+                skill_status_change_end (bl, SC_WINDWALK, -1);
+            break;
+        case SC_DECREASEAGI:   /* 速度減少 */
+            calc_flag = 1;
+            if (sc_data[SC_INCREASEAGI].timer != -1)
+                skill_status_change_end (bl, SC_INCREASEAGI, -1);
+            break;
+        case SC_SIGNUMCRUCIS:  /* シグナムクルシス */
+            calc_flag = 1;
+//          val2 = 14 + val1;
+            val2 = 10 + val1 * 2;
+            tick = 600 * 1000;
+            clif_emotion (bl, 4);
+            break;
+        case SC_SLOWPOISON:
+            if (sc_data[SC_POISON].timer == -1)
+                return 0;
+            break;
+        case SC_TWOHANDQUICKEN:    /* 2HQ */
+            *opt3 |= 1;
+            calc_flag = 1;
+            break;
+        case SC_ADRENALINE:    /* アドレナリンラッシュ */
+            calc_flag = 1;
+            break;
+        case SC_WEAPONPERFECTION:  /* ウェポンパーフェクション */
+            if (battle_config.party_skill_penaly && !val2)
+                tick /= 5;
+            break;
+        case SC_OVERTHRUST:    /* オーバースラスト */
+            *opt3 |= 2;
+            if (battle_config.party_skill_penaly && !val2)
+                tick /= 10;
+            break;
+        case SC_MAXIMIZEPOWER: /* マキシマイズパワー(SPが1減る時間,val2にも) */
+            if (bl->type == BL_PC)
+                val2 = tick;
+            else
+                tick = 5000 * val1;
+            break;
+        case SC_ENCPOISON:     /* エンチャントポイズン */
+            calc_flag = 1;
+            val2 = (((val1 - 1) / 2) + 3) * 100;    /* 毒付与確率 */
+            skill_encchant_eremental_end (bl, SC_ENCPOISON);
+            break;
+        case SC_POISONREACT:   /* ポイズンリアクト */
+            break;
+        case SC_IMPOSITIO:     /* インポシティオマヌス */
+            calc_flag = 1;
+            break;
+        case SC_ASPERSIO:      /* アスペルシオ */
+            skill_encchant_eremental_end (bl, SC_ASPERSIO);
+            break;
+        case SC_SUFFRAGIUM:    /* サフラギム */
+        case SC_BENEDICTIO:    /* 聖体 */
+        case SC_MAGNIFICAT:    /* マグニフィカート */
+        case SC_AETERNA:       /* エーテルナ */
+            break;
+        case SC_ENERGYCOAT:    /* エナジーコート */
+            *opt3 |= 4;
+            break;
+        case SC_MAGICROD:
+            val2 = val1 * 20;
+            break;
+        case SC_KYRIE:         /* キリエエレイソン */
+            val2 = battle_get_max_hp (bl) * (val1 * 2 + 10) / 100;  /* 耐久度 */
+            val3 = (val1 / 2 + 5);  /* 回数 */
+// -- moonsoul (added to undo assumptio status if target has it)
+            if (sc_data[SC_ASSUMPTIO].timer != -1)
+                skill_status_change_end (bl, SC_ASSUMPTIO, -1);
+            break;
+        case SC_MINDBREAKER:
+            calc_flag = 1;
+            if (tick <= 0)
+                tick = 1000;    /* (オートバーサーク) */
+        case SC_GLORIA:        /* グロリア */
+            calc_flag = 1;
+            break;
+        case SC_LOUD:          /* ラウドボイス */
+            calc_flag = 1;
+            break;
+        case SC_TRICKDEAD:     /* 死んだふり */
+            break;
+        case SC_QUAGMIRE:      /* クァグマイア */
+            calc_flag = 1;
+            if (sc_data[SC_CONCENTRATE].timer != -1)    /* 集中力向上解除 */
+                skill_status_change_end (bl, SC_CONCENTRATE, -1);
+            if (sc_data[SC_INCREASEAGI].timer != -1)    /* 速度上昇解除 */
+                skill_status_change_end (bl, SC_INCREASEAGI, -1);
+            if (sc_data[SC_TWOHANDQUICKEN].timer != -1)
+                skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1);
+            if (sc_data[SC_SPEARSQUICKEN].timer != -1)
+                skill_status_change_end (bl, SC_SPEARSQUICKEN, -1);
+            if (sc_data[SC_ADRENALINE].timer != -1)
+                skill_status_change_end (bl, SC_ADRENALINE, -1);
+            if (sc_data[SC_LOUD].timer != -1)
+                skill_status_change_end (bl, SC_LOUD, -1);
+            if (sc_data[SC_TRUESIGHT].timer != -1)  /* トゥルーサイト */
+                skill_status_change_end (bl, SC_TRUESIGHT, -1);
+            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
+                skill_status_change_end (bl, SC_WINDWALK, -1);
+            if (sc_data[SC_CARTBOOST].timer != -1)  /* カートブースト */
+                skill_status_change_end (bl, SC_CARTBOOST, -1);
+            break;
+        case SC_FLAMELAUNCHER: /* フレームランチャー */
+            skill_encchant_eremental_end (bl, SC_FLAMELAUNCHER);
+            break;
+        case SC_FROSTWEAPON:   /* フロストウェポン */
+            skill_encchant_eremental_end (bl, SC_FROSTWEAPON);
+            break;
+        case SC_LIGHTNINGLOADER:   /* ライトニングローダー */
+            skill_encchant_eremental_end (bl, SC_LIGHTNINGLOADER);
+            break;
+        case SC_SEISMICWEAPON: /* サイズミックウェポン */
+            skill_encchant_eremental_end (bl, SC_SEISMICWEAPON);
+            break;
+        case SC_DEVOTION:      /* ディボーション */
+            calc_flag = 1;
+            break;
+        case SC_PROVIDENCE:    /* プロヴィデンス */
+            calc_flag = 1;
+            val2 = val1 * 5;
+            break;
+        case SC_REFLECTSHIELD:
+            val2 = 10 + val1 * 3;
+            break;
+        case SC_STRIPWEAPON:
+        case SC_STRIPSHIELD:
+        case SC_STRIPARMOR:
+        case SC_STRIPHELM:
+        case SC_CP_WEAPON:
+        case SC_CP_SHIELD:
+        case SC_CP_ARMOR:
+        case SC_CP_HELM:
+            break;
+
+        case SC_AUTOSPELL:     /* オートスペル */
+            val4 = 5 + val1 * 2;
+            break;
+
+        case SC_VOLCANO:
+            calc_flag = 1;
+            val3 = val1 * 10;
+            val4 =
+                val1 >= 5 ? 20 : (val1 ==
+                                  4 ? 19 : (val1 ==
+                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
+            break;
+        case SC_DELUGE:
+            calc_flag = 1;
+            val3 =
+                val1 >= 5 ? 15 : (val1 ==
+                                  4 ? 14 : (val1 ==
+                                            3 ? 12 : (val1 == 2 ? 9 : 5)));
+            val4 =
+                val1 >= 5 ? 20 : (val1 ==
+                                  4 ? 19 : (val1 ==
+                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
+            break;
+        case SC_VIOLENTGALE:
+            calc_flag = 1;
+            val3 = val1 * 3;
+            val4 =
+                val1 >= 5 ? 20 : (val1 ==
+                                  4 ? 19 : (val1 ==
+                                            3 ? 17 : (val1 == 2 ? 14 : 10)));
+            break;
+
+        case SC_SPEARSQUICKEN: /* スピアクイッケン */
+            calc_flag = 1;
+            val2 = 20 + val1;
+            *opt3 |= 1;
+            break;
+        case SC_COMBO:
+            break;
+        case SC_BLADESTOP_WAIT:    /* 白刃取り(待ち) */
+            break;
+        case SC_BLADESTOP:     /* 白刃取り */
+            if (val2 == 2)
+                clif_bladestop ((struct block_list *) val3,
+                                (struct block_list *) val4, 1);
+            *opt3 |= 32;
+            break;
+
+        case SC_LULLABY:       /* 子守唄 */
+            val2 = 11;
+            break;
+        case SC_RICHMANKIM:
+            break;
+        case SC_ETERNALCHAOS:  /* エターナルカオス */
+            calc_flag = 1;
+            break;
+        case SC_DRUMBATTLE:    /* 戦太鼓の響き */
+            calc_flag = 1;
+            val2 = (val1 + 1) * 25;
+            val3 = (val1 + 1) * 2;
+            break;
+        case SC_NIBELUNGEN:    /* ニーベルングの指輪 */
+            calc_flag = 1;
+            val2 = (val1 + 2) * 50;
+            val3 = (val1 + 2) * 25;
+            break;
+        case SC_ROKISWEIL:     /* ロキの叫び */
+            break;
+        case SC_INTOABYSS:     /* 深淵の中に */
+            break;
+        case SC_SIEGFRIED:     /* 不死身のジークフリード */
+            calc_flag = 1;
+            val2 = 40 + val1 * 5;
+            val3 = val1 * 10;
+            break;
+        case SC_DISSONANCE:    /* 不協和音 */
+            val2 = 10;
+            break;
+        case SC_WHISTLE:       /* 口笛 */
+            calc_flag = 1;
+            break;
+        case SC_ASSNCROS:      /* 夕陽のアサシンクロス */
+            calc_flag = 1;
+            break;
+        case SC_POEMBRAGI:     /* ブラギの詩 */
+            break;
+        case SC_APPLEIDUN:     /* イドゥンの林檎 */
+            calc_flag = 1;
+            break;
+        case SC_UGLYDANCE:     /* 自分勝手なダンス */
+            val2 = 10;
+            break;
+        case SC_HUMMING:       /* ハミング */
+            calc_flag = 1;
+            break;
+        case SC_DONTFORGETME:  /* 私を忘れないで */
+            calc_flag = 1;
+            if (sc_data[SC_INCREASEAGI].timer != -1)    /* 速度上昇解除 */
+                skill_status_change_end (bl, SC_INCREASEAGI, -1);
+            if (sc_data[SC_TWOHANDQUICKEN].timer != -1)
+                skill_status_change_end (bl, SC_TWOHANDQUICKEN, -1);
+            if (sc_data[SC_SPEARSQUICKEN].timer != -1)
+                skill_status_change_end (bl, SC_SPEARSQUICKEN, -1);
+            if (sc_data[SC_ADRENALINE].timer != -1)
+                skill_status_change_end (bl, SC_ADRENALINE, -1);
+            if (sc_data[SC_ASSNCROS].timer != -1)
+                skill_status_change_end (bl, SC_ASSNCROS, -1);
+            if (sc_data[SC_TRUESIGHT].timer != -1)  /* トゥルーサイト */
+                skill_status_change_end (bl, SC_TRUESIGHT, -1);
+            if (sc_data[SC_WINDWALK].timer != -1)   /* ウインドウォーク */
+                skill_status_change_end (bl, SC_WINDWALK, -1);
+            if (sc_data[SC_CARTBOOST].timer != -1)  /* カートブースト */
+                skill_status_change_end (bl, SC_CARTBOOST, -1);
+            break;
+        case SC_FORTUNE:       /* 幸運のキス */
+            calc_flag = 1;
+            break;
+        case SC_SERVICE4U:     /* サービスフォーユー */
+            calc_flag = 1;
+            break;
+        case SC_DANCING:       /* ダンス/演奏中 */
+            calc_flag = 1;
+            val3 = tick / 1000;
+            tick = 1000;
+            break;
+
+        case SC_EXPLOSIONSPIRITS:  // 爆裂波動
+            calc_flag = 1;
+            val2 = 75 + 25 * val1;
+            *opt3 |= 8;
+            break;
+        case SC_STEELBODY:     // 金剛
+            calc_flag = 1;
+            *opt3 |= 16;
+            break;
+        case SC_EXTREMITYFIST: /* 阿修羅覇凰拳 */
+            break;
+        case SC_AUTOCOUNTER:
+            val3 = val4 = 0;
+            break;
+
+        case SC_SPEEDPOTION0:  /* 増速ポーション */
+            *opt2 |= 0x20;
+        case SC_SPEEDPOTION1:
+        case SC_SPEEDPOTION2:
+            calc_flag = 1;
+            tick = 1000 * tick;
+//          val2 = 5*(2+type-SC_SPEEDPOTION0);
+            break;
+
+            /* atk & matk potions [Valaris] */
+        case SC_ATKPOT:
+            *opt2 |= 0x80;
+        case SC_MATKPOT:
+            calc_flag = 1;
+            tick = 1000 * tick;
+            break;
+        case SC_WEDDING:       //結婚用(結婚衣裳になって歩くのが遅いとか)
+        {
+            time_t timer;
+
+            calc_flag = 1;
+            tick = 10000;
+            if (!val2)
+                val2 = time (&timer);
+        }
+            break;
+        case SC_NOCHAT:        //チャット禁止状態
+        {
+            time_t timer;
+
+            if (!battle_config.muting_players)
+                break;
+
+            tick = 60000;
+            if (!val2)
+                val2 = time (&timer);
+            updateflag = SP_MANNER;
+        }
+            break;
+        case SC_SELFDESTRUCTION:   //自爆
+            clif_skillcasting (bl, bl->id, bl->id, 0, 0, 331,
+                               skill_get_time (val2, val1));
+            val3 = tick / 1000;
+            tick = 1000;
+            break;
+
+            /* option1 */
+        case SC_STONE:         /* 石化 */
+            if (!(flag & 2))
+            {
+                int  sc_def = battle_get_mdef (bl) * 200;
+                tick = tick - sc_def;
+            }
+            val3 = tick / 1000;
+            if (val3 < 1)
+                val3 = 1;
+            tick = 5000;
+            val2 = 1;
+            break;
+        case SC_SLEEP:         /* 睡眠 */
+            if (!(flag & 2))
+            {
+//              int sc_def = 100 - (battle_get_int(bl) + battle_get_luk(bl)/3);
+//              tick = tick * sc_def / 100;
+//              if(tick < 1000) tick = 1000;
+                tick = 30000;   //睡眠はステータス耐性に関わらず30秒
+            }
+            break;
+        case SC_FREEZE:        /* 凍結 */
+            if (!(flag & 2))
+            {
+                int  sc_def = 100 - battle_get_mdef (bl);
+                tick = tick * sc_def / 100;
+            }
+            break;
+        case SC_STAN:          /* スタン(val2にミリ秒セット) */
+            if (!(flag & 2))
+            {
+                int  sc_def =
+                    100 - (battle_get_vit (bl) + battle_get_luk (bl) / 3);
+                tick = tick * sc_def / 100;
+            }
+            break;
+
+            /* option2 */
+        case SC_POISON:        /* 毒 */
+            calc_flag = 1;
+            if (!(flag & 2))
+            {
+                int  sc_def =
+                    100 - (battle_get_vit (bl) + battle_get_luk (bl) / 5);
+                tick = tick * sc_def / 100;
+            }
+            val3 = tick / 1000;
+            if (val3 < 1)
+                val3 = 1;
+            tick = 1000;
+            break;
+        case SC_SILENCE:       /* 沈黙(レックスデビーナ) */
+            if (!(flag & 2))
+            {
+                int  sc_def = 100 - battle_get_vit (bl);
+                tick = tick * sc_def / 100;
+            }
+            break;
+        case SC_BLIND:         /* 暗黒 */
+            calc_flag = 1;
+            if (!(flag & 2))
+            {
+                int  sc_def =
+                    battle_get_lv (bl) / 10 + battle_get_int (bl) / 15;
+                tick = 30000 - sc_def;
+            }
+            break;
+        case SC_CURSE:
+            calc_flag = 1;
+            if (!(flag & 2))
+            {
+                int  sc_def = 100 - battle_get_vit (bl);
+                tick = tick * sc_def / 100;
+            }
+            break;
+
+            /* option */
+        case SC_HIDING:        /* ハイディング */
+            calc_flag = 1;
+            if (bl->type == BL_PC)
+            {
+                val2 = tick / 1000; /* 持続時間 */
+                tick = 1000;
+            }
+            break;
+        case SC_CHASEWALK:
+        case SC_CLOAKING:      /* クローキング */
+            if (bl->type == BL_PC)
+                val2 = tick;
+            else
+                tick = 5000 * val1;
+            break;
+        case SC_SIGHT:         /* サイト/ルアフ */
+        case SC_RUWACH:
+            val2 = tick / 250;
+            tick = 10;
+            break;
+
+            /* セーフティウォール、ニューマ */
+        case SC_SAFETYWALL:
+        case SC_PNEUMA:
+            tick = ((struct skill_unit *) val2)->group->limit;
+            break;
+
+            /* アンクル */
+        case SC_ANKLE:
+            break;
+
+            /* ウォーターボール */
+        case SC_WATERBALL:
+            tick = 150;
+            if (val1 > 5)       //レベルが5以上の場合は25発に制限(1発目はすでに打ってるので-1)
+                val3 = 5 * 5 - 1;
+            else
+                val3 = (val1 | 1) * (val1 | 1) - 1;
+            break;
+
+            /* スキルじゃない/時間に関係しない */
+        case SC_RIDING:
+            calc_flag = 1;
+            tick = 600 * 1000;
+            break;
+        case SC_FALCON:
+        case SC_WEIGHT50:
+        case SC_WEIGHT90:
+        case SC_BROKNWEAPON:
+        case SC_BROKNARMOR:
+            tick = 600 * 1000;
+            break;
+
+        case SC_AUTOGUARD:
+        {
+            int  i, t;
+            for (i = val2 = 0; i < val1; i++)
+            {
+                t = 5 - (i >> 1);
+                val2 += (t < 0) ? 1 : t;
+            }
+        }
+            break;
+
+        case SC_DEFENDER:
+            calc_flag = 1;
+            val2 = 5 + val1 * 15;
+            break;
+
+        case SC_KEEPING:
+        case SC_BARRIER:
+        case SC_HALLUCINATION:
+            break;
+        case SC_CONCENTRATION: /* コンセントレーション */
+            *opt3 |= 1;
+            calc_flag = 1;
+            break;
+        case SC_TENSIONRELAX:  /* テンションリラックス */
+            calc_flag = 1;
+            if (bl->type == BL_PC)
+            {
+                tick = 10000;
+            }
+            break;
+        case SC_AURABLADE:     /* オーラブレード */
+        case SC_PARRYING:      /* パリイング */
+//      case SC_ASSUMPTIO:      /*  */
+        case SC_HEADCRUSH:     /* ヘッドクラッシュ */
+        case SC_JOINTBEAT:     /* ジョイントビート */
+//      case SC_MARIONETTE:     /* マリオネットコントロール */
+
+            //とりあえず手抜き
+            break;
+
+// -- moonsoul  (for new upper class related skill status effects)
+/*
+		case SC_AURABLADE:
+			val2 = val1*10;
+			break;
+		case SC_PARRYING:
+			val2=val1*3;
+			break;
+		case SC_CONCENTRATION:
+			calc_flag=1;
+			val2=val1*10;
+			val3=val1*5;
+			break;
+		case SC_TENSIONRELAX:
+//			val2 = 10;
+//			val3 = 15;
+			break;
+		case SC_BERSERK:
+			calc_flag=1;
+			break;
+		case SC_ASSUMPTIO:
+			if(sc_data[SC_KYRIE].timer!=-1 )
+				skill_status_change_end(bl,SC_KYRIE,-1);
+				break;
+*/
+        case SC_WINDWALK:      /* ウインドウォーク */
+            calc_flag = 1;
+            val2 = (val1 / 2);  //Flee上昇率
+            break;
+        case SC_BERSERK:       /* バーサーク */
+            if (sd)
+            {
+                sd->status.sp = 0;
+                clif_updatestatus (sd, SP_SP);
+                clif_status_change (bl, SC_INCREASEAGI, 1); /* アイコン表示 */
+            }
+            *opt3 |= 128;
+            tick = 1000;
+            calc_flag = 1;
+            break;
+        case SC_ASSUMPTIO:     /* アスムプティオ */
+            *opt3 |= 2048;
+            break;
+        case SC_MARIONETTE:    /* マリオネットコントロール */
+            *opt3 |= 1024;
+            break;
+        case SC_MELTDOWN:      /* メルトダウン */
+        case SC_CARTBOOST:     /* カートブースト */
+        case SC_TRUESIGHT:     /* トゥルーサイト */
+        case SC_SPIDERWEB:     /* スパイダーウェッブ */
+        case SC_MAGICPOWER:    /* 魔法力増幅 */
+            calc_flag = 1;
+            break;
+        case SC_REJECTSWORD:   /* リジェクトソード */
+            val2 = 3;           //3回攻撃を跳ね返す
+            break;
+        case SC_MEMORIZE:      /* メモライズ */
+            val2 = 3;           //3回詠唱を1/3にする
+            break;
+        case SC_GRAFFITI:      /* グラフィティ */
+        {
+            struct skill_unit_group *sg =
+                skill_unitsetting (bl, RG_GRAFFITI, val1, val2, val3, 0);
+            if (sg)
+                val4 = (int) sg;
+        }
+            break;
+        case SC_HASTE:
+            calc_flag = 1;
+        case SC_SPLASHER:      /* ベナムスプラッシャー */
+        case SC_PHYS_SHIELD:
+        case SC_MBARRIER:
+        case SC_HALT_REGENERATE:
+        case SC_HIDE:
+            break;
+        case SC_FLYING_BACKPACK:
+            updateflag = SP_WEIGHT;
+            break;
+        default:
+            if (battle_config.error_log)
+                printf ("UnknownStatusChange [%d]\n", type);
+            return 0;
+    }
+
+    if (bl->type == BL_PC && type < SC_SENDMAX)
+        clif_status_change (bl, type, 1);   /* アイコン表示 */
+
+    /* optionの変更 */
+    switch (type)
+    {
+        case SC_STONE:
+        case SC_FREEZE:
+        case SC_STAN:
+        case SC_SLEEP:
+            battle_stopattack (bl); /* 攻撃停止 */
+            skill_stop_dancing (bl, 0); /* 演奏/ダンスの中断 */
+            {                   /* 同時に掛からないステータス異常を解除 */
+                int  i;
+                for (i = SC_STONE; i <= SC_SLEEP; i++)
+                {
+                    if (sc_data[i].timer != -1)
+                    {
+                        (*sc_count)--;
+                        delete_timer (sc_data[i].timer,
+                                      skill_status_change_timer);
+                        sc_data[i].timer = -1;
+                    }
+                }
+            }
+            if (type == SC_STONE)
+                *opt1 = 6;
+            else
+                *opt1 = type - SC_STONE + 1;
+            opt_flag = 1;
+            break;
+        case SC_POISON:
+            if (sc_data[SC_SLOWPOISON].timer == -1)
+            {
+                *opt2 |= 0x1;
+                opt_flag = 1;
+            }
+            break;
+
+        case SC_CURSE:
+        case SC_SILENCE:
+        case SC_BLIND:
+            *opt2 |= 1 << (type - SC_POISON);
+            opt_flag = 1;
+            break;
+        case SC_SLOWPOISON:
+            *opt2 &= ~0x1;
+            *opt2 |= 0x200;
+            opt_flag = 1;
+            break;
+        case SC_SIGNUMCRUCIS:
+            *opt2 |= 0x40;
+            opt_flag = 1;
+            break;
+        case SC_HIDING:
+        case SC_CLOAKING:
+            battle_stopattack (bl); /* 攻撃停止 */
+            *option |= ((type == SC_HIDING) ? 2 : 4);
+            opt_flag = 1;
+            break;
+        case SC_CHASEWALK:
+            battle_stopattack (bl); /* 攻撃停止 */
+            *option |= 16388;
+            opt_flag = 1;
+            break;
+        case SC_SIGHT:
+            *option |= 1;
+            opt_flag = 1;
+            break;
+        case SC_RUWACH:
+            *option |= 8192;
+            opt_flag = 1;
+            break;
+        case SC_WEDDING:
+            *option |= 4096;
+            opt_flag = 1;
+    }
+
+    if (opt_flag)               /* optionの変更 */
+        clif_changeoption (bl);
+
+    (*sc_count)++;              /* ステータス異常の数 */
+
+    sc_data[type].val1 = val1;
+    sc_data[type].val2 = val2;
+    sc_data[type].val3 = val3;
+    sc_data[type].val4 = val4;
+    if (sc_data[type].spell_invocation) // Supplant by newer spell
+        spell_effect_report_termination (sc_data[type].spell_invocation,
+                                         bl->id, type, 1);
+
+    sc_data[type].spell_invocation = spell_invocation;
+
+    /* タイマー設定 */
+    sc_data[type].timer =
+        add_timer (gettick () + tick, skill_status_change_timer, bl->id,
+                   type);
+
+    if (bl->type == BL_PC && calc_flag)
+        pc_calcstatus (sd, 0);  /* ステータス再計算 */
+
+    if (bl->type == BL_PC && updateflag)
+        clif_updatestatus (sd, updateflag); /* ステータスをクライアントに送る */
+
+    return 0;
+}
+
+/*==========================================
+ * ステータス異常全解除
+ *------------------------------------------
+ */
+int skill_status_change_clear (struct block_list *bl, int type)
+{
+    struct status_change *sc_data;
+    short *sc_count, *option, *opt1, *opt2, *opt3;
+    int  i;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, sc_data = battle_get_sc_data (bl));
+    nullpo_retr (0, sc_count = battle_get_sc_count (bl));
+    nullpo_retr (0, option = battle_get_option (bl));
+    nullpo_retr (0, opt1 = battle_get_opt1 (bl));
+    nullpo_retr (0, opt2 = battle_get_opt2 (bl));
+    nullpo_retr (0, opt3 = battle_get_opt3 (bl));
+
+    if (*sc_count == 0)
+        return 0;
+    for (i = 0; i < MAX_STATUSCHANGE; i++)
+    {
+        if (sc_data[i].timer != -1)
+        {                       /* 異常があるならタイマーを削除する */
+/*
+			delete_timer(sc_data[i].timer, skill_status_change_timer);
+			sc_data[i].timer = -1;
+
+			if (!type && i < SC_SENDMAX)
+				clif_status_change(bl, i, 0);
+*/
+
+            skill_status_change_end (bl, i, -1);
+        }
+    }
+    *sc_count = 0;
+    *opt1 = 0;
+    *opt2 = 0;
+    *opt3 = 0;
+    *option &= OPTION_MASK;
+
+    if (night_flag == 1 && type == BL_PC)   // by [Yor]
+        *opt2 |= STATE_BLIND;
+
+    if (!type || type & 2)
+        clif_changeoption (bl);
+
+    return 0;
+}
+
+/* クローキング検査(周りに移動不可能地帯があるか) */
+int skill_check_cloaking (struct block_list *bl)
+{
+    struct map_session_data *sd = NULL;
+    static int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
+    static int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
+    int  end = 1, i;
+
+    nullpo_retr (0, bl);
+
+    if (pc_checkskill (sd, AS_CLOAKING) > 2)
+        return 0;
+    if (bl->type == BL_PC && battle_config.pc_cloak_check_type & 1)
+        return 0;
+    if (bl->type == BL_MOB && battle_config.monster_cloak_check_type & 1)
+        return 0;
+    for (i = 0; i < sizeof (dx) / sizeof (dx[0]); i++)
+    {
+        int  c = map_getcell (bl->m, bl->x + dx[i], bl->y + dy[i]);
+        if (c == 1 || c == 5)
+            end = 0;
+    }
+    if (end)
+    {
+        skill_status_change_end (bl, SC_CLOAKING, -1);
+        *battle_get_option (bl) &= ~4;  /* 念のための処理 */
+    }
+    return end;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * スキルユニット
+ *----------------------------------------------------------------------------
+ */
+
+/*==========================================
+ * 演奏/ダンススキルかどうか判定
+ * 引数 スキルID
+ * 戻り ダンスじゃない=0 合奏=2 それ以外のダンス=1
+ *------------------------------------------
+ */
+int skill_is_danceskill (int id)
+{
+    int  i;
+    switch (id)
+    {
+        case BD_LULLABY:       /* 子守歌 */
+        case BD_RICHMANKIM:    /* ニヨルドの宴 */
+        case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+        case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+        case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+        case BD_ROKISWEIL:     /* ロキの叫び */
+        case BD_INTOABYSS:     /* 深淵の中に */
+        case BD_SIEGFRIED:     /* 不死身のジークフリード */
+        case BD_RAGNAROK:      /* 神々の黄昏 */
+        case CG_MOONLIT:       /* 月明りの泉に落ちる花びら */
+            i = 2;
+            break;
+        case BA_DISSONANCE:    /* 不協和音 */
+        case BA_FROSTJOKE:     /* 寒いジョーク */
+        case BA_WHISTLE:       /* 口笛 */
+        case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */
+        case BA_POEMBRAGI:     /* ブラギの詩 */
+        case BA_APPLEIDUN:     /* イドゥンの林檎 */
+        case DC_UGLYDANCE:     /* 自分勝手なダンス */
+        case DC_SCREAM:        /* スクリーム */
+        case DC_HUMMING:       /* ハミング */
+        case DC_DONTFORGETME:  /* 私を忘れないで… */
+        case DC_FORTUNEKISS:   /* 幸運のキス */
+        case DC_SERVICEFORYOU: /* サービスフォーユー */
+            i = 1;
+            break;
+        default:
+            i = 0;
+    }
+    return i;
+}
+
+/*==========================================
+ * 演奏/ダンスをやめる
+ * flag 1で合奏中なら相方にユニットを任せる
+ *
+ *------------------------------------------
+ */
+void skill_stop_dancing (struct block_list *src, int flag)
+{
+    struct status_change *sc_data;
+    struct skill_unit_group *group;
+
+    nullpo_retv (src);
+
+    sc_data = battle_get_sc_data (src);
+    if (sc_data && sc_data[SC_DANCING].timer == -1)
+        return;
+    group = (struct skill_unit_group *) sc_data[SC_DANCING].val2;   //ダンスのスキルユニットIDはval2に入ってる
+    if (group && src->type == BL_PC && sc_data && sc_data[SC_DANCING].val4)
+    {                           //合奏中断
+        struct map_session_data *dsd = map_id2sd (sc_data[SC_DANCING].val4);    //相方のsd取得
+        if (flag)
+        {                       //ログアウトなど片方が落ちても演奏が継続される
+            if (dsd && src->id == group->src_id)
+            {                   //グループを持ってるPCが落ちる
+                group->src_id = sc_data[SC_DANCING].val4;   //相方にグループを任せる
+                if (flag & 1)   //ログアウト
+                    dsd->sc_data[SC_DANCING].val4 = 0;  //相方の相方を0にして合奏終了→通常のダンス状態
+                if (flag & 2)   //ハエ飛びなど
+                    return;     //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり
+            }
+            else if (dsd && dsd->bl.id == group->src_id)
+            {                   //相方がグループを持っているPCが落ちる(自分はグループを持っていない)
+                if (flag & 1)   //ログアウト
+                    dsd->sc_data[SC_DANCING].val4 = 0;  //相方の相方を0にして合奏終了→通常のダンス状態
+                if (flag & 2)   //ハエ飛びなど
+                    return;     //合奏もダンス状態も終了させない&スキルユニットは置いてけぼり
+            }
+            skill_status_change_end (src, SC_DANCING, -1);  //自分のステータスを終了させる
+            //そしてグループは消さない&消さないのでステータス計算もいらない?
+            return;
+        }
+        else
+        {
+            if (dsd && src->id == group->src_id)
+            {                   //グループを持ってるPCが止める
+                skill_status_change_end ((struct block_list *) dsd, SC_DANCING, -1);    //相手のステータスを終了させる
+            }
+            if (dsd && dsd->bl.id == group->src_id)
+            {                   //相方がグループを持っているPCが止める(自分はグループを持っていない)
+                skill_status_change_end (src, SC_DANCING, -1);  //自分のステータスを終了させる
+            }
+        }
+    }
+    if (flag & 2 && group && src->type == BL_PC)
+    {                           //ハエで飛んだときとかはユニットも飛ぶ
+        struct map_session_data *sd = (struct map_session_data *) src;
+        skill_unit_move_unit_group (group, sd->bl.m, (sd->to_x - sd->bl.x),
+                                    (sd->to_y - sd->bl.y));
+        return;
+    }
+    skill_delunitgroup (group);
+    if (src->type == BL_PC)
+        pc_calcstatus ((struct map_session_data *) src, 0);
+}
+
+/*==========================================
+ * スキルユニット初期化
+ *------------------------------------------
+ */
+struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx,
+                                   int x, int y)
+{
+    struct skill_unit *unit;
+
+    nullpo_retr (NULL, group);
+    nullpo_retr (NULL, unit = &group->unit[idx]);
+
+    if (!unit->alive)
+        group->alive_count++;
+
+    unit->bl.id = map_addobject (&unit->bl);
+    unit->bl.type = BL_SKILL;
+    unit->bl.m = group->map;
+    unit->bl.x = x;
+    unit->bl.y = y;
+    unit->group = group;
+    unit->val1 = unit->val2 = 0;
+    unit->alive = 1;
+
+    map_addblock (&unit->bl);
+    clif_skill_setunit (unit);
+    return unit;
+}
+
+int  skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap);
+/*==========================================
+ * スキルユニット削除
+ *------------------------------------------
+ */
+int skill_delunit (struct skill_unit *unit)
+{
+    struct skill_unit_group *group;
+    int  range;
+
+    nullpo_retr (0, unit);
+    if (!unit->alive)
+        return 0;
+    nullpo_retr (0, group = unit->group);
+
+    /* onlimitイベント呼び出し */
+    skill_unit_onlimit (unit, gettick ());
+
+    /* ondeleteイベント呼び出し */
+    range = group->range;
+    map_foreachinarea (skill_unit_timer_sub_ondelete, unit->bl.m,
+                       unit->bl.x - range, unit->bl.y - range,
+                       unit->bl.x + range, unit->bl.y + range, 0, &unit->bl,
+                       gettick ());
+
+    clif_skill_delunit (unit);
+
+    unit->group = NULL;
+    unit->alive = 0;
+    map_delobjectnofree (unit->bl.id, BL_SKILL);
+    if (group->alive_count > 0 && (--group->alive_count) <= 0)
+        skill_delunitgroup (group);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットグループ初期化
+ *------------------------------------------
+ */
+static int skill_unit_group_newid = 10;
+struct skill_unit_group *skill_initunitgroup (struct block_list *src,
+                                              int count, int skillid,
+                                              int skilllv, int unit_id)
+{
+    int  i;
+    struct skill_unit_group *group = NULL, *list = NULL;
+    int  maxsug = 0;
+
+    nullpo_retr (NULL, src);
+
+    if (src->type == BL_PC)
+    {
+        list = ((struct map_session_data *) src)->skillunit;
+        maxsug = MAX_SKILLUNITGROUP;
+    }
+    else if (src->type == BL_MOB)
+    {
+        list = ((struct mob_data *) src)->skillunit;
+        maxsug = MAX_MOBSKILLUNITGROUP;
+    }
+    if (list)
+    {
+        for (i = 0; i < maxsug; i++)    /* 空いているもの検索 */
+            if (list[i].group_id == 0)
+            {
+                group = &list[i];
+                break;
+            }
+
+        if (group == NULL)
+        {                       /* 空いてないので古いもの検索 */
+            int  j = 0;
+            unsigned maxdiff = 0, x, tick = gettick ();
+            for (i = 0; i < maxsug; i++)
+                if ((x = DIFF_TICK (tick, list[i].tick)) > maxdiff)
+                {
+                    maxdiff = x;
+                    j = i;
+                }
+            skill_delunitgroup (&list[j]);
+            group = &list[j];
+        }
+    }
+
+    if (group == NULL)
+    {
+        printf ("skill_initunitgroup: error unit group !\n");
+        exit (1);
+    }
+
+    group->src_id = src->id;
+    group->party_id = battle_get_party_id (src);
+    group->guild_id = battle_get_guild_id (src);
+    group->group_id = skill_unit_group_newid++;
+    if (skill_unit_group_newid <= 0)
+        skill_unit_group_newid = 10;
+    CREATE (group->unit, struct skill_unit, count);
+    group->unit_count = count;
+    group->val1 = group->val2 = 0;
+    group->skill_id = skillid;
+    group->skill_lv = skilllv;
+    group->unit_id = unit_id;
+    group->map = src->m;
+    group->range = 0;
+    group->limit = 10000;
+    group->interval = 1000;
+    group->tick = gettick ();
+    group->valstr = NULL;
+
+    if (skill_is_danceskill (skillid))
+    {
+        struct map_session_data *sd = NULL;
+        if (src->type == BL_PC && (sd = (struct map_session_data *) src))
+        {
+            sd->skillid_dance = skillid;
+            sd->skilllv_dance = skilllv;
+        }
+        skill_status_change_start (src, SC_DANCING, skillid, (int) group, 0,
+                                   0, skill_get_time (skillid,
+                                                      skilllv) + 1000, 0);
+        switch (skillid)
+        {                       //合奏スキルは相方をダンス状態にする
+            case BD_LULLABY:   /* 子守歌 */
+            case BD_RICHMANKIM:    /* ニヨルドの宴 */
+            case BD_ETERNALCHAOS:  /* 永遠の混沌 */
+            case BD_DRUMBATTLEFIELD:   /* 戦太鼓の響き */
+            case BD_RINGNIBELUNGEN:    /* ニーベルングの指輪 */
+            case BD_ROKISWEIL: /* ロキの叫び */
+            case BD_INTOABYSS: /* 深淵の中に */
+            case BD_SIEGFRIED: /* 不死身のジークフリード */
+            case BD_RAGNAROK:  /* 神々の黄昏 */
+            case CG_MOONLIT:   /* 月明りの泉に落ちる花びら */
+            {
+                int  range = 1;
+                int  c = 0;
+                if (sd)
+                {
+                    map_foreachinarea (skill_check_condition_use_sub,
+                                       sd->bl.m, sd->bl.x - range,
+                                       sd->bl.y - range, sd->bl.x + range,
+                                       sd->bl.y + range, BL_PC, &sd->bl, &c);
+                }
+            }
+        }
+    }
+    return group;
+}
+
+/*==========================================
+ * スキルユニットグループ削除
+ *------------------------------------------
+ */
+int skill_delunitgroup (struct skill_unit_group *group)
+{
+    struct block_list *src;
+    int  i;
+
+    nullpo_retr (0, group);
+    if (group->unit_count <= 0)
+        return 0;
+
+    src = map_id2bl (group->src_id);
+    if (skill_is_danceskill (group->skill_id))
+    {                           //ダンススキルはダンス状態を解除する
+        if (src)
+            skill_status_change_end (src, SC_DANCING, -1);
+    }
+
+    group->alive_count = 0;
+    if (group->unit != NULL)
+    {
+        for (i = 0; i < group->unit_count; i++)
+            if (group->unit[i].alive)
+                skill_delunit (&group->unit[i]);
+    }
+    if (group->valstr != NULL)
+    {
+        map_freeblock (group->valstr);
+        group->valstr = NULL;
+    }
+
+    map_freeblock (group->unit);    /* free()の替わり */
+    group->unit = NULL;
+    group->src_id = 0;
+    group->group_id = 0;
+    group->unit_count = 0;
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットグループ全削除
+ *------------------------------------------
+ */
+int skill_clear_unitgroup (struct block_list *src)
+{
+    struct skill_unit_group *group = NULL;
+    int  maxsug = 0;
+
+    nullpo_retr (0, src);
+
+    if (src->type == BL_PC)
+    {
+        group = ((struct map_session_data *) src)->skillunit;
+        maxsug = MAX_SKILLUNITGROUP;
+    }
+    else if (src->type == BL_MOB)
+    {
+        group = ((struct mob_data *) src)->skillunit;
+        maxsug = MAX_MOBSKILLUNITGROUP;
+    }
+    if (group)
+    {
+        int  i;
+        for (i = 0; i < maxsug; i++)
+            if (group[i].group_id > 0 && group[i].src_id == src->id)
+                skill_delunitgroup (&group[i]);
+    }
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットグループの被影響tick検索
+ *------------------------------------------
+ */
+struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct
+                                                                block_list
+                                                                *bl,
+                                                                int group_id)
+{
+    int  i, j = 0, k, s = group_id % MAX_SKILLUNITGROUPTICKSET;
+    struct skill_unit_group_tickset *set = NULL;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+    {
+        set = ((struct map_session_data *) bl)->skillunittick;
+    }
+    else
+    {
+        set = ((struct mob_data *) bl)->skillunittick;
+    }
+    if (set == NULL)
+        return 0;
+    for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++)
+        if (set[(k = (i + s) % MAX_SKILLUNITGROUPTICKSET)].group_id ==
+            group_id)
+            return &set[k];
+        else if (set[k].group_id == 0)
+            j = k;
+
+    return &set[j];
+}
+
+/*==========================================
+ * スキルユニットグループの被影響tick削除
+ *------------------------------------------
+ */
+int skill_unitgrouptickset_delete (struct block_list *bl, int group_id)
+{
+    int  i, s = group_id % MAX_SKILLUNITGROUPTICKSET;
+    struct skill_unit_group_tickset *set = NULL, *ts;
+
+    nullpo_retr (0, bl);
+
+    if (bl->type == BL_PC)
+    {
+        set = ((struct map_session_data *) bl)->skillunittick;
+    }
+    else
+    {
+        set = ((struct mob_data *) bl)->skillunittick;
+    }
+
+    if (set != NULL)
+    {
+
+        for (i = 0; i < MAX_SKILLUNITGROUPTICKSET; i++)
+            if ((ts =
+                 &set[(i + s) % MAX_SKILLUNITGROUPTICKSET])->group_id ==
+                group_id)
+                ts->group_id = 0;
+
+    }
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットタイマー発動処理用(foreachinarea)
+ *------------------------------------------
+ */
+int skill_unit_timer_sub_onplace (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    struct skill_unit *su;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    src = va_arg (ap, struct block_list *);
+
+    tick = va_arg (ap, unsigned int);
+    su = (struct skill_unit *) src;
+
+    if (su && su->alive)
+    {
+        struct skill_unit_group *sg;
+        sg = su->group;
+        if (sg && battle_check_target (src, bl, sg->target_flag) > 0)
+            skill_unit_onplace (su, bl, tick);
+    }
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットタイマー削除処理用(foreachinarea)
+ *------------------------------------------
+ */
+int skill_unit_timer_sub_ondelete (struct block_list *bl, va_list ap)
+{
+    struct block_list *src;
+    struct skill_unit *su;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    src = va_arg (ap, struct block_list *);
+
+    tick = va_arg (ap, unsigned int);
+    su = (struct skill_unit *) src;
+
+    if (su && su->alive)
+    {
+        struct skill_unit_group *sg;
+        sg = su->group;
+        if (sg && battle_check_target (src, bl, sg->target_flag) > 0)
+            skill_unit_ondelete (su, bl, tick);
+    }
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットタイマー処理用(foreachobject)
+ *------------------------------------------
+ */
+int skill_unit_timer_sub (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    struct skill_unit_group *group;
+    int  range;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, unit = (struct skill_unit *) bl);
+    nullpo_retr (0, group = unit->group);
+    tick = va_arg (ap, unsigned int);
+
+    if (!unit->alive)
+        return 0;
+
+    range = (unit->range != 0) ? unit->range : group->range;
+
+    /* onplaceイベント呼び出し */
+    if (unit->alive && unit->range >= 0)
+    {
+        map_foreachinarea (skill_unit_timer_sub_onplace, bl->m,
+                           bl->x - range, bl->y - range, bl->x + range,
+                           bl->y + range, 0, bl, tick);
+        if (group->unit_id == 0xaa
+            && DIFF_TICK (tick, group->tick) >= 6000 * group->val2)
+        {
+            map_foreachinarea (skill_idun_heal, bl->m,
+                               bl->x - range, bl->y - range, bl->x + range,
+                               bl->y + range, 0, unit);
+            group->val2++;
+        }
+    }
+    /* 時間切れ削除 */
+    if (unit->alive &&
+        (DIFF_TICK (tick, group->tick) >= group->limit
+         || DIFF_TICK (tick, group->tick) >= unit->limit))
+    {
+        switch (group->unit_id)
+        {
+
+            case 0x8f:         /* ブラストマイン */
+                group->unit_id = 0x8c;
+                clif_changelook (bl, LOOK_BASE, group->unit_id);
+                group->limit = DIFF_TICK (tick + 1500, group->tick);
+                unit->limit = DIFF_TICK (tick + 1500, group->tick);
+                break;
+            case 0x90:         /* スキッドトラップ */
+            case 0x91:         /* アンクルスネア */
+            case 0x93:         /* ランドマイン */
+            case 0x94:         /* ショックウェーブトラップ */
+            case 0x95:         /* サンドマン */
+            case 0x96:         /* フラッシャー */
+            case 0x97:         /* フリージングトラップ */
+            case 0x98:         /* クレイモアートラップ */
+            case 0x99:         /* トーキーボックス */
+            {
+                struct block_list *src = map_id2bl (group->src_id);
+                if (group->unit_id == 0x91 && group->val2);
+                else
+                {
+                    if (src && src->type == BL_PC)
+                    {
+                        struct item item_tmp;
+                        memset (&item_tmp, 0, sizeof (item_tmp));
+                        item_tmp.nameid = 1065;
+                        item_tmp.identify = 1;
+                        map_addflooritem (&item_tmp, 1, bl->m, bl->x, bl->y, NULL, NULL, NULL, 0);  // 罠返還
+                    }
+                }
+            }
+            default:
+                skill_delunit (unit);
+        }
+    }
+
+    if (group->unit_id == 0x8d)
+    {
+        unit->val1 -= 5;
+        if (unit->val1 <= 0 && unit->limit + group->tick > tick + 700)
+            unit->limit = DIFF_TICK (tick + 700, group->tick);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニットタイマー処理
+ *------------------------------------------
+ */
+void skill_unit_timer (timer_id tid, tick_t tick, custom_id_t id, custom_data_t data)
+{
+    map_freeblock_lock ();
+
+    map_foreachobject (skill_unit_timer_sub, BL_SKILL, tick);
+
+    map_freeblock_unlock ();
+}
+
+/*==========================================
+ * スキルユニット移動時処理用(foreachinarea)
+ *------------------------------------------
+ */
+int skill_unit_out_all_sub (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    struct skill_unit_group *group;
+    struct block_list *src;
+    int  range;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    nullpo_retr (0, unit = (struct skill_unit *) bl);
+    nullpo_retr (0, group = unit->group);
+
+    tick = va_arg (ap, unsigned int);
+
+    if (!unit->alive || src->prev == NULL)
+        return 0;
+
+    range = (unit->range != 0) ? unit->range : group->range;
+
+    if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0)
+        return 0;
+
+    if (src->x >= bl->x - range && src->x <= bl->x + range &&
+        src->y >= bl->y - range && src->y <= bl->y + range)
+        skill_unit_onout (unit, src, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット移動時処理
+ *------------------------------------------
+ */
+int skill_unit_out_all (struct block_list *bl, unsigned int tick, int range)
+{
+    nullpo_retr (0, bl);
+
+    if (bl->prev == NULL)
+        return 0;
+
+    if (range < 7)
+        range = 7;
+    map_foreachinarea (skill_unit_out_all_sub,
+                       bl->m, bl->x - range, bl->y - range, bl->x + range,
+                       bl->y + range, BL_SKILL, bl, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット移動時処理用(foreachinarea)
+ *------------------------------------------
+ */
+int skill_unit_move_sub (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    struct skill_unit_group *group;
+    struct block_list *src;
+    int  range;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, unit = (struct skill_unit *) bl);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+
+    tick = va_arg (ap, unsigned int);
+
+    if (!unit->alive || src->prev == NULL)
+        return 0;
+
+    if ((group = unit->group) == NULL)
+        return 0;
+    range = (unit->range != 0) ? unit->range : group->range;
+
+    if (range < 0 || battle_check_target (bl, src, group->target_flag) <= 0)
+        return 0;
+
+    if (src->x >= bl->x - range && src->x <= bl->x + range &&
+        src->y >= bl->y - range && src->y <= bl->y + range)
+        skill_unit_onplace (unit, src, tick);
+    else
+        skill_unit_onout (unit, src, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット移動時処理
+ *------------------------------------------
+ */
+int skill_unit_move (struct block_list *bl, unsigned int tick, int range)
+{
+    nullpo_retr (0, bl);
+
+    if (bl->prev == NULL)
+        return 0;
+
+    if (range < 7)
+        range = 7;
+    map_foreachinarea (skill_unit_move_sub,
+                       bl->m, bl->x - range, bl->y - range, bl->x + range,
+                       bl->y + range, BL_SKILL, bl, tick);
+
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット自体の移動時処理(foreachinarea)
+ *------------------------------------------
+ */
+int skill_unit_move_unit_group_sub (struct block_list *bl, va_list ap)
+{
+    struct skill_unit *unit;
+    struct skill_unit_group *group;
+    struct block_list *src;
+    int  range;
+    unsigned int tick;
+
+    nullpo_retr (0, bl);
+    nullpo_retr (0, ap);
+    nullpo_retr (0, src = va_arg (ap, struct block_list *));
+    nullpo_retr (0, unit = (struct skill_unit *) src);
+    nullpo_retr (0, group = unit->group);
+
+    tick = va_arg (ap, unsigned int);
+
+    if (!unit->alive || bl->prev == NULL)
+        return 0;
+
+    range = (unit->range != 0) ? unit->range : group->range;
+
+    if (range < 0 || battle_check_target (src, bl, group->target_flag) <= 0)
+        return 0;
+    if (bl->x >= src->x - range && bl->x <= src->x + range &&
+        bl->y >= src->y - range && bl->y <= src->y + range)
+        skill_unit_onplace (unit, bl, tick);
+    else
+        skill_unit_onout (unit, bl, tick);
+    return 0;
+}
+
+/*==========================================
+ * スキルユニット自体の移動時処理
+ * 引数はグループと移動量
+ *------------------------------------------
+ */
+int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx,
+                                int dy)
+{
+    nullpo_retr (0, group);
+
+    if (group->unit_count <= 0)
+        return 0;
+
+    if (group->unit != NULL)
+    {
+        if (!battle_config.unit_movement_type)
+        {
+            int  i;
+            for (i = 0; i < group->unit_count; i++)
+            {
+                struct skill_unit *unit = &group->unit[i];
+                if (unit->alive && !(m == unit->bl.m && dx == 0 && dy == 0))
+                {
+                    int  range = unit->range;
+                    map_delblock (&unit->bl);
+                    unit->bl.m = m;
+                    unit->bl.x += dx;
+                    unit->bl.y += dy;
+                    map_addblock (&unit->bl);
+                    clif_skill_setunit (unit);
+                    if (range > 0)
+                    {
+                        if (range < 7)
+                            range = 7;
+                        map_foreachinarea (skill_unit_move_unit_group_sub,
+                                           unit->bl.m, unit->bl.x - range,
+                                           unit->bl.y - range,
+                                           unit->bl.x + range,
+                                           unit->bl.y + range, 0, &unit->bl,
+                                           gettick ());
+                    }
+                }
+            }
+        }
+        else
+        {
+            int  i, j, *r_flag, *s_flag, *m_flag;
+            struct skill_unit *unit1;
+            struct skill_unit *unit2;
+            r_flag = (int *) malloc (sizeof (int) * group->unit_count);
+            s_flag = (int *) malloc (sizeof (int) * group->unit_count);
+            m_flag = (int *) malloc (sizeof (int) * group->unit_count);
+            memset (r_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
+            memset (s_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
+            memset (m_flag, 0, sizeof (int) * group->unit_count);   // 継承フラグ
+
+            //先にフラグを全部決める
+            for (i = 0; i < group->unit_count; i++)
+            {
+                int  move_check = 0;    // かぶりフラグ
+                unit1 = &group->unit[i];
+                for (j = 0; j < group->unit_count; j++)
+                {
+                    unit2 = &group->unit[j];
+                    if (unit1->bl.m == m && unit1->bl.x + dx == unit2->bl.x
+                        && unit1->bl.y + dy == unit2->bl.y)
+                    {
+                        //移動先にユニットがかぶってたら
+                        s_flag[i] = 1;  // 移動前のユニットナンバーの継承フラグon
+                        r_flag[j] = 1;  // かぶるユニットナンバーの残留フラグon
+                        move_check = 1; //ユニットがかぶった。
+                        break;
+                    }
+                }
+                if (!move_check)    // ユニットがかぶってなかったら
+                    m_flag[i] = 1;  // 移動前ユニットナンバーの移動フラグon
+            }
+
+            //フラグに基づいてユニット移動
+            for (i = 0; i < group->unit_count; i++)
+            {
+                unit1 = &group->unit[i];
+                if (m_flag[i])
+                {               // 移動フラグがonで
+                    if (!r_flag[i])
+                    {           // 残留フラグがoffなら
+                        //単純移動(rangeも継承の必要無し)
+                        int  range = unit1->range;
+                        map_delblock (&unit1->bl);
+                        unit1->bl.m = m;
+                        unit1->bl.x += dx;
+                        unit1->bl.y += dy;
+                        map_addblock (&unit1->bl);
+                        clif_skill_setunit (unit1);
+                        if (range > 0)
+                        {
+                            if (range < 7)
+                                range = 7;
+                            map_foreachinarea (skill_unit_move_unit_group_sub,
+                                               unit1->bl.m,
+                                               unit1->bl.x - range,
+                                               unit1->bl.y - range,
+                                               unit1->bl.x + range,
+                                               unit1->bl.y + range, 0,
+                                               &unit1->bl, gettick ());
+                        }
+                    }
+                    else
+                    {           // 残留フラグがonなら
+                        //空ユニットになるので、継承可能なユニットを探す
+                        for (j = 0; j < group->unit_count; j++)
+                        {
+                            unit2 = &group->unit[j];
+                            if (s_flag[j] && !r_flag[j])
+                            {
+                                // 継承移動(range継承付き)
+                                int  range = unit1->range;
+                                map_delblock (&unit2->bl);
+                                unit2->bl.m = m;
+                                unit2->bl.x = unit1->bl.x + dx;
+                                unit2->bl.y = unit1->bl.y + dy;
+                                unit2->range = unit1->range;
+                                map_addblock (&unit2->bl);
+                                clif_skill_setunit (unit2);
+                                if (range > 0)
+                                {
+                                    if (range < 7)
+                                        range = 7;
+                                    map_foreachinarea
+                                        (skill_unit_move_unit_group_sub,
+                                         unit2->bl.m, unit2->bl.x - range,
+                                         unit2->bl.y - range,
+                                         unit2->bl.x + range,
+                                         unit2->bl.y + range, 0, &unit2->bl,
+                                         gettick ());
+                                }
+                                s_flag[j] = 0;  // 継承完了したのでoff
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            free (r_flag);
+            free (s_flag);
+            free (m_flag);
+        }
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * アイテム合成
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * 初期化系
+ */
+
+static int scan_stat (char *statname)
+{
+    if (!strcasecmp (statname, "str"))
+        return SP_STR;
+    if (!strcasecmp (statname, "dex"))
+        return SP_DEX;
+    if (!strcasecmp (statname, "agi"))
+        return SP_AGI;
+    if (!strcasecmp (statname, "vit"))
+        return SP_VIT;
+    if (!strcasecmp (statname, "int"))
+        return SP_INT;
+    if (!strcasecmp (statname, "luk"))
+        return SP_LUK;
+    if (!strcasecmp (statname, "none"))
+        return 0;
+
+    else
+        fprintf (stderr, "Unknown stat `%s'\n", statname);
+    return 0;
+}
+
+extern void skill_pool_register (int id);   // [Fate] Remember that a certain skill ID belongs to a pool skill
+
+/*==========================================
+ * スキル関係ファイル読み込み
+ * skill_db.txt スキルデータ
+ * skill_cast_db.txt スキルの詠唱時間とディレイデータ
+ *------------------------------------------
+ */
+int skill_readdb (void)
+{
+    int  i, j, k, l;
+    FILE *fp;
+    char line[1024], *p;
+
+    /* The main skill database */
+    memset (skill_db, 0, sizeof (skill_db));
+    fp = fopen_ ("db/skill_db.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/skill_db.txt\n");
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        char *split[50], *split2[MAX_SKILL_LEVEL];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 18 && p; j++)
+        {
+            while (*p == '\t' || *p == ' ')
+                p++;
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (split[17] == NULL || j < 18)
+        {
+            fprintf (stderr, "Incomplete skill db data online (%d entries)\n",
+                     j);
+            continue;
+        }
+
+        i = atoi (split[0]);
+        if (i < 0 || i > MAX_SKILL_DB)
+            continue;
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].range[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+        skill_db[i].hit = atoi (split[2]);
+        skill_db[i].inf = atoi (split[3]);
+        skill_db[i].pl = atoi (split[4]);
+        skill_db[i].nk = atoi (split[5]);
+        skill_db[i].max_raise = atoi (split[6]);
+        skill_db[i].max = atoi (split[7]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[8]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].num[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        if (strcasecmp (split[9], "yes") == 0)
+            skill_db[i].castcancel = 1;
+        else
+            skill_db[i].castcancel = 0;
+        skill_db[i].cast_def_rate = atoi (split[9]);
+        skill_db[i].inf2 = atoi (split[10]);
+        skill_db[i].maxcount = atoi (split[11]);
+        if (strcasecmp (split[13], "weapon") == 0)
+            skill_db[i].skill_type = BF_WEAPON;
+        else if (strcasecmp (split[12], "magic") == 0)
+            skill_db[i].skill_type = BF_MAGIC;
+        else if (strcasecmp (split[12], "misc") == 0)
+            skill_db[i].skill_type = BF_MISC;
+        else
+            skill_db[i].skill_type = 0;
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[14]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].blewcount[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        if (!strcasecmp (split[15], "passive"))
+        {
+            skill_pool_register (i);
+            skill_db[i].poolflags = SKILL_POOL_FLAG;
+        }
+        else if (!strcasecmp (split[15], "active"))
+        {
+            skill_pool_register (i);
+            skill_db[i].poolflags = SKILL_POOL_FLAG | SKILL_POOL_ACTIVE;
+        }
+        else
+            skill_db[i].poolflags = 0;
+
+        skill_db[i].stat = scan_stat (split[16]);
+
+        skill_names[i].desc = strdup (split[17]);
+        {                       // replace "_" by " "
+            char *s = skill_names[i].desc;
+            while ((s = strchr (s, '_')))
+                *s = ' ';
+            if ((s = strchr (skill_names[i].desc, '\t'))
+                || (s = strchr (skill_names[i].desc, ' '))
+                || (s = strchr (skill_names[i].desc, '\n')))
+                *s = '\000';
+        }
+    }
+    fclose_ (fp);
+    printf ("read db/skill_db.txt done\n");
+
+    fp = fopen_ ("db/skill_require_db.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/skill_require_db.txt\n");
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        char *split[51], *split2[MAX_SKILL_LEVEL];
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 30 && p; j++)
+        {
+            while (*p == '\t' || *p == ' ')
+                p++;
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (split[29] == NULL || j < 30)
+            continue;
+
+        i = atoi (split[0]);
+        if (i < 0 || i > MAX_SKILL_DB)
+            continue;
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].hp[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].mhp[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].sp[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].hp_rate[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[5]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].sp_rate[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[6]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].zeny[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[7]; j < 32 && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < 32 && split2[k]; k++)
+        {
+            l = atoi (split2[k]);
+            if (l == 99)
+            {
+                skill_db[i].weapon = 0xffffffff;
+                break;
+            }
+            else
+                skill_db[i].weapon |= 1 << l;
+        }
+
+        if (strcasecmp (split[8], "hiding") == 0)
+            skill_db[i].state = ST_HIDING;
+        else if (strcasecmp (split[8], "cloaking") == 0)
+            skill_db[i].state = ST_CLOAKING;
+        else if (strcasecmp (split[8], "hidden") == 0)
+            skill_db[i].state = ST_HIDDEN;
+        else if (strcasecmp (split[8], "riding") == 0)
+            skill_db[i].state = ST_RIDING;
+        else if (strcasecmp (split[8], "falcon") == 0)
+            skill_db[i].state = ST_FALCON;
+        else if (strcasecmp (split[8], "cart") == 0)
+            skill_db[i].state = ST_CART;
+        else if (strcasecmp (split[8], "shield") == 0)
+            skill_db[i].state = ST_SHIELD;
+        else if (strcasecmp (split[8], "sight") == 0)
+            skill_db[i].state = ST_SIGHT;
+        else if (strcasecmp (split[8], "explosionspirits") == 0)
+            skill_db[i].state = ST_EXPLOSIONSPIRITS;
+        else if (strcasecmp (split[8], "recover_weight_rate") == 0)
+            skill_db[i].state = ST_RECOV_WEIGHT_RATE;
+        else if (strcasecmp (split[8], "move_enable") == 0)
+            skill_db[i].state = ST_MOVE_ENABLE;
+        else if (strcasecmp (split[8], "water") == 0)
+            skill_db[i].state = ST_WATER;
+        else
+            skill_db[i].state = ST_NONE;
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[9]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].spiritball[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+        skill_db[i].itemid[0] = atoi (split[10]);
+        skill_db[i].amount[0] = atoi (split[11]);
+        skill_db[i].itemid[1] = atoi (split[12]);
+        skill_db[i].amount[1] = atoi (split[13]);
+        skill_db[i].itemid[2] = atoi (split[14]);
+        skill_db[i].amount[2] = atoi (split[15]);
+        skill_db[i].itemid[3] = atoi (split[16]);
+        skill_db[i].amount[3] = atoi (split[17]);
+        skill_db[i].itemid[4] = atoi (split[18]);
+        skill_db[i].amount[4] = atoi (split[19]);
+        skill_db[i].itemid[5] = atoi (split[20]);
+        skill_db[i].amount[5] = atoi (split[21]);
+        skill_db[i].itemid[6] = atoi (split[22]);
+        skill_db[i].amount[6] = atoi (split[23]);
+        skill_db[i].itemid[7] = atoi (split[24]);
+        skill_db[i].amount[7] = atoi (split[25]);
+        skill_db[i].itemid[8] = atoi (split[26]);
+        skill_db[i].amount[8] = atoi (split[27]);
+        skill_db[i].itemid[9] = atoi (split[28]);
+        skill_db[i].amount[9] = atoi (split[29]);
+    }
+    fclose_ (fp);
+    printf ("read db/skill_require_db.txt done\n");
+
+    /* ? */
+    fp = fopen_ ("db/skill_cast_db.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/skill_cast_db.txt\n");
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        char *split[50], *split2[MAX_SKILL_LEVEL];
+        memset (split, 0, sizeof (split));  // [Valaris] thanks to fov
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 5 && p; j++)
+        {
+            while (*p == '\t' || *p == ' ')
+                p++;
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+        if (split[4] == NULL || j < 5)
+            continue;
+
+        i = atoi (split[0]);
+        if (i < 0 || i > MAX_SKILL_DB)
+            continue;
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].cast[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[2]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].delay[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[3]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].upkeep_time[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[4]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].upkeep_time2[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+    }
+    fclose_ (fp);
+    printf ("read db/skill_cast_db.txt done\n");
+
+    fp = fopen_ ("db/skill_castnodex_db.txt", "r");
+    if (fp == NULL)
+    {
+        printf ("can't read db/skill_castnodex_db.txt\n");
+        return 1;
+    }
+    while (fgets (line, 1020, fp))
+    {
+        char *split[50], *split2[MAX_SKILL_LEVEL];
+        memset (split, 0, sizeof (split));
+        if (line[0] == '/' && line[1] == '/')
+            continue;
+        for (j = 0, p = line; j < 2 && p; j++)
+        {
+            while (*p == '\t' || *p == ' ')
+                p++;
+            split[j] = p;
+            p = strchr (p, ',');
+            if (p)
+                *p++ = 0;
+        }
+
+        i = atoi (split[0]);
+        if (i < 0 || i > MAX_SKILL_DB)
+            continue;
+
+        memset (split2, 0, sizeof (split2));
+        for (j = 0, p = split[1]; j < MAX_SKILL_LEVEL && p; j++)
+        {
+            split2[j] = p;
+            p = strchr (p, ':');
+            if (p)
+                *p++ = 0;
+        }
+        for (k = 0; k < MAX_SKILL_LEVEL; k++)
+            skill_db[i].castnodex[k] =
+                (split2[k]) ? atoi (split2[k]) : atoi (split2[0]);
+    }
+    fclose_ (fp);
+    printf ("read db/skill_castnodex_db.txt done\n");
+
+    return 0;
+}
+
+void skill_reload (void)
+{
+    /*
+     *
+     * <empty skill database>
+     * <?>
+     *
+     */
+
+    do_init_skill ();
+}
+
+/*==========================================
+ * スキル関係初期化処理
+ *------------------------------------------
+ */
+int do_init_skill (void)
+{
+    skill_readdb ();
+
+    add_timer_interval (gettick () + SKILLUNITTIMER_INVERVAL,
+                        skill_unit_timer, 0, 0, SKILLUNITTIMER_INVERVAL);
+
+    return 0;
+}
diff --git a/src/map/skill.h b/src/map/skill.h
deleted file mode 100644
index 6c8795a..0000000
--- a/src/map/skill.h
+++ /dev/null
@@ -1,891 +0,0 @@
-// $Id: skill.h,v 1.5 2004/09/25 05:32:19 MouseJstr Exp $
-#ifndef _SKILL_H_
-#define _SKILL_H_
-
-#include "../common/timer.h"
-
-#include "map.h"
-#include "magic.h"
-
-#define MAX_SKILL_DB			450
-#define MAX_SKILL_PRODUCE_DB	 150
-#define MAX_SKILL_ARROW_DB	 150
-#define MAX_SKILL_ABRA_DB	 350
-
-#define SKILL_POOL_FLAG		0x1 // is a pool skill
-#define SKILL_POOL_ACTIVE	0x2 // is an active pool skill
-#define SKILL_POOL_ACTIVATED	0x4 // pool skill has been activated (used for clif)
-
-// スキルデータベース
-struct skill_db
-{
-    int  range[MAX_SKILL_LEVEL], hit, inf, pl, nk, max, stat, poolflags, max_raise; // `max' is the global max, `max_raise' is the maximum attainable via skill-ups
-    int  num[MAX_SKILL_LEVEL];
-    int  cast[MAX_SKILL_LEVEL], delay[MAX_SKILL_LEVEL];
-    int  upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL];
-    int  castcancel, cast_def_rate;
-    int  inf2, maxcount, skill_type;
-    int  blewcount[MAX_SKILL_LEVEL];
-    int  hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL],
-        hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL],
-        zeny[MAX_SKILL_LEVEL];
-    int  weapon, state, spiritball[MAX_SKILL_LEVEL];
-    int  itemid[10], amount[10];
-    int  castnodex[MAX_SKILL_LEVEL];
-};
-extern struct skill_db skill_db[MAX_SKILL_DB];
-
-struct skill_name_db
-{
-    int  id;                    // skill id
-    const char *name;                 // search strings
-    const char *desc;                 // description that shows up for search's
-};
-extern struct skill_name_db skill_names[];
-
-struct block_list;
-struct map_session_data;
-struct skill_unit;
-struct skill_unit_group;
-
-int  do_init_skill (void);
-
-// スキルデータベースへのアクセサ
-int  skill_get_hit (int id);
-int  skill_get_inf (int id);
-int  skill_get_pl (int id);
-int  skill_get_nk (int id);
-int  skill_get_max (int id);
-int  skill_get_max_raise (int id);
-int  skill_get_range (int id, int lv);
-int  skill_get_hp (int id, int lv);
-int  skill_get_mhp (int id, int lv);
-int  skill_get_sp (int id, int lv);
-int  skill_get_zeny (int id, int lv);
-int  skill_get_num (int id, int lv);
-int  skill_get_cast (int id, int lv);
-int  skill_get_delay (int id, int lv);
-int  skill_get_time (int id, int lv);
-int  skill_get_time2 (int id, int lv);
-int  skill_get_castdef (int id);
-int  skill_get_weapontype (int id);
-int  skill_get_unit_id (int id, int flag);
-int  skill_get_inf2 (int id);
-int  skill_get_maxcount (int id);
-int  skill_get_blewcount (int id, int lv);
-
-// スキルの使用
-int  skill_use_id (struct map_session_data *sd, int target_id,
-                   int skill_num, int skill_lv);
-int  skill_use_pos (struct map_session_data *sd,
-                    int skill_x, int skill_y, int skill_num, int skill_lv);
-
-int  skill_castend_map (struct map_session_data *sd, int skill_num,
-                        const char *map);
-
-int  skill_cleartimerskill (struct block_list *src);
-int  skill_addtimerskill (struct block_list *src, unsigned int tick,
-                          int target, int x, int y, int skill_id,
-                          int skill_lv, int type, int flag);
-
-// 追加効果
-int  skill_additional_effect (struct block_list *src, struct block_list *bl,
-                              int skillid, int skilllv, int attack_type,
-                              unsigned int tick);
-
-// ユニットスキル
-struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx,
-                                   int x, int y);
-int  skill_delunit (struct skill_unit *unit);
-struct skill_unit_group *skill_initunitgroup (struct block_list *src,
-                                              int count, int skillid,
-                                              int skilllv, int unit_id);
-int  skill_delunitgroup (struct skill_unit_group *group);
-struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct
-                                                                block_list
-                                                                *bl,
-                                                                int group_id);
-int  skill_unitgrouptickset_delete (struct block_list *bl, int group_id);
-int  skill_clear_unitgroup (struct block_list *src);
-
-int  skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl,
-                           int damage, unsigned int tick);
-
-int  skill_castfix (struct block_list *bl, int time);
-int  skill_delayfix (struct block_list *bl, int time);
-int  skill_check_unit_range (int m, int x, int y, int range, int skillid);
-int  skill_check_unit_range2 (int m, int x, int y, int range);
-// -- moonsoul  (added skill_check_unit_cell)
-int  skill_check_unit_cell (int skillid, int m, int x, int y, int unit_id);
-int  skill_unit_out_all (struct block_list *bl, unsigned int tick, int range);
-int  skill_unit_move (struct block_list *bl, unsigned int tick, int range);
-int  skill_unit_move_unit_group (struct skill_unit_group *group, int m,
-                                 int dx, int dy);
-
-struct skill_unit_group *skill_check_dancing (struct block_list *src);
-void skill_stop_dancing (struct block_list *src, int flag);
-
-// 詠唱キャンセル
-int  skill_castcancel (struct block_list *bl, int type);
-
-int  skill_gangsterparadise (struct map_session_data *sd, int type);
-void skill_brandishspear_first (struct square *tc, int dir, int x, int y);
-void skill_brandishspear_dir (struct square *tc, int dir, int are);
-int  skill_autospell (struct map_session_data *md, int skillid);
-void skill_devotion (struct map_session_data *md, int target);
-void skill_devotion2 (struct block_list *bl, int crusader);
-int  skill_devotion3 (struct block_list *bl, int target);
-void skill_devotion_end (struct map_session_data *md,
-                         struct map_session_data *sd, int target);
-
-#define skill_calc_heal(bl,skill_lv) (( battle_get_lv(bl)+battle_get_int(bl) )/8 *(4+ skill_lv*8))
-
-// その他
-int  skill_check_cloaking (struct block_list *bl);
-int  skill_is_danceskill (int id);
-
-// ステータス異常
-int  skill_status_effect (struct block_list *bl, int type, int val1, int val2,
-                          int val3, int val4, int tick, int flag,
-                          int spell_invocation);
-int  skill_status_change_start (struct block_list *bl, int type, int val1,
-                                int val2, int val3, int val4, int tick,
-                                int flag);
-void skill_status_change_timer (timer_id, tick_t, custom_id_t, custom_data_t);
-int  skill_status_change_active (struct block_list *bl, int type);  // [fate]
-int  skill_encchant_eremental_end (struct block_list *bl, int type);
-int  skill_status_change_end (struct block_list *bl, int type, int tid);
-int  skill_status_change_clear (struct block_list *bl, int type);
-
-// mobスキルのため
-int  skill_castend_nodamage_id (struct block_list *src, struct block_list *bl,
-                                int skillid, int skilllv, unsigned int tick,
-                                int flag);
-int  skill_castend_damage_id (struct block_list *src, struct block_list *bl,
-                              int skillid, int skilllv, unsigned int tick,
-                              int flag);
-int  skill_castend_pos2 (struct block_list *src, int x, int y, int skillid,
-                         int skilllv, unsigned int tick, int flag);
-
-// スキル攻撃一括処理
-int  skill_attack (int attack_type, struct block_list *src,
-                   struct block_list *dsrc, struct block_list *bl,
-                   int skillid, int skilllv, unsigned int tick, int flag);
-
-int  skill_update_heal_animation (struct map_session_data *sd); // [Fate]  Check whether the healing flag must be updated, do so if needed
-
-void skill_reload (void);
-
-enum
-{
-    ST_NONE, ST_HIDING, ST_CLOAKING, ST_HIDDEN, ST_RIDING, ST_FALCON, ST_CART,
-    ST_SHIELD, ST_SIGHT, ST_EXPLOSIONSPIRITS,
-    ST_RECOV_WEIGHT_RATE, ST_MOVE_ENABLE, ST_WATER,
-};
-
-enum
-{                               // struct map_session_data の status_changeの番号テーブル
-    SC_SENDMAX = 256,
-    SC_PROVOKE = 0,
-    SC_ENDURE = 1,
-    SC_TWOHANDQUICKEN = 2,
-    SC_CONCENTRATE = 3,
-    SC_HIDING = 4,
-    SC_CLOAKING = 5,
-    SC_ENCPOISON = 6,
-    SC_POISONREACT = 7,
-    SC_QUAGMIRE = 8,
-    SC_ANGELUS = 9,
-    SC_BLESSING = 10,
-    SC_SIGNUMCRUCIS = 11,
-    SC_INCREASEAGI = 12,
-    SC_DECREASEAGI = 13,
-    SC_SLOWPOISON = 14,
-    SC_IMPOSITIO = 15,
-    SC_SUFFRAGIUM = 16,
-    SC_ASPERSIO = 17,
-    SC_BENEDICTIO = 18,
-    SC_KYRIE = 19,
-    SC_MAGNIFICAT = 20,
-    SC_GLORIA = 21,
-    SC_AETERNA = 22,
-    SC_ADRENALINE = 23,
-    SC_WEAPONPERFECTION = 24,
-    SC_OVERTHRUST = 25,
-    SC_MAXIMIZEPOWER = 26,
-    SC_RIDING = 27,
-    SC_FALCON = 28,
-    SC_TRICKDEAD = 29,
-    SC_LOUD = 30,
-    SC_ENERGYCOAT = 31,
-    SC_BROKNARMOR = 32,
-    SC_BROKNWEAPON = 33,
-    SC_HALLUCINATION = 34,
-    SC_WEIGHT50 = 35,
-    SC_WEIGHT90 = 36,
-    SC_SPEEDPOTION0 = 37,
-    SC_SPEEDPOTION1 = 38,
-    SC_SPEEDPOTION2 = 39,
-
-    SC_STRIPWEAPON = 50,
-    SC_STRIPSHIELD = 51,
-    SC_STRIPARMOR = 52,
-    SC_STRIPHELM = 53,
-    SC_CP_WEAPON = 54,
-    SC_CP_SHIELD = 55,
-    SC_CP_ARMOR = 56,
-    SC_CP_HELM = 57,
-    SC_AUTOGUARD = 58,
-    SC_REFLECTSHIELD = 59,
-    SC_DEVOTION = 60,
-    SC_PROVIDENCE = 61,
-    SC_DEFENDER = 62,
-    SC_AUTOSPELL = 65,
-    SC_EXPLOSIONSPIRITS = 86,
-    SC_STEELBODY = 87,
-    SC_SPEARSQUICKEN = 68,
-
-    SC_HEALING = 70,
-
-    SC_SIGHTTRASHER = 73,
-
-    SC_COMBO = 89,
-    SC_FLAMELAUNCHER = 90,
-    SC_FROSTWEAPON = 91,
-    SC_LIGHTNINGLOADER = 92,
-    SC_SEISMICWEAPON = 93,
-
-    SC_AURABLADE = 103,
-    SC_PARRYING = 104,
-    SC_CONCENTRATION = 105,
-    SC_TENSIONRELAX = 106,
-    SC_BERSERK = 107,
-
-    SC_ASSUMPTIO = 110,
-
-    SC_MAGICPOWER = 113,
-
-    SC_TRUESIGHT = 115,
-    SC_WINDWALK = 116,
-    SC_MELTDOWN = 117,
-    SC_CARTBOOST = 118,
-
-    SC_REJECTSWORD = 120,
-    SC_MARIONETTE = 121,
-
-    SC_HEADCRUSH = 124,
-    SC_JOINTBEAT = 125,
-    SC_BASILICA = 125,
-
-    SC_STONE = 128,
-    SC_FREEZE = 129,
-    SC_STAN = 130,
-    SC_SLEEP = 131,
-    SC_POISON = 132,
-    SC_CURSE = 133,
-    SC_SILENCE = 134,
-    SC_CONFUSION = 135,
-    SC_BLIND = 136,
-
-    SC_SAFETYWALL = 140,
-    SC_PNEUMA = 141,
-    SC_WATERBALL = 142,
-    SC_ANKLE = 143,
-    SC_DANCING = 144,
-    SC_KEEPING = 145,
-    SC_BARRIER = 146,
-
-    SC_MAGICROD = 149,
-    SC_SIGHT = 150,
-    SC_RUWACH = 151,
-    SC_AUTOCOUNTER = 152,
-    SC_VOLCANO = 153,
-    SC_DELUGE = 154,
-    SC_VIOLENTGALE = 155,
-    SC_BLADESTOP_WAIT = 156,
-    SC_BLADESTOP = 157,
-    SC_EXTREMITYFIST = 158,
-    SC_GRAFFITI = 159,
-    SC_ENSEMBLE = 159,
-
-    SC_LULLABY = 160,
-    SC_RICHMANKIM = 161,
-    SC_ETERNALCHAOS = 162,
-    SC_DRUMBATTLE = 163,
-    SC_NIBELUNGEN = 164,
-    SC_ROKISWEIL = 165,
-    SC_INTOABYSS = 166,
-    SC_SIEGFRIED = 167,
-    SC_DISSONANCE = 168,
-    SC_WHISTLE = 169,
-    SC_ASSNCROS = 170,
-    SC_POEMBRAGI = 171,
-    SC_APPLEIDUN = 172,
-    SC_UGLYDANCE = 173,
-    SC_HUMMING = 174,
-    SC_DONTFORGETME = 175,
-    SC_FORTUNE = 176,
-    SC_SERVICE4U = 177,
-    SC_FOGWALL = 178,
-    SC_GOSPEL = 179,
-    SC_SPIDERWEB = 180,
-    SC_MEMORIZE = 181,
-    SC_LANDPROTECTOR = 182,
-    SC_ADAPTATION = 183,
-    SC_CHASEWALK = 184,
-    SC_ATKPOT = 185,
-    SC_MATKPOT = 186,
-    SC_WEDDING = 187,
-    SC_NOCHAT = 188,
-    SC_SPLASHER = 189,
-    SC_SELFDESTRUCTION = 190,
-    SC_MINDBREAKER = 191,
-    SC_SPELLBREAKER = 192,
-
-// Added for Fate's spells
-    SC_HIDE = 194,              // Hide from `detect' magic
-    SC_HALT_REGENERATE = 195,   // Suspend regeneration
-    SC_FLYING_BACKPACK = 196,   // Flying backpack
-    SC_MBARRIER = 197,          // Magical barrier, magic resistance (val1 : power (%))
-    SC_HASTE = 198,             // `Haste' spell (val1 : power)
-    SC_PHYS_SHIELD = 199,       // `Protect' spell, reduce damage (val1: power)
-
-    SC_DIVINA = SC_SILENCE,
-};
-extern int SkillStatusChangeTable[];
-
-enum
-{
-    NV_EMOTE = 1,
-    NV_TRADE,
-    NV_PARTY,
-
-    SM_SWORD,
-    SM_TWOHAND,
-    SM_RECOVERY,
-    SM_BASH,
-    SM_PROVOKE,
-    SM_MAGNUM,
-    SM_ENDURE,
-
-    MG_SRECOVERY,
-    MG_SIGHT,
-    MG_NAPALMBEAT,
-    MG_SAFETYWALL,
-    MG_SOULSTRIKE,
-    MG_COLDBOLT,
-    MG_FROSTDIVER,
-    MG_STONECURSE,
-    MG_FIREBALL,
-    MG_FIREWALL,
-    MG_FIREBOLT,
-    MG_LIGHTNINGBOLT,
-    MG_THUNDERSTORM,
-
-    AL_DP,
-    AL_DEMONBANE,
-    AL_RUWACH,
-    AL_PNEUMA,
-    AL_TELEPORT,
-    AL_WARP,
-    AL_HEAL,
-    AL_INCAGI,
-    AL_DECAGI,
-    AL_HOLYWATER,
-    AL_CRUCIS,
-    AL_ANGELUS,
-    AL_BLESSING,
-    AL_CURE,
-
-    MC_INCCARRY,
-    MC_DISCOUNT,
-    MC_OVERCHARGE,
-    MC_PUSHCART,
-    MC_IDENTIFY,
-    MC_VENDING,
-    MC_MAMMONITE,
-
-    AC_OWL = 45,
-    AC_VULTURE,
-    AC_CONCENTRATION,
-    AC_DOUBLE,
-    AC_SHOWER,
-
-    TF_DOUBLE,
-    TF_MISS,
-    TF_STEAL,
-    TF_HIDING,
-    TF_POISON,
-    TF_DETOXIFY,
-
-    ALL_RESURRECTION,
-
-    KN_SPEARMASTERY,
-    KN_PIERCE,
-    KN_BRANDISHSPEAR,
-    KN_SPEARSTAB,
-    KN_SPEARBOOMERANG,
-    KN_TWOHANDQUICKEN,
-    KN_AUTOCOUNTER,
-    KN_BOWLINGBASH,
-    KN_RIDING,
-    KN_CAVALIERMASTERY,
-
-    PR_MACEMASTERY,
-    PR_IMPOSITIO,
-    PR_SUFFRAGIUM,
-    PR_ASPERSIO,
-    PR_BENEDICTIO,
-    PR_SANCTUARY,
-    PR_SLOWPOISON,
-    PR_STRECOVERY,
-    PR_KYRIE,
-    PR_MAGNIFICAT,
-    PR_GLORIA,
-    PR_LEXDIVINA,
-    PR_TURNUNDEAD,
-    PR_LEXAETERNA,
-    PR_MAGNUS,
-
-    WZ_FIREPILLAR,
-    WZ_SIGHTRASHER,
-    WZ_FIREIVY,
-    WZ_METEOR,
-    WZ_JUPITEL,
-    WZ_VERMILION,
-    WZ_WATERBALL,
-    WZ_ICEWALL,
-    WZ_FROSTNOVA,
-    WZ_STORMGUST,
-    WZ_EARTHSPIKE,
-    WZ_HEAVENDRIVE,
-    WZ_QUAGMIRE,
-    WZ_ESTIMATION,
-
-    BS_IRON,
-    BS_STEEL,
-    BS_ENCHANTEDSTONE,
-    BS_ORIDEOCON,
-    BS_DAGGER,
-    BS_SWORD,
-    BS_TWOHANDSWORD,
-    BS_AXE,
-    BS_MACE,
-    BS_KNUCKLE,
-    BS_SPEAR,
-    BS_HILTBINDING,
-    BS_FINDINGORE,
-    BS_WEAPONRESEARCH,
-    BS_REPAIRWEAPON,
-    BS_SKINTEMPER,
-    BS_HAMMERFALL,
-    BS_ADRENALINE,
-    BS_WEAPONPERFECT,
-    BS_OVERTHRUST,
-    BS_MAXIMIZE,
-
-    HT_SKIDTRAP,
-    HT_LANDMINE,
-    HT_ANKLESNARE,
-    HT_SHOCKWAVE,
-    HT_SANDMAN,
-    HT_FLASHER,
-    HT_FREEZINGTRAP,
-    HT_BLASTMINE,
-    HT_CLAYMORETRAP,
-    HT_REMOVETRAP,
-    HT_TALKIEBOX,
-    HT_BEASTBANE,
-    HT_FALCON,
-    HT_STEELCROW,
-    HT_BLITZBEAT,
-    HT_DETECTING,
-    HT_SPRINGTRAP,
-
-    AS_RIGHT,
-    AS_LEFT,
-    AS_KATAR,
-    AS_CLOAKING,
-    AS_SONICBLOW,
-    AS_GRIMTOOTH,
-    AS_ENCHANTPOISON,
-    AS_POISONREACT,
-    AS_VENOMDUST,
-    AS_SPLASHER,
-
-    NV_FIRSTAID,
-    NV_TRICKDEAD,
-    SM_MOVINGRECOVERY,
-    SM_FATALBLOW,
-    SM_AUTOBERSERK,
-    AC_MAKINGARROW,
-    AC_CHARGEARROW,
-    TF_SPRINKLESAND,
-    TF_BACKSLIDING,
-    TF_PICKSTONE,
-    TF_THROWSTONE,
-    MC_CARTREVOLUTION,
-    MC_CHANGECART,
-    MC_LOUD,
-    AL_HOLYLIGHT,
-    MG_ENERGYCOAT,
-
-    NPC_PIERCINGATT,
-    NPC_MENTALBREAKER,
-    NPC_RANGEATTACK,
-    NPC_ATTRICHANGE,
-    NPC_CHANGEWATER,
-    NPC_CHANGEGROUND,
-    NPC_CHANGEFIRE,
-    NPC_CHANGEWIND,
-    NPC_CHANGEPOISON,
-    NPC_CHANGEHOLY,
-    NPC_CHANGEDARKNESS,
-    NPC_CHANGETELEKINESIS,
-    NPC_CRITICALSLASH,
-    NPC_COMBOATTACK,
-    NPC_GUIDEDATTACK,
-    NPC_SELFDESTRUCTION,
-    NPC_SPLASHATTACK,
-    NPC_SUICIDE,
-    NPC_POISON,
-    NPC_BLINDATTACK,
-    NPC_SILENCEATTACK,
-    NPC_STUNATTACK,
-    NPC_PETRIFYATTACK,
-    NPC_CURSEATTACK,
-    NPC_SLEEPATTACK,
-    NPC_RANDOMATTACK,
-    NPC_WATERATTACK,
-    NPC_GROUNDATTACK,
-    NPC_FIREATTACK,
-    NPC_WINDATTACK,
-    NPC_POISONATTACK,
-    NPC_HOLYATTACK,
-    NPC_DARKNESSATTACK,
-    NPC_TELEKINESISATTACK,
-    NPC_MAGICALATTACK,
-    NPC_METAMORPHOSIS,
-    NPC_PROVOCATION,
-    NPC_SMOKING,
-    NPC_SUMMONSLAVE,
-    NPC_EMOTION,
-    NPC_TRANSFORMATION,
-    NPC_BLOODDRAIN,
-    NPC_ENERGYDRAIN,
-    NPC_KEEPING,
-    NPC_DARKBREATH,
-    NPC_DARKBLESSING,
-    NPC_BARRIER,
-    NPC_DEFENDER,
-    NPC_LICK,
-    NPC_HALLUCINATION,
-    NPC_REBIRTH,
-    NPC_SUMMONMONSTER,
-
-    RG_SNATCHER,
-    RG_STEALCOIN,
-    RG_BACKSTAP,
-    RG_TUNNELDRIVE,
-    RG_RAID,
-    RG_STRIPWEAPON,
-    RG_STRIPSHIELD,
-    RG_STRIPARMOR,
-    RG_STRIPHELM,
-    RG_INTIMIDATE,
-    RG_GRAFFITI,
-    RG_FLAGGRAFFITI,
-    RG_CLEANER,
-    RG_GANGSTER,
-    RG_COMPULSION,
-    RG_PLAGIARISM,
-
-    AM_AXEMASTERY,
-    AM_LEARNINGPOTION,
-    AM_PHARMACY,
-    AM_DEMONSTRATION,
-    AM_ACIDTERROR,
-    AM_POTIONPITCHER,
-    AM_CANNIBALIZE,
-    AM_SPHEREMINE,
-    AM_CP_WEAPON,
-    AM_CP_SHIELD,
-    AM_CP_ARMOR,
-    AM_CP_HELM,
-    AM_BIOETHICS,
-    AM_BIOTECHNOLOGY,
-    AM_CREATECREATURE,
-    AM_CULTIVATION,
-    AM_FLAMECONTROL,
-    AM_CALLHOMUN,
-    AM_REST,
-    AM_DRILLMASTER,
-    AM_HEALHOMUN,
-    AM_RESURRECTHOMUN,
-
-    CR_TRUST,
-    CR_AUTOGUARD,
-    CR_SHIELDCHARGE,
-    CR_SHIELDBOOMERANG,
-    CR_REFLECTSHIELD,
-    CR_HOLYCROSS,
-    CR_GRANDCROSS,
-    CR_DEVOTION,
-    CR_PROVIDENCE,
-    CR_DEFENDER,
-    CR_SPEARQUICKEN,
-
-    MO_IRONHAND,
-    MO_SPIRITSRECOVERY,
-    MO_CALLSPIRITS,
-    MO_ABSORBSPIRITS,
-    MO_TRIPLEATTACK,
-    MO_BODYRELOCATION,
-    MO_DODGE,
-    MO_INVESTIGATE,
-    MO_FINGEROFFENSIVE,
-    MO_STEELBODY,
-    MO_BLADESTOP,
-    MO_EXPLOSIONSPIRITS,
-    MO_EXTREMITYFIST,
-    MO_CHAINCOMBO,
-    MO_COMBOFINISH,
-
-    SA_ADVANCEDBOOK,
-    SA_CASTCANCEL,
-    SA_MAGICROD,
-    SA_SPELLBREAKER,
-    SA_FREECAST,
-    SA_AUTOSPELL,
-    SA_FLAMELAUNCHER,
-    SA_FROSTWEAPON,
-    SA_LIGHTNINGLOADER,
-    SA_SEISMICWEAPON,
-    SA_DRAGONOLOGY,
-    SA_VOLCANO,
-    SA_DELUGE,
-    SA_VIOLENTGALE,
-    SA_LANDPROTECTOR,
-    SA_DISPELL,
-    SA_ABRACADABRA,
-    SA_MONOCELL,
-    SA_CLASSCHANGE,
-    SA_SUMMONMONSTER,
-    SA_REVERSEORCISH,
-    SA_DEATH,
-    SA_FORTUNE,
-    SA_TAMINGMONSTER,
-    SA_QUESTION,
-    SA_GRAVITY,
-    SA_LEVELUP,
-    SA_INSTANTDEATH,
-    SA_FULLRECOVERY,
-    SA_COMA,
-
-    BD_ADAPTATION,
-    BD_ENCORE,
-    BD_LULLABY,
-    BD_RICHMANKIM,
-    BD_ETERNALCHAOS,
-    BD_DRUMBATTLEFIELD,
-    BD_RINGNIBELUNGEN,
-    BD_ROKISWEIL,
-    BD_INTOABYSS,
-    BD_SIEGFRIED,
-    BD_RAGNAROK,
-
-    BA_MUSICALLESSON,
-    BA_MUSICALSTRIKE,
-    BA_DISSONANCE,
-    BA_FROSTJOKE,
-    BA_WHISTLE,
-    BA_ASSASSINCROSS,
-    BA_POEMBRAGI,
-    BA_APPLEIDUN,
-
-    DC_DANCINGLESSON,
-    DC_THROWARROW,
-    DC_UGLYDANCE,
-    DC_SCREAM,
-    DC_HUMMING,
-    DC_DONTFORGETME,
-    DC_FORTUNEKISS,
-    DC_SERVICEFORYOU,
-
-    NPC_SELFDESTRUCTION2 = 333,
-
-    WE_MALE = 334,
-    WE_FEMALE,
-    WE_CALLPARTNER,
-
-    NPC_DARKCROSS = 338,
-
-    TMW_SKILLPOOL = 339,        // skill pool size
-
-    TMW_MAGIC = 340,
-    TMW_MAGIC_LIFE = 341,
-    TMW_MAGIC_WAR = 342,
-    TMW_MAGIC_TRANSMUTE = 343,
-    TMW_MAGIC_NATURE = 344,
-    TMW_MAGIC_ETHER = 345,
-    TMW_MAGIC_DARK = 346,
-    TMW_MAGIC_LIGHT = 347,
-
-    TMW_BRAWLING = 350,
-    TMW_LUCKY_COUNTER = 351,
-    TMW_SPEED = 352,
-    TMW_RESIST_POISON = 353,
-    TMW_ASTRAL_SOUL = 354,
-    TMW_RAGING = 355,
-
-    LK_AURABLADE = 356,
-    LK_PARRYING,
-    LK_CONCENTRATION,
-    LK_TENSIONRELAX,
-    LK_BERSERK,
-    LK_FURY,
-    HP_ASSUMPTIO,
-    HP_BASILICA,
-    HP_MEDITATIO,
-    HW_SOULDRAIN,
-    HW_MAGICCRASHER,
-    HW_MAGICPOWER,
-    PA_PRESSURE,
-    PA_SACRIFICE,
-    PA_GOSPEL,
-    CH_PALMSTRIKE,
-    CH_TIGERFIST,
-    CH_CHAINCRUSH,
-    PF_HPCONVERSION,
-    PF_SOULCHANGE,
-    PF_SOULBURN,
-    ASC_KATAR,
-    ASC_HALLUCINATION,
-    ASC_EDP,
-    ASC_BREAKER,
-    SN_SIGHT,
-    SN_FALCONASSAULT,
-    SN_SHARPSHOOTING,
-    SN_WINDWALK,
-    WS_MELTDOWN,
-    WS_CREATECOIN,
-    WS_CREATENUGGET,
-    WS_CARTBOOST,
-    WS_SYSTEMCREATE,
-    ST_CHASEWALK,
-    ST_REJECTSWORD,
-    ST_STEALBACKPACK,
-    CR_ALCHEMY,
-    CR_SYNTHESISPOTION,
-    CG_ARROWVULCAN,
-    CG_MOONLIT,
-    CG_MARIONETTE,
-    LK_SPIRALPIERCE,
-    LK_HEADCRUSH,
-    LK_JOINTBEAT,
-    HW_NAPALMVULCAN,
-    CH_SOULCOLLECT,
-    PF_MINDBREAKER,
-    PF_MEMORIZE,
-    PF_FOGWALL,
-    PF_SPIDERWEB,
-    ASC_METEORASSAULT,
-    ASC_CDP,
-    WE_BABY,
-    WE_CALLPARENT,
-    WE_CALLBABY,
-    TK_RUN,
-    TK_READYSTORM,
-    TK_STORMKICK,
-    TK_READYDOWN,
-    TK_DOWNKICK,
-    TK_READYTURN,
-    TK_TURNKICK,
-    TK_READYCOUNTER,
-    TK_COUNTER,
-    TK_DODGE,
-    TK_JUMPKICK,
-    TK_HPTIME,
-    TK_SPTIME,
-    TK_POWER,
-    TK_SEVENWIND,
-    TK_HIGHJUMP,
-    SG_FEEL,
-    SG_SUN_WARM,
-    SG_MOON_WARM,
-    SG_STAR_WARM,
-    SG_SUN_COMFORT,
-    SG_MOON_COMFORT,
-    SG_STAR_COMFORT,
-    SG_HATE,
-    SG_SUN_ANGER,
-    SG_MOON_ANGER,
-    SG_STAR_ANGER,
-    SG_SUN_BLESS,
-    SG_MOON_BLESS,
-    SG_STAR_BLESS,
-    SG_DEVIL,
-    SG_FRIEND,
-    SG_KNOWLEDGE,
-    SG_FUSION,
-    SL_ALCHEMIST,
-    AM_BERSERKPITCHER,
-    SL_MONK,
-    SL_STAR,
-    SL_SAGE,
-    SL_CRUSADER,
-    SL_SUPERNOVICE,
-    SL_KNIGHT,
-    SL_WIZARD,
-    SL_PRIEST,
-    SL_BARDDANCER,
-    SL_ROGUE,
-    SL_ASSASIN,
-    SL_BLACKSMITH,
-    BS_ADRENALINE2,
-    SL_HUNTER,
-    SL_SOULLINKER,
-    SL_KAIZEL,
-    SL_KAAHI,
-    SL_KAUPE,
-    SL_KAITE,
-    SL_KAINA,
-    SL_STIN,
-    SL_STUN,
-    SL_SMA,
-    SL_SWOO,
-    SL_SKE,
-    SL_SKA,
-
-    GD_APPROVAL = 10000,
-    GD_KAFRACONTACT,
-    GD_GUARDIANRESEARCH,
-    GD_CHARISMA,
-    GD_EXTENSION,
-};
-
-// [Fate] Skill pools API
-
-// Max. # of active entries in the skill pool
-#define MAX_SKILL_POOL 3
-// Max. # of skills that may be classified as pool skills in db/skill_db.txt
-#define MAX_POOL_SKILLS 128
-
-extern int skill_pool_skills[MAX_POOL_SKILLS];  // All pool skills
-extern int skill_pool_skills_size;  // Number of entries in skill_pool_skills
-
-int  skill_pool (struct map_session_data *sd, int *skills); // Yields all active skills in the skill pool; no more than MAX_SKILL_POOL.  Return is number of skills.
-int  skill_pool_size (struct map_session_data *sd);
-int  skill_pool_max (struct map_session_data *sd);  // Max. number of pool skills
-void skill_pool_empty (struct map_session_data *sd);    // Deactivate all pool skills
-int  skill_pool_activate (struct map_session_data *sd, int skill);  // Skill into skill pool.  Return is zero iff okay.
-int  skill_pool_is_activated (struct map_session_data *sd, int skill);  // Skill into skill pool.  Return is zero when activated.
-int  skill_pool_deactivate (struct map_session_data *sd, int skill);    // Skill out of skill pool.  Return is zero iff okay.
-char *skill_name (int skill);   // Yield configurable skill name
-int  skill_stat (int skill);    // Yields the stat associated with a skill.  Returns zero if none, or SP_STR, SP_VIT, ... otherwise
-int  skill_power (struct map_session_data *sd, int skill);  // Yields the power of a skill.  This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
-                             // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
-int  skill_power_bl (struct block_list *bl, int skill); // Yields the power of a skill.  This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
-                             // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
-
-#endif
diff --git a/src/map/skill.hpp b/src/map/skill.hpp
new file mode 100644
index 0000000..e2aaba5
--- /dev/null
+++ b/src/map/skill.hpp
@@ -0,0 +1,891 @@
+// $Id: skill.h,v 1.5 2004/09/25 05:32:19 MouseJstr Exp $
+#ifndef SKILL_HPP
+#define SKILL_HPP
+
+#include "../common/timer.hpp"
+
+#include "map.hpp"
+#include "magic.hpp"
+
+#define MAX_SKILL_DB			450
+#define MAX_SKILL_PRODUCE_DB	 150
+#define MAX_SKILL_ARROW_DB	 150
+#define MAX_SKILL_ABRA_DB	 350
+
+#define SKILL_POOL_FLAG		0x1 // is a pool skill
+#define SKILL_POOL_ACTIVE	0x2 // is an active pool skill
+#define SKILL_POOL_ACTIVATED	0x4 // pool skill has been activated (used for clif)
+
+// スキルデータベース
+struct skill_db
+{
+    int  range[MAX_SKILL_LEVEL], hit, inf, pl, nk, max, stat, poolflags, max_raise; // `max' is the global max, `max_raise' is the maximum attainable via skill-ups
+    int  num[MAX_SKILL_LEVEL];
+    int  cast[MAX_SKILL_LEVEL], delay[MAX_SKILL_LEVEL];
+    int  upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL];
+    int  castcancel, cast_def_rate;
+    int  inf2, maxcount, skill_type;
+    int  blewcount[MAX_SKILL_LEVEL];
+    int  hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL],
+        hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL],
+        zeny[MAX_SKILL_LEVEL];
+    int  weapon, state, spiritball[MAX_SKILL_LEVEL];
+    int  itemid[10], amount[10];
+    int  castnodex[MAX_SKILL_LEVEL];
+};
+extern struct skill_db skill_db[MAX_SKILL_DB];
+
+struct skill_name_db
+{
+    int  id;                    // skill id
+    const char *name;                 // search strings
+    const char *desc;                 // description that shows up for search's
+};
+extern struct skill_name_db skill_names[];
+
+struct block_list;
+struct map_session_data;
+struct skill_unit;
+struct skill_unit_group;
+
+int  do_init_skill (void);
+
+// スキルデータベースへのアクセサ
+int  skill_get_hit (int id);
+int  skill_get_inf (int id);
+int  skill_get_pl (int id);
+int  skill_get_nk (int id);
+int  skill_get_max (int id);
+int  skill_get_max_raise (int id);
+int  skill_get_range (int id, int lv);
+int  skill_get_hp (int id, int lv);
+int  skill_get_mhp (int id, int lv);
+int  skill_get_sp (int id, int lv);
+int  skill_get_zeny (int id, int lv);
+int  skill_get_num (int id, int lv);
+int  skill_get_cast (int id, int lv);
+int  skill_get_delay (int id, int lv);
+int  skill_get_time (int id, int lv);
+int  skill_get_time2 (int id, int lv);
+int  skill_get_castdef (int id);
+int  skill_get_weapontype (int id);
+int  skill_get_unit_id (int id, int flag);
+int  skill_get_inf2 (int id);
+int  skill_get_maxcount (int id);
+int  skill_get_blewcount (int id, int lv);
+
+// スキルの使用
+int  skill_use_id (struct map_session_data *sd, int target_id,
+                   int skill_num, int skill_lv);
+int  skill_use_pos (struct map_session_data *sd,
+                    int skill_x, int skill_y, int skill_num, int skill_lv);
+
+int  skill_castend_map (struct map_session_data *sd, int skill_num,
+                        const char *map);
+
+int  skill_cleartimerskill (struct block_list *src);
+int  skill_addtimerskill (struct block_list *src, unsigned int tick,
+                          int target, int x, int y, int skill_id,
+                          int skill_lv, int type, int flag);
+
+// 追加効果
+int  skill_additional_effect (struct block_list *src, struct block_list *bl,
+                              int skillid, int skilllv, int attack_type,
+                              unsigned int tick);
+
+// ユニットスキル
+struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx,
+                                   int x, int y);
+int  skill_delunit (struct skill_unit *unit);
+struct skill_unit_group *skill_initunitgroup (struct block_list *src,
+                                              int count, int skillid,
+                                              int skilllv, int unit_id);
+int  skill_delunitgroup (struct skill_unit_group *group);
+struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct
+                                                                block_list
+                                                                *bl,
+                                                                int group_id);
+int  skill_unitgrouptickset_delete (struct block_list *bl, int group_id);
+int  skill_clear_unitgroup (struct block_list *src);
+
+int  skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl,
+                           int damage, unsigned int tick);
+
+int  skill_castfix (struct block_list *bl, int time);
+int  skill_delayfix (struct block_list *bl, int time);
+int  skill_check_unit_range (int m, int x, int y, int range, int skillid);
+int  skill_check_unit_range2 (int m, int x, int y, int range);
+// -- moonsoul  (added skill_check_unit_cell)
+int  skill_check_unit_cell (int skillid, int m, int x, int y, int unit_id);
+int  skill_unit_out_all (struct block_list *bl, unsigned int tick, int range);
+int  skill_unit_move (struct block_list *bl, unsigned int tick, int range);
+int  skill_unit_move_unit_group (struct skill_unit_group *group, int m,
+                                 int dx, int dy);
+
+struct skill_unit_group *skill_check_dancing (struct block_list *src);
+void skill_stop_dancing (struct block_list *src, int flag);
+
+// 詠唱キャンセル
+int  skill_castcancel (struct block_list *bl, int type);
+
+int  skill_gangsterparadise (struct map_session_data *sd, int type);
+void skill_brandishspear_first (struct square *tc, int dir, int x, int y);
+void skill_brandishspear_dir (struct square *tc, int dir, int are);
+int  skill_autospell (struct map_session_data *md, int skillid);
+void skill_devotion (struct map_session_data *md, int target);
+void skill_devotion2 (struct block_list *bl, int crusader);
+int  skill_devotion3 (struct block_list *bl, int target);
+void skill_devotion_end (struct map_session_data *md,
+                         struct map_session_data *sd, int target);
+
+#define skill_calc_heal(bl,skill_lv) (( battle_get_lv(bl)+battle_get_int(bl) )/8 *(4+ skill_lv*8))
+
+// その他
+int  skill_check_cloaking (struct block_list *bl);
+int  skill_is_danceskill (int id);
+
+// ステータス異常
+int  skill_status_effect (struct block_list *bl, int type, int val1, int val2,
+                          int val3, int val4, int tick, int flag,
+                          int spell_invocation);
+int  skill_status_change_start (struct block_list *bl, int type, int val1,
+                                int val2, int val3, int val4, int tick,
+                                int flag);
+void skill_status_change_timer (timer_id, tick_t, custom_id_t, custom_data_t);
+int  skill_status_change_active (struct block_list *bl, int type);  // [fate]
+int  skill_encchant_eremental_end (struct block_list *bl, int type);
+int  skill_status_change_end (struct block_list *bl, int type, int tid);
+int  skill_status_change_clear (struct block_list *bl, int type);
+
+// mobスキルのため
+int  skill_castend_nodamage_id (struct block_list *src, struct block_list *bl,
+                                int skillid, int skilllv, unsigned int tick,
+                                int flag);
+int  skill_castend_damage_id (struct block_list *src, struct block_list *bl,
+                              int skillid, int skilllv, unsigned int tick,
+                              int flag);
+int  skill_castend_pos2 (struct block_list *src, int x, int y, int skillid,
+                         int skilllv, unsigned int tick, int flag);
+
+// スキル攻撃一括処理
+int  skill_attack (int attack_type, struct block_list *src,
+                   struct block_list *dsrc, struct block_list *bl,
+                   int skillid, int skilllv, unsigned int tick, int flag);
+
+int  skill_update_heal_animation (struct map_session_data *sd); // [Fate]  Check whether the healing flag must be updated, do so if needed
+
+void skill_reload (void);
+
+enum
+{
+    ST_NONE, ST_HIDING, ST_CLOAKING, ST_HIDDEN, ST_RIDING, ST_FALCON, ST_CART,
+    ST_SHIELD, ST_SIGHT, ST_EXPLOSIONSPIRITS,
+    ST_RECOV_WEIGHT_RATE, ST_MOVE_ENABLE, ST_WATER,
+};
+
+enum
+{                               // struct map_session_data の status_changeの番号テーブル
+    SC_SENDMAX = 256,
+    SC_PROVOKE = 0,
+    SC_ENDURE = 1,
+    SC_TWOHANDQUICKEN = 2,
+    SC_CONCENTRATE = 3,
+    SC_HIDING = 4,
+    SC_CLOAKING = 5,
+    SC_ENCPOISON = 6,
+    SC_POISONREACT = 7,
+    SC_QUAGMIRE = 8,
+    SC_ANGELUS = 9,
+    SC_BLESSING = 10,
+    SC_SIGNUMCRUCIS = 11,
+    SC_INCREASEAGI = 12,
+    SC_DECREASEAGI = 13,
+    SC_SLOWPOISON = 14,
+    SC_IMPOSITIO = 15,
+    SC_SUFFRAGIUM = 16,
+    SC_ASPERSIO = 17,
+    SC_BENEDICTIO = 18,
+    SC_KYRIE = 19,
+    SC_MAGNIFICAT = 20,
+    SC_GLORIA = 21,
+    SC_AETERNA = 22,
+    SC_ADRENALINE = 23,
+    SC_WEAPONPERFECTION = 24,
+    SC_OVERTHRUST = 25,
+    SC_MAXIMIZEPOWER = 26,
+    SC_RIDING = 27,
+    SC_FALCON = 28,
+    SC_TRICKDEAD = 29,
+    SC_LOUD = 30,
+    SC_ENERGYCOAT = 31,
+    SC_BROKNARMOR = 32,
+    SC_BROKNWEAPON = 33,
+    SC_HALLUCINATION = 34,
+    SC_WEIGHT50 = 35,
+    SC_WEIGHT90 = 36,
+    SC_SPEEDPOTION0 = 37,
+    SC_SPEEDPOTION1 = 38,
+    SC_SPEEDPOTION2 = 39,
+
+    SC_STRIPWEAPON = 50,
+    SC_STRIPSHIELD = 51,
+    SC_STRIPARMOR = 52,
+    SC_STRIPHELM = 53,
+    SC_CP_WEAPON = 54,
+    SC_CP_SHIELD = 55,
+    SC_CP_ARMOR = 56,
+    SC_CP_HELM = 57,
+    SC_AUTOGUARD = 58,
+    SC_REFLECTSHIELD = 59,
+    SC_DEVOTION = 60,
+    SC_PROVIDENCE = 61,
+    SC_DEFENDER = 62,
+    SC_AUTOSPELL = 65,
+    SC_EXPLOSIONSPIRITS = 86,
+    SC_STEELBODY = 87,
+    SC_SPEARSQUICKEN = 68,
+
+    SC_HEALING = 70,
+
+    SC_SIGHTTRASHER = 73,
+
+    SC_COMBO = 89,
+    SC_FLAMELAUNCHER = 90,
+    SC_FROSTWEAPON = 91,
+    SC_LIGHTNINGLOADER = 92,
+    SC_SEISMICWEAPON = 93,
+
+    SC_AURABLADE = 103,
+    SC_PARRYING = 104,
+    SC_CONCENTRATION = 105,
+    SC_TENSIONRELAX = 106,
+    SC_BERSERK = 107,
+
+    SC_ASSUMPTIO = 110,
+
+    SC_MAGICPOWER = 113,
+
+    SC_TRUESIGHT = 115,
+    SC_WINDWALK = 116,
+    SC_MELTDOWN = 117,
+    SC_CARTBOOST = 118,
+
+    SC_REJECTSWORD = 120,
+    SC_MARIONETTE = 121,
+
+    SC_HEADCRUSH = 124,
+    SC_JOINTBEAT = 125,
+    SC_BASILICA = 125,
+
+    SC_STONE = 128,
+    SC_FREEZE = 129,
+    SC_STAN = 130,
+    SC_SLEEP = 131,
+    SC_POISON = 132,
+    SC_CURSE = 133,
+    SC_SILENCE = 134,
+    SC_CONFUSION = 135,
+    SC_BLIND = 136,
+
+    SC_SAFETYWALL = 140,
+    SC_PNEUMA = 141,
+    SC_WATERBALL = 142,
+    SC_ANKLE = 143,
+    SC_DANCING = 144,
+    SC_KEEPING = 145,
+    SC_BARRIER = 146,
+
+    SC_MAGICROD = 149,
+    SC_SIGHT = 150,
+    SC_RUWACH = 151,
+    SC_AUTOCOUNTER = 152,
+    SC_VOLCANO = 153,
+    SC_DELUGE = 154,
+    SC_VIOLENTGALE = 155,
+    SC_BLADESTOP_WAIT = 156,
+    SC_BLADESTOP = 157,
+    SC_EXTREMITYFIST = 158,
+    SC_GRAFFITI = 159,
+    SC_ENSEMBLE = 159,
+
+    SC_LULLABY = 160,
+    SC_RICHMANKIM = 161,
+    SC_ETERNALCHAOS = 162,
+    SC_DRUMBATTLE = 163,
+    SC_NIBELUNGEN = 164,
+    SC_ROKISWEIL = 165,
+    SC_INTOABYSS = 166,
+    SC_SIEGFRIED = 167,
+    SC_DISSONANCE = 168,
+    SC_WHISTLE = 169,
+    SC_ASSNCROS = 170,
+    SC_POEMBRAGI = 171,
+    SC_APPLEIDUN = 172,
+    SC_UGLYDANCE = 173,
+    SC_HUMMING = 174,
+    SC_DONTFORGETME = 175,
+    SC_FORTUNE = 176,
+    SC_SERVICE4U = 177,
+    SC_FOGWALL = 178,
+    SC_GOSPEL = 179,
+    SC_SPIDERWEB = 180,
+    SC_MEMORIZE = 181,
+    SC_LANDPROTECTOR = 182,
+    SC_ADAPTATION = 183,
+    SC_CHASEWALK = 184,
+    SC_ATKPOT = 185,
+    SC_MATKPOT = 186,
+    SC_WEDDING = 187,
+    SC_NOCHAT = 188,
+    SC_SPLASHER = 189,
+    SC_SELFDESTRUCTION = 190,
+    SC_MINDBREAKER = 191,
+    SC_SPELLBREAKER = 192,
+
+// Added for Fate's spells
+    SC_HIDE = 194,              // Hide from `detect' magic
+    SC_HALT_REGENERATE = 195,   // Suspend regeneration
+    SC_FLYING_BACKPACK = 196,   // Flying backpack
+    SC_MBARRIER = 197,          // Magical barrier, magic resistance (val1 : power (%))
+    SC_HASTE = 198,             // `Haste' spell (val1 : power)
+    SC_PHYS_SHIELD = 199,       // `Protect' spell, reduce damage (val1: power)
+
+    SC_DIVINA = SC_SILENCE,
+};
+extern int SkillStatusChangeTable[];
+
+enum
+{
+    NV_EMOTE = 1,
+    NV_TRADE,
+    NV_PARTY,
+
+    SM_SWORD,
+    SM_TWOHAND,
+    SM_RECOVERY,
+    SM_BASH,
+    SM_PROVOKE,
+    SM_MAGNUM,
+    SM_ENDURE,
+
+    MG_SRECOVERY,
+    MG_SIGHT,
+    MG_NAPALMBEAT,
+    MG_SAFETYWALL,
+    MG_SOULSTRIKE,
+    MG_COLDBOLT,
+    MG_FROSTDIVER,
+    MG_STONECURSE,
+    MG_FIREBALL,
+    MG_FIREWALL,
+    MG_FIREBOLT,
+    MG_LIGHTNINGBOLT,
+    MG_THUNDERSTORM,
+
+    AL_DP,
+    AL_DEMONBANE,
+    AL_RUWACH,
+    AL_PNEUMA,
+    AL_TELEPORT,
+    AL_WARP,
+    AL_HEAL,
+    AL_INCAGI,
+    AL_DECAGI,
+    AL_HOLYWATER,
+    AL_CRUCIS,
+    AL_ANGELUS,
+    AL_BLESSING,
+    AL_CURE,
+
+    MC_INCCARRY,
+    MC_DISCOUNT,
+    MC_OVERCHARGE,
+    MC_PUSHCART,
+    MC_IDENTIFY,
+    MC_VENDING,
+    MC_MAMMONITE,
+
+    AC_OWL = 45,
+    AC_VULTURE,
+    AC_CONCENTRATION,
+    AC_DOUBLE,
+    AC_SHOWER,
+
+    TF_DOUBLE,
+    TF_MISS,
+    TF_STEAL,
+    TF_HIDING,
+    TF_POISON,
+    TF_DETOXIFY,
+
+    ALL_RESURRECTION,
+
+    KN_SPEARMASTERY,
+    KN_PIERCE,
+    KN_BRANDISHSPEAR,
+    KN_SPEARSTAB,
+    KN_SPEARBOOMERANG,
+    KN_TWOHANDQUICKEN,
+    KN_AUTOCOUNTER,
+    KN_BOWLINGBASH,
+    KN_RIDING,
+    KN_CAVALIERMASTERY,
+
+    PR_MACEMASTERY,
+    PR_IMPOSITIO,
+    PR_SUFFRAGIUM,
+    PR_ASPERSIO,
+    PR_BENEDICTIO,
+    PR_SANCTUARY,
+    PR_SLOWPOISON,
+    PR_STRECOVERY,
+    PR_KYRIE,
+    PR_MAGNIFICAT,
+    PR_GLORIA,
+    PR_LEXDIVINA,
+    PR_TURNUNDEAD,
+    PR_LEXAETERNA,
+    PR_MAGNUS,
+
+    WZ_FIREPILLAR,
+    WZ_SIGHTRASHER,
+    WZ_FIREIVY,
+    WZ_METEOR,
+    WZ_JUPITEL,
+    WZ_VERMILION,
+    WZ_WATERBALL,
+    WZ_ICEWALL,
+    WZ_FROSTNOVA,
+    WZ_STORMGUST,
+    WZ_EARTHSPIKE,
+    WZ_HEAVENDRIVE,
+    WZ_QUAGMIRE,
+    WZ_ESTIMATION,
+
+    BS_IRON,
+    BS_STEEL,
+    BS_ENCHANTEDSTONE,
+    BS_ORIDEOCON,
+    BS_DAGGER,
+    BS_SWORD,
+    BS_TWOHANDSWORD,
+    BS_AXE,
+    BS_MACE,
+    BS_KNUCKLE,
+    BS_SPEAR,
+    BS_HILTBINDING,
+    BS_FINDINGORE,
+    BS_WEAPONRESEARCH,
+    BS_REPAIRWEAPON,
+    BS_SKINTEMPER,
+    BS_HAMMERFALL,
+    BS_ADRENALINE,
+    BS_WEAPONPERFECT,
+    BS_OVERTHRUST,
+    BS_MAXIMIZE,
+
+    HT_SKIDTRAP,
+    HT_LANDMINE,
+    HT_ANKLESNARE,
+    HT_SHOCKWAVE,
+    HT_SANDMAN,
+    HT_FLASHER,
+    HT_FREEZINGTRAP,
+    HT_BLASTMINE,
+    HT_CLAYMORETRAP,
+    HT_REMOVETRAP,
+    HT_TALKIEBOX,
+    HT_BEASTBANE,
+    HT_FALCON,
+    HT_STEELCROW,
+    HT_BLITZBEAT,
+    HT_DETECTING,
+    HT_SPRINGTRAP,
+
+    AS_RIGHT,
+    AS_LEFT,
+    AS_KATAR,
+    AS_CLOAKING,
+    AS_SONICBLOW,
+    AS_GRIMTOOTH,
+    AS_ENCHANTPOISON,
+    AS_POISONREACT,
+    AS_VENOMDUST,
+    AS_SPLASHER,
+
+    NV_FIRSTAID,
+    NV_TRICKDEAD,
+    SM_MOVINGRECOVERY,
+    SM_FATALBLOW,
+    SM_AUTOBERSERK,
+    AC_MAKINGARROW,
+    AC_CHARGEARROW,
+    TF_SPRINKLESAND,
+    TF_BACKSLIDING,
+    TF_PICKSTONE,
+    TF_THROWSTONE,
+    MC_CARTREVOLUTION,
+    MC_CHANGECART,
+    MC_LOUD,
+    AL_HOLYLIGHT,
+    MG_ENERGYCOAT,
+
+    NPC_PIERCINGATT,
+    NPC_MENTALBREAKER,
+    NPC_RANGEATTACK,
+    NPC_ATTRICHANGE,
+    NPC_CHANGEWATER,
+    NPC_CHANGEGROUND,
+    NPC_CHANGEFIRE,
+    NPC_CHANGEWIND,
+    NPC_CHANGEPOISON,
+    NPC_CHANGEHOLY,
+    NPC_CHANGEDARKNESS,
+    NPC_CHANGETELEKINESIS,
+    NPC_CRITICALSLASH,
+    NPC_COMBOATTACK,
+    NPC_GUIDEDATTACK,
+    NPC_SELFDESTRUCTION,
+    NPC_SPLASHATTACK,
+    NPC_SUICIDE,
+    NPC_POISON,
+    NPC_BLINDATTACK,
+    NPC_SILENCEATTACK,
+    NPC_STUNATTACK,
+    NPC_PETRIFYATTACK,
+    NPC_CURSEATTACK,
+    NPC_SLEEPATTACK,
+    NPC_RANDOMATTACK,
+    NPC_WATERATTACK,
+    NPC_GROUNDATTACK,
+    NPC_FIREATTACK,
+    NPC_WINDATTACK,
+    NPC_POISONATTACK,
+    NPC_HOLYATTACK,
+    NPC_DARKNESSATTACK,
+    NPC_TELEKINESISATTACK,
+    NPC_MAGICALATTACK,
+    NPC_METAMORPHOSIS,
+    NPC_PROVOCATION,
+    NPC_SMOKING,
+    NPC_SUMMONSLAVE,
+    NPC_EMOTION,
+    NPC_TRANSFORMATION,
+    NPC_BLOODDRAIN,
+    NPC_ENERGYDRAIN,
+    NPC_KEEPING,
+    NPC_DARKBREATH,
+    NPC_DARKBLESSING,
+    NPC_BARRIER,
+    NPC_DEFENDER,
+    NPC_LICK,
+    NPC_HALLUCINATION,
+    NPC_REBIRTH,
+    NPC_SUMMONMONSTER,
+
+    RG_SNATCHER,
+    RG_STEALCOIN,
+    RG_BACKSTAP,
+    RG_TUNNELDRIVE,
+    RG_RAID,
+    RG_STRIPWEAPON,
+    RG_STRIPSHIELD,
+    RG_STRIPARMOR,
+    RG_STRIPHELM,
+    RG_INTIMIDATE,
+    RG_GRAFFITI,
+    RG_FLAGGRAFFITI,
+    RG_CLEANER,
+    RG_GANGSTER,
+    RG_COMPULSION,
+    RG_PLAGIARISM,
+
+    AM_AXEMASTERY,
+    AM_LEARNINGPOTION,
+    AM_PHARMACY,
+    AM_DEMONSTRATION,
+    AM_ACIDTERROR,
+    AM_POTIONPITCHER,
+    AM_CANNIBALIZE,
+    AM_SPHEREMINE,
+    AM_CP_WEAPON,
+    AM_CP_SHIELD,
+    AM_CP_ARMOR,
+    AM_CP_HELM,
+    AM_BIOETHICS,
+    AM_BIOTECHNOLOGY,
+    AM_CREATECREATURE,
+    AM_CULTIVATION,
+    AM_FLAMECONTROL,
+    AM_CALLHOMUN,
+    AM_REST,
+    AM_DRILLMASTER,
+    AM_HEALHOMUN,
+    AM_RESURRECTHOMUN,
+
+    CR_TRUST,
+    CR_AUTOGUARD,
+    CR_SHIELDCHARGE,
+    CR_SHIELDBOOMERANG,
+    CR_REFLECTSHIELD,
+    CR_HOLYCROSS,
+    CR_GRANDCROSS,
+    CR_DEVOTION,
+    CR_PROVIDENCE,
+    CR_DEFENDER,
+    CR_SPEARQUICKEN,
+
+    MO_IRONHAND,
+    MO_SPIRITSRECOVERY,
+    MO_CALLSPIRITS,
+    MO_ABSORBSPIRITS,
+    MO_TRIPLEATTACK,
+    MO_BODYRELOCATION,
+    MO_DODGE,
+    MO_INVESTIGATE,
+    MO_FINGEROFFENSIVE,
+    MO_STEELBODY,
+    MO_BLADESTOP,
+    MO_EXPLOSIONSPIRITS,
+    MO_EXTREMITYFIST,
+    MO_CHAINCOMBO,
+    MO_COMBOFINISH,
+
+    SA_ADVANCEDBOOK,
+    SA_CASTCANCEL,
+    SA_MAGICROD,
+    SA_SPELLBREAKER,
+    SA_FREECAST,
+    SA_AUTOSPELL,
+    SA_FLAMELAUNCHER,
+    SA_FROSTWEAPON,
+    SA_LIGHTNINGLOADER,
+    SA_SEISMICWEAPON,
+    SA_DRAGONOLOGY,
+    SA_VOLCANO,
+    SA_DELUGE,
+    SA_VIOLENTGALE,
+    SA_LANDPROTECTOR,
+    SA_DISPELL,
+    SA_ABRACADABRA,
+    SA_MONOCELL,
+    SA_CLASSCHANGE,
+    SA_SUMMONMONSTER,
+    SA_REVERSEORCISH,
+    SA_DEATH,
+    SA_FORTUNE,
+    SA_TAMINGMONSTER,
+    SA_QUESTION,
+    SA_GRAVITY,
+    SA_LEVELUP,
+    SA_INSTANTDEATH,
+    SA_FULLRECOVERY,
+    SA_COMA,
+
+    BD_ADAPTATION,
+    BD_ENCORE,
+    BD_LULLABY,
+    BD_RICHMANKIM,
+    BD_ETERNALCHAOS,
+    BD_DRUMBATTLEFIELD,
+    BD_RINGNIBELUNGEN,
+    BD_ROKISWEIL,
+    BD_INTOABYSS,
+    BD_SIEGFRIED,
+    BD_RAGNAROK,
+
+    BA_MUSICALLESSON,
+    BA_MUSICALSTRIKE,
+    BA_DISSONANCE,
+    BA_FROSTJOKE,
+    BA_WHISTLE,
+    BA_ASSASSINCROSS,
+    BA_POEMBRAGI,
+    BA_APPLEIDUN,
+
+    DC_DANCINGLESSON,
+    DC_THROWARROW,
+    DC_UGLYDANCE,
+    DC_SCREAM,
+    DC_HUMMING,
+    DC_DONTFORGETME,
+    DC_FORTUNEKISS,
+    DC_SERVICEFORYOU,
+
+    NPC_SELFDESTRUCTION2 = 333,
+
+    WE_MALE = 334,
+    WE_FEMALE,
+    WE_CALLPARTNER,
+
+    NPC_DARKCROSS = 338,
+
+    TMW_SKILLPOOL = 339,        // skill pool size
+
+    TMW_MAGIC = 340,
+    TMW_MAGIC_LIFE = 341,
+    TMW_MAGIC_WAR = 342,
+    TMW_MAGIC_TRANSMUTE = 343,
+    TMW_MAGIC_NATURE = 344,
+    TMW_MAGIC_ETHER = 345,
+    TMW_MAGIC_DARK = 346,
+    TMW_MAGIC_LIGHT = 347,
+
+    TMW_BRAWLING = 350,
+    TMW_LUCKY_COUNTER = 351,
+    TMW_SPEED = 352,
+    TMW_RESIST_POISON = 353,
+    TMW_ASTRAL_SOUL = 354,
+    TMW_RAGING = 355,
+
+    LK_AURABLADE = 356,
+    LK_PARRYING,
+    LK_CONCENTRATION,
+    LK_TENSIONRELAX,
+    LK_BERSERK,
+    LK_FURY,
+    HP_ASSUMPTIO,
+    HP_BASILICA,
+    HP_MEDITATIO,
+    HW_SOULDRAIN,
+    HW_MAGICCRASHER,
+    HW_MAGICPOWER,
+    PA_PRESSURE,
+    PA_SACRIFICE,
+    PA_GOSPEL,
+    CH_PALMSTRIKE,
+    CH_TIGERFIST,
+    CH_CHAINCRUSH,
+    PF_HPCONVERSION,
+    PF_SOULCHANGE,
+    PF_SOULBURN,
+    ASC_KATAR,
+    ASC_HALLUCINATION,
+    ASC_EDP,
+    ASC_BREAKER,
+    SN_SIGHT,
+    SN_FALCONASSAULT,
+    SN_SHARPSHOOTING,
+    SN_WINDWALK,
+    WS_MELTDOWN,
+    WS_CREATECOIN,
+    WS_CREATENUGGET,
+    WS_CARTBOOST,
+    WS_SYSTEMCREATE,
+    ST_CHASEWALK,
+    ST_REJECTSWORD,
+    ST_STEALBACKPACK,
+    CR_ALCHEMY,
+    CR_SYNTHESISPOTION,
+    CG_ARROWVULCAN,
+    CG_MOONLIT,
+    CG_MARIONETTE,
+    LK_SPIRALPIERCE,
+    LK_HEADCRUSH,
+    LK_JOINTBEAT,
+    HW_NAPALMVULCAN,
+    CH_SOULCOLLECT,
+    PF_MINDBREAKER,
+    PF_MEMORIZE,
+    PF_FOGWALL,
+    PF_SPIDERWEB,
+    ASC_METEORASSAULT,
+    ASC_CDP,
+    WE_BABY,
+    WE_CALLPARENT,
+    WE_CALLBABY,
+    TK_RUN,
+    TK_READYSTORM,
+    TK_STORMKICK,
+    TK_READYDOWN,
+    TK_DOWNKICK,
+    TK_READYTURN,
+    TK_TURNKICK,
+    TK_READYCOUNTER,
+    TK_COUNTER,
+    TK_DODGE,
+    TK_JUMPKICK,
+    TK_HPTIME,
+    TK_SPTIME,
+    TK_POWER,
+    TK_SEVENWIND,
+    TK_HIGHJUMP,
+    SG_FEEL,
+    SG_SUN_WARM,
+    SG_MOON_WARM,
+    SG_STAR_WARM,
+    SG_SUN_COMFORT,
+    SG_MOON_COMFORT,
+    SG_STAR_COMFORT,
+    SG_HATE,
+    SG_SUN_ANGER,
+    SG_MOON_ANGER,
+    SG_STAR_ANGER,
+    SG_SUN_BLESS,
+    SG_MOON_BLESS,
+    SG_STAR_BLESS,
+    SG_DEVIL,
+    SG_FRIEND,
+    SG_KNOWLEDGE,
+    SG_FUSION,
+    SL_ALCHEMIST,
+    AM_BERSERKPITCHER,
+    SL_MONK,
+    SL_STAR,
+    SL_SAGE,
+    SL_CRUSADER,
+    SL_SUPERNOVICE,
+    SL_KNIGHT,
+    SL_WIZARD,
+    SL_PRIEST,
+    SL_BARDDANCER,
+    SL_ROGUE,
+    SL_ASSASIN,
+    SL_BLACKSMITH,
+    BS_ADRENALINE2,
+    SL_HUNTER,
+    SL_SOULLINKER,
+    SL_KAIZEL,
+    SL_KAAHI,
+    SL_KAUPE,
+    SL_KAITE,
+    SL_KAINA,
+    SL_STIN,
+    SL_STUN,
+    SL_SMA,
+    SL_SWOO,
+    SL_SKE,
+    SL_SKA,
+
+    GD_APPROVAL = 10000,
+    GD_KAFRACONTACT,
+    GD_GUARDIANRESEARCH,
+    GD_CHARISMA,
+    GD_EXTENSION,
+};
+
+// [Fate] Skill pools API
+
+// Max. # of active entries in the skill pool
+#define MAX_SKILL_POOL 3
+// Max. # of skills that may be classified as pool skills in db/skill_db.txt
+#define MAX_POOL_SKILLS 128
+
+extern int skill_pool_skills[MAX_POOL_SKILLS];  // All pool skills
+extern int skill_pool_skills_size;  // Number of entries in skill_pool_skills
+
+int  skill_pool (struct map_session_data *sd, int *skills); // Yields all active skills in the skill pool; no more than MAX_SKILL_POOL.  Return is number of skills.
+int  skill_pool_size (struct map_session_data *sd);
+int  skill_pool_max (struct map_session_data *sd);  // Max. number of pool skills
+void skill_pool_empty (struct map_session_data *sd);    // Deactivate all pool skills
+int  skill_pool_activate (struct map_session_data *sd, int skill);  // Skill into skill pool.  Return is zero iff okay.
+int  skill_pool_is_activated (struct map_session_data *sd, int skill);  // Skill into skill pool.  Return is zero when activated.
+int  skill_pool_deactivate (struct map_session_data *sd, int skill);    // Skill out of skill pool.  Return is zero iff okay.
+char *skill_name (int skill);   // Yield configurable skill name
+int  skill_stat (int skill);    // Yields the stat associated with a skill.  Returns zero if none, or SP_STR, SP_VIT, ... otherwise
+int  skill_power (struct map_session_data *sd, int skill);  // Yields the power of a skill.  This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
+                             // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
+int  skill_power_bl (struct block_list *bl, int skill); // Yields the power of a skill.  This is zero if the skill is unknown or if it's a pool skill that is outside of the skill pool,
+                             // otherwise a value from 0 to 255 (with 200 being the `normal maximum')
+
+#endif
diff --git a/src/map/storage.c b/src/map/storage.c
deleted file mode 100644
index 4a0d934..0000000
--- a/src/map/storage.c
+++ /dev/null
@@ -1,787 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/db.h"
-#include "../common/nullpo.h"
-
-#include "storage.h"
-#include "chrif.h"
-#include "itemdb.h"
-#include "clif.h"
-#include "intif.h"
-#include "pc.h"
-#include "guild.h"
-#include "battle.h"
-#include "atcommand.h"
-
-static struct dbt *storage_db;
-static struct dbt *guild_storage_db;
-
-/*==========================================
- * 倉庫内アイテムソート
- *------------------------------------------
- */
-int storage_comp_item (const void *_i1, const void *_i2)
-{
-    struct item *i1 = (struct item *) _i1;
-    struct item *i2 = (struct item *) _i2;
-
-    if (i1->nameid == i2->nameid)
-        return 0;
-    else if (!(i1->nameid) || !(i1->amount))
-        return 1;
-    else if (!(i2->nameid) || !(i2->amount))
-        return -1;
-    return i1->nameid - i2->nameid;
-}
-
-static void guild_storage_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    struct guild_storage *gstor = (struct guild_storage *) data;
-    free (gstor);
-}
-
-static void storage_db_final (db_key_t key, db_val_t data, va_list ap)
-{
-    struct storage *stor = (struct storage *) data;
-    free (stor);
-}
-
-void sortage_sortitem (struct storage *stor)
-{
-    nullpo_retv (stor);
-    qsort (stor->storage_, MAX_STORAGE, sizeof (struct item),
-           storage_comp_item);
-}
-
-void sortage_gsortitem (struct guild_storage *gstor)
-{
-    nullpo_retv (gstor);
-    qsort (gstor->storage_, MAX_GUILD_STORAGE, sizeof (struct item),
-           storage_comp_item);
-}
-
-/*==========================================
- * 初期化とか
- *------------------------------------------
- */
-int do_init_storage (void)      // map.c::do_init()から呼ばれる
-{
-    storage_db = numdb_init ();
-    guild_storage_db = numdb_init ();
-    return 1;
-}
-
-void do_final_storage (void)    // by [MC Cameri]
-{
-    if (storage_db)
-        numdb_final (storage_db, storage_db_final);
-    if (guild_storage_db)
-        numdb_final (guild_storage_db, guild_storage_db_final);
-}
-
-static void storage_reconnect_sub (db_key_t key, db_val_t data, va_list ap)
-{                               //Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
-    int  type = va_arg (ap, int);
-    if (type)
-    {                           //Guild Storage
-        struct guild_storage *stor = (struct guild_storage *) data;
-        if (stor->dirty && stor->storage_status == 0)   //Save closed storages.
-            storage_guild_storagesave (0, stor->guild_id, 0);
-    }
-    else
-    {                           //Account Storage
-        struct storage *stor = (struct storage *) data;
-        if (stor->dirty && stor->storage_status == 0)   //Save closed storages.
-            storage_storage_save (stor->account_id, stor->dirty == 2 ? 1 : 0);
-    }
-}
-
-//Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex
-void do_reconnect_storage (void)
-{
-    numdb_foreach (storage_db, storage_reconnect_sub, 0);
-    numdb_foreach (guild_storage_db, storage_reconnect_sub, 1);
-}
-
-struct storage *account2storage (int account_id)
-{
-    struct storage *stor =
-        (struct storage *) numdb_search (storage_db, account_id);
-    if (stor == NULL)
-    {
-        CREATE (stor, struct storage, 1);
-        stor->account_id = account_id;
-        numdb_insert (storage_db, stor->account_id, stor);
-    }
-    return stor;
-}
-
-// Just to ask storage, without creation
-struct storage *account2storage2 (int account_id)
-{
-    return (struct storage *) numdb_search (storage_db, account_id);
-}
-
-int storage_delete (int account_id)
-{
-    struct storage *stor =
-        (struct storage *) numdb_search (storage_db, account_id);
-    if (stor)
-    {
-        numdb_erase (storage_db, account_id);
-        free (stor);
-    }
-    return 0;
-}
-
-/*==========================================
- * カプラ倉庫を開く
- *------------------------------------------
- */
-int storage_storageopen (struct map_session_data *sd)
-{
-    struct storage *stor;
-    nullpo_retr (0, sd);
-
-    if (sd->state.storage_flag)
-        return 1;               //Already open?
-
-    if ((stor =
-         (struct storage *) numdb_search (storage_db,
-                                          sd->status.account_id)) == NULL)
-    {                           //Request storage.
-        intif_request_storage (sd->status.account_id);
-        return 1;
-    }
-
-    if (stor->storage_status)
-        return 1;               //Already open/player already has it open...
-
-    stor->storage_status = 1;
-    sd->state.storage_flag = 1;
-    clif_storageitemlist (sd, stor);
-    clif_storageequiplist (sd, stor);
-    clif_updatestorageamount (sd, stor);
-    return 0;
-}
-
-/*==========================================
- * Internal add-item function.
- *------------------------------------------
- */
-static int storage_additem (struct map_session_data *sd, struct storage *stor,
-                            struct item *item_data, int amount)
-{
-    struct item_data *data;
-    int  i;
-
-    if (item_data->nameid <= 0 || amount <= 0)
-        return 1;
-
-    data = itemdb_search (item_data->nameid);
-
-    if (!itemdb_isequip2 (data))
-    {                           //Stackable
-        for (i = 0; i < MAX_STORAGE; i++)
-        {
-            if (compare_item (&stor->storage_[i], item_data))
-            {
-                if (amount > MAX_AMOUNT - stor->storage_[i].amount)
-                    return 1;
-                stor->storage_[i].amount += amount;
-                clif_storageitemadded (sd, stor, i, amount);
-                stor->dirty = 1;
-                return 0;
-            }
-        }
-    }
-    //Add item
-    for (i = 0; i < MAX_STORAGE && stor->storage_[i].nameid; i++);
-
-    if (i >= MAX_STORAGE)
-        return 1;
-
-    memcpy (&stor->storage_[i], item_data, sizeof (stor->storage_[0]));
-    stor->storage_[i].amount = amount;
-    stor->storage_amount++;
-    clif_storageitemadded (sd, stor, i, amount);
-    clif_updatestorageamount (sd, stor);
-    stor->dirty = 1;
-    return 0;
-}
-
-/*==========================================
- * Internal del-item function
- *------------------------------------------
- */
-static int storage_delitem (struct map_session_data *sd, struct storage *stor,
-                            int n, int amount)
-{
-
-    if (stor->storage_[n].nameid == 0 || stor->storage_[n].amount < amount)
-        return 1;
-
-    stor->storage_[n].amount -= amount;
-    if (stor->storage_[n].amount == 0)
-    {
-        memset (&stor->storage_[n], 0, sizeof (stor->storage_[0]));
-        stor->storage_amount--;
-        clif_updatestorageamount (sd, stor);
-    }
-    clif_storageitemremoved (sd, n, amount);
-
-    stor->dirty = 1;
-    return 0;
-}
-
-/*==========================================
- * Add an item to the storage from the inventory.
- *------------------------------------------
- */
-int storage_storageadd (struct map_session_data *sd, int index, int amount)
-{
-    struct storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
-
-    if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status)
-        return 0;               // storage full / storage closed
-
-    if (index < 0 || index >= MAX_INVENTORY)
-        return 0;
-
-    if (sd->status.inventory[index].nameid <= 0)
-        return 0;               //No item on that spot
-
-    if (amount < 1 || amount > sd->status.inventory[index].amount)
-        return 0;
-
-//  log_tostorage(sd, index, 0);
-    if (storage_additem (sd, stor, &sd->status.inventory[index], amount) == 0)
-    {
-        // remove item from inventory
-        pc_unequipinvyitem (sd, index, 0);
-        pc_delitem (sd, index, amount, 0);
-    }
-
-    return 1;
-}
-
-/*==========================================
- * Retrieve an item from the storage.
- *------------------------------------------
- */
-int storage_storageget (struct map_session_data *sd, int index, int amount)
-{
-    struct storage *stor;
-    int  flag;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
-
-    if (index < 0 || index >= MAX_STORAGE)
-        return 0;
-
-    if (stor->storage_[index].nameid <= 0)
-        return 0;               //Nothing there
-
-    if (amount < 1 || amount > stor->storage_[index].amount)
-        return 0;
-
-    if ((flag = pc_additem (sd, &stor->storage_[index], amount)) == 0)
-        storage_delitem (sd, stor, index, amount);
-    else
-        clif_additem (sd, 0, 0, flag);
-//  log_fromstorage(sd, index, 0);
-    return 1;
-}
-
-/*==========================================
- * Move an item from cart to storage.
- *------------------------------------------
- */
-int storage_storageaddfromcart (struct map_session_data *sd, int index,
-                                int amount)
-{
-    struct storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
-
-    if (stor->storage_amount > MAX_STORAGE || !stor->storage_status)
-        return 0;               // storage full / storage closed
-
-    if (index < 0 || index >= MAX_CART)
-        return 0;
-
-    if (sd->status.cart[index].nameid <= 0)
-        return 0;               //No item there.
-
-    if (amount < 1 || amount > sd->status.cart[index].amount)
-        return 0;
-
-    if (storage_additem (sd, stor, &sd->status.cart[index], amount) == 0)
-        pc_cart_delitem (sd, index, amount, 0);
-
-    return 1;
-}
-
-/*==========================================
- * Get from Storage to the Cart
- *------------------------------------------
- */
-int storage_storagegettocart (struct map_session_data *sd, int index,
-                              int amount)
-{
-    struct storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
-
-    if (!stor->storage_status)
-        return 0;
-
-    if (index < 0 || index >= MAX_STORAGE)
-        return 0;
-
-    if (stor->storage_[index].nameid <= 0)
-        return 0;               //Nothing there.
-
-    if (amount < 1 || amount > stor->storage_[index].amount)
-        return 0;
-
-    if (pc_cart_additem (sd, &stor->storage_[index], amount) == 0)
-        storage_delitem (sd, stor, index, amount);
-
-    return 1;
-}
-
-/*==========================================
- * Modified By Valaris to save upon closing [massdriller]
- *------------------------------------------
- */
-int storage_storageclose (struct map_session_data *sd)
-{
-    struct storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
-
-    clif_storageclose (sd);
-    if (stor->storage_status)
-    {
-        if (save_settings & 4)
-            chrif_save (sd);    //Invokes the storage saving as well.
-        else
-            storage_storage_save (sd->status.account_id, 0);
-    }
-    stor->storage_status = 0;
-    sd->state.storage_flag = 0;
-
-    if (sd->npc_flags.storage)
-    {
-        sd->npc_flags.storage = 0;
-        map_scriptcont (sd, sd->npc_id);
-    }
-
-    return 0;
-}
-
-/*==========================================
- * When quitting the game.
- *------------------------------------------
- */
-int storage_storage_quit (struct map_session_data *sd)
-{
-    struct storage *stor;
-
-    nullpo_retr (0, sd);
-
-    stor = account2storage2 (sd->status.account_id);
-    if (stor)
-    {
-        chrif_save (sd);        //Invokes the storage saving as well.
-        stor->storage_status = 0;
-        sd->state.storage_flag = 0;
-    }
-
-    return 0;
-}
-
-void storage_storage_dirty (struct map_session_data *sd)
-{
-    struct storage *stor;
-
-    stor = account2storage2 (sd->status.account_id);
-
-    if (stor)
-        stor->dirty = 1;
-}
-
-int storage_storage_save (int account_id, int final)
-{
-    struct storage *stor;
-
-    stor = account2storage2 (account_id);
-    if (!stor)
-        return 0;
-
-    if (stor->dirty)
-    {
-        if (final)
-        {
-            stor->dirty = 2;
-            stor->storage_status = 0;   //To prevent further manipulation of it.
-        }
-        intif_send_storage (stor);
-        return 1;
-    }
-    if (final)
-    {                           //Clear storage from memory. Nothing to save.
-        storage_delete (account_id);
-        return 1;
-    }
-
-    return 0;
-}
-
-//Ack from Char-server indicating the storage was saved. [Skotlex]
-int storage_storage_saved (int account_id)
-{
-    struct storage *stor;
-
-    if ((stor = account2storage2 (account_id)) != NULL)
-    {                           //Only mark it clean if it's not in use. [Skotlex]
-        if (stor->dirty && stor->storage_status == 0)
-        {
-            stor->dirty = 0;
-            sortage_sortitem (stor);
-        }
-        return 1;
-    }
-    return 0;
-}
-
-struct guild_storage *guild2storage (int guild_id)
-{
-    struct guild_storage *gs = NULL;
-    if (guild_search (guild_id) != NULL)
-    {
-        gs = (struct guild_storage *) numdb_search (guild_storage_db,
-                                                    guild_id);
-        if (gs == NULL)
-        {
-            CREATE (gs, struct guild_storage, 1);
-            gs->guild_id = guild_id;
-            numdb_insert (guild_storage_db, gs->guild_id, gs);
-        }
-    }
-    return gs;
-}
-
-struct guild_storage *guild2storage2 (int guild_id)
-{                               //For just locating a storage without creating one. [Skotlex]
-    return (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
-}
-
-int guild_storage_delete (int guild_id)
-{
-    struct guild_storage *gstor =
-        (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
-    if (gstor)
-    {
-        numdb_erase (guild_storage_db, guild_id);
-        free (gstor);
-    }
-    return 0;
-}
-
-int storage_guild_storageopen (struct map_session_data *sd)
-{
-    struct guild_storage *gstor;
-
-    nullpo_retr (0, sd);
-
-    if (sd->status.guild_id <= 0)
-        return 2;
-
-    if (sd->state.storage_flag)
-        return 1;               //Can't open both storages at a time.
-
-    if ((gstor = guild2storage2 (sd->status.guild_id)) == NULL)
-    {
-        intif_request_guild_storage (sd->status.account_id,
-                                     sd->status.guild_id);
-        return 0;
-    }
-    if (gstor->storage_status)
-        return 1;
-
-    gstor->storage_status = 1;
-    sd->state.storage_flag = 2;
-    clif_guildstorageitemlist (sd, gstor);
-    clif_guildstorageequiplist (sd, gstor);
-    clif_updateguildstorageamount (sd, gstor);
-    return 0;
-}
-
-int guild_storage_additem (struct map_session_data *sd,
-                           struct guild_storage *stor, struct item *item_data,
-                           int amount)
-{
-    struct item_data *data;
-    int  i;
-
-    nullpo_retr (1, sd);
-    nullpo_retr (1, stor);
-    nullpo_retr (1, item_data);
-    nullpo_retr (1, data = itemdb_search (item_data->nameid));
-
-    if (item_data->nameid <= 0 || amount <= 0)
-        return 1;
-
-    if (!itemdb_isequip2 (data))
-    {                           //Stackable
-        for (i = 0; i < MAX_GUILD_STORAGE; i++)
-        {
-            if (compare_item (&stor->storage_[i], item_data))
-            {
-                if (stor->storage_[i].amount + amount > MAX_AMOUNT)
-                    return 1;
-                stor->storage_[i].amount += amount;
-                clif_guildstorageitemadded (sd, stor, i, amount);
-                stor->dirty = 1;
-                return 0;
-            }
-        }
-    }
-    //Add item
-    for (i = 0; i < MAX_GUILD_STORAGE && stor->storage_[i].nameid; i++);
-
-    if (i >= MAX_GUILD_STORAGE)
-        return 1;
-
-    memcpy (&stor->storage_[i], item_data, sizeof (stor->storage_[0]));
-    stor->storage_[i].amount = amount;
-    stor->storage_amount++;
-    clif_guildstorageitemadded (sd, stor, i, amount);
-    clif_updateguildstorageamount (sd, stor);
-    stor->dirty = 1;
-    return 0;
-}
-
-int guild_storage_delitem (struct map_session_data *sd,
-                           struct guild_storage *stor, int n, int amount)
-{
-    nullpo_retr (1, sd);
-    nullpo_retr (1, stor);
-
-    if (stor->storage_[n].nameid == 0 || stor->storage_[n].amount < amount)
-        return 1;
-
-    stor->storage_[n].amount -= amount;
-    if (stor->storage_[n].amount == 0)
-    {
-        memset (&stor->storage_[n], 0, sizeof (stor->storage_[0]));
-        stor->storage_amount--;
-        clif_updateguildstorageamount (sd, stor);
-    }
-    clif_storageitemremoved (sd, n, amount);
-    stor->dirty = 1;
-    return 0;
-}
-
-int storage_guild_storageadd (struct map_session_data *sd, int index,
-                              int amount)
-{
-    struct guild_storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE)
-        return 0;
-
-    if (index < 0 || index >= MAX_INVENTORY)
-        return 0;
-
-    if (sd->status.inventory[index].nameid <= 0)
-        return 0;
-
-    if (amount < 1 || amount > sd->status.inventory[index].amount)
-        return 0;
-
-//  log_tostorage(sd, index, 1);
-    if (guild_storage_additem (sd, stor, &sd->status.inventory[index], amount)
-        == 0)
-        pc_delitem (sd, index, amount, 0);
-
-    return 1;
-}
-
-int storage_guild_storageget (struct map_session_data *sd, int index,
-                              int amount)
-{
-    struct guild_storage *stor;
-    int  flag;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    if (!stor->storage_status)
-        return 0;
-
-    if (index < 0 || index >= MAX_GUILD_STORAGE)
-        return 0;
-
-    if (stor->storage_[index].nameid <= 0)
-        return 0;
-
-    if (amount < 1 || amount > stor->storage_[index].amount)
-        return 0;
-
-    if ((flag = pc_additem (sd, &stor->storage_[index], amount)) == 0)
-        guild_storage_delitem (sd, stor, index, amount);
-    else
-        clif_additem (sd, 0, 0, flag);
-//  log_fromstorage(sd, index, 1);
-
-    return 0;
-}
-
-int storage_guild_storageaddfromcart (struct map_session_data *sd, int index,
-                                      int amount)
-{
-    struct guild_storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE)
-        return 0;
-
-    if (index < 0 || index >= MAX_CART)
-        return 0;
-
-    if (sd->status.cart[index].nameid <= 0)
-        return 0;
-
-    if (amount < 1 || amount > sd->status.cart[index].amount)
-        return 0;
-
-    if (guild_storage_additem (sd, stor, &sd->status.cart[index], amount) ==
-        0)
-        pc_cart_delitem (sd, index, amount, 0);
-
-    return 1;
-}
-
-int storage_guild_storagegettocart (struct map_session_data *sd, int index,
-                                    int amount)
-{
-    struct guild_storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    if (!stor->storage_status)
-        return 0;
-
-    if (index < 0 || index >= MAX_GUILD_STORAGE)
-        return 0;
-
-    if (stor->storage_[index].nameid <= 0)
-        return 0;
-
-    if (amount < 1 || amount > stor->storage_[index].amount)
-        return 0;
-
-    if (pc_cart_additem (sd, &stor->storage_[index], amount) == 0)
-        guild_storage_delitem (sd, stor, index, amount);
-
-    return 1;
-}
-
-int storage_guild_storagesave (int account_id, int guild_id, int flag)
-{
-    struct guild_storage *stor = guild2storage2 (guild_id);
-
-    if (stor)
-    {
-        if (flag)               //Char quitting, close it.
-            stor->storage_status = 0;
-        if (stor->dirty)
-            intif_send_guild_storage (account_id, stor);
-        return 1;
-    }
-    return 0;
-}
-
-int storage_guild_storagesaved (int guild_id)
-{
-    struct guild_storage *stor;
-
-    if ((stor = guild2storage2 (guild_id)) != NULL)
-    {
-        if (stor->dirty && stor->storage_status == 0)
-        {                       //Storage has been correctly saved.
-            stor->dirty = 0;
-            sortage_gsortitem (stor);
-        }
-        return 1;
-    }
-    return 0;
-}
-
-int storage_guild_storageclose (struct map_session_data *sd)
-{
-    struct guild_storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    clif_storageclose (sd);
-    chrif_save (sd);            //This one also saves the storage. [Skotlex]
-
-    stor->storage_status = 0;
-    sd->state.storage_flag = 0;
-
-    return 0;
-}
-
-int storage_guild_storage_quit (struct map_session_data *sd, int flag)
-{
-    struct guild_storage *stor;
-
-    nullpo_retr (0, sd);
-    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
-
-    if (flag)
-    {                           //Only during a guild break flag is 1 (don't save storage)
-        sd->state.storage_flag = 0;
-        stor->storage_status = 0;
-        clif_storageclose (sd);
-        if (save_settings & 4)
-            chrif_save (sd);
-        return 0;
-    }
-
-    if (stor->storage_status)
-    {
-        if (save_settings & 4)
-            chrif_save (sd);
-        else
-            storage_guild_storagesave (sd->status.account_id,
-                                       sd->status.guild_id, 1);
-    }
-    sd->state.storage_flag = 0;
-    stor->storage_status = 0;
-
-    return 0;
-}
diff --git a/src/map/storage.cpp b/src/map/storage.cpp
new file mode 100644
index 0000000..d1d3cb0
--- /dev/null
+++ b/src/map/storage.cpp
@@ -0,0 +1,787 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../common/db.hpp"
+#include "../common/nullpo.hpp"
+
+#include "storage.hpp"
+#include "chrif.hpp"
+#include "itemdb.hpp"
+#include "clif.hpp"
+#include "intif.hpp"
+#include "pc.hpp"
+#include "guild.hpp"
+#include "battle.hpp"
+#include "atcommand.hpp"
+
+static struct dbt *storage_db;
+static struct dbt *guild_storage_db;
+
+/*==========================================
+ * 倉庫内アイテムソート
+ *------------------------------------------
+ */
+int storage_comp_item (const void *_i1, const void *_i2)
+{
+    struct item *i1 = (struct item *) _i1;
+    struct item *i2 = (struct item *) _i2;
+
+    if (i1->nameid == i2->nameid)
+        return 0;
+    else if (!(i1->nameid) || !(i1->amount))
+        return 1;
+    else if (!(i2->nameid) || !(i2->amount))
+        return -1;
+    return i1->nameid - i2->nameid;
+}
+
+static void guild_storage_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    struct guild_storage *gstor = (struct guild_storage *) data;
+    free (gstor);
+}
+
+static void storage_db_final (db_key_t key, db_val_t data, va_list ap)
+{
+    struct storage *stor = (struct storage *) data;
+    free (stor);
+}
+
+void sortage_sortitem (struct storage *stor)
+{
+    nullpo_retv (stor);
+    qsort (stor->storage_, MAX_STORAGE, sizeof (struct item),
+           storage_comp_item);
+}
+
+void sortage_gsortitem (struct guild_storage *gstor)
+{
+    nullpo_retv (gstor);
+    qsort (gstor->storage_, MAX_GUILD_STORAGE, sizeof (struct item),
+           storage_comp_item);
+}
+
+/*==========================================
+ * 初期化とか
+ *------------------------------------------
+ */
+int do_init_storage (void)      // map.c::do_init()から呼ばれる
+{
+    storage_db = numdb_init ();
+    guild_storage_db = numdb_init ();
+    return 1;
+}
+
+void do_final_storage (void)    // by [MC Cameri]
+{
+    if (storage_db)
+        numdb_final (storage_db, storage_db_final);
+    if (guild_storage_db)
+        numdb_final (guild_storage_db, guild_storage_db_final);
+}
+
+static void storage_reconnect_sub (db_key_t key, db_val_t data, va_list ap)
+{                               //Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
+    int  type = va_arg (ap, int);
+    if (type)
+    {                           //Guild Storage
+        struct guild_storage *stor = (struct guild_storage *) data;
+        if (stor->dirty && stor->storage_status == 0)   //Save closed storages.
+            storage_guild_storagesave (0, stor->guild_id, 0);
+    }
+    else
+    {                           //Account Storage
+        struct storage *stor = (struct storage *) data;
+        if (stor->dirty && stor->storage_status == 0)   //Save closed storages.
+            storage_storage_save (stor->account_id, stor->dirty == 2 ? 1 : 0);
+    }
+}
+
+//Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex
+void do_reconnect_storage (void)
+{
+    numdb_foreach (storage_db, storage_reconnect_sub, 0);
+    numdb_foreach (guild_storage_db, storage_reconnect_sub, 1);
+}
+
+struct storage *account2storage (int account_id)
+{
+    struct storage *stor =
+        (struct storage *) numdb_search (storage_db, account_id);
+    if (stor == NULL)
+    {
+        CREATE (stor, struct storage, 1);
+        stor->account_id = account_id;
+        numdb_insert (storage_db, stor->account_id, stor);
+    }
+    return stor;
+}
+
+// Just to ask storage, without creation
+struct storage *account2storage2 (int account_id)
+{
+    return (struct storage *) numdb_search (storage_db, account_id);
+}
+
+int storage_delete (int account_id)
+{
+    struct storage *stor =
+        (struct storage *) numdb_search (storage_db, account_id);
+    if (stor)
+    {
+        numdb_erase (storage_db, account_id);
+        free (stor);
+    }
+    return 0;
+}
+
+/*==========================================
+ * カプラ倉庫を開く
+ *------------------------------------------
+ */
+int storage_storageopen (struct map_session_data *sd)
+{
+    struct storage *stor;
+    nullpo_retr (0, sd);
+
+    if (sd->state.storage_flag)
+        return 1;               //Already open?
+
+    if ((stor =
+         (struct storage *) numdb_search (storage_db,
+                                          sd->status.account_id)) == NULL)
+    {                           //Request storage.
+        intif_request_storage (sd->status.account_id);
+        return 1;
+    }
+
+    if (stor->storage_status)
+        return 1;               //Already open/player already has it open...
+
+    stor->storage_status = 1;
+    sd->state.storage_flag = 1;
+    clif_storageitemlist (sd, stor);
+    clif_storageequiplist (sd, stor);
+    clif_updatestorageamount (sd, stor);
+    return 0;
+}
+
+/*==========================================
+ * Internal add-item function.
+ *------------------------------------------
+ */
+static int storage_additem (struct map_session_data *sd, struct storage *stor,
+                            struct item *item_data, int amount)
+{
+    struct item_data *data;
+    int  i;
+
+    if (item_data->nameid <= 0 || amount <= 0)
+        return 1;
+
+    data = itemdb_search (item_data->nameid);
+
+    if (!itemdb_isequip2 (data))
+    {                           //Stackable
+        for (i = 0; i < MAX_STORAGE; i++)
+        {
+            if (compare_item (&stor->storage_[i], item_data))
+            {
+                if (amount > MAX_AMOUNT - stor->storage_[i].amount)
+                    return 1;
+                stor->storage_[i].amount += amount;
+                clif_storageitemadded (sd, stor, i, amount);
+                stor->dirty = 1;
+                return 0;
+            }
+        }
+    }
+    //Add item
+    for (i = 0; i < MAX_STORAGE && stor->storage_[i].nameid; i++);
+
+    if (i >= MAX_STORAGE)
+        return 1;
+
+    memcpy (&stor->storage_[i], item_data, sizeof (stor->storage_[0]));
+    stor->storage_[i].amount = amount;
+    stor->storage_amount++;
+    clif_storageitemadded (sd, stor, i, amount);
+    clif_updatestorageamount (sd, stor);
+    stor->dirty = 1;
+    return 0;
+}
+
+/*==========================================
+ * Internal del-item function
+ *------------------------------------------
+ */
+static int storage_delitem (struct map_session_data *sd, struct storage *stor,
+                            int n, int amount)
+{
+
+    if (stor->storage_[n].nameid == 0 || stor->storage_[n].amount < amount)
+        return 1;
+
+    stor->storage_[n].amount -= amount;
+    if (stor->storage_[n].amount == 0)
+    {
+        memset (&stor->storage_[n], 0, sizeof (stor->storage_[0]));
+        stor->storage_amount--;
+        clif_updatestorageamount (sd, stor);
+    }
+    clif_storageitemremoved (sd, n, amount);
+
+    stor->dirty = 1;
+    return 0;
+}
+
+/*==========================================
+ * Add an item to the storage from the inventory.
+ *------------------------------------------
+ */
+int storage_storageadd (struct map_session_data *sd, int index, int amount)
+{
+    struct storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
+
+    if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status)
+        return 0;               // storage full / storage closed
+
+    if (index < 0 || index >= MAX_INVENTORY)
+        return 0;
+
+    if (sd->status.inventory[index].nameid <= 0)
+        return 0;               //No item on that spot
+
+    if (amount < 1 || amount > sd->status.inventory[index].amount)
+        return 0;
+
+//  log_tostorage(sd, index, 0);
+    if (storage_additem (sd, stor, &sd->status.inventory[index], amount) == 0)
+    {
+        // remove item from inventory
+        pc_unequipinvyitem (sd, index, 0);
+        pc_delitem (sd, index, amount, 0);
+    }
+
+    return 1;
+}
+
+/*==========================================
+ * Retrieve an item from the storage.
+ *------------------------------------------
+ */
+int storage_storageget (struct map_session_data *sd, int index, int amount)
+{
+    struct storage *stor;
+    int  flag;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
+
+    if (index < 0 || index >= MAX_STORAGE)
+        return 0;
+
+    if (stor->storage_[index].nameid <= 0)
+        return 0;               //Nothing there
+
+    if (amount < 1 || amount > stor->storage_[index].amount)
+        return 0;
+
+    if ((flag = pc_additem (sd, &stor->storage_[index], amount)) == 0)
+        storage_delitem (sd, stor, index, amount);
+    else
+        clif_additem (sd, 0, 0, flag);
+//  log_fromstorage(sd, index, 0);
+    return 1;
+}
+
+/*==========================================
+ * Move an item from cart to storage.
+ *------------------------------------------
+ */
+int storage_storageaddfromcart (struct map_session_data *sd, int index,
+                                int amount)
+{
+    struct storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
+
+    if (stor->storage_amount > MAX_STORAGE || !stor->storage_status)
+        return 0;               // storage full / storage closed
+
+    if (index < 0 || index >= MAX_CART)
+        return 0;
+
+    if (sd->status.cart[index].nameid <= 0)
+        return 0;               //No item there.
+
+    if (amount < 1 || amount > sd->status.cart[index].amount)
+        return 0;
+
+    if (storage_additem (sd, stor, &sd->status.cart[index], amount) == 0)
+        pc_cart_delitem (sd, index, amount, 0);
+
+    return 1;
+}
+
+/*==========================================
+ * Get from Storage to the Cart
+ *------------------------------------------
+ */
+int storage_storagegettocart (struct map_session_data *sd, int index,
+                              int amount)
+{
+    struct storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
+
+    if (!stor->storage_status)
+        return 0;
+
+    if (index < 0 || index >= MAX_STORAGE)
+        return 0;
+
+    if (stor->storage_[index].nameid <= 0)
+        return 0;               //Nothing there.
+
+    if (amount < 1 || amount > stor->storage_[index].amount)
+        return 0;
+
+    if (pc_cart_additem (sd, &stor->storage_[index], amount) == 0)
+        storage_delitem (sd, stor, index, amount);
+
+    return 1;
+}
+
+/*==========================================
+ * Modified By Valaris to save upon closing [massdriller]
+ *------------------------------------------
+ */
+int storage_storageclose (struct map_session_data *sd)
+{
+    struct storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = account2storage2 (sd->status.account_id));
+
+    clif_storageclose (sd);
+    if (stor->storage_status)
+    {
+        if (save_settings & 4)
+            chrif_save (sd);    //Invokes the storage saving as well.
+        else
+            storage_storage_save (sd->status.account_id, 0);
+    }
+    stor->storage_status = 0;
+    sd->state.storage_flag = 0;
+
+    if (sd->npc_flags.storage)
+    {
+        sd->npc_flags.storage = 0;
+        map_scriptcont (sd, sd->npc_id);
+    }
+
+    return 0;
+}
+
+/*==========================================
+ * When quitting the game.
+ *------------------------------------------
+ */
+int storage_storage_quit (struct map_session_data *sd)
+{
+    struct storage *stor;
+
+    nullpo_retr (0, sd);
+
+    stor = account2storage2 (sd->status.account_id);
+    if (stor)
+    {
+        chrif_save (sd);        //Invokes the storage saving as well.
+        stor->storage_status = 0;
+        sd->state.storage_flag = 0;
+    }
+
+    return 0;
+}
+
+void storage_storage_dirty (struct map_session_data *sd)
+{
+    struct storage *stor;
+
+    stor = account2storage2 (sd->status.account_id);
+
+    if (stor)
+        stor->dirty = 1;
+}
+
+int storage_storage_save (int account_id, int final)
+{
+    struct storage *stor;
+
+    stor = account2storage2 (account_id);
+    if (!stor)
+        return 0;
+
+    if (stor->dirty)
+    {
+        if (final)
+        {
+            stor->dirty = 2;
+            stor->storage_status = 0;   //To prevent further manipulation of it.
+        }
+        intif_send_storage (stor);
+        return 1;
+    }
+    if (final)
+    {                           //Clear storage from memory. Nothing to save.
+        storage_delete (account_id);
+        return 1;
+    }
+
+    return 0;
+}
+
+//Ack from Char-server indicating the storage was saved. [Skotlex]
+int storage_storage_saved (int account_id)
+{
+    struct storage *stor;
+
+    if ((stor = account2storage2 (account_id)) != NULL)
+    {                           //Only mark it clean if it's not in use. [Skotlex]
+        if (stor->dirty && stor->storage_status == 0)
+        {
+            stor->dirty = 0;
+            sortage_sortitem (stor);
+        }
+        return 1;
+    }
+    return 0;
+}
+
+struct guild_storage *guild2storage (int guild_id)
+{
+    struct guild_storage *gs = NULL;
+    if (guild_search (guild_id) != NULL)
+    {
+        gs = (struct guild_storage *) numdb_search (guild_storage_db,
+                                                    guild_id);
+        if (gs == NULL)
+        {
+            CREATE (gs, struct guild_storage, 1);
+            gs->guild_id = guild_id;
+            numdb_insert (guild_storage_db, gs->guild_id, gs);
+        }
+    }
+    return gs;
+}
+
+struct guild_storage *guild2storage2 (int guild_id)
+{                               //For just locating a storage without creating one. [Skotlex]
+    return (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
+}
+
+int guild_storage_delete (int guild_id)
+{
+    struct guild_storage *gstor =
+        (struct guild_storage *) numdb_search (guild_storage_db, guild_id);
+    if (gstor)
+    {
+        numdb_erase (guild_storage_db, guild_id);
+        free (gstor);
+    }
+    return 0;
+}
+
+int storage_guild_storageopen (struct map_session_data *sd)
+{
+    struct guild_storage *gstor;
+
+    nullpo_retr (0, sd);
+
+    if (sd->status.guild_id <= 0)
+        return 2;
+
+    if (sd->state.storage_flag)
+        return 1;               //Can't open both storages at a time.
+
+    if ((gstor = guild2storage2 (sd->status.guild_id)) == NULL)
+    {
+        intif_request_guild_storage (sd->status.account_id,
+                                     sd->status.guild_id);
+        return 0;
+    }
+    if (gstor->storage_status)
+        return 1;
+
+    gstor->storage_status = 1;
+    sd->state.storage_flag = 2;
+    clif_guildstorageitemlist (sd, gstor);
+    clif_guildstorageequiplist (sd, gstor);
+    clif_updateguildstorageamount (sd, gstor);
+    return 0;
+}
+
+int guild_storage_additem (struct map_session_data *sd,
+                           struct guild_storage *stor, struct item *item_data,
+                           int amount)
+{
+    struct item_data *data;
+    int  i;
+
+    nullpo_retr (1, sd);
+    nullpo_retr (1, stor);
+    nullpo_retr (1, item_data);
+    nullpo_retr (1, data = itemdb_search (item_data->nameid));
+
+    if (item_data->nameid <= 0 || amount <= 0)
+        return 1;
+
+    if (!itemdb_isequip2 (data))
+    {                           //Stackable
+        for (i = 0; i < MAX_GUILD_STORAGE; i++)
+        {
+            if (compare_item (&stor->storage_[i], item_data))
+            {
+                if (stor->storage_[i].amount + amount > MAX_AMOUNT)
+                    return 1;
+                stor->storage_[i].amount += amount;
+                clif_guildstorageitemadded (sd, stor, i, amount);
+                stor->dirty = 1;
+                return 0;
+            }
+        }
+    }
+    //Add item
+    for (i = 0; i < MAX_GUILD_STORAGE && stor->storage_[i].nameid; i++);
+
+    if (i >= MAX_GUILD_STORAGE)
+        return 1;
+
+    memcpy (&stor->storage_[i], item_data, sizeof (stor->storage_[0]));
+    stor->storage_[i].amount = amount;
+    stor->storage_amount++;
+    clif_guildstorageitemadded (sd, stor, i, amount);
+    clif_updateguildstorageamount (sd, stor);
+    stor->dirty = 1;
+    return 0;
+}
+
+int guild_storage_delitem (struct map_session_data *sd,
+                           struct guild_storage *stor, int n, int amount)
+{
+    nullpo_retr (1, sd);
+    nullpo_retr (1, stor);
+
+    if (stor->storage_[n].nameid == 0 || stor->storage_[n].amount < amount)
+        return 1;
+
+    stor->storage_[n].amount -= amount;
+    if (stor->storage_[n].amount == 0)
+    {
+        memset (&stor->storage_[n], 0, sizeof (stor->storage_[0]));
+        stor->storage_amount--;
+        clif_updateguildstorageamount (sd, stor);
+    }
+    clif_storageitemremoved (sd, n, amount);
+    stor->dirty = 1;
+    return 0;
+}
+
+int storage_guild_storageadd (struct map_session_data *sd, int index,
+                              int amount)
+{
+    struct guild_storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE)
+        return 0;
+
+    if (index < 0 || index >= MAX_INVENTORY)
+        return 0;
+
+    if (sd->status.inventory[index].nameid <= 0)
+        return 0;
+
+    if (amount < 1 || amount > sd->status.inventory[index].amount)
+        return 0;
+
+//  log_tostorage(sd, index, 1);
+    if (guild_storage_additem (sd, stor, &sd->status.inventory[index], amount)
+        == 0)
+        pc_delitem (sd, index, amount, 0);
+
+    return 1;
+}
+
+int storage_guild_storageget (struct map_session_data *sd, int index,
+                              int amount)
+{
+    struct guild_storage *stor;
+    int  flag;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    if (!stor->storage_status)
+        return 0;
+
+    if (index < 0 || index >= MAX_GUILD_STORAGE)
+        return 0;
+
+    if (stor->storage_[index].nameid <= 0)
+        return 0;
+
+    if (amount < 1 || amount > stor->storage_[index].amount)
+        return 0;
+
+    if ((flag = pc_additem (sd, &stor->storage_[index], amount)) == 0)
+        guild_storage_delitem (sd, stor, index, amount);
+    else
+        clif_additem (sd, 0, 0, flag);
+//  log_fromstorage(sd, index, 1);
+
+    return 0;
+}
+
+int storage_guild_storageaddfromcart (struct map_session_data *sd, int index,
+                                      int amount)
+{
+    struct guild_storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE)
+        return 0;
+
+    if (index < 0 || index >= MAX_CART)
+        return 0;
+
+    if (sd->status.cart[index].nameid <= 0)
+        return 0;
+
+    if (amount < 1 || amount > sd->status.cart[index].amount)
+        return 0;
+
+    if (guild_storage_additem (sd, stor, &sd->status.cart[index], amount) ==
+        0)
+        pc_cart_delitem (sd, index, amount, 0);
+
+    return 1;
+}
+
+int storage_guild_storagegettocart (struct map_session_data *sd, int index,
+                                    int amount)
+{
+    struct guild_storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    if (!stor->storage_status)
+        return 0;
+
+    if (index < 0 || index >= MAX_GUILD_STORAGE)
+        return 0;
+
+    if (stor->storage_[index].nameid <= 0)
+        return 0;
+
+    if (amount < 1 || amount > stor->storage_[index].amount)
+        return 0;
+
+    if (pc_cart_additem (sd, &stor->storage_[index], amount) == 0)
+        guild_storage_delitem (sd, stor, index, amount);
+
+    return 1;
+}
+
+int storage_guild_storagesave (int account_id, int guild_id, int flag)
+{
+    struct guild_storage *stor = guild2storage2 (guild_id);
+
+    if (stor)
+    {
+        if (flag)               //Char quitting, close it.
+            stor->storage_status = 0;
+        if (stor->dirty)
+            intif_send_guild_storage (account_id, stor);
+        return 1;
+    }
+    return 0;
+}
+
+int storage_guild_storagesaved (int guild_id)
+{
+    struct guild_storage *stor;
+
+    if ((stor = guild2storage2 (guild_id)) != NULL)
+    {
+        if (stor->dirty && stor->storage_status == 0)
+        {                       //Storage has been correctly saved.
+            stor->dirty = 0;
+            sortage_gsortitem (stor);
+        }
+        return 1;
+    }
+    return 0;
+}
+
+int storage_guild_storageclose (struct map_session_data *sd)
+{
+    struct guild_storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    clif_storageclose (sd);
+    chrif_save (sd);            //This one also saves the storage. [Skotlex]
+
+    stor->storage_status = 0;
+    sd->state.storage_flag = 0;
+
+    return 0;
+}
+
+int storage_guild_storage_quit (struct map_session_data *sd, int flag)
+{
+    struct guild_storage *stor;
+
+    nullpo_retr (0, sd);
+    nullpo_retr (0, stor = guild2storage2 (sd->status.guild_id));
+
+    if (flag)
+    {                           //Only during a guild break flag is 1 (don't save storage)
+        sd->state.storage_flag = 0;
+        stor->storage_status = 0;
+        clif_storageclose (sd);
+        if (save_settings & 4)
+            chrif_save (sd);
+        return 0;
+    }
+
+    if (stor->storage_status)
+    {
+        if (save_settings & 4)
+            chrif_save (sd);
+        else
+            storage_guild_storagesave (sd->status.account_id,
+                                       sd->status.guild_id, 1);
+    }
+    sd->state.storage_flag = 0;
+    stor->storage_status = 0;
+
+    return 0;
+}
diff --git a/src/map/storage.h b/src/map/storage.h
deleted file mode 100644
index daaec2c..0000000
--- a/src/map/storage.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#ifndef _STORAGE_H_
-#define _STORAGE_H_
-
-#include "../common/mmo.h"
-
-int  storage_storageopen (struct map_session_data *sd);
-int  storage_storageadd (struct map_session_data *sd, int index, int amount);
-int  storage_storageget (struct map_session_data *sd, int index, int amount);
-int  storage_storageaddfromcart (struct map_session_data *sd, int index,
-                                 int amount);
-int  storage_storagegettocart (struct map_session_data *sd, int index,
-                               int amount);
-int  storage_storageclose (struct map_session_data *sd);
-int  do_init_storage (void);
-void do_final_storage (void);
-void do_reconnect_storage (void);
-struct storage *account2storage (int account_id);
-struct storage *account2storage2 (int account_id);
-int  storage_delete (int account_id);
-int  storage_storage_quit (struct map_session_data *sd);
-int  storage_storage_save (int account_id, int final);
-int  storage_storage_saved (int account_id);    //Ack from char server that guild store was saved.
-void storage_storage_dirty (struct map_session_data *sd);
-
-struct guild_storage *guild2storage (int guild_id);
-int  guild_storage_delete (int guild_id);
-int  storage_guild_storageopen (struct map_session_data *sd);
-int  guild_storage_additem (struct map_session_data *sd,
-                            struct guild_storage *stor,
-                            struct item *item_data, int amount);
-int  guild_storage_delitem (struct map_session_data *sd,
-                            struct guild_storage *stor, int n, int amount);
-int  storage_guild_storageadd (struct map_session_data *sd, int index,
-                               int amount);
-int  storage_guild_storageget (struct map_session_data *sd, int index,
-                               int amount);
-int  storage_guild_storageaddfromcart (struct map_session_data *sd, int index,
-                                       int amount);
-int  storage_guild_storagegettocart (struct map_session_data *sd, int index,
-                                     int amount);
-int  storage_guild_storageclose (struct map_session_data *sd);
-int  storage_guild_storage_quit (struct map_session_data *sd, int flag);
-int  storage_guild_storagesave (int account_id, int guild_id, int flag);
-int  storage_guild_storagesaved (int guild_id); //Ack from char server that guild store was saved.
-
-int  storage_comp_item (const void *_i1, const void *_i2);
-//int storage_comp_item(const struct item* i1, const struct item* i2);
-void sortage_sortitem (struct storage *stor);
-void sortage_gsortitem (struct guild_storage *gstor);
-
-#endif
diff --git a/src/map/storage.hpp b/src/map/storage.hpp
new file mode 100644
index 0000000..22625df
--- /dev/null
+++ b/src/map/storage.hpp
@@ -0,0 +1,54 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef STORAGE_HPP
+#define STORAGE_HPP
+
+#include "../common/mmo.hpp"
+
+int  storage_storageopen (struct map_session_data *sd);
+int  storage_storageadd (struct map_session_data *sd, int index, int amount);
+int  storage_storageget (struct map_session_data *sd, int index, int amount);
+int  storage_storageaddfromcart (struct map_session_data *sd, int index,
+                                 int amount);
+int  storage_storagegettocart (struct map_session_data *sd, int index,
+                               int amount);
+int  storage_storageclose (struct map_session_data *sd);
+int  do_init_storage (void);
+void do_final_storage (void);
+void do_reconnect_storage (void);
+struct storage *account2storage (int account_id);
+struct storage *account2storage2 (int account_id);
+int  storage_delete (int account_id);
+int  storage_storage_quit (struct map_session_data *sd);
+int  storage_storage_save (int account_id, int final);
+int  storage_storage_saved (int account_id);    //Ack from char server that guild store was saved.
+void storage_storage_dirty (struct map_session_data *sd);
+
+struct guild_storage *guild2storage (int guild_id);
+int  guild_storage_delete (int guild_id);
+int  storage_guild_storageopen (struct map_session_data *sd);
+int  guild_storage_additem (struct map_session_data *sd,
+                            struct guild_storage *stor,
+                            struct item *item_data, int amount);
+int  guild_storage_delitem (struct map_session_data *sd,
+                            struct guild_storage *stor, int n, int amount);
+int  storage_guild_storageadd (struct map_session_data *sd, int index,
+                               int amount);
+int  storage_guild_storageget (struct map_session_data *sd, int index,
+                               int amount);
+int  storage_guild_storageaddfromcart (struct map_session_data *sd, int index,
+                                       int amount);
+int  storage_guild_storagegettocart (struct map_session_data *sd, int index,
+                                     int amount);
+int  storage_guild_storageclose (struct map_session_data *sd);
+int  storage_guild_storage_quit (struct map_session_data *sd, int flag);
+int  storage_guild_storagesave (int account_id, int guild_id, int flag);
+int  storage_guild_storagesaved (int guild_id); //Ack from char server that guild store was saved.
+
+int  storage_comp_item (const void *_i1, const void *_i2);
+//int storage_comp_item(const struct item* i1, const struct item* i2);
+void sortage_sortitem (struct storage *stor);
+void sortage_gsortitem (struct guild_storage *gstor);
+
+#endif
diff --git a/src/map/tmw.c b/src/map/tmw.c
deleted file mode 100644
index 3487c1d..0000000
--- a/src/map/tmw.c
+++ /dev/null
@@ -1,187 +0,0 @@
-//
-
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-#include "tmw.h"
-
-#include "../common/socket.h"
-#include "../common/timer.h"
-#include "../common/version.h"
-#include "../common/nullpo.h"
-
-#include "atcommand.h"
-#include "battle.h"
-#include "chat.h"
-#include "chrif.h"
-#include "clif.h"
-#include "guild.h"
-#include "intif.h"
-#include "itemdb.h"
-#include "magic.h"
-#include "map.h"
-#include "mob.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
-#include "script.h"
-#include "skill.h"
-#include "storage.h"
-#include "trade.h"
-
-int tmw_CheckChatSpam (struct map_session_data *sd, char *message)
-{
-    nullpo_retr (1, sd);
-    time_t now = time (NULL);
-
-    if (pc_isGM (sd))
-        return 0;
-
-    if (now > sd->chat_reset_due)
-    {
-        sd->chat_reset_due = now + battle_config.chat_spam_threshold;
-        sd->chat_lines_in = 0;
-    }
-
-    if (now > sd->chat_repeat_reset_due)
-    {
-        sd->chat_repeat_reset_due =
-            now + (battle_config.chat_spam_threshold * 60);
-        sd->chat_total_repeats = 0;
-    }
-
-    sd->chat_lines_in++;
-
-    // Penalty for repeats.
-    if (strncmp
-        (sd->chat_lastmsg, message,
-         tmw_ShorterStrlen (sd->chat_lastmsg, message)) == 0)
-    {
-        sd->chat_lines_in += battle_config.chat_lame_penalty;
-        sd->chat_total_repeats++;
-    }
-    else
-    {
-        sd->chat_total_repeats = 0;
-    }
-
-    // Penalty for lame, it can stack on top of the repeat penalty.
-    if (tmw_CheckChatLameness (sd, message))
-        sd->chat_lines_in += battle_config.chat_lame_penalty;
-
-    strncpy ((char *) sd->chat_lastmsg, message, battle_config.chat_maxline);
-
-    if (sd->chat_lines_in >= battle_config.chat_spam_flood
-        || sd->chat_total_repeats >= battle_config.chat_spam_flood)
-    {
-        sd->chat_lines_in = sd->chat_total_repeats = 0;
-
-        tmw_AutoBan (sd, "chat", battle_config.chat_spam_ban);
-
-        return 1;
-    }
-
-    if (battle_config.chat_spam_ban &&
-        (sd->chat_lines_in >= battle_config.chat_spam_warn
-         || sd->chat_total_repeats >= battle_config.chat_spam_warn))
-    {
-        /* "WARNING: You are about to be automatically banned for spam!" */
-        clif_displaymessage (sd->fd, msg_txt (506));
-        /* "WARNING: Please slow down, do not repeat, and do not SHOUT!" */
-        clif_displaymessage (sd->fd, msg_txt (507));
-    }
-
-    return 0;
-}
-
-void tmw_AutoBan(struct map_session_data *sd, char *reason, int length)
-{
-    char anotherbuf[512];
-
-    if (length == 0 || sd->auto_ban_info.in_progress)
-        return;
-
-    sd->auto_ban_info.in_progress = 1;
-
-    tmw_GmHackMsg ("%s has been autobanned for %s spam",
-                   sd->status.name, reason);
-
-    gm_log ("%s(%d,%d) Server : @autoban %s %dh (%s spam)",
-            map[sd->bl.m].name, sd->bl.x, sd->bl.y,
-            sd->status.name, length, reason);
-
-    /* "You have been banned for %s spamming. Please do not spam." */
-    snprintf (anotherbuf, 511, msg_txt (508), reason);
-
-    clif_displaymessage (sd->fd, anotherbuf);
-    /* type: 2 - ban (year, month, day, hour, minute, second) */
-    chrif_char_ask_name (-1, sd->status.name, 2, 0, 0, 0, length, 0, 0);
-    clif_setwaitclose (sd->fd);
-}
-
-// Compares the length of two strings and returns that of the shorter
-int tmw_ShorterStrlen (char *s1, char *s2)
-{
-    int  s1_len = strlen (s1);
-    int  s2_len = strlen (s2);
-    return (s2_len >= s1_len ? s1_len : s2_len);
-}
-
-// Returns true if more than 50% of input message is caps or punctuation
-int tmw_CheckChatLameness (struct map_session_data *sd, char *message)
-{
-    int  count, lame;
-
-    for (count = lame = 0; *message; message++, count++)
-        if (isupper (*message) || ispunct (*message))
-            lame++;
-
-    if (count > 7 && lame > count / 2)
-        return (1);
-
-    return (0);
-}
-
-// Sends a whisper to all GMs
-void tmw_GmHackMsg (const char *fmt, ...)
-{
-    char buf[512];
-    va_list ap;
-
-    va_start (ap, fmt);
-    vsnprintf (buf, 511, fmt, ap);
-    va_end (ap);
-
-    char outbuf[512 + 5];
-    strcpy (outbuf, "[GM] ");
-    strcat (outbuf, buf);
-
-    intif_wis_message_to_gm (wisp_server_name,
-                             battle_config.hack_info_GM_level, outbuf,
-                             strlen (outbuf) + 1);
-}
-
-/* Remove leading and trailing spaces from a string, modifying in place. */
-void tmw_TrimStr (char *str)
-{
-    char *l;
-    char *a;
-    char *e;
-
-    if (!*str)
-        return;
-
-    e = str + strlen (str) - 1;
-
-    /* Skip all leading spaces. */
-    for (l = str; *l && isspace (*l); ++l)
-        ;
-
-    /* Find the end of the string, or the start of trailing spaces. */
-    for (a = e; *a && a > l && isspace (*a); --a)
-        ;
-
-    memmove (str, l, a - l + 1);
-    str[a - l + 1] = '\0';
-}
diff --git a/src/map/tmw.cpp b/src/map/tmw.cpp
new file mode 100644
index 0000000..7506270
--- /dev/null
+++ b/src/map/tmw.cpp
@@ -0,0 +1,187 @@
+//
+
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "tmw.hpp"
+
+#include "../common/socket.hpp"
+#include "../common/timer.hpp"
+#include "../common/version.hpp"
+#include "../common/nullpo.hpp"
+
+#include "atcommand.hpp"
+#include "battle.hpp"
+#include "chat.hpp"
+#include "chrif.hpp"
+#include "clif.hpp"
+#include "guild.hpp"
+#include "intif.hpp"
+#include "itemdb.hpp"
+#include "magic.hpp"
+#include "map.hpp"
+#include "mob.hpp"
+#include "npc.hpp"
+#include "party.hpp"
+#include "pc.hpp"
+#include "script.hpp"
+#include "skill.hpp"
+#include "storage.hpp"
+#include "trade.hpp"
+
+int tmw_CheckChatSpam (struct map_session_data *sd, char *message)
+{
+    nullpo_retr (1, sd);
+    time_t now = time (NULL);
+
+    if (pc_isGM (sd))
+        return 0;
+
+    if (now > sd->chat_reset_due)
+    {
+        sd->chat_reset_due = now + battle_config.chat_spam_threshold;
+        sd->chat_lines_in = 0;
+    }
+
+    if (now > sd->chat_repeat_reset_due)
+    {
+        sd->chat_repeat_reset_due =
+            now + (battle_config.chat_spam_threshold * 60);
+        sd->chat_total_repeats = 0;
+    }
+
+    sd->chat_lines_in++;
+
+    // Penalty for repeats.
+    if (strncmp
+        (sd->chat_lastmsg, message,
+         tmw_ShorterStrlen (sd->chat_lastmsg, message)) == 0)
+    {
+        sd->chat_lines_in += battle_config.chat_lame_penalty;
+        sd->chat_total_repeats++;
+    }
+    else
+    {
+        sd->chat_total_repeats = 0;
+    }
+
+    // Penalty for lame, it can stack on top of the repeat penalty.
+    if (tmw_CheckChatLameness (sd, message))
+        sd->chat_lines_in += battle_config.chat_lame_penalty;
+
+    strncpy ((char *) sd->chat_lastmsg, message, battle_config.chat_maxline);
+
+    if (sd->chat_lines_in >= battle_config.chat_spam_flood
+        || sd->chat_total_repeats >= battle_config.chat_spam_flood)
+    {
+        sd->chat_lines_in = sd->chat_total_repeats = 0;
+
+        tmw_AutoBan (sd, "chat", battle_config.chat_spam_ban);
+
+        return 1;
+    }
+
+    if (battle_config.chat_spam_ban &&
+        (sd->chat_lines_in >= battle_config.chat_spam_warn
+         || sd->chat_total_repeats >= battle_config.chat_spam_warn))
+    {
+        /* "WARNING: You are about to be automatically banned for spam!" */
+        clif_displaymessage (sd->fd, msg_txt (506));
+        /* "WARNING: Please slow down, do not repeat, and do not SHOUT!" */
+        clif_displaymessage (sd->fd, msg_txt (507));
+    }
+
+    return 0;
+}
+
+void tmw_AutoBan(struct map_session_data *sd, char *reason, int length)
+{
+    char anotherbuf[512];
+
+    if (length == 0 || sd->auto_ban_info.in_progress)
+        return;
+
+    sd->auto_ban_info.in_progress = 1;
+
+    tmw_GmHackMsg ("%s has been autobanned for %s spam",
+                   sd->status.name, reason);
+
+    gm_log ("%s(%d,%d) Server : @autoban %s %dh (%s spam)",
+            map[sd->bl.m].name, sd->bl.x, sd->bl.y,
+            sd->status.name, length, reason);
+
+    /* "You have been banned for %s spamming. Please do not spam." */
+    snprintf (anotherbuf, 511, msg_txt (508), reason);
+
+    clif_displaymessage (sd->fd, anotherbuf);
+    /* type: 2 - ban (year, month, day, hour, minute, second) */
+    chrif_char_ask_name (-1, sd->status.name, 2, 0, 0, 0, length, 0, 0);
+    clif_setwaitclose (sd->fd);
+}
+
+// Compares the length of two strings and returns that of the shorter
+int tmw_ShorterStrlen (char *s1, char *s2)
+{
+    int  s1_len = strlen (s1);
+    int  s2_len = strlen (s2);
+    return (s2_len >= s1_len ? s1_len : s2_len);
+}
+
+// Returns true if more than 50% of input message is caps or punctuation
+int tmw_CheckChatLameness (struct map_session_data *sd, char *message)
+{
+    int  count, lame;
+
+    for (count = lame = 0; *message; message++, count++)
+        if (isupper (*message) || ispunct (*message))
+            lame++;
+
+    if (count > 7 && lame > count / 2)
+        return (1);
+
+    return (0);
+}
+
+// Sends a whisper to all GMs
+void tmw_GmHackMsg (const char *fmt, ...)
+{
+    char buf[512];
+    va_list ap;
+
+    va_start (ap, fmt);
+    vsnprintf (buf, 511, fmt, ap);
+    va_end (ap);
+
+    char outbuf[512 + 5];
+    strcpy (outbuf, "[GM] ");
+    strcat (outbuf, buf);
+
+    intif_wis_message_to_gm (wisp_server_name,
+                             battle_config.hack_info_GM_level, outbuf,
+                             strlen (outbuf) + 1);
+}
+
+/* Remove leading and trailing spaces from a string, modifying in place. */
+void tmw_TrimStr (char *str)
+{
+    char *l;
+    char *a;
+    char *e;
+
+    if (!*str)
+        return;
+
+    e = str + strlen (str) - 1;
+
+    /* Skip all leading spaces. */
+    for (l = str; *l && isspace (*l); ++l)
+        ;
+
+    /* Find the end of the string, or the start of trailing spaces. */
+    for (a = e; *a && a > l && isspace (*a); --a)
+        ;
+
+    memmove (str, l, a - l + 1);
+    str[a - l + 1] = '\0';
+}
diff --git a/src/map/tmw.h b/src/map/tmw.h
deleted file mode 100644
index 5141159..0000000
--- a/src/map/tmw.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-#ifndef _TMW_H_
-#define _TMW_H_
-
-#include "map.h"
-
-int  tmw_CheckChatSpam (struct map_session_data *sd, char *message);
-int  tmw_ShorterStrlen (char *s1, char *s2);
-int  tmw_CheckChatLameness (struct map_session_data *sd, char *message);
-void tmw_GmHackMsg (const char *fmt, ...);
-void tmw_AutoBan (struct map_session_data *sd, char *reason, int length);
-void tmw_TrimStr (char *str);
-
-#endif /* _TMW_H_ */
diff --git a/src/map/tmw.hpp b/src/map/tmw.hpp
new file mode 100644
index 0000000..5b20a6c
--- /dev/null
+++ b/src/map/tmw.hpp
@@ -0,0 +1,14 @@
+//
+#ifndef TMW_HPP
+#define TMW_HPP
+
+#include "map.hpp"
+
+int  tmw_CheckChatSpam (struct map_session_data *sd, char *message);
+int  tmw_ShorterStrlen (char *s1, char *s2);
+int  tmw_CheckChatLameness (struct map_session_data *sd, char *message);
+void tmw_GmHackMsg (const char *fmt, ...);
+void tmw_AutoBan (struct map_session_data *sd, char *reason, int length);
+void tmw_TrimStr (char *str);
+
+#endif /* TMW_H_ */
diff --git a/src/map/trade.c b/src/map/trade.c
deleted file mode 100644
index ae70f0d..0000000
--- a/src/map/trade.c
+++ /dev/null
@@ -1,432 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-
-#include "clif.h"
-#include "itemdb.h"
-#include "map.h"
-#include "trade.h"
-#include "pc.h"
-#include "npc.h"
-#include "battle.h"
-#include "storage.h"
-#include "../common/nullpo.h"
-
-/*==========================================
- * 取引要請を相手に送る
- *------------------------------------------
- */
-void trade_traderequest (struct map_session_data *sd, int target_id)
-{
-    struct map_session_data *target_sd;
-
-    nullpo_retv (sd);
-
-    if ((target_sd = map_id2sd (target_id)) != NULL)
-    {
-        if (!battle_config.invite_request_check)
-        {
-            if (target_sd->guild_invite > 0 || target_sd->party_invite > 0)
-            {
-                clif_tradestart (sd, 2);    // 相手はPT要請中かGuild要請中
-                return;
-            }
-        }
-        if (target_sd->npc_id)
-        {
-            //Trade fails if you are using an NPC.
-            clif_tradestart (sd, 2);
-            return;
-        }
-        if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0))
-        {
-            trade_tradecancel (sd); //person is in another trade
-        }
-        else
-        {
-            if (sd->bl.m != target_sd->bl.m
-                || (sd->bl.x - target_sd->bl.x <= -5
-                    || sd->bl.x - target_sd->bl.x >= 5)
-                || (sd->bl.y - target_sd->bl.y <= -5
-                    || sd->bl.y - target_sd->bl.y >= 5))
-            {
-                clif_tradestart (sd, 0);    //too far
-            }
-            else if (sd != target_sd)
-            {
-                target_sd->trade_partner = sd->status.account_id;
-                sd->trade_partner = target_sd->status.account_id;
-                clif_traderequest (target_sd, sd->status.name);
-            }
-        }
-    }
-    else
-    {
-        clif_tradestart (sd, 1);    //character does not exist
-    }
-}
-
-/*==========================================
- * 取引要請
- *------------------------------------------
- */
-void trade_tradeack (struct map_session_data *sd, int type)
-{
-    struct map_session_data *target_sd;
-    nullpo_retv (sd);
-
-    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-    {
-        clif_tradestart (target_sd, type);
-        clif_tradestart (sd, type);
-        if (type == 4)
-        {                       // Cancel
-            sd->deal_locked = 0;
-            sd->trade_partner = 0;
-            target_sd->deal_locked = 0;
-            target_sd->trade_partner = 0;
-        }
-        if (sd->npc_id != 0)
-            npc_event_dequeue (sd);
-        if (target_sd->npc_id != 0)
-            npc_event_dequeue (target_sd);
-
-        //close STORAGE window if it's open. It protects from spooffing packets [Lupus]
-        if (sd->state.storage_flag == 1)
-            storage_storageclose (sd);
-        else if (sd->state.storage_flag == 2)
-            storage_guild_storageclose (sd);
-    }
-}
-
-/*==========================================
- * アイテム追加
- *------------------------------------------
- */
-void trade_tradeadditem (struct map_session_data *sd, int index, int amount)
-{
-    struct map_session_data *target_sd;
-    struct item_data *id;
-    int  trade_i;
-    int  trade_weight = 0;
-    int  free = 0;
-    int  c;
-    int  i;
-
-    nullpo_retv (sd);
-
-    if (((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-        && (sd->deal_locked < 1))
-    {
-        if (index < 2 || index >= MAX_INVENTORY + 2)
-        {
-            if (index == 0 && amount > 0 && amount <= sd->status.zeny)
-            {
-                sd->deal_zeny = amount;
-                clif_tradeadditem (sd, target_sd, 0, amount);
-            }
-        }
-        else if (amount <= sd->status.inventory[index - 2].amount
-                 && amount > 0)
-        {
-            // determine free slots of receiver
-            for (i = 0; i < MAX_INVENTORY; i++)
-            {
-                if (target_sd->status.inventory[i].nameid == 0
-                    && target_sd->inventory_data[i] == NULL)
-                    free++;
-            }
-            for (trade_i = 0; trade_i < 10; trade_i++)
-            {
-                if (sd->deal_item_amount[trade_i] == 0)
-                {
-                    // calculate trade weight
-                    trade_weight +=
-                        sd->inventory_data[index - 2]->weight * amount;
-
-                    // determine if item is a stackable already in receivers inventory, and up free count
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (target_sd->status.inventory[i].nameid ==
-                            sd->status.inventory[index - 2].nameid
-                            && target_sd->inventory_data[i] != NULL)
-                        {
-                            id = target_sd->inventory_data[i];
-                            if (id->type != 4 && id->type != 5
-                                && id->type != 7 && id->type != 8)
-                            {
-                                free++;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (target_sd->weight + trade_weight >
-                        target_sd->max_weight)
-                    {
-                        clif_tradeitemok (sd, index, 0, 1); //fail to add item -- the player was over weighted.
-                        amount = 0; // [MouseJstr]
-                    }
-                    else if (free <= 0)
-                    {
-                        clif_tradeitemok (sd, index, 0, 2); //fail to add item -- no free slots at receiver
-                        amount = 0; // peavey
-                    }
-                    else
-                    {
-                        for (c = 0; c == trade_i - 1; c++)
-                        {       // re-deal exploit protection [Valaris]
-                            if (sd->deal_item_index[c] == index)
-                            {
-                                trade_tradecancel (sd);
-                                return;
-                            }
-                        }
-                        pc_unequipinvyitem (sd, index - 2, 0);
-                        sd->deal_item_index[trade_i] = index;
-                        sd->deal_item_amount[trade_i] += amount;
-                        clif_tradeitemok (sd, index, amount, 0);    //success to add item
-                        clif_tradeadditem (sd, target_sd, index, amount);
-                    }
-                    break;
-                }
-                else
-                {
-                    // calculate weight for stored deal
-                    trade_weight +=
-                        sd->inventory_data[sd->deal_item_index[trade_i] -
-                                           2]->weight *
-                        sd->deal_item_amount[trade_i];
-                    // count free stackables in stored deal
-                    for (i = 0; i < MAX_INVENTORY; i++)
-                    {
-                        if (target_sd->status.inventory[i].nameid ==
-                            sd->status.
-                            inventory[sd->deal_item_index[trade_i] - 2].nameid
-                            && target_sd->inventory_data[i] != NULL)
-                        {
-                            id = target_sd->inventory_data[i];
-                            if (id->type != 4 && id->type != 5
-                                && id->type != 7 && id->type != 8)
-                            {
-                                free++;
-                                break;
-                            }
-                        }
-                    }
-                }
-                // used a slot, but might be cancelled out by stackable checks above
-                free--;
-            }
-        }
-    }
-}
-
-/*==========================================
- * アイテム追加完了(ok押し)
- *------------------------------------------
- */
-void trade_tradeok (struct map_session_data *sd)
-{
-    struct map_session_data *target_sd;
-    int  trade_i;
-
-    nullpo_retv (sd);
-
-    for (trade_i = 0; trade_i < 10; trade_i++)
-    {
-        if (sd->deal_item_amount[trade_i] >
-            sd->status.inventory[sd->deal_item_index[trade_i] - 2].amount
-            || sd->deal_item_amount[trade_i] < 0)
-        {
-            trade_tradecancel (sd);
-            return;
-        }
-
-    }
-
-    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-    {
-        sd->deal_locked = 1;
-        clif_tradeitemok (sd, 0, 0, 0);
-        clif_tradedeal_lock (sd, 0);
-        clif_tradedeal_lock (target_sd, 1);
-    }
-}
-
-/*==========================================
- * 取引キャンセル
- *------------------------------------------
- */
-void trade_tradecancel (struct map_session_data *sd)
-{
-    struct map_session_data *target_sd;
-    int  trade_i;
-
-    nullpo_retv (sd);
-
-    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-    {
-        for (trade_i = 0; trade_i < 10; trade_i++)
-        {                       //give items back (only virtual)
-            if (sd->deal_item_amount[trade_i] != 0)
-            {
-                clif_additem (sd, sd->deal_item_index[trade_i] - 2,
-                              sd->deal_item_amount[trade_i], 0);
-                sd->deal_item_index[trade_i] = 0;
-                sd->deal_item_amount[trade_i] = 0;
-            }
-            if (target_sd->deal_item_amount[trade_i] != 0)
-            {
-                clif_additem (target_sd,
-                              target_sd->deal_item_index[trade_i] - 2,
-                              target_sd->deal_item_amount[trade_i], 0);
-                target_sd->deal_item_index[trade_i] = 0;
-                target_sd->deal_item_amount[trade_i] = 0;
-            }
-        }
-        if (sd->deal_zeny)
-        {
-            sd->deal_zeny = 0;
-            clif_updatestatus (sd, SP_ZENY);
-        }
-        if (target_sd->deal_zeny)
-        {
-            clif_updatestatus (target_sd, SP_ZENY);
-            target_sd->deal_zeny = 0;
-        }
-        sd->deal_locked = 0;
-        sd->trade_partner = 0;
-        target_sd->deal_locked = 0;
-        target_sd->trade_partner = 0;
-        clif_tradecancelled (sd);
-        clif_tradecancelled (target_sd);
-    }
-}
-
-#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
-
-/*==========================================
- * 取引許諾(trade押し)
- *------------------------------------------
- */
-void trade_tradecommit (struct map_session_data *sd)
-{
-    struct map_session_data *target_sd;
-    int  trade_i;
-
-    nullpo_retv (sd);
-
-    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-    {
-        MAP_LOG_PC (sd, " TRADECOMMIT WITH %d GIVE %d GET %d",
-                    target_sd->status.char_id, sd->deal_zeny,
-                    target_sd->deal_zeny);
-        if ((sd->deal_locked >= 1) && (target_sd->deal_locked >= 1))
-        {                       // both have pressed 'ok'
-            if (sd->deal_locked < 2)
-            {
-                sd->deal_locked = 2;
-            }                   // set locked to 2
-            if (target_sd->deal_locked == 2)
-            {                   // the other one pressed 'trade' too
-                if (sd->deal_zeny > sd->status.zeny)
-                {
-                    sd->deal_zeny = 0;
-                    trade_tradecancel (sd);
-                    MAP_LOG_PC (sd, " TRADECANCEL");
-                    return;
-                }
-                if (target_sd->deal_zeny > target_sd->status.zeny)
-                {
-                    target_sd->deal_zeny = 0;
-                    trade_tradecancel (sd);
-                    MAP_LOG_PC (sd, " TRADECANCEL");
-                    return;
-                }
-                sd->trade_partner = 0;
-                target_sd->trade_partner = 0;
-                for (trade_i = 0; trade_i < 10; trade_i++)
-                {
-                    if (sd->deal_item_amount[trade_i] != 0)
-                    {
-                        int  n = sd->deal_item_index[trade_i] - 2;
-                        int  flag;
-                        flag =
-                            pc_additem (target_sd, &sd->status.inventory[n],
-                                        sd->deal_item_amount[trade_i]);
-                        if (flag == 0)
-                            pc_delitem (sd, n, sd->deal_item_amount[trade_i],
-                                        1);
-                        else
-                            clif_additem (sd, n,
-                                          sd->deal_item_amount[trade_i], 0);
-                        sd->deal_item_index[trade_i] = 0;
-                        sd->deal_item_amount[trade_i] = 0;
-                    }
-                    if (target_sd->deal_item_amount[trade_i] != 0)
-                    {
-                        int  n = target_sd->deal_item_index[trade_i] - 2;
-                        int  flag;
-                        flag =
-                            pc_additem (sd, &target_sd->status.inventory[n],
-                                        target_sd->deal_item_amount[trade_i]);
-                        if (flag == 0)
-                            pc_delitem (target_sd, n,
-                                        target_sd->deal_item_amount[trade_i],
-                                        1);
-                        else
-                            clif_additem (target_sd, n,
-                                          target_sd->deal_item_amount
-                                          [trade_i], 0);
-                        target_sd->deal_item_index[trade_i] = 0;
-                        target_sd->deal_item_amount[trade_i] = 0;
-                    }
-                }
-                if (sd->deal_zeny)
-                {
-                    int  deal = sd->deal_zeny;
-                    sd->deal_zeny = 0;
-                    sd->status.zeny -= deal;
-                    clif_updatestatus (sd, SP_ZENY);
-                    target_sd->status.zeny += deal;
-                    clif_updatestatus (target_sd, SP_ZENY);
-                }
-                if (target_sd->deal_zeny)
-                {
-                    int  deal = target_sd->deal_zeny;
-                    target_sd->deal_zeny = 0;
-                    target_sd->status.zeny -= deal;
-                    clif_updatestatus (target_sd, SP_ZENY);
-                    sd->status.zeny += deal;
-                    clif_updatestatus (sd, SP_ZENY);
-                }
-                sd->deal_locked = 0;
-                target_sd->deal_locked = 0;
-                clif_tradecompleted (sd, 0);
-                clif_tradecompleted (target_sd, 0);
-                MAP_LOG_PC (sd, " TRADEOK");
-            }
-        }
-    }
-}
-
-// This is called when a char's zeny is changed
-// This helps prevent money duplication and other problems
-// [Jaxad0127]
-void trade_verifyzeny (struct map_session_data *sd)
-{
-    struct map_session_data *target_sd;
-
-    nullpo_retv (sd);
-
-    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
-    {
-        if (sd->deal_zeny > sd->status.zeny)
-        {
-            if (sd->deal_locked < 1)
-                trade_tradeadditem (sd, 0, sd->status.zeny);    // Fix money ammount
-            else
-                trade_tradecancel (sd); // Or cancel the trade if we can't fix it
-        }
-    }
-}
diff --git a/src/map/trade.cpp b/src/map/trade.cpp
new file mode 100644
index 0000000..147db1b
--- /dev/null
+++ b/src/map/trade.cpp
@@ -0,0 +1,432 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "clif.hpp"
+#include "itemdb.hpp"
+#include "map.hpp"
+#include "trade.hpp"
+#include "pc.hpp"
+#include "npc.hpp"
+#include "battle.hpp"
+#include "storage.hpp"
+#include "../common/nullpo.hpp"
+
+/*==========================================
+ * 取引要請を相手に送る
+ *------------------------------------------
+ */
+void trade_traderequest (struct map_session_data *sd, int target_id)
+{
+    struct map_session_data *target_sd;
+
+    nullpo_retv (sd);
+
+    if ((target_sd = map_id2sd (target_id)) != NULL)
+    {
+        if (!battle_config.invite_request_check)
+        {
+            if (target_sd->guild_invite > 0 || target_sd->party_invite > 0)
+            {
+                clif_tradestart (sd, 2);    // 相手はPT要請中かGuild要請中
+                return;
+            }
+        }
+        if (target_sd->npc_id)
+        {
+            //Trade fails if you are using an NPC.
+            clif_tradestart (sd, 2);
+            return;
+        }
+        if ((target_sd->trade_partner != 0) || (sd->trade_partner != 0))
+        {
+            trade_tradecancel (sd); //person is in another trade
+        }
+        else
+        {
+            if (sd->bl.m != target_sd->bl.m
+                || (sd->bl.x - target_sd->bl.x <= -5
+                    || sd->bl.x - target_sd->bl.x >= 5)
+                || (sd->bl.y - target_sd->bl.y <= -5
+                    || sd->bl.y - target_sd->bl.y >= 5))
+            {
+                clif_tradestart (sd, 0);    //too far
+            }
+            else if (sd != target_sd)
+            {
+                target_sd->trade_partner = sd->status.account_id;
+                sd->trade_partner = target_sd->status.account_id;
+                clif_traderequest (target_sd, sd->status.name);
+            }
+        }
+    }
+    else
+    {
+        clif_tradestart (sd, 1);    //character does not exist
+    }
+}
+
+/*==========================================
+ * 取引要請
+ *------------------------------------------
+ */
+void trade_tradeack (struct map_session_data *sd, int type)
+{
+    struct map_session_data *target_sd;
+    nullpo_retv (sd);
+
+    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+    {
+        clif_tradestart (target_sd, type);
+        clif_tradestart (sd, type);
+        if (type == 4)
+        {                       // Cancel
+            sd->deal_locked = 0;
+            sd->trade_partner = 0;
+            target_sd->deal_locked = 0;
+            target_sd->trade_partner = 0;
+        }
+        if (sd->npc_id != 0)
+            npc_event_dequeue (sd);
+        if (target_sd->npc_id != 0)
+            npc_event_dequeue (target_sd);
+
+        //close STORAGE window if it's open. It protects from spooffing packets [Lupus]
+        if (sd->state.storage_flag == 1)
+            storage_storageclose (sd);
+        else if (sd->state.storage_flag == 2)
+            storage_guild_storageclose (sd);
+    }
+}
+
+/*==========================================
+ * アイテム追加
+ *------------------------------------------
+ */
+void trade_tradeadditem (struct map_session_data *sd, int index, int amount)
+{
+    struct map_session_data *target_sd;
+    struct item_data *id;
+    int  trade_i;
+    int  trade_weight = 0;
+    int  free = 0;
+    int  c;
+    int  i;
+
+    nullpo_retv (sd);
+
+    if (((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+        && (sd->deal_locked < 1))
+    {
+        if (index < 2 || index >= MAX_INVENTORY + 2)
+        {
+            if (index == 0 && amount > 0 && amount <= sd->status.zeny)
+            {
+                sd->deal_zeny = amount;
+                clif_tradeadditem (sd, target_sd, 0, amount);
+            }
+        }
+        else if (amount <= sd->status.inventory[index - 2].amount
+                 && amount > 0)
+        {
+            // determine free slots of receiver
+            for (i = 0; i < MAX_INVENTORY; i++)
+            {
+                if (target_sd->status.inventory[i].nameid == 0
+                    && target_sd->inventory_data[i] == NULL)
+                    free++;
+            }
+            for (trade_i = 0; trade_i < 10; trade_i++)
+            {
+                if (sd->deal_item_amount[trade_i] == 0)
+                {
+                    // calculate trade weight
+                    trade_weight +=
+                        sd->inventory_data[index - 2]->weight * amount;
+
+                    // determine if item is a stackable already in receivers inventory, and up free count
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (target_sd->status.inventory[i].nameid ==
+                            sd->status.inventory[index - 2].nameid
+                            && target_sd->inventory_data[i] != NULL)
+                        {
+                            id = target_sd->inventory_data[i];
+                            if (id->type != 4 && id->type != 5
+                                && id->type != 7 && id->type != 8)
+                            {
+                                free++;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (target_sd->weight + trade_weight >
+                        target_sd->max_weight)
+                    {
+                        clif_tradeitemok (sd, index, 0, 1); //fail to add item -- the player was over weighted.
+                        amount = 0; // [MouseJstr]
+                    }
+                    else if (free <= 0)
+                    {
+                        clif_tradeitemok (sd, index, 0, 2); //fail to add item -- no free slots at receiver
+                        amount = 0; // peavey
+                    }
+                    else
+                    {
+                        for (c = 0; c == trade_i - 1; c++)
+                        {       // re-deal exploit protection [Valaris]
+                            if (sd->deal_item_index[c] == index)
+                            {
+                                trade_tradecancel (sd);
+                                return;
+                            }
+                        }
+                        pc_unequipinvyitem (sd, index - 2, 0);
+                        sd->deal_item_index[trade_i] = index;
+                        sd->deal_item_amount[trade_i] += amount;
+                        clif_tradeitemok (sd, index, amount, 0);    //success to add item
+                        clif_tradeadditem (sd, target_sd, index, amount);
+                    }
+                    break;
+                }
+                else
+                {
+                    // calculate weight for stored deal
+                    trade_weight +=
+                        sd->inventory_data[sd->deal_item_index[trade_i] -
+                                           2]->weight *
+                        sd->deal_item_amount[trade_i];
+                    // count free stackables in stored deal
+                    for (i = 0; i < MAX_INVENTORY; i++)
+                    {
+                        if (target_sd->status.inventory[i].nameid ==
+                            sd->status.
+                            inventory[sd->deal_item_index[trade_i] - 2].nameid
+                            && target_sd->inventory_data[i] != NULL)
+                        {
+                            id = target_sd->inventory_data[i];
+                            if (id->type != 4 && id->type != 5
+                                && id->type != 7 && id->type != 8)
+                            {
+                                free++;
+                                break;
+                            }
+                        }
+                    }
+                }
+                // used a slot, but might be cancelled out by stackable checks above
+                free--;
+            }
+        }
+    }
+}
+
+/*==========================================
+ * アイテム追加完了(ok押し)
+ *------------------------------------------
+ */
+void trade_tradeok (struct map_session_data *sd)
+{
+    struct map_session_data *target_sd;
+    int  trade_i;
+
+    nullpo_retv (sd);
+
+    for (trade_i = 0; trade_i < 10; trade_i++)
+    {
+        if (sd->deal_item_amount[trade_i] >
+            sd->status.inventory[sd->deal_item_index[trade_i] - 2].amount
+            || sd->deal_item_amount[trade_i] < 0)
+        {
+            trade_tradecancel (sd);
+            return;
+        }
+
+    }
+
+    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+    {
+        sd->deal_locked = 1;
+        clif_tradeitemok (sd, 0, 0, 0);
+        clif_tradedeal_lock (sd, 0);
+        clif_tradedeal_lock (target_sd, 1);
+    }
+}
+
+/*==========================================
+ * 取引キャンセル
+ *------------------------------------------
+ */
+void trade_tradecancel (struct map_session_data *sd)
+{
+    struct map_session_data *target_sd;
+    int  trade_i;
+
+    nullpo_retv (sd);
+
+    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+    {
+        for (trade_i = 0; trade_i < 10; trade_i++)
+        {                       //give items back (only virtual)
+            if (sd->deal_item_amount[trade_i] != 0)
+            {
+                clif_additem (sd, sd->deal_item_index[trade_i] - 2,
+                              sd->deal_item_amount[trade_i], 0);
+                sd->deal_item_index[trade_i] = 0;
+                sd->deal_item_amount[trade_i] = 0;
+            }
+            if (target_sd->deal_item_amount[trade_i] != 0)
+            {
+                clif_additem (target_sd,
+                              target_sd->deal_item_index[trade_i] - 2,
+                              target_sd->deal_item_amount[trade_i], 0);
+                target_sd->deal_item_index[trade_i] = 0;
+                target_sd->deal_item_amount[trade_i] = 0;
+            }
+        }
+        if (sd->deal_zeny)
+        {
+            sd->deal_zeny = 0;
+            clif_updatestatus (sd, SP_ZENY);
+        }
+        if (target_sd->deal_zeny)
+        {
+            clif_updatestatus (target_sd, SP_ZENY);
+            target_sd->deal_zeny = 0;
+        }
+        sd->deal_locked = 0;
+        sd->trade_partner = 0;
+        target_sd->deal_locked = 0;
+        target_sd->trade_partner = 0;
+        clif_tradecancelled (sd);
+        clif_tradecancelled (target_sd);
+    }
+}
+
+#define MAP_LOG_PC(sd, fmt, args...) MAP_LOG("PC%d %d:%d,%d " fmt, sd->status.char_id, sd->bl.m, sd->bl.x, sd->bl.y, ## args)
+
+/*==========================================
+ * 取引許諾(trade押し)
+ *------------------------------------------
+ */
+void trade_tradecommit (struct map_session_data *sd)
+{
+    struct map_session_data *target_sd;
+    int  trade_i;
+
+    nullpo_retv (sd);
+
+    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+    {
+        MAP_LOG_PC (sd, " TRADECOMMIT WITH %d GIVE %d GET %d",
+                    target_sd->status.char_id, sd->deal_zeny,
+                    target_sd->deal_zeny);
+        if ((sd->deal_locked >= 1) && (target_sd->deal_locked >= 1))
+        {                       // both have pressed 'ok'
+            if (sd->deal_locked < 2)
+            {
+                sd->deal_locked = 2;
+            }                   // set locked to 2
+            if (target_sd->deal_locked == 2)
+            {                   // the other one pressed 'trade' too
+                if (sd->deal_zeny > sd->status.zeny)
+                {
+                    sd->deal_zeny = 0;
+                    trade_tradecancel (sd);
+                    MAP_LOG_PC (sd, " TRADECANCEL");
+                    return;
+                }
+                if (target_sd->deal_zeny > target_sd->status.zeny)
+                {
+                    target_sd->deal_zeny = 0;
+                    trade_tradecancel (sd);
+                    MAP_LOG_PC (sd, " TRADECANCEL");
+                    return;
+                }
+                sd->trade_partner = 0;
+                target_sd->trade_partner = 0;
+                for (trade_i = 0; trade_i < 10; trade_i++)
+                {
+                    if (sd->deal_item_amount[trade_i] != 0)
+                    {
+                        int  n = sd->deal_item_index[trade_i] - 2;
+                        int  flag;
+                        flag =
+                            pc_additem (target_sd, &sd->status.inventory[n],
+                                        sd->deal_item_amount[trade_i]);
+                        if (flag == 0)
+                            pc_delitem (sd, n, sd->deal_item_amount[trade_i],
+                                        1);
+                        else
+                            clif_additem (sd, n,
+                                          sd->deal_item_amount[trade_i], 0);
+                        sd->deal_item_index[trade_i] = 0;
+                        sd->deal_item_amount[trade_i] = 0;
+                    }
+                    if (target_sd->deal_item_amount[trade_i] != 0)
+                    {
+                        int  n = target_sd->deal_item_index[trade_i] - 2;
+                        int  flag;
+                        flag =
+                            pc_additem (sd, &target_sd->status.inventory[n],
+                                        target_sd->deal_item_amount[trade_i]);
+                        if (flag == 0)
+                            pc_delitem (target_sd, n,
+                                        target_sd->deal_item_amount[trade_i],
+                                        1);
+                        else
+                            clif_additem (target_sd, n,
+                                          target_sd->deal_item_amount
+                                          [trade_i], 0);
+                        target_sd->deal_item_index[trade_i] = 0;
+                        target_sd->deal_item_amount[trade_i] = 0;
+                    }
+                }
+                if (sd->deal_zeny)
+                {
+                    int  deal = sd->deal_zeny;
+                    sd->deal_zeny = 0;
+                    sd->status.zeny -= deal;
+                    clif_updatestatus (sd, SP_ZENY);
+                    target_sd->status.zeny += deal;
+                    clif_updatestatus (target_sd, SP_ZENY);
+                }
+                if (target_sd->deal_zeny)
+                {
+                    int  deal = target_sd->deal_zeny;
+                    target_sd->deal_zeny = 0;
+                    target_sd->status.zeny -= deal;
+                    clif_updatestatus (target_sd, SP_ZENY);
+                    sd->status.zeny += deal;
+                    clif_updatestatus (sd, SP_ZENY);
+                }
+                sd->deal_locked = 0;
+                target_sd->deal_locked = 0;
+                clif_tradecompleted (sd, 0);
+                clif_tradecompleted (target_sd, 0);
+                MAP_LOG_PC (sd, " TRADEOK");
+            }
+        }
+    }
+}
+
+// This is called when a char's zeny is changed
+// This helps prevent money duplication and other problems
+// [Jaxad0127]
+void trade_verifyzeny (struct map_session_data *sd)
+{
+    struct map_session_data *target_sd;
+
+    nullpo_retv (sd);
+
+    if ((target_sd = map_id2sd (sd->trade_partner)) != NULL)
+    {
+        if (sd->deal_zeny > sd->status.zeny)
+        {
+            if (sd->deal_locked < 1)
+                trade_tradeadditem (sd, 0, sd->status.zeny);    // Fix money ammount
+            else
+                trade_tradecancel (sd); // Or cancel the trade if we can't fix it
+        }
+    }
+}
diff --git a/src/map/trade.h b/src/map/trade.h
deleted file mode 100644
index a846388..0000000
--- a/src/map/trade.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// $Id: trade.h,v 1.2 2004/09/25 05:32:19 MouseJstr Exp $
-#ifndef	_TRADE_H_
-#define	_TRADE_H_
-
-#include "map.h"
-void trade_traderequest (struct map_session_data *sd, int target_id);
-void trade_tradeack (struct map_session_data *sd, int type);
-void trade_tradeadditem (struct map_session_data *sd, int index, int amount);
-void trade_tradeok (struct map_session_data *sd);
-void trade_tradecancel (struct map_session_data *sd);
-void trade_tradecommit (struct map_session_data *sd);
-void trade_verifyzeny (struct map_session_data *sd);
-
-#endif // _TRADE_H_
diff --git a/src/map/trade.hpp b/src/map/trade.hpp
new file mode 100644
index 0000000..1e885f4
--- /dev/null
+++ b/src/map/trade.hpp
@@ -0,0 +1,14 @@
+// $Id: trade.h,v 1.2 2004/09/25 05:32:19 MouseJstr Exp $
+#ifndef TRADE_HPP
+#define TRADE_HPP
+
+#include "map.hpp"
+void trade_traderequest (struct map_session_data *sd, int target_id);
+void trade_tradeack (struct map_session_data *sd, int type);
+void trade_tradeadditem (struct map_session_data *sd, int index, int amount);
+void trade_tradeok (struct map_session_data *sd);
+void trade_tradecancel (struct map_session_data *sd);
+void trade_tradecommit (struct map_session_data *sd);
+void trade_verifyzeny (struct map_session_data *sd);
+
+#endif // TRADE_HPP
diff --git a/src/tool/adduser.c b/src/tool/adduser.c
deleted file mode 100644
index 1954b66..0000000
--- a/src/tool/adduser.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-	This program adds an user to account.txt
-	Don't usr it When login-sever is working.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-char *account_txt = "../save/account.txt";
-
-//-----------------------------------------------------
-// Function to suppress control characters in a string.
-//-----------------------------------------------------
-int remove_control_chars (unsigned char *str)
-{
-    int  i;
-    int  change = 0;
-
-    for (i = 0; str[i]; i++)
-    {
-        if (str[i] < 32)
-        {
-            str[i] = '_';
-            change = 1;
-        }
-    }
-
-    return change;
-}
-
-int main (int argc, char *argv[])
-{
-
-    char username[24];
-    char password[24];
-    char sex[2];
-
-    int  next_id, id;
-    char line[1024];
-
-    // Check to see if account.txt exists.
-    printf ("Checking if '%s' file exists...\n", account_txt);
-    FILE *FPaccin = fopen (account_txt, "r");
-    if (FPaccin == NULL)
-    {
-        printf ("'%s' file not found!\n", account_txt);
-        printf ("Run the setup wizard please.\n");
-        exit (0);
-    }
-
-    next_id = 2000000;
-    while (fgets (line, sizeof (line) - 1, FPaccin))
-    {
-        if (line[0] == '/' && line[1] == '/')
-        {
-            continue;
-        }
-        if (sscanf (line, "%d\t%%newid%%\n", &id) == 1)
-        {
-            if (next_id < id)
-            {
-                next_id = id;
-            }
-        }
-        else
-        {
-            sscanf (line, "%i%[^	]", &id);
-            if (next_id <= id)
-            {
-                next_id = id + 1;
-            }
-        }
-    }
-    fclose (FPaccin);
-    printf ("File exists.\n");
-
-    printf ("Don't create an account if the login-server is online!!!\n");
-    printf
-        ("If the login-server is online, press ctrl+C now to stop this software.\n");
-    printf ("\n");
-
-    strcpy (username, "");
-    while (strlen (username) < 4 || strlen (username) > 23)
-    {
-        printf ("Enter an username (4-23 characters): ");
-        scanf ("%s", &username);
-        username[23] = 0;
-        remove_control_chars (username);
-    }
-
-    strcpy (password, "");
-    while (strlen (password) < 4 || strlen (password) > 23)
-    {
-        printf ("Enter a password (4-23 characters): ");
-        scanf ("%s", &password);
-        password[23] = 0;
-        remove_control_chars (password);
-    }
-
-    strcpy (sex, "");
-    while (strcmp (sex, "F") != 0 && strcmp (sex, "M") != 0)
-    {
-        printf ("Enter a gender (M for male, F for female): ");
-        scanf ("%s", &sex);
-    }
-
-    FILE *FPaccout = fopen (account_txt, "r+");
-    fseek (FPaccout, 0, SEEK_END);
-    fprintf (FPaccout, "%i	%s	%s	-	%s	-\r\n", next_id, username,
-             password, sex);
-    fclose (FPaccout);
-
-    printf ("Account added.\n");
-}
diff --git a/src/tool/adduser.cpp b/src/tool/adduser.cpp
new file mode 100644
index 0000000..1954b66
--- /dev/null
+++ b/src/tool/adduser.cpp
@@ -0,0 +1,115 @@
+/*
+	This program adds an user to account.txt
+	Don't usr it When login-sever is working.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *account_txt = "../save/account.txt";
+
+//-----------------------------------------------------
+// Function to suppress control characters in a string.
+//-----------------------------------------------------
+int remove_control_chars (unsigned char *str)
+{
+    int  i;
+    int  change = 0;
+
+    for (i = 0; str[i]; i++)
+    {
+        if (str[i] < 32)
+        {
+            str[i] = '_';
+            change = 1;
+        }
+    }
+
+    return change;
+}
+
+int main (int argc, char *argv[])
+{
+
+    char username[24];
+    char password[24];
+    char sex[2];
+
+    int  next_id, id;
+    char line[1024];
+
+    // Check to see if account.txt exists.
+    printf ("Checking if '%s' file exists...\n", account_txt);
+    FILE *FPaccin = fopen (account_txt, "r");
+    if (FPaccin == NULL)
+    {
+        printf ("'%s' file not found!\n", account_txt);
+        printf ("Run the setup wizard please.\n");
+        exit (0);
+    }
+
+    next_id = 2000000;
+    while (fgets (line, sizeof (line) - 1, FPaccin))
+    {
+        if (line[0] == '/' && line[1] == '/')
+        {
+            continue;
+        }
+        if (sscanf (line, "%d\t%%newid%%\n", &id) == 1)
+        {
+            if (next_id < id)
+            {
+                next_id = id;
+            }
+        }
+        else
+        {
+            sscanf (line, "%i%[^	]", &id);
+            if (next_id <= id)
+            {
+                next_id = id + 1;
+            }
+        }
+    }
+    fclose (FPaccin);
+    printf ("File exists.\n");
+
+    printf ("Don't create an account if the login-server is online!!!\n");
+    printf
+        ("If the login-server is online, press ctrl+C now to stop this software.\n");
+    printf ("\n");
+
+    strcpy (username, "");
+    while (strlen (username) < 4 || strlen (username) > 23)
+    {
+        printf ("Enter an username (4-23 characters): ");
+        scanf ("%s", &username);
+        username[23] = 0;
+        remove_control_chars (username);
+    }
+
+    strcpy (password, "");
+    while (strlen (password) < 4 || strlen (password) > 23)
+    {
+        printf ("Enter a password (4-23 characters): ");
+        scanf ("%s", &password);
+        password[23] = 0;
+        remove_control_chars (password);
+    }
+
+    strcpy (sex, "");
+    while (strcmp (sex, "F") != 0 && strcmp (sex, "M") != 0)
+    {
+        printf ("Enter a gender (M for male, F for female): ");
+        scanf ("%s", &sex);
+    }
+
+    FILE *FPaccout = fopen (account_txt, "r+");
+    fseek (FPaccout, 0, SEEK_END);
+    fprintf (FPaccout, "%i	%s	%s	-	%s	-\r\n", next_id, username,
+             password, sex);
+    fclose (FPaccout);
+
+    printf ("Account added.\n");
+}
diff --git a/src/tool/convert.c b/src/tool/convert.c
deleted file mode 100644
index e256fc9..0000000
--- a/src/tool/convert.c
+++ /dev/null
@@ -1,302 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#define MAX_INVENTORY 100
-#define MAX_CART 100
-#define MAX_SKILL 350
-#define GLOBAL_REG_NUM 16
-
-struct item
-{
-    int  id;
-    short nameid;
-    short amount;
-    short equip;
-    char identify;
-    char refine;
-    char attribute;
-    short card[4];
-};
-struct point
-{
-    char map[16];
-    short x, y;
-};
-struct skill
-{
-    unsigned short id, lv, flag;
-};
-struct global_reg
-{
-    char str[16];
-    int  value;
-};
-
-struct mmo_charstatus
-{
-    int  char_id;
-    int  account_id;
-    int  base_exp, job_exp, zeny;
-
-    short class;
-    short status_point, skill_point;
-    short hp, max_hp, sp, max_sp;
-    short option, karma, manner;
-    short hair, hair_color, clothes_color;
-    int  party_id, guild_id, pet_id;
-
-    short weapon, shield;
-    short head_top, head_mid, head_bottom;
-
-    char name[24];
-    unsigned char base_level, job_level;
-    unsigned char str, agi, vit, int_, dex, luk, char_num, sex;
-
-    struct point last_point, save_point, memo_point[3];
-    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
-    struct skill skill[MAX_SKILL];
-    int  global_reg_num;
-    struct global_reg global_reg[GLOBAL_REG_NUM];
-};
-
-int mmo_char_tostr (char *str, struct mmo_charstatus *p)
-{
-    int  i;
-    sprintf (str, "%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%s,%d,%d\t%s,%d,%d", p->char_id, p->account_id, p->char_num, p->name,  //
-             p->class, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->hp, p->max_hp, p->sp, p->max_sp, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, p->status_point, p->skill_point, p->option, p->karma, p->manner, //
-             p->party_id, p->guild_id, p->pet_id, p->hair, p->hair_color, p->clothes_color, 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);
-    strcat (str, "\t");
-    for (i = 0; i < 3; i++)
-        if (p->memo_point[i].map[0])
-        {
-            sprintf (str + strlen (str), "%s,%d,%d", p->memo_point[i].map,
-                     p->memo_point[i].x, p->memo_point[i].y);
-        }
-    strcat (str, "\t");
-    for (i = 0; i < MAX_INVENTORY; i++)
-        if (p->inventory[i].nameid)
-        {
-            sprintf (str + strlen (str), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                     p->inventory[i].id, p->inventory[i].nameid,
-                     p->inventory[i].amount, p->inventory[i].equip,
-                     p->inventory[i].identify, p->inventory[i].refine,
-                     p->inventory[i].attribute, p->inventory[i].card[0],
-                     p->inventory[i].card[1], p->inventory[i].card[2],
-                     p->inventory[i].card[3]);
-        }
-    strcat (str, "\t");
-    for (i = 0; i < MAX_CART; i++)
-        if (p->cart[i].nameid)
-        {
-            sprintf (str + strlen (str), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
-                     p->cart[i].id, p->cart[i].nameid, p->cart[i].amount,
-                     p->cart[i].equip, p->cart[i].identify, p->cart[i].refine,
-                     p->cart[i].attribute, p->cart[i].card[0],
-                     p->cart[i].card[1], p->cart[i].card[2],
-                     p->cart[i].card[3]);
-        }
-    strcat (str, "\t");
-    for (i = 0; i < MAX_SKILL; i++)
-        if (p->skill[i].id)
-        {
-            sprintf (str + strlen (str), "%d,%d ", p->skill[i].id,
-                     p->skill[i].lv);
-        }
-    strcat (str, "\t");
-    for (i = 0; i < p->global_reg_num; i++)
-        sprintf (str + strlen (str), "%s,%d ", p->global_reg[i].str,
-                 p->global_reg[i].value);
-    strcat (str, "\t");
-    return 0;
-}
-
-int mmo_char_fromstr (char *str, struct mmo_charstatus *p)
-{
-    int  tmp_int[256];
-    int  set, next, len, i;
-
-    set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
-                  &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], p->last_point.map, &tmp_int[34], &tmp_int[35],    //
-                  p->save_point.map, &tmp_int[36], &tmp_int[37], &next);
-    p->char_id = tmp_int[0];
-    p->account_id = tmp_int[1];
-    p->char_num = tmp_int[2];
-    p->class = tmp_int[3];
-    p->base_level = tmp_int[4];
-    p->job_level = tmp_int[5];
-    p->base_exp = tmp_int[6];
-    p->job_exp = tmp_int[7];
-    p->zeny = tmp_int[8];
-    p->hp = tmp_int[9];
-    p->max_hp = tmp_int[10];
-    p->sp = tmp_int[11];
-    p->max_sp = tmp_int[12];
-    p->str = tmp_int[13];
-    p->agi = tmp_int[14];
-    p->vit = tmp_int[15];
-    p->int_ = tmp_int[16];
-    p->dex = tmp_int[17];
-    p->luk = tmp_int[18];
-    p->status_point = tmp_int[19];
-    p->skill_point = tmp_int[20];
-    p->option = tmp_int[21];
-    p->karma = tmp_int[22];
-    p->manner = tmp_int[23];
-    p->party_id = tmp_int[24];
-    p->guild_id = tmp_int[25];
-    p->pet_id = 0;
-    p->hair = tmp_int[26];
-    p->hair_color = tmp_int[27];
-    p->clothes_color = tmp_int[28];
-    p->weapon = tmp_int[29];
-    p->shield = tmp_int[30];
-    p->head_top = tmp_int[31];
-    p->head_mid = tmp_int[32];
-    p->head_bottom = tmp_int[33];
-    p->last_point.x = tmp_int[34];
-    p->last_point.y = tmp_int[35];
-    p->save_point.x = tmp_int[36];
-    p->save_point.y = tmp_int[37];
-    if (set != 41)
-        return 0;
-    if (str[next] == '\n' || str[next] == '\r')
-        return 1;               // 新規データ
-    next++;
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        set =
-            sscanf (str + next, "%[^,],%d,%d%n", p->memo_point[i].map,
-                    &tmp_int[0], &tmp_int[1], &len);
-        if (set != 3)
-            return 0;
-        p->memo_point[i].x = tmp_int[0];
-        p->memo_point[i].y = tmp_int[1];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    next++;
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        set = sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                      &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                      &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                      &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                      &len);
-        if (set != 11)
-            return 0;
-        p->inventory[i].id = tmp_int[0];
-        p->inventory[i].nameid = tmp_int[1];
-        p->inventory[i].amount = tmp_int[2];
-        p->inventory[i].equip = tmp_int[3];
-        p->inventory[i].identify = tmp_int[4];
-        p->inventory[i].refine = tmp_int[5];
-        p->inventory[i].attribute = tmp_int[6];
-        p->inventory[i].card[0] = tmp_int[7];
-        p->inventory[i].card[1] = tmp_int[8];
-        p->inventory[i].card[2] = tmp_int[9];
-        p->inventory[i].card[3] = tmp_int[10];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    next++;
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        set = sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
-                      &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
-                      &tmp_int[4], &tmp_int[5], &tmp_int[6],
-                      &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
-                      &len);
-        if (set != 11)
-            return 0;
-        p->cart[i].id = tmp_int[0];
-        p->cart[i].nameid = tmp_int[1];
-        p->cart[i].amount = tmp_int[2];
-        p->cart[i].equip = tmp_int[3];
-        p->cart[i].identify = tmp_int[4];
-        p->cart[i].refine = tmp_int[5];
-        p->cart[i].attribute = tmp_int[6];
-        p->cart[i].card[0] = tmp_int[7];
-        p->cart[i].card[1] = tmp_int[8];
-        p->cart[i].card[2] = tmp_int[9];
-        p->cart[i].card[3] = tmp_int[10];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    next++;
-    for (i = 0; str[next] && str[next] != '\t'; i++)
-    {
-        set = sscanf (str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len);
-        if (set != 2)
-            return 0;
-        p->skill[tmp_int[0]].id = tmp_int[0];
-        p->skill[tmp_int[0]].lv = tmp_int[1];
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    next++;
-    for (i = 0;
-         str[next] && str[next] != '\t' && str[next] != '\n'
-         && str[next] != '\r'; i++)
-    {                           //global_reg実装以前のathena.txt互換のため一応'\n'チェック
-        set = sscanf (str + next, "%[^,],%d%n",
-                      p->global_reg[i].str, &p->global_reg[i].value, &len);
-        if (set != 2)
-            return 0;
-        next += len;
-        if (str[next] == ' ')
-            next++;
-    }
-    p->global_reg_num = i;
-    return 1;
-}
-
-int mmo_char_convert (char *fname1, char *fname2)
-{
-    char line[65536];
-    int  ret;
-    struct mmo_charstatus char_dat;
-    FILE *ifp, *ofp;
-
-    ifp = fopen_ (fname1, "r");
-    ofp = fopen_ (fname2, "w");
-    if (ifp == NULL)
-    {
-        printf ("file not found %s\n", fname1);
-        return 0;
-    }
-    if (ofp == NULL)
-    {
-        printf ("file open error %s\n", fname2);
-        return 0;
-    }
-    while (fgets (line, 65535, ifp))
-    {
-        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
-        ret = mmo_char_fromstr (line, &char_dat);
-        if (ret)
-        {
-            mmo_char_tostr (line, &char_dat);
-            fprintf (ofp, "%s\n", line);
-        }
-    }
-    fcloseall ();
-    return 0;
-}
-
-int main (int argc, char *argv[])
-{
-    if (argc < 3)
-    {
-        printf ("Usage: convert <input filename> <output filename>\n");
-        exit (0);
-    }
-    mmo_char_convert (argv[1], argv[2]);
-
-    return 0;
-}
diff --git a/src/tool/convert.cpp b/src/tool/convert.cpp
new file mode 100644
index 0000000..e256fc9
--- /dev/null
+++ b/src/tool/convert.cpp
@@ -0,0 +1,302 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_INVENTORY 100
+#define MAX_CART 100
+#define MAX_SKILL 350
+#define GLOBAL_REG_NUM 16
+
+struct item
+{
+    int  id;
+    short nameid;
+    short amount;
+    short equip;
+    char identify;
+    char refine;
+    char attribute;
+    short card[4];
+};
+struct point
+{
+    char map[16];
+    short x, y;
+};
+struct skill
+{
+    unsigned short id, lv, flag;
+};
+struct global_reg
+{
+    char str[16];
+    int  value;
+};
+
+struct mmo_charstatus
+{
+    int  char_id;
+    int  account_id;
+    int  base_exp, job_exp, zeny;
+
+    short class;
+    short status_point, skill_point;
+    short hp, max_hp, sp, max_sp;
+    short option, karma, manner;
+    short hair, hair_color, clothes_color;
+    int  party_id, guild_id, pet_id;
+
+    short weapon, shield;
+    short head_top, head_mid, head_bottom;
+
+    char name[24];
+    unsigned char base_level, job_level;
+    unsigned char str, agi, vit, int_, dex, luk, char_num, sex;
+
+    struct point last_point, save_point, memo_point[3];
+    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
+    struct skill skill[MAX_SKILL];
+    int  global_reg_num;
+    struct global_reg global_reg[GLOBAL_REG_NUM];
+};
+
+int mmo_char_tostr (char *str, struct mmo_charstatus *p)
+{
+    int  i;
+    sprintf (str, "%d\t%d,%d\t%s\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%s,%d,%d\t%s,%d,%d", p->char_id, p->account_id, p->char_num, p->name,  //
+             p->class, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, p->hp, p->max_hp, p->sp, p->max_sp, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, p->status_point, p->skill_point, p->option, p->karma, p->manner, //
+             p->party_id, p->guild_id, p->pet_id, p->hair, p->hair_color, p->clothes_color, 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);
+    strcat (str, "\t");
+    for (i = 0; i < 3; i++)
+        if (p->memo_point[i].map[0])
+        {
+            sprintf (str + strlen (str), "%s,%d,%d", p->memo_point[i].map,
+                     p->memo_point[i].x, p->memo_point[i].y);
+        }
+    strcat (str, "\t");
+    for (i = 0; i < MAX_INVENTORY; i++)
+        if (p->inventory[i].nameid)
+        {
+            sprintf (str + strlen (str), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                     p->inventory[i].id, p->inventory[i].nameid,
+                     p->inventory[i].amount, p->inventory[i].equip,
+                     p->inventory[i].identify, p->inventory[i].refine,
+                     p->inventory[i].attribute, p->inventory[i].card[0],
+                     p->inventory[i].card[1], p->inventory[i].card[2],
+                     p->inventory[i].card[3]);
+        }
+    strcat (str, "\t");
+    for (i = 0; i < MAX_CART; i++)
+        if (p->cart[i].nameid)
+        {
+            sprintf (str + strlen (str), "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d ",
+                     p->cart[i].id, p->cart[i].nameid, p->cart[i].amount,
+                     p->cart[i].equip, p->cart[i].identify, p->cart[i].refine,
+                     p->cart[i].attribute, p->cart[i].card[0],
+                     p->cart[i].card[1], p->cart[i].card[2],
+                     p->cart[i].card[3]);
+        }
+    strcat (str, "\t");
+    for (i = 0; i < MAX_SKILL; i++)
+        if (p->skill[i].id)
+        {
+            sprintf (str + strlen (str), "%d,%d ", p->skill[i].id,
+                     p->skill[i].lv);
+        }
+    strcat (str, "\t");
+    for (i = 0; i < p->global_reg_num; i++)
+        sprintf (str + strlen (str), "%s,%d ", p->global_reg[i].str,
+                 p->global_reg[i].value);
+    strcat (str, "\t");
+    return 0;
+}
+
+int mmo_char_fromstr (char *str, struct mmo_charstatus *p)
+{
+    int  tmp_int[256];
+    int  set, next, len, i;
+
+    set = sscanf (str, "%d\t%d,%d\t%[^\t]\t%d,%d,%d\t%d,%d,%d\t%d,%d,%d,%d\t%d,%d,%d,%d,%d,%d\t%d,%d" "\t%d,%d,%d\t%d,%d\t%d,%d,%d\t%d,%d,%d,%d,%d" "\t%[^,],%d,%d\t%[^,],%d,%d%n", &tmp_int[0], &tmp_int[1], &tmp_int[2], p->name, //
+                  &tmp_int[3], &tmp_int[4], &tmp_int[5], &tmp_int[6], &tmp_int[7], &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[27], &tmp_int[28], &tmp_int[29], &tmp_int[30], &tmp_int[31], &tmp_int[32], &tmp_int[33], p->last_point.map, &tmp_int[34], &tmp_int[35],    //
+                  p->save_point.map, &tmp_int[36], &tmp_int[37], &next);
+    p->char_id = tmp_int[0];
+    p->account_id = tmp_int[1];
+    p->char_num = tmp_int[2];
+    p->class = tmp_int[3];
+    p->base_level = tmp_int[4];
+    p->job_level = tmp_int[5];
+    p->base_exp = tmp_int[6];
+    p->job_exp = tmp_int[7];
+    p->zeny = tmp_int[8];
+    p->hp = tmp_int[9];
+    p->max_hp = tmp_int[10];
+    p->sp = tmp_int[11];
+    p->max_sp = tmp_int[12];
+    p->str = tmp_int[13];
+    p->agi = tmp_int[14];
+    p->vit = tmp_int[15];
+    p->int_ = tmp_int[16];
+    p->dex = tmp_int[17];
+    p->luk = tmp_int[18];
+    p->status_point = tmp_int[19];
+    p->skill_point = tmp_int[20];
+    p->option = tmp_int[21];
+    p->karma = tmp_int[22];
+    p->manner = tmp_int[23];
+    p->party_id = tmp_int[24];
+    p->guild_id = tmp_int[25];
+    p->pet_id = 0;
+    p->hair = tmp_int[26];
+    p->hair_color = tmp_int[27];
+    p->clothes_color = tmp_int[28];
+    p->weapon = tmp_int[29];
+    p->shield = tmp_int[30];
+    p->head_top = tmp_int[31];
+    p->head_mid = tmp_int[32];
+    p->head_bottom = tmp_int[33];
+    p->last_point.x = tmp_int[34];
+    p->last_point.y = tmp_int[35];
+    p->save_point.x = tmp_int[36];
+    p->save_point.y = tmp_int[37];
+    if (set != 41)
+        return 0;
+    if (str[next] == '\n' || str[next] == '\r')
+        return 1;               // 新規データ
+    next++;
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        set =
+            sscanf (str + next, "%[^,],%d,%d%n", p->memo_point[i].map,
+                    &tmp_int[0], &tmp_int[1], &len);
+        if (set != 3)
+            return 0;
+        p->memo_point[i].x = tmp_int[0];
+        p->memo_point[i].y = tmp_int[1];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    next++;
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        set = sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                      &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                      &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                      &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                      &len);
+        if (set != 11)
+            return 0;
+        p->inventory[i].id = tmp_int[0];
+        p->inventory[i].nameid = tmp_int[1];
+        p->inventory[i].amount = tmp_int[2];
+        p->inventory[i].equip = tmp_int[3];
+        p->inventory[i].identify = tmp_int[4];
+        p->inventory[i].refine = tmp_int[5];
+        p->inventory[i].attribute = tmp_int[6];
+        p->inventory[i].card[0] = tmp_int[7];
+        p->inventory[i].card[1] = tmp_int[8];
+        p->inventory[i].card[2] = tmp_int[9];
+        p->inventory[i].card[3] = tmp_int[10];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    next++;
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        set = sscanf (str + next, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
+                      &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
+                      &tmp_int[4], &tmp_int[5], &tmp_int[6],
+                      &tmp_int[7], &tmp_int[8], &tmp_int[9], &tmp_int[10],
+                      &len);
+        if (set != 11)
+            return 0;
+        p->cart[i].id = tmp_int[0];
+        p->cart[i].nameid = tmp_int[1];
+        p->cart[i].amount = tmp_int[2];
+        p->cart[i].equip = tmp_int[3];
+        p->cart[i].identify = tmp_int[4];
+        p->cart[i].refine = tmp_int[5];
+        p->cart[i].attribute = tmp_int[6];
+        p->cart[i].card[0] = tmp_int[7];
+        p->cart[i].card[1] = tmp_int[8];
+        p->cart[i].card[2] = tmp_int[9];
+        p->cart[i].card[3] = tmp_int[10];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    next++;
+    for (i = 0; str[next] && str[next] != '\t'; i++)
+    {
+        set = sscanf (str + next, "%d,%d%n", &tmp_int[0], &tmp_int[1], &len);
+        if (set != 2)
+            return 0;
+        p->skill[tmp_int[0]].id = tmp_int[0];
+        p->skill[tmp_int[0]].lv = tmp_int[1];
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    next++;
+    for (i = 0;
+         str[next] && str[next] != '\t' && str[next] != '\n'
+         && str[next] != '\r'; i++)
+    {                           //global_reg実装以前のathena.txt互換のため一応'\n'チェック
+        set = sscanf (str + next, "%[^,],%d%n",
+                      p->global_reg[i].str, &p->global_reg[i].value, &len);
+        if (set != 2)
+            return 0;
+        next += len;
+        if (str[next] == ' ')
+            next++;
+    }
+    p->global_reg_num = i;
+    return 1;
+}
+
+int mmo_char_convert (char *fname1, char *fname2)
+{
+    char line[65536];
+    int  ret;
+    struct mmo_charstatus char_dat;
+    FILE *ifp, *ofp;
+
+    ifp = fopen_ (fname1, "r");
+    ofp = fopen_ (fname2, "w");
+    if (ifp == NULL)
+    {
+        printf ("file not found %s\n", fname1);
+        return 0;
+    }
+    if (ofp == NULL)
+    {
+        printf ("file open error %s\n", fname2);
+        return 0;
+    }
+    while (fgets (line, 65535, ifp))
+    {
+        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
+        ret = mmo_char_fromstr (line, &char_dat);
+        if (ret)
+        {
+            mmo_char_tostr (line, &char_dat);
+            fprintf (ofp, "%s\n", line);
+        }
+    }
+    fcloseall ();
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    if (argc < 3)
+    {
+        printf ("Usage: convert <input filename> <output filename>\n");
+        exit (0);
+    }
+    mmo_char_convert (argv[1], argv[2]);
+
+    return 0;
+}
diff --git a/src/tool/eathena-monitor.c b/src/tool/eathena-monitor.c
deleted file mode 100644
index 1b1abd5..0000000
--- a/src/tool/eathena-monitor.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * Name:    eAthena processes monitor
- * Original Author:  Bartosz Waszak <waszi@evil.org.pl>
- * Rewrite Author: Ben Longbons <b.r.longbons@gmail.com>
- * License: GPL
- * Compilation:
- * gcc -o eathena-monitor eathena-monitor.c
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include <time.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#define HOME getenv("HOME")
-#define LOGIN_SERVER "./login-server"
-#define MAP_SERVER "./map-server"
-#define CHAR_SERVER "./char-server"
-#define CONFIG "conf/eathena-monitor.conf"
-#define LOGFILE "log/eathena-monitor.log"
-
-
-#define SKIP_BLANK(ptr) ptr += skip_blank(ptr)
-static inline size_t skip_blank(const char* ptr) {
-    size_t i = 0;
-    while (
-        (ptr[i] == ' ') ||
-        (ptr[i] == '\b') ||
-        (ptr[i] == '\n') ||
-        (ptr[i] == '\r')
-    ) ptr++;
-    return i;
-}
-
-#define GOTO_EQL(ptr) ptr += goto_eql(ptr)
-static inline size_t goto_eql(const char* ptr) {
-    size_t i = 0;
-    while (
-        (ptr[i] != '\0') &&
-        (ptr[i] != '=') &&
-        (ptr[i] != '\n') &&
-        (ptr[i] != '\r')
-    ) ptr++;
-    return i;
-}
-
-#define GOTO_EOL(ptr) ptr += goto_newline(ptr)
-static inline size_t goto_newline(const char* ptr) {
-    size_t i = 0;
-    while (
-        (ptr[i] != '\0') &&
-        (ptr[i] != '\n') &&
-        (ptr[i] != '\r')
-    ) ptr++;
-    return i;
-}
-
-// initialiized to $HOME/tmwserver
-const char *workdir;
-//the rest are relative to workdir
-const char *login_server = LOGIN_SERVER;
-const char *map_server = MAP_SERVER;
-const char *char_server = CHAR_SERVER;
-const char *logfile = LOGFILE;
-// this variable is hard-coded, but the command-line is checked first
-const char *config = CONFIG;
-
-pid_t pid_login, pid_map, pid_char;
-
-const char* make_path (const char* base, const char* path) {
-    size_t base_len = strlen(base);
-    size_t path_len = strlen(path);
-    char* out = (char *)malloc(base_len + 1 + path_len + 1);
-    memcpy(out, base, base_len);
-    out[base_len] = '/';
-    memcpy(out + base_len + 1, path, path_len);
-    out[base_len + 1 + path_len] = '\0';
-    return out;
-}
-
-void parse_option (char *name, char *value) {
-    if (!strcasecmp(name, "login_server")) {
-        login_server = strdup(value);
-    } else if (!strcasecmp(name, "map_server")) {
-        map_server = strdup(value);
-    } else if (!strcasecmp(name, "char_server")) {
-        char_server = strdup(value);
-    } else if (!strcasecmp(name, "workdir")) {
-        workdir = strdup(value);
-    } else if (!strcasecmp(name, "logfile")) {
-        logfile = strdup(value);
-    } else {
-        fprintf(stderr, "WARNING: ingnoring invalid option '%s' = '%s'\n", name, value);
-    }
-}
-
-void read_config(const char *filename) {
-    FILE *input;
-    char string[1000];
-
-    if (!(input = fopen(filename,"r")) && !(input = fopen (config, "r"))) {
-        perror("Unable to load config file");
-        return;
-    }
-
-    while (1) {
-        if (fgets (string, sizeof (string) - 1, input) == NULL)
-            break;
-        char *str = string, *name, *value;
-        SKIP_BLANK(str);
-        string[sizeof (string) - 1] = '\0';
-        if (*str == '#')
-            continue;
-        if (*str == '\0')
-            continue;
-        name = str;
-
-        GOTO_EQL (str);
-
-        if (*str != '=') {
-            continue;
-        }
-
-        *str++ = '\0';
-        SKIP_BLANK(str);
-        value = str;
-        GOTO_EOL(str);
-        *str = '\0';
-        parse_option(name, value);
-    }
-
-    fclose (input);
-}
-
-pid_t start_process(const char *exec) {
-    const char *args[2] = {exec, NULL};
-    pid_t pid = fork();
-    if (pid == -1) {
-        fprintf(stderr, "Failed to fork");
-        return 0;
-    }
-    if (pid == 0) {
-        execv(exec, (char**)args);
-        perror("Failed to exec");
-        kill(getppid(), SIGABRT);
-        exit(1);
-    }
-    return pid;
-}
-
-// Kill all children with the same signal we got, then ourself.
-void stop_process(int sig) {
-    if (pid_map) kill(pid_map, sig);
-    if (pid_login) kill(pid_login, sig);
-    if (pid_char) kill(pid_char, sig);
-    signal(sig, SIG_DFL);
-    raise(sig);
-}
-
-int main(int argc, char *argv[]) {
-    // These are all the signals we are likely to get
-    // The shell handles stop/cont
-    signal(SIGTERM, stop_process);
-    signal(SIGINT, stop_process);
-    signal(SIGQUIT, stop_process);
-    signal(SIGABRT, stop_process);
-
-    workdir = make_path(HOME, "tmwserver");
-
-    read_config(argc>1 ? argv[1] : NULL);
-
-    if (chdir(workdir) < 0) perror("Failed to change directory"), exit(1);
-
-    printf ("Starting:\n");
-    printf ("* workdir: %s\n",  workdir);
-    printf ("* login_server: %s\n", login_server);
-    printf ("* map_server: %s\n", map_server);
-    printf ("* char_server: %s\n", char_server);
-    {
-        //make sure all possible file descriptors are free for use by the servers
-        //if there are file descriptors higher than the max open from before the limit dropped, that's not our problem
-        int fd = sysconf(_SC_OPEN_MAX);
-        while (--fd > 2)
-           if (close(fd) == 0)
-               fprintf(stderr, "close fd %d\n", fd);
-        fd = open("/dev/null", O_RDWR);
-        if (fd < 0) perror("open /dev/null"), exit(1);
-        dup2(fd, 0);
-        dup2(fd, 1);
-        close(fd);
-    }
-    while (1) {
-        // write stuff to stderr
-        time_t t = time(NULL);
-        struct tm *tmp = localtime(&t);
-        char timestamp[256];
-        strftime(timestamp, sizeof(timestamp), "%F %T", tmp);
-
-        if (!pid_login) {
-            pid_login = start_process(login_server);
-            fprintf (stderr, "[%s] forked login server: %lu\n", timestamp, (unsigned long)pid_login);
-        }
-        if (!pid_char) {
-            pid_char = start_process(char_server);
-            fprintf (stderr, "[%s] forked char server: %lu\n", timestamp, (unsigned long)pid_char);
-        }
-        if (!pid_map) {
-            pid_map = start_process(map_server);
-            fprintf (stderr, "[%s] forked map server: %lu\n", timestamp, (unsigned long)pid_map);
-        }
-        pid_t dead = wait(NULL);
-        if (dead < 0) perror("Failed to wait for child"), exit(1);
-        if (pid_login == dead) pid_login = 0;
-        if (pid_char == dead) pid_char = 0;
-        if (pid_map == dead) pid_map = 0;
-    }
-}
diff --git a/src/tool/eathena-monitor.cpp b/src/tool/eathena-monitor.cpp
new file mode 100644
index 0000000..1b1abd5
--- /dev/null
+++ b/src/tool/eathena-monitor.cpp
@@ -0,0 +1,223 @@
+/**
+ * Name:    eAthena processes monitor
+ * Original Author:  Bartosz Waszak <waszi@evil.org.pl>
+ * Rewrite Author: Ben Longbons <b.r.longbons@gmail.com>
+ * License: GPL
+ * Compilation:
+ * gcc -o eathena-monitor eathena-monitor.c
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <time.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define HOME getenv("HOME")
+#define LOGIN_SERVER "./login-server"
+#define MAP_SERVER "./map-server"
+#define CHAR_SERVER "./char-server"
+#define CONFIG "conf/eathena-monitor.conf"
+#define LOGFILE "log/eathena-monitor.log"
+
+
+#define SKIP_BLANK(ptr) ptr += skip_blank(ptr)
+static inline size_t skip_blank(const char* ptr) {
+    size_t i = 0;
+    while (
+        (ptr[i] == ' ') ||
+        (ptr[i] == '\b') ||
+        (ptr[i] == '\n') ||
+        (ptr[i] == '\r')
+    ) ptr++;
+    return i;
+}
+
+#define GOTO_EQL(ptr) ptr += goto_eql(ptr)
+static inline size_t goto_eql(const char* ptr) {
+    size_t i = 0;
+    while (
+        (ptr[i] != '\0') &&
+        (ptr[i] != '=') &&
+        (ptr[i] != '\n') &&
+        (ptr[i] != '\r')
+    ) ptr++;
+    return i;
+}
+
+#define GOTO_EOL(ptr) ptr += goto_newline(ptr)
+static inline size_t goto_newline(const char* ptr) {
+    size_t i = 0;
+    while (
+        (ptr[i] != '\0') &&
+        (ptr[i] != '\n') &&
+        (ptr[i] != '\r')
+    ) ptr++;
+    return i;
+}
+
+// initialiized to $HOME/tmwserver
+const char *workdir;
+//the rest are relative to workdir
+const char *login_server = LOGIN_SERVER;
+const char *map_server = MAP_SERVER;
+const char *char_server = CHAR_SERVER;
+const char *logfile = LOGFILE;
+// this variable is hard-coded, but the command-line is checked first
+const char *config = CONFIG;
+
+pid_t pid_login, pid_map, pid_char;
+
+const char* make_path (const char* base, const char* path) {
+    size_t base_len = strlen(base);
+    size_t path_len = strlen(path);
+    char* out = (char *)malloc(base_len + 1 + path_len + 1);
+    memcpy(out, base, base_len);
+    out[base_len] = '/';
+    memcpy(out + base_len + 1, path, path_len);
+    out[base_len + 1 + path_len] = '\0';
+    return out;
+}
+
+void parse_option (char *name, char *value) {
+    if (!strcasecmp(name, "login_server")) {
+        login_server = strdup(value);
+    } else if (!strcasecmp(name, "map_server")) {
+        map_server = strdup(value);
+    } else if (!strcasecmp(name, "char_server")) {
+        char_server = strdup(value);
+    } else if (!strcasecmp(name, "workdir")) {
+        workdir = strdup(value);
+    } else if (!strcasecmp(name, "logfile")) {
+        logfile = strdup(value);
+    } else {
+        fprintf(stderr, "WARNING: ingnoring invalid option '%s' = '%s'\n", name, value);
+    }
+}
+
+void read_config(const char *filename) {
+    FILE *input;
+    char string[1000];
+
+    if (!(input = fopen(filename,"r")) && !(input = fopen (config, "r"))) {
+        perror("Unable to load config file");
+        return;
+    }
+
+    while (1) {
+        if (fgets (string, sizeof (string) - 1, input) == NULL)
+            break;
+        char *str = string, *name, *value;
+        SKIP_BLANK(str);
+        string[sizeof (string) - 1] = '\0';
+        if (*str == '#')
+            continue;
+        if (*str == '\0')
+            continue;
+        name = str;
+
+        GOTO_EQL (str);
+
+        if (*str != '=') {
+            continue;
+        }
+
+        *str++ = '\0';
+        SKIP_BLANK(str);
+        value = str;
+        GOTO_EOL(str);
+        *str = '\0';
+        parse_option(name, value);
+    }
+
+    fclose (input);
+}
+
+pid_t start_process(const char *exec) {
+    const char *args[2] = {exec, NULL};
+    pid_t pid = fork();
+    if (pid == -1) {
+        fprintf(stderr, "Failed to fork");
+        return 0;
+    }
+    if (pid == 0) {
+        execv(exec, (char**)args);
+        perror("Failed to exec");
+        kill(getppid(), SIGABRT);
+        exit(1);
+    }
+    return pid;
+}
+
+// Kill all children with the same signal we got, then ourself.
+void stop_process(int sig) {
+    if (pid_map) kill(pid_map, sig);
+    if (pid_login) kill(pid_login, sig);
+    if (pid_char) kill(pid_char, sig);
+    signal(sig, SIG_DFL);
+    raise(sig);
+}
+
+int main(int argc, char *argv[]) {
+    // These are all the signals we are likely to get
+    // The shell handles stop/cont
+    signal(SIGTERM, stop_process);
+    signal(SIGINT, stop_process);
+    signal(SIGQUIT, stop_process);
+    signal(SIGABRT, stop_process);
+
+    workdir = make_path(HOME, "tmwserver");
+
+    read_config(argc>1 ? argv[1] : NULL);
+
+    if (chdir(workdir) < 0) perror("Failed to change directory"), exit(1);
+
+    printf ("Starting:\n");
+    printf ("* workdir: %s\n",  workdir);
+    printf ("* login_server: %s\n", login_server);
+    printf ("* map_server: %s\n", map_server);
+    printf ("* char_server: %s\n", char_server);
+    {
+        //make sure all possible file descriptors are free for use by the servers
+        //if there are file descriptors higher than the max open from before the limit dropped, that's not our problem
+        int fd = sysconf(_SC_OPEN_MAX);
+        while (--fd > 2)
+           if (close(fd) == 0)
+               fprintf(stderr, "close fd %d\n", fd);
+        fd = open("/dev/null", O_RDWR);
+        if (fd < 0) perror("open /dev/null"), exit(1);
+        dup2(fd, 0);
+        dup2(fd, 1);
+        close(fd);
+    }
+    while (1) {
+        // write stuff to stderr
+        time_t t = time(NULL);
+        struct tm *tmp = localtime(&t);
+        char timestamp[256];
+        strftime(timestamp, sizeof(timestamp), "%F %T", tmp);
+
+        if (!pid_login) {
+            pid_login = start_process(login_server);
+            fprintf (stderr, "[%s] forked login server: %lu\n", timestamp, (unsigned long)pid_login);
+        }
+        if (!pid_char) {
+            pid_char = start_process(char_server);
+            fprintf (stderr, "[%s] forked char server: %lu\n", timestamp, (unsigned long)pid_char);
+        }
+        if (!pid_map) {
+            pid_map = start_process(map_server);
+            fprintf (stderr, "[%s] forked map server: %lu\n", timestamp, (unsigned long)pid_map);
+        }
+        pid_t dead = wait(NULL);
+        if (dead < 0) perror("Failed to wait for child"), exit(1);
+        if (pid_login == dead) pid_login = 0;
+        if (pid_char == dead) pid_char = 0;
+        if (pid_map == dead) pid_map = 0;
+    }
+}
diff --git a/src/tool/itemfrob.c b/src/tool/itemfrob.c
deleted file mode 100644
index 4651452..0000000
--- a/src/tool/itemfrob.c
+++ /dev/null
@@ -1,130 +0,0 @@
-// Compile with
-//  gcc -m32 -I src/char -I src/common charfrob.c -o charfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_pet.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "../common/mmo.h"
-// Yes, this is intentional
-#include "../char/char.c"
-
-// Well, this is not terribly elegant, but I don't have that much time.
-#define MAX_ITEM_ID 65535
-int  inv_translate[MAX_ITEM_ID];
-
-void transform_char (struct mmo_charstatus *p)
-{
-    int  k;
-    for (k = 0; k < MAX_INVENTORY; k++)
-        p->inventory[k].nameid = inv_translate[p->inventory[k].nameid];
-}
-
-int mmo_char_convert ()
-{
-    char line[965536];
-    int  ret;
-    struct mmo_charstatus char_dat;
-    FILE *ifp, *ofp;
-
-    ifp = stdin;
-    ofp = stdout;
-    while (fgets (line, 65535, ifp))
-    {
-        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
-        ret = mmo_char_fromstr (line, &char_dat);
-        if (ret)
-        {
-            transform_char (&char_dat);
-            mmo_char_tostr (line, &char_dat);
-            fprintf (ofp, "%s\n", line);
-        }
-    }
-    return 0;
-}
-
-#define PARSE_MODE_NEXTNUM 0
-#define PARSE_MODE_RANGE 1
-
-int init (char *source, char *dest)
-{
-    int  i;
-    char *end_of_num;
-    int  dest_nr = strtol (dest, &end_of_num, 0);
-    int  range_start;
-    int  mode = PARSE_MODE_NEXTNUM;
-
-    if (*end_of_num)
-    {
-        fprintf (stderr, "Invalid inventory ID: `%s'\n", dest);
-        return 1;
-    }
-
-    /* init */
-    for (i = 0; i < MAX_ITEM_ID; i++)
-        inv_translate[i] = i;
-
-    while (*source)
-    {
-        int  nr = strtol (source, &end_of_num, 0);
-        char sep;
-
-        if (end_of_num == source)
-        {
-            fprintf (stderr, "Invalid source range description: `%s'\n",
-                     source);
-            return 1;
-        }
-
-        switch (mode)
-        {
-            case PARSE_MODE_NEXTNUM:
-                inv_translate[nr] = dest_nr;
-                break;
-            case PARSE_MODE_RANGE:
-                for (i = range_start; i <= nr; i++)
-                    inv_translate[i] = dest_nr;
-                break;
-            default:
-                fprintf (stderr, "Internal error at %d\n", __LINE__);
-                return 1;
-        };
-
-        sep = *end_of_num++;
-
-        switch (sep)
-        {
-            case '-':
-                range_start = nr;
-                mode = PARSE_MODE_RANGE;
-                break;
-            case ',':
-                mode = PARSE_MODE_NEXTNUM;
-                break;
-            case 0:
-                return 0;
-            default:
-                fprintf (stderr, "Invalid token in range spec: `%c'\n", sep);
-                return 1;
-        }
-
-        source = end_of_num;
-    }
-    return 0;
-}
-
-int main (int argc, char *argv[])
-{
-    if (argc < 3)
-    {
-        printf
-            ("Usage: %s <inventory ID input range> <inventory ID output>\n",
-             argv[0]);
-        printf ("e.g., %s 501-555 701\n", argv[0]);
-        exit (0);
-    }
-    if (init (argv[1], argv[2]))
-        return 1;
-
-    mmo_char_convert ();
-
-    return 0;
-}
diff --git a/src/tool/itemfrob.cpp b/src/tool/itemfrob.cpp
new file mode 100644
index 0000000..81638eb
--- /dev/null
+++ b/src/tool/itemfrob.cpp
@@ -0,0 +1,130 @@
+// Compile with
+//  gcc -m32 -I src/char -I src/common charfrob.c -o charfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_pet.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../common/mmo.hpp"
+// Yes, this is intentional
+#include "../char/char.cpp"
+
+// Well, this is not terribly elegant, but I don't have that much time.
+#define MAX_ITEM_ID 65535
+int  inv_translate[MAX_ITEM_ID];
+
+void transform_char (struct mmo_charstatus *p)
+{
+    int  k;
+    for (k = 0; k < MAX_INVENTORY; k++)
+        p->inventory[k].nameid = inv_translate[p->inventory[k].nameid];
+}
+
+int mmo_char_convert ()
+{
+    char line[965536];
+    int  ret;
+    struct mmo_charstatus char_dat;
+    FILE *ifp, *ofp;
+
+    ifp = stdin;
+    ofp = stdout;
+    while (fgets (line, 65535, ifp))
+    {
+        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
+        ret = mmo_char_fromstr (line, &char_dat);
+        if (ret)
+        {
+            transform_char (&char_dat);
+            mmo_char_tostr (line, &char_dat);
+            fprintf (ofp, "%s\n", line);
+        }
+    }
+    return 0;
+}
+
+#define PARSE_MODE_NEXTNUM 0
+#define PARSE_MODE_RANGE 1
+
+int init (char *source, char *dest)
+{
+    int  i;
+    char *end_of_num;
+    int  dest_nr = strtol (dest, &end_of_num, 0);
+    int  range_start;
+    int  mode = PARSE_MODE_NEXTNUM;
+
+    if (*end_of_num)
+    {
+        fprintf (stderr, "Invalid inventory ID: `%s'\n", dest);
+        return 1;
+    }
+
+    /* init */
+    for (i = 0; i < MAX_ITEM_ID; i++)
+        inv_translate[i] = i;
+
+    while (*source)
+    {
+        int  nr = strtol (source, &end_of_num, 0);
+        char sep;
+
+        if (end_of_num == source)
+        {
+            fprintf (stderr, "Invalid source range description: `%s'\n",
+                     source);
+            return 1;
+        }
+
+        switch (mode)
+        {
+            case PARSE_MODE_NEXTNUM:
+                inv_translate[nr] = dest_nr;
+                break;
+            case PARSE_MODE_RANGE:
+                for (i = range_start; i <= nr; i++)
+                    inv_translate[i] = dest_nr;
+                break;
+            default:
+                fprintf (stderr, "Internal error at %d\n", __LINE__);
+                return 1;
+        };
+
+        sep = *end_of_num++;
+
+        switch (sep)
+        {
+            case '-':
+                range_start = nr;
+                mode = PARSE_MODE_RANGE;
+                break;
+            case ',':
+                mode = PARSE_MODE_NEXTNUM;
+                break;
+            case 0:
+                return 0;
+            default:
+                fprintf (stderr, "Invalid token in range spec: `%c'\n", sep);
+                return 1;
+        }
+
+        source = end_of_num;
+    }
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    if (argc < 3)
+    {
+        printf
+            ("Usage: %s <inventory ID input range> <inventory ID output>\n",
+             argv[0]);
+        printf ("e.g., %s 501-555 701\n", argv[0]);
+        exit (0);
+    }
+    if (init (argv[1], argv[2]))
+        return 1;
+
+    mmo_char_convert ();
+
+    return 0;
+}
diff --git a/src/tool/mapfrob.c b/src/tool/mapfrob.c
deleted file mode 100644
index 9dc1a5b..0000000
--- a/src/tool/mapfrob.c
+++ /dev/null
@@ -1,129 +0,0 @@
-// Compile with
-//  gcc -m32 -I src/char -I src/common charfrob.c -o charfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_pet.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "../common/mmo.h"
-// Yes, this is intentional
-#include "../char/char.c"
-
-// Well, this is not terribly elegant, but I don't have that much time.
-#define MAX_MAP 1024
-#define MAP_NAME_SIZE 32
-int  maps_nr = 0;
-struct
-{
-    char old[MAP_NAME_SIZE], new[MAP_NAME_SIZE];
-} maps[MAX_MAP];
-
-void transform_point (struct point *p)
-{
-    int  k;
-
-    if (!p->map[0])
-        return;
-
-    for (k = 0; k < maps_nr; k++)
-        if (!strcmp (p->map, maps[k].old))
-        {
-            strcpy (p->map, maps[k].new);
-            return;
-        }
-
-    fprintf (stderr, "Warning: untranslated map `%s'\n", p->map);
-}
-
-void transform_char (struct mmo_charstatus *p)
-{
-    int  i;
-
-    transform_point (&p->last_point);
-    transform_point (&p->save_point);
-
-    for (i = 0; i < 10; i++)
-        transform_point (&p->memo_point[i]);
-}
-
-int mmo_char_convert ()
-{
-    char line[965536];
-    int  ret;
-    struct mmo_charstatus char_dat;
-    FILE *ifp, *ofp;
-
-    ifp = stdin;
-    ofp = stdout;
-    while (fgets (line, 65535, ifp))
-    {
-        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
-        ret = mmo_char_fromstr (line, &char_dat);
-        if (ret)
-        {
-            transform_char (&char_dat);
-            mmo_char_tostr (line, &char_dat);
-            fprintf (ofp, "%s\n", line);
-        }
-    }
-    return 0;
-}
-
-#define PARSE_MODE_NEXTNUM 0
-#define PARSE_MODE_RANGE 1
-
-int init (int count, char **translates)
-{
-    int  i;
-    char *suffix = ".gat";
-
-    for (i = 0; i < count; i++)
-    {
-        char *src = translates[i];
-        char *dest = strchr (src, ':');
-
-        if (!dest)
-        {
-            fprintf (stderr, "Missing colon in: `%s'\n", src);
-            return 1;
-        }
-
-        *dest++ = 0;
-
-        if (strlen (src) + strlen (suffix) >= MAP_NAME_SIZE)
-        {
-            fprintf (stderr, "Map name prefix too long: `%s'\n", src);
-            return 1;
-        }
-
-        if (strlen (dest) + strlen (suffix) >= MAP_NAME_SIZE)
-        {
-            fprintf (stderr, "Map name prefix too long: `%s'\n", dest);
-            return 1;
-        }
-
-        strncpy (maps[maps_nr].old, src, MAP_NAME_SIZE);
-        strcat (maps[maps_nr].old, suffix);
-        strncpy (maps[maps_nr].new, dest, MAP_NAME_SIZE);
-        strcat (maps[maps_nr].new, suffix);
-
-        ++maps_nr;
-    }
-
-    return 0;
-}
-
-int main (int argc, char *argv[])
-{
-    if (argc < 2)
-    {
-        printf ("Usage: %s oldmap0:newmap0 oldmap1:newmap1 ...\n", argv[0]);
-        printf ("e.g., %s new_1-1:001-2 new_2-1:001-1\n", argv[0]);
-        puts ("The extension `.gat' is appended implicitly.");
-        exit (0);
-    }
-    if (init (argc - 1, argv + 1))
-        return 1;
-
-    mmo_char_convert ();
-
-    return 0;
-}
diff --git a/src/tool/mapfrob.cpp b/src/tool/mapfrob.cpp
new file mode 100644
index 0000000..8663ae0
--- /dev/null
+++ b/src/tool/mapfrob.cpp
@@ -0,0 +1,129 @@
+// Compile with
+//  gcc -m32 -I src/char -I src/common charfrob.c -o charfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_pet.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../common/mmo.hpp"
+// Yes, this is intentional
+#include "../char/char.cpp"
+
+// Well, this is not terribly elegant, but I don't have that much time.
+#define MAX_MAP 1024
+#define MAP_NAME_SIZE 32
+int  maps_nr = 0;
+struct
+{
+    char old[MAP_NAME_SIZE], new[MAP_NAME_SIZE];
+} maps[MAX_MAP];
+
+void transform_point (struct point *p)
+{
+    int  k;
+
+    if (!p->map[0])
+        return;
+
+    for (k = 0; k < maps_nr; k++)
+        if (!strcmp (p->map, maps[k].old))
+        {
+            strcpy (p->map, maps[k].new);
+            return;
+        }
+
+    fprintf (stderr, "Warning: untranslated map `%s'\n", p->map);
+}
+
+void transform_char (struct mmo_charstatus *p)
+{
+    int  i;
+
+    transform_point (&p->last_point);
+    transform_point (&p->save_point);
+
+    for (i = 0; i < 10; i++)
+        transform_point (&p->memo_point[i]);
+}
+
+int mmo_char_convert ()
+{
+    char line[965536];
+    int  ret;
+    struct mmo_charstatus char_dat;
+    FILE *ifp, *ofp;
+
+    ifp = stdin;
+    ofp = stdout;
+    while (fgets (line, 65535, ifp))
+    {
+        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
+        ret = mmo_char_fromstr (line, &char_dat);
+        if (ret)
+        {
+            transform_char (&char_dat);
+            mmo_char_tostr (line, &char_dat);
+            fprintf (ofp, "%s\n", line);
+        }
+    }
+    return 0;
+}
+
+#define PARSE_MODE_NEXTNUM 0
+#define PARSE_MODE_RANGE 1
+
+int init (int count, char **translates)
+{
+    int  i;
+    char *suffix = ".gat";
+
+    for (i = 0; i < count; i++)
+    {
+        char *src = translates[i];
+        char *dest = strchr (src, ':');
+
+        if (!dest)
+        {
+            fprintf (stderr, "Missing colon in: `%s'\n", src);
+            return 1;
+        }
+
+        *dest++ = 0;
+
+        if (strlen (src) + strlen (suffix) >= MAP_NAME_SIZE)
+        {
+            fprintf (stderr, "Map name prefix too long: `%s'\n", src);
+            return 1;
+        }
+
+        if (strlen (dest) + strlen (suffix) >= MAP_NAME_SIZE)
+        {
+            fprintf (stderr, "Map name prefix too long: `%s'\n", dest);
+            return 1;
+        }
+
+        strncpy (maps[maps_nr].old, src, MAP_NAME_SIZE);
+        strcat (maps[maps_nr].old, suffix);
+        strncpy (maps[maps_nr].new, dest, MAP_NAME_SIZE);
+        strcat (maps[maps_nr].new, suffix);
+
+        ++maps_nr;
+    }
+
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    if (argc < 2)
+    {
+        printf ("Usage: %s oldmap0:newmap0 oldmap1:newmap1 ...\n", argv[0]);
+        printf ("e.g., %s new_1-1:001-2 new_2-1:001-1\n", argv[0]);
+        puts ("The extension `.gat' is appended implicitly.");
+        exit (0);
+    }
+    if (init (argc - 1, argv + 1))
+        return 1;
+
+    mmo_char_convert ();
+
+    return 0;
+}
diff --git a/src/tool/marriage-info.c b/src/tool/marriage-info.c
deleted file mode 100644
index 4d7cbc3..0000000
--- a/src/tool/marriage-info.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/* To build:
-gcc -O2 -m32 -Isrc/common -Isrc/char -Isrc/map -Isrc/login -o marriage-info \
-marriage-info.c src/common/socket.o src/common/timer.o src/common/db.o \
-src/common/lock.o src/common/malloc.o src/char/int_guild.o \
-src/char/int_party.o src/char/int_storage.o src/char/inter.o
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "../login/login.h"
-#include "../common/mmo.h"
-// Yes, this is intentional
-#include "../char/char.c"
-
-int mode;
-#define MODE_MARRIED	0
-#define MODE_SINGLES_F	1
-#define MODE_SINGLES_M	2
-#define MODE_SINGLES_A	3	
-
-#define CHUNK_SIZE 1024
-
-/* chunked list to represent leaves */
-typedef struct {
-        int char_id;
-        int exp;
-        char name[24];
-        unsigned char level;
-        unsigned char sex;
-} char_leaf_t;
-
-/* Chunks are in descending order, but chars are in ascending order */
-typedef struct chunklist_node {
-        int size;
-        char_leaf_t chars[CHUNK_SIZE];
-        struct chunklist_node *next;
-} chunklist_node_t;
-
-chunklist_node_t *list = NULL;
-
-static void
-insert(chunklist_node_t **listp, struct mmo_charstatus *p)
-{
-        chunklist_node_t *chunk = *listp;
-        char_leaf_t *l;
-
-        if ((chunk && chunk->size == CHUNK_SIZE)
-            || (!chunk)) {
-                chunk = malloc(sizeof(chunklist_node_t));
-                chunk->size = 0;
-                chunk->next = *listp;
-                *listp = chunk;
-        }
-
-        l = &chunk->chars[chunk->size++];
-
-        l->char_id = p->char_id;
-        l->level = p->base_level;
-        l->exp = p->base_exp;
-        l->sex = p->sex;
-        strcpy(l->name, p->name);
-}
-
-static int
-compare_leaf(const void *l, const void *r)
-{
-        return ((char_leaf_t *)l)->char_id - ((char_leaf_t *)r)->char_id;
-}
-
-static char_leaf_t *
-find(chunklist_node_t *list, int char_id)
-{
-        if (!list)
-                return NULL; /*  fatal error */
-        else {
-                int start = list->chars[0].char_id;
-                int stop = list->chars[list->size - 1].char_id;
-
-                if (char_id >= start && char_id <= stop) { /* in this chunk */
-                        char_leaf_t key;
-                        key.char_id = char_id;
-                        return (char_leaf_t *)
-                                bsearch(&key, &list->chars, list->size, sizeof(char_leaf_t),
-                                        compare_leaf);
-                }
-                else find(list->next, char_id);
-        }
-}
-
-
-void /* replace blanks with percent signs */
-namefrob(char *n)
-{
-        while (*n++) /*  can't start with a blank */
-                if (*n == ' ')
-                        *n = '%';
-}
-
-/*
---------------------------------------------------------------------------------
- Copied and pasted due to lacking modularity
-*/
-
-char account_filename[1024] = "save/account.txt";
-int account_id_count = START_ACCOUNT_NUM;
-
-struct auth_dat {
-	int account_id, sex;
-	char userid[24], pass[24], lastlogin[24];
-	int logincount;
-	int state;
-	char email[40];
-	char error_message[20];
-	time_t ban_until_time; 
-	time_t connect_until_time;
-	char last_ip[16];
-	char memo[255];
-	int account_reg2_num;
-	struct global_reg account_reg2[ACCOUNT_REG2_NUM];
-} *auth_dat;
-
-int auth_num = 0, auth_max = 0;
-
-
-/*
- Reading of the accounts database
-*/
-int mmo_auth_init(void) {
-	FILE *fp;
-	int account_id, logincount, state, n, i, j, v;
-	char line[2048], *p, userid[2048], pass[2048], lastlogin[2048], sex, email[2048], error_message[2048], last_ip[2048], memo[2048];
-	time_t ban_until_time;
-	time_t connect_until_time;
-	char str[2048];
-	int GM_count = 0;
-	int server_count = 0;
-
-	auth_dat = calloc(sizeof(struct auth_dat) * 256, 1);
-	auth_max = 256;
-
-	fp = fopen(account_filename, "r");
-	if (fp == NULL) {
-		printf("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n", account_filename);
-		return 0;
-	}
-
-	while(fgets(line, sizeof(line)-1, fp) != NULL) {
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-		line[sizeof(line)-1] = '\0';
-		p = line;
-
-		if (((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
-		                 "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n",
-		    &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
-		    email, error_message, &connect_until_time, last_ip, memo, &ban_until_time, &n)) == 13 && line[n] == '\t') ||
-		    ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
-		                 "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]%n",
-		    &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
-		    email, error_message, &connect_until_time, last_ip, memo, &n)) == 12 && line[n] == '\t')) {
-			n = n + 1;
-
-			if (account_id > END_ACCOUNT_NUM) {
-				continue;
-			}
-			userid[23] = '\0';
-			remove_control_chars(userid);
-			for(j = 0; j < auth_num; j++) {
-				if (auth_dat[j].account_id == account_id) {
-					break;
-				} else if (strcmp(auth_dat[j].userid, userid) == 0) {
-					break;
-				}
-			}
-			if (j != auth_num)
-				continue;
-
-			if (auth_num >= auth_max) {
-				auth_max += 256;
-				auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max);
-			}
-
-			memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
-
-			auth_dat[auth_num].account_id = account_id;
-
-			strncpy(auth_dat[auth_num].userid, userid, 24);
-
-			pass[23] = '\0';
-			remove_control_chars(pass);
-			strncpy(auth_dat[auth_num].pass, pass, 24);
-
-			lastlogin[23] = '\0';
-			remove_control_chars(lastlogin);
-			strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
-
-			auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
-
-			if (logincount >= 0)
-				auth_dat[auth_num].logincount = logincount;
-			else
-				auth_dat[auth_num].logincount = 0;
-
-			if (state > 255)
-				auth_dat[auth_num].state = 100;
-			else if (state < 0)
-				auth_dat[auth_num].state = 0;
-			else
-				auth_dat[auth_num].state = state;
-
-			if (e_mail_check(email) == 0) {
-				strncpy(auth_dat[auth_num].email, "a@a.com", 40);
-			} else {
-				remove_control_chars(email);
-				strncpy(auth_dat[auth_num].email, email, 40);
-			}
-
-			error_message[19] = '\0';
-			remove_control_chars(error_message);
-			if (error_message[0] == '\0' || state != 7) {
-				strncpy(auth_dat[auth_num].error_message, "-", 20);
-			} else {
-				strncpy(auth_dat[auth_num].error_message, error_message, 20);
-			}
-
-			if (i == 13)
-				auth_dat[auth_num].ban_until_time = ban_until_time;
-			else
-				auth_dat[auth_num].ban_until_time = 0;
-
-			auth_dat[auth_num].connect_until_time = connect_until_time;
-
-			last_ip[15] = '\0';
-			remove_control_chars(last_ip);
-			strncpy(auth_dat[auth_num].last_ip, last_ip, 16);
-
-			memo[254] = '\0';
-			remove_control_chars(memo);
-			strncpy(auth_dat[auth_num].memo, memo, 255);
-
-			for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
-				p += n;
-				if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
-					if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
-						j--;
-						continue;
-					} else
-						break;
-				}
-				str[31] = '\0';
-				remove_control_chars(str);
-				strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
-				auth_dat[auth_num].account_reg2[j].value = v;
-			}
-			auth_dat[auth_num].account_reg2_num = j;
-
-			if (isGM(account_id) > 0)
-				GM_count++;
-			if (auth_dat[auth_num].sex == 2)
-				server_count++;
-
-			auth_num++;
-			if (account_id >= account_id_count)
-				account_id_count = account_id + 1;
-
-		} else if ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
-		           &account_id, userid, pass, lastlogin, &sex, &logincount, &state, &n)) >= 5) {
-			if (account_id > END_ACCOUNT_NUM) {
-				continue;
-			}
-			userid[23] = '\0';
-			remove_control_chars(userid);
-			for(j = 0; j < auth_num; j++) {
-				if (auth_dat[j].account_id == account_id) {
-					break;
-				} else if (strcmp(auth_dat[j].userid, userid) == 0) {
-					break;
-				}
-			}
-			if (j != auth_num)
-				continue;
-
-			if (auth_num >= auth_max) {
-				auth_max += 256;
-				auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max);
-			}
-
-			memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
-
-			auth_dat[auth_num].account_id = account_id;
-
-			strncpy(auth_dat[auth_num].userid, userid, 24);
-
-			pass[23] = '\0';
-			remove_control_chars(pass);
-			strncpy(auth_dat[auth_num].pass, pass, 24);
-
-			lastlogin[23] = '\0';
-			remove_control_chars(lastlogin);
-			strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
-
-			auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
-
-			if (i >= 6) {
-				if (logincount >= 0)
-					auth_dat[auth_num].logincount = logincount;
-				else
-					auth_dat[auth_num].logincount = 0;
-			} else
-				auth_dat[auth_num].logincount = 0;
-
-			if (i >= 7) {
-				if (state > 255)
-					auth_dat[auth_num].state = 100;
-				else if (state < 0)
-					auth_dat[auth_num].state = 0;
-				else
-					auth_dat[auth_num].state = state;
-			} else
-				auth_dat[auth_num].state = 0;
-
-			strncpy(auth_dat[auth_num].email, "a@a.com", 40);
-			strncpy(auth_dat[auth_num].error_message, "-", 20);
-			auth_dat[auth_num].ban_until_time = 0;
-			auth_dat[auth_num].connect_until_time = 0;
-			strncpy(auth_dat[auth_num].last_ip, "-", 16);
-			strncpy(auth_dat[auth_num].memo, "-", 255);
-
-			for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
-				p += n;
-				if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
-					if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
-						j--;
-						continue;
-					} else
-						break;
-				}
-				str[31] = '\0';
-				remove_control_chars(str);
-				strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
-				auth_dat[auth_num].account_reg2[j].value = v;
-			}
-			auth_dat[auth_num].account_reg2_num = j;
-
-			if (isGM(account_id) > 0)
-				GM_count++;
-			if (auth_dat[auth_num].sex == 2)
-				server_count++;
-
-			auth_num++;
-			if (account_id >= account_id_count)
-				account_id_count = account_id + 1;
-
-		} else {
-			i = 0;
-			if (sscanf(line, "%d\t%%newid%%\n%n", &account_id, &i) == 1 &&
-			    i > 0 && account_id > account_id_count)
-				account_id_count = account_id;
-		}
-	}
-	fclose(fp);
-
-	if (auth_num == 0) {
-		sprintf(line, "No account found in %s.", account_filename);
-	} else {
-		if (auth_num == 1) {
-			sprintf(line, "1 account read in %s,", account_filename);
-		} else {
-			sprintf(line, "%d accounts read in %s,", auth_num, account_filename);
-		}
-		if (GM_count == 0) {
-			sprintf(str, "%s of which is no GM account and", line);
-		} else if (GM_count == 1) {
-			sprintf(str, "%s of which is 1 GM account and", line);
-		} else {
-			sprintf(str, "%s of which is %d GM accounts and", line, GM_count);
-		}
-		if (server_count == 0) {
-			sprintf(line, "%s no server account ('S').", str);
-		} else if (server_count == 1) {
-			sprintf(line, "%s 1 server account ('S').", str);
-		} else {
-			sprintf(line, "%s %d server accounts ('S').", str, server_count);
-		}
-	}
-
-	return 0;
-}
-
-/*--------------------------------------------------------------------------------*/
-
-
-void
-mmo_check_dumpworthy(struct mmo_charstatus *p)
-{
-        int i;
-        namefrob(p->name);
-
-        for (i = 0; i < auth_num; i++)
-                if (auth_dat[i].account_id == p->account_id) {
-                        p->sex = auth_dat[i].sex;
-                        break;
-                }
-
-        if (p->partner_id) {
-                if (mode != MODE_MARRIED)
-                        return;
-
-                if (p->partner_id < p->char_id) {
-                        char_leaf_t *partner = find(list, p->partner_id);
-                        if (!partner)
-                                fprintf(stderr, "Char %d (%s)'s partner (%d) no longer available\n",
-                                        p->char_id,
-                                        p->name,
-                                        p->partner_id);
-                        else
-                                printf ("%d\t%d\t%s\t%s\t%d\t%s\t%s\t%d--%d,%d\n",
-                                        p->base_level + partner->level,
-                                        p->base_exp + partner->exp,
-                                        p->name, p->sex? "M" : "F", p->base_level,
-                                        partner->name, partner->sex? "M" : "F", partner->level);
-                } else {
-                        insert(&list, p);
-                }
-        } else if (p->sex == (mode - 1))
-                        printf("%d\t%d\t%s\n", p->base_level, p->base_exp, p->name);
-        else if (mode == MODE_SINGLES_A)
-                        printf("%d\t%d\t%s\t%s\n", p->base_level, p->base_exp, p->name, p->sex? "M" : "F");
-}
-
-int mmo_char_dump()
-{
-        char line[965536];
-        int ret;
-	struct mmo_charstatus char_dat;
-        FILE *ifp,*ofp;
-
-	ifp=stdin;
-        while(fgets(line,65535,ifp)){
-                memset(&char_dat,0,sizeof(struct mmo_charstatus));
-                ret=mmo_char_fromstr(line,&char_dat);
-                if(ret){
-                        mmo_check_dumpworthy(&char_dat);
-                }
-        }
-        return 0;
-}
-
-
-int init(char *mode_s)
-{
-        if (!strcmp(mode_s, "-c"))
-                mode = MODE_MARRIED;
-        else if (!strcmp(mode_s, "-f"))
-                mode = MODE_SINGLES_F;
-        else if (!strcmp(mode_s, "-m"))
-                mode = MODE_SINGLES_M;
-        else if (!strcmp(mode_s, "-s"))
-                mode = MODE_SINGLES_A;
-        else {
-                fprintf(stderr, "Unknown mode `%s'\n", mode_s);
-                return 1;
-        }
-        return 0;
-}
-
-int main(int argc,char *argv[])
-{
-        mmo_auth_init();
-
-	if(argc < 2) {
-		printf("Usage: %s <mode>\n", argv[0]);
-                printf("Where <mode> is one of -c (couples), -s (singles), -f (female singles), -m (male singles)\n", argv[0]);
-		exit(0);
-	}
-        if (init(argv[1]))
-                return 1;
-
-	mmo_char_dump();
-
-	return 0;
-}
diff --git a/src/tool/marriage-info.cpp b/src/tool/marriage-info.cpp
new file mode 100644
index 0000000..3552a9b
--- /dev/null
+++ b/src/tool/marriage-info.cpp
@@ -0,0 +1,482 @@
+/* To build:
+gcc -O2 -m32 -Isrc/common -Isrc/char -Isrc/map -Isrc/login -o marriage-info \
+marriage-info.c src/common/socket.o src/common/timer.o src/common/db.o \
+src/common/lock.o src/common/malloc.o src/char/int_guild.o \
+src/char/int_party.o src/char/int_storage.o src/char/inter.o
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../login/login.hpp"
+#include "../common/mmo.hpp"
+// Yes, this is intentional
+#include "../char/char.cpp"
+
+int mode;
+#define MODE_MARRIED	0
+#define MODE_SINGLES_F	1
+#define MODE_SINGLES_M	2
+#define MODE_SINGLES_A	3	
+
+#define CHUNK_SIZE 1024
+
+/* chunked list to represent leaves */
+typedef struct {
+        int char_id;
+        int exp;
+        char name[24];
+        unsigned char level;
+        unsigned char sex;
+} char_leaf_t;
+
+/* Chunks are in descending order, but chars are in ascending order */
+typedef struct chunklist_node {
+        int size;
+        char_leaf_t chars[CHUNK_SIZE];
+        struct chunklist_node *next;
+} chunklist_node_t;
+
+chunklist_node_t *list = NULL;
+
+static void
+insert(chunklist_node_t **listp, struct mmo_charstatus *p)
+{
+        chunklist_node_t *chunk = *listp;
+        char_leaf_t *l;
+
+        if ((chunk && chunk->size == CHUNK_SIZE)
+            || (!chunk)) {
+                chunk = malloc(sizeof(chunklist_node_t));
+                chunk->size = 0;
+                chunk->next = *listp;
+                *listp = chunk;
+        }
+
+        l = &chunk->chars[chunk->size++];
+
+        l->char_id = p->char_id;
+        l->level = p->base_level;
+        l->exp = p->base_exp;
+        l->sex = p->sex;
+        strcpy(l->name, p->name);
+}
+
+static int
+compare_leaf(const void *l, const void *r)
+{
+        return ((char_leaf_t *)l)->char_id - ((char_leaf_t *)r)->char_id;
+}
+
+static char_leaf_t *
+find(chunklist_node_t *list, int char_id)
+{
+        if (!list)
+                return NULL; /*  fatal error */
+        else {
+                int start = list->chars[0].char_id;
+                int stop = list->chars[list->size - 1].char_id;
+
+                if (char_id >= start && char_id <= stop) { /* in this chunk */
+                        char_leaf_t key;
+                        key.char_id = char_id;
+                        return (char_leaf_t *)
+                                bsearch(&key, &list->chars, list->size, sizeof(char_leaf_t),
+                                        compare_leaf);
+                }
+                else find(list->next, char_id);
+        }
+}
+
+
+void /* replace blanks with percent signs */
+namefrob(char *n)
+{
+        while (*n++) /*  can't start with a blank */
+                if (*n == ' ')
+                        *n = '%';
+}
+
+/*
+--------------------------------------------------------------------------------
+ Copied and pasted due to lacking modularity
+*/
+
+char account_filename[1024] = "save/account.txt";
+int account_id_count = START_ACCOUNT_NUM;
+
+struct auth_dat {
+	int account_id, sex;
+	char userid[24], pass[24], lastlogin[24];
+	int logincount;
+	int state;
+	char email[40];
+	char error_message[20];
+	time_t ban_until_time; 
+	time_t connect_until_time;
+	char last_ip[16];
+	char memo[255];
+	int account_reg2_num;
+	struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+} *auth_dat;
+
+int auth_num = 0, auth_max = 0;
+
+
+/*
+ Reading of the accounts database
+*/
+int mmo_auth_init(void) {
+	FILE *fp;
+	int account_id, logincount, state, n, i, j, v;
+	char line[2048], *p, userid[2048], pass[2048], lastlogin[2048], sex, email[2048], error_message[2048], last_ip[2048], memo[2048];
+	time_t ban_until_time;
+	time_t connect_until_time;
+	char str[2048];
+	int GM_count = 0;
+	int server_count = 0;
+
+	auth_dat = calloc(sizeof(struct auth_dat) * 256, 1);
+	auth_max = 256;
+
+	fp = fopen(account_filename, "r");
+	if (fp == NULL) {
+		printf("\033[1;31mmmo_auth_init: Accounts file [%s] not found.\033[0m\n", account_filename);
+		return 0;
+	}
+
+	while(fgets(line, sizeof(line)-1, fp) != NULL) {
+		if (line[0] == '/' && line[1] == '/')
+			continue;
+		line[sizeof(line)-1] = '\0';
+		p = line;
+
+		if (((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
+		                 "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]\t%ld%n",
+		    &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
+		    email, error_message, &connect_until_time, last_ip, memo, &ban_until_time, &n)) == 13 && line[n] == '\t') ||
+		    ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t"
+		                 "%[^\t]\t%[^\t]\t%ld\t%[^\t]\t%[^\t]%n",
+		    &account_id, userid, pass, lastlogin, &sex, &logincount, &state,
+		    email, error_message, &connect_until_time, last_ip, memo, &n)) == 12 && line[n] == '\t')) {
+			n = n + 1;
+
+			if (account_id > END_ACCOUNT_NUM) {
+				continue;
+			}
+			userid[23] = '\0';
+			remove_control_chars(userid);
+			for(j = 0; j < auth_num; j++) {
+				if (auth_dat[j].account_id == account_id) {
+					break;
+				} else if (strcmp(auth_dat[j].userid, userid) == 0) {
+					break;
+				}
+			}
+			if (j != auth_num)
+				continue;
+
+			if (auth_num >= auth_max) {
+				auth_max += 256;
+				auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max);
+			}
+
+			memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
+
+			auth_dat[auth_num].account_id = account_id;
+
+			strncpy(auth_dat[auth_num].userid, userid, 24);
+
+			pass[23] = '\0';
+			remove_control_chars(pass);
+			strncpy(auth_dat[auth_num].pass, pass, 24);
+
+			lastlogin[23] = '\0';
+			remove_control_chars(lastlogin);
+			strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
+
+			auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
+
+			if (logincount >= 0)
+				auth_dat[auth_num].logincount = logincount;
+			else
+				auth_dat[auth_num].logincount = 0;
+
+			if (state > 255)
+				auth_dat[auth_num].state = 100;
+			else if (state < 0)
+				auth_dat[auth_num].state = 0;
+			else
+				auth_dat[auth_num].state = state;
+
+			if (e_mail_check(email) == 0) {
+				strncpy(auth_dat[auth_num].email, "a@a.com", 40);
+			} else {
+				remove_control_chars(email);
+				strncpy(auth_dat[auth_num].email, email, 40);
+			}
+
+			error_message[19] = '\0';
+			remove_control_chars(error_message);
+			if (error_message[0] == '\0' || state != 7) {
+				strncpy(auth_dat[auth_num].error_message, "-", 20);
+			} else {
+				strncpy(auth_dat[auth_num].error_message, error_message, 20);
+			}
+
+			if (i == 13)
+				auth_dat[auth_num].ban_until_time = ban_until_time;
+			else
+				auth_dat[auth_num].ban_until_time = 0;
+
+			auth_dat[auth_num].connect_until_time = connect_until_time;
+
+			last_ip[15] = '\0';
+			remove_control_chars(last_ip);
+			strncpy(auth_dat[auth_num].last_ip, last_ip, 16);
+
+			memo[254] = '\0';
+			remove_control_chars(memo);
+			strncpy(auth_dat[auth_num].memo, memo, 255);
+
+			for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
+				p += n;
+				if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
+					if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
+						j--;
+						continue;
+					} else
+						break;
+				}
+				str[31] = '\0';
+				remove_control_chars(str);
+				strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
+				auth_dat[auth_num].account_reg2[j].value = v;
+			}
+			auth_dat[auth_num].account_reg2_num = j;
+
+			if (isGM(account_id) > 0)
+				GM_count++;
+			if (auth_dat[auth_num].sex == 2)
+				server_count++;
+
+			auth_num++;
+			if (account_id >= account_id_count)
+				account_id_count = account_id + 1;
+
+		} else if ((i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%n",
+		           &account_id, userid, pass, lastlogin, &sex, &logincount, &state, &n)) >= 5) {
+			if (account_id > END_ACCOUNT_NUM) {
+				continue;
+			}
+			userid[23] = '\0';
+			remove_control_chars(userid);
+			for(j = 0; j < auth_num; j++) {
+				if (auth_dat[j].account_id == account_id) {
+					break;
+				} else if (strcmp(auth_dat[j].userid, userid) == 0) {
+					break;
+				}
+			}
+			if (j != auth_num)
+				continue;
+
+			if (auth_num >= auth_max) {
+				auth_max += 256;
+				auth_dat = realloc(auth_dat, sizeof(struct auth_dat) * auth_max);
+			}
+
+			memset(&auth_dat[auth_num], '\0', sizeof(struct auth_dat));
+
+			auth_dat[auth_num].account_id = account_id;
+
+			strncpy(auth_dat[auth_num].userid, userid, 24);
+
+			pass[23] = '\0';
+			remove_control_chars(pass);
+			strncpy(auth_dat[auth_num].pass, pass, 24);
+
+			lastlogin[23] = '\0';
+			remove_control_chars(lastlogin);
+			strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24);
+
+			auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
+
+			if (i >= 6) {
+				if (logincount >= 0)
+					auth_dat[auth_num].logincount = logincount;
+				else
+					auth_dat[auth_num].logincount = 0;
+			} else
+				auth_dat[auth_num].logincount = 0;
+
+			if (i >= 7) {
+				if (state > 255)
+					auth_dat[auth_num].state = 100;
+				else if (state < 0)
+					auth_dat[auth_num].state = 0;
+				else
+					auth_dat[auth_num].state = state;
+			} else
+				auth_dat[auth_num].state = 0;
+
+			strncpy(auth_dat[auth_num].email, "a@a.com", 40);
+			strncpy(auth_dat[auth_num].error_message, "-", 20);
+			auth_dat[auth_num].ban_until_time = 0;
+			auth_dat[auth_num].connect_until_time = 0;
+			strncpy(auth_dat[auth_num].last_ip, "-", 16);
+			strncpy(auth_dat[auth_num].memo, "-", 255);
+
+			for(j = 0; j < ACCOUNT_REG2_NUM; j++) {
+				p += n;
+				if (sscanf(p, "%[^\t,],%d %n", str, &v, &n) != 2) {
+					if (p[0] == ',' && sscanf(p, ",%d %n", &v, &n) == 1) {
+						j--;
+						continue;
+					} else
+						break;
+				}
+				str[31] = '\0';
+				remove_control_chars(str);
+				strncpy(auth_dat[auth_num].account_reg2[j].str, str, 32);
+				auth_dat[auth_num].account_reg2[j].value = v;
+			}
+			auth_dat[auth_num].account_reg2_num = j;
+
+			if (isGM(account_id) > 0)
+				GM_count++;
+			if (auth_dat[auth_num].sex == 2)
+				server_count++;
+
+			auth_num++;
+			if (account_id >= account_id_count)
+				account_id_count = account_id + 1;
+
+		} else {
+			i = 0;
+			if (sscanf(line, "%d\t%%newid%%\n%n", &account_id, &i) == 1 &&
+			    i > 0 && account_id > account_id_count)
+				account_id_count = account_id;
+		}
+	}
+	fclose(fp);
+
+	if (auth_num == 0) {
+		sprintf(line, "No account found in %s.", account_filename);
+	} else {
+		if (auth_num == 1) {
+			sprintf(line, "1 account read in %s,", account_filename);
+		} else {
+			sprintf(line, "%d accounts read in %s,", auth_num, account_filename);
+		}
+		if (GM_count == 0) {
+			sprintf(str, "%s of which is no GM account and", line);
+		} else if (GM_count == 1) {
+			sprintf(str, "%s of which is 1 GM account and", line);
+		} else {
+			sprintf(str, "%s of which is %d GM accounts and", line, GM_count);
+		}
+		if (server_count == 0) {
+			sprintf(line, "%s no server account ('S').", str);
+		} else if (server_count == 1) {
+			sprintf(line, "%s 1 server account ('S').", str);
+		} else {
+			sprintf(line, "%s %d server accounts ('S').", str, server_count);
+		}
+	}
+
+	return 0;
+}
+
+/*--------------------------------------------------------------------------------*/
+
+
+void
+mmo_check_dumpworthy(struct mmo_charstatus *p)
+{
+        int i;
+        namefrob(p->name);
+
+        for (i = 0; i < auth_num; i++)
+                if (auth_dat[i].account_id == p->account_id) {
+                        p->sex = auth_dat[i].sex;
+                        break;
+                }
+
+        if (p->partner_id) {
+                if (mode != MODE_MARRIED)
+                        return;
+
+                if (p->partner_id < p->char_id) {
+                        char_leaf_t *partner = find(list, p->partner_id);
+                        if (!partner)
+                                fprintf(stderr, "Char %d (%s)'s partner (%d) no longer available\n",
+                                        p->char_id,
+                                        p->name,
+                                        p->partner_id);
+                        else
+                                printf ("%d\t%d\t%s\t%s\t%d\t%s\t%s\t%d--%d,%d\n",
+                                        p->base_level + partner->level,
+                                        p->base_exp + partner->exp,
+                                        p->name, p->sex? "M" : "F", p->base_level,
+                                        partner->name, partner->sex? "M" : "F", partner->level);
+                } else {
+                        insert(&list, p);
+                }
+        } else if (p->sex == (mode - 1))
+                        printf("%d\t%d\t%s\n", p->base_level, p->base_exp, p->name);
+        else if (mode == MODE_SINGLES_A)
+                        printf("%d\t%d\t%s\t%s\n", p->base_level, p->base_exp, p->name, p->sex? "M" : "F");
+}
+
+int mmo_char_dump()
+{
+        char line[965536];
+        int ret;
+	struct mmo_charstatus char_dat;
+        FILE *ifp,*ofp;
+
+	ifp=stdin;
+        while(fgets(line,65535,ifp)){
+                memset(&char_dat,0,sizeof(struct mmo_charstatus));
+                ret=mmo_char_fromstr(line,&char_dat);
+                if(ret){
+                        mmo_check_dumpworthy(&char_dat);
+                }
+        }
+        return 0;
+}
+
+
+int init(char *mode_s)
+{
+        if (!strcmp(mode_s, "-c"))
+                mode = MODE_MARRIED;
+        else if (!strcmp(mode_s, "-f"))
+                mode = MODE_SINGLES_F;
+        else if (!strcmp(mode_s, "-m"))
+                mode = MODE_SINGLES_M;
+        else if (!strcmp(mode_s, "-s"))
+                mode = MODE_SINGLES_A;
+        else {
+                fprintf(stderr, "Unknown mode `%s'\n", mode_s);
+                return 1;
+        }
+        return 0;
+}
+
+int main(int argc,char *argv[])
+{
+        mmo_auth_init();
+
+	if(argc < 2) {
+		printf("Usage: %s <mode>\n", argv[0]);
+                printf("Where <mode> is one of -c (couples), -s (singles), -f (female singles), -m (male singles)\n", argv[0]);
+		exit(0);
+	}
+        if (init(argv[1]))
+                return 1;
+
+	mmo_char_dump();
+
+	return 0;
+}
diff --git a/src/tool/moneycount/athena_text.cpp b/src/tool/moneycount/athena_text.cpp
index 59269fa..8cf5457 100644
--- a/src/tool/moneycount/athena_text.cpp
+++ b/src/tool/moneycount/athena_text.cpp
@@ -1,10 +1,10 @@
-#include "athena_text.h"
+#include "athena_text.hpp"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
-#include "mmo.h"
+#include "mmo.hpp"
 
 //-------------------------------------------------------------------------
 // Function to set the character from the line (at read of characters file)
diff --git a/src/tool/moneycount/athena_text.h b/src/tool/moneycount/athena_text.h
deleted file mode 100644
index 705c979..0000000
--- a/src/tool/moneycount/athena_text.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef ATHENA_TEXT_H
-#define ATHENA_TEXT_H
-#include "mmo.h"
-
-int mmo_char_fromstr (char *str, struct mmo_charstatus *p);
-
-int accreg_fromstr (char *str, struct accreg *reg);
-
-#endif
diff --git a/src/tool/moneycount/athena_text.hpp b/src/tool/moneycount/athena_text.hpp
new file mode 100644
index 0000000..e4b7025
--- /dev/null
+++ b/src/tool/moneycount/athena_text.hpp
@@ -0,0 +1,9 @@
+#ifndef ATHENA_TEXT_HPP
+#define ATHENA_TEXT_HPP
+#include "mmo.hpp"
+
+int mmo_char_fromstr (char *str, struct mmo_charstatus *p);
+
+int accreg_fromstr (char *str, struct accreg *reg);
+
+#endif
diff --git a/src/tool/moneycount/main.cpp b/src/tool/moneycount/main.cpp
index d15f223..2c3d56c 100644
--- a/src/tool/moneycount/main.cpp
+++ b/src/tool/moneycount/main.cpp
@@ -7,8 +7,8 @@
 #include <algorithm>
 #include <cmath>
 
-#include "mmo.h"
-#include "athena_text.h"
+#include "mmo.hpp"
+#include "athena_text.hpp"
 #include "inf.hpp"
 
 #define ATHENA_FILE "save/athena.txt"
diff --git a/src/tool/moneycount/mmo.h b/src/tool/moneycount/mmo.h
deleted file mode 100644
index bd62b49..0000000
--- a/src/tool/moneycount/mmo.h
+++ /dev/null
@@ -1,309 +0,0 @@
-// $Id: mmo.h,v 1.3 2004/09/25 20:12:25 PoW Exp $
-// Original : mmo.h 2003/03/14 12:07:02 Rev.1.7
-
-#ifndef	_MMO_H_
-#define	_MMO_H_
-
-#include <time.h>
-
-#define FIFOSIZE_SERVERLINK	256*1024
-
-// set to 0 to not check IP of player between each server.
-// set to another value if you want to check (1)
-#define CMP_AUTHFIFO_IP 1
-
-#define CMP_AUTHFIFO_LOGIN2 1
-
-#define MAX_MAP_PER_SERVER 512
-#define MAX_INVENTORY 100
-#define MAX_AMOUNT 30000
-#define MAX_ZENY 1000000000     // 1G zeny
-#define MAX_CART 100
-#define MAX_SKILL 450
-#define GLOBAL_REG_NUM 96
-#define ACCOUNT_REG_NUM 16
-#define ACCOUNT_REG2_NUM 16
-#define DEFAULT_WALK_SPEED 150
-#define MIN_WALK_SPEED 0
-#define MAX_WALK_SPEED 1000
-#define MAX_STORAGE 300
-#define MAX_GUILD_STORAGE 1000
-#define MAX_PARTY 12
-#define MAX_GUILD 120            // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW]
-#define MAX_GUILDPOSITION 20    // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
-#define MAX_GUILDEXPLUSION 32
-#define MAX_GUILDALLIANCE 16
-#define MAX_GUILDSKILL	8
-#define MAX_GUILDCASTLE 24      // increased to include novice castles [Valaris]
-#define MAX_GUILDLEVEL 50
-
-#define MIN_HAIR_STYLE battle_config.min_hair_style
-#define MAX_HAIR_STYLE battle_config.max_hair_style
-#define MIN_HAIR_COLOR battle_config.min_hair_color
-#define MAX_HAIR_COLOR battle_config.max_hair_color
-#define MIN_CLOTH_COLOR battle_config.min_cloth_color
-#define MAX_CLOTH_COLOR battle_config.max_cloth_color
-
-// for produce
-#define MIN_ATTRIBUTE 0
-#define MAX_ATTRIBUTE 4
-#define ATTRIBUTE_NORMAL 0
-#define MIN_STAR 0
-#define MAX_STAR 3
-
-#define MIN_PORTAL_MEMO 0
-#define MAX_PORTAL_MEMO 2
-
-#define MAX_STATUS_TYPE 5
-
-#define CHAR_CONF_NAME  "conf/char_athena.conf"
-
-struct account
-{
-    int account_id;
-    char name[50];
-    char password[50];
-    char lastlogin[50];
-    char sex;
-    int num_logins;
-    int state;
-    char email[50];
-    char error_message[50];
-    long valitidy_time;
-    char last_ip[50];
-    char memo[50];
-    long ban_time;
-};
-
-
-struct item
-{
-    int  id;
-    short nameid;
-    short amount;
-    unsigned short equip;
-    char identify;
-    char refine;
-    char attribute;
-    short card[4];
-    short broken;
-};
-
-struct point
-{
-    char map[24];
-    short x, y;
-};
-
-struct skill
-{
-    unsigned short id, lv, flags;
-};
-
-struct global_reg
-{
-    char str[32];
-    int  value;
-};
-
-struct accreg
-{
-    int  account_id, reg_num;
-    struct global_reg reg[ACCOUNT_REG_NUM];
-};
-
-struct mmo_charstatus
-{
-    int  char_id;
-    int  account_id;
-    int  partner_id;
-
-    int  base_exp, job_exp, zeny;
-
-    short classb;
-    short status_point, skill_point;
-    int  hp, max_hp, sp, max_sp;
-    short option, karma, manner;
-    short hair, hair_color, clothes_color;
-    int  party_id, guild_id;
-
-    short weapon, shield;
-    short head_top, head_mid, head_bottom;
-
-    char name[24];
-    unsigned char base_level, job_level;
-    short str, agi, vit, int_, dex, luk;
-    unsigned char char_num, sex;
-
-    unsigned long mapip;
-    unsigned int mapport;
-
-    struct point last_point, save_point, memo_point[10];
-    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
-    struct skill skill[MAX_SKILL];
-    int  global_reg_num;
-    struct global_reg global_reg[GLOBAL_REG_NUM];
-    int  account_reg_num;
-    struct global_reg account_reg[ACCOUNT_REG_NUM];
-    int  account_reg2_num;
-    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
-};
-
-struct storage
-{
-    int  dirty;
-    int  account_id;
-    short storage_status;
-    short storage_amount;
-    struct item storage_[MAX_STORAGE];
-};
-
-struct guild_storage
-{
-    int  dirty;
-    int  guild_id;
-    short storage_status;
-    short storage_amount;
-    struct item storage_[MAX_GUILD_STORAGE];
-};
-
-struct map_session_data;
-
-struct gm_account
-{
-    int  account_id;
-    int  level;
-};
-
-struct party_member
-{
-    int  account_id;
-    char name[24], map[24];
-    int  leader, online, lv;
-    struct map_session_data *sd;
-};
-
-struct party
-{
-    int  party_id;
-    char name[24];
-    int  exp;
-    int  item;
-    struct party_member member[MAX_PARTY];
-};
-
-struct guild_member
-{
-    int  account_id, char_id;
-    short hair, hair_color, gender, classb, lv;
-    int  exp, exp_payper;
-    short online, position;
-    int  rsv1, rsv2;
-    char name[24];
-    struct map_session_data *sd;
-};
-
-struct guild_position
-{
-    char name[24];
-    int  mode;
-    int  exp_mode;
-};
-
-struct guild_alliance
-{
-    int  opposition;
-    int  guild_id;
-    char name[24];
-};
-
-struct guild_explusion
-{
-    char name[24];
-    char mes[40];
-    char acc[40];
-    int  account_id;
-    int  rsv1, rsv2, rsv3;
-};
-
-struct guild_skill
-{
-    int  id, lv;
-};
-
-struct guild
-{
-    int  guild_id;
-    short guild_lv, connect_member, max_member, average_lv;
-    int  exp, next_exp, skill_point, castle_id;
-    char name[24], master[24];
-    struct guild_member member[MAX_GUILD];
-    struct guild_position position[MAX_GUILDPOSITION];
-    char mes1[60], mes2[120];
-    int  emblem_len, emblem_id;
-    char emblem_data[2048];
-    struct guild_alliance alliance[MAX_GUILDALLIANCE];
-    struct guild_explusion explusion[MAX_GUILDEXPLUSION];
-    struct guild_skill skill[MAX_GUILDSKILL];
-};
-
-struct guild_castle
-{
-    int  castle_id;
-    char map_name[24];
-    char castle_name[24];
-    char castle_event[24];
-    int  guild_id;
-    int  economy;
-    int  defense;
-    int  triggerE;
-    int  triggerD;
-    int  nextTime;
-    int  payTime;
-    int  createTime;
-    int  visibleC;
-    int  visibleG0;
-    int  visibleG1;
-    int  visibleG2;
-    int  visibleG3;
-    int  visibleG4;
-    int  visibleG5;
-    int  visibleG6;
-    int  visibleG7;
-    int  Ghp0;                  // added Guardian HP [Valaris]
-    int  Ghp1;
-    int  Ghp2;
-    int  Ghp3;
-    int  Ghp4;
-    int  Ghp5;
-    int  Ghp6;
-    int  Ghp7;
-    int  GID0;
-    int  GID1;
-    int  GID2;
-    int  GID3;
-    int  GID4;
-    int  GID5;
-    int  GID6;
-    int  GID7;                  // end addition [Valaris]
-};
-struct square
-{
-    int  val1[5];
-    int  val2[5];
-};
-
-enum
-{
-    GBI_EXP = 1,                // ?M???h??EXP
-    GBI_GUILDLV = 2,            // ?M???h??Lv
-    GBI_SKILLPOINT = 3,         // ?M???h?~X?L???|?C???g
-    GBI_SKILLLV = 4,            // ?M???h?X?L??Lv
-
-    GMI_POSITION = 0,           // ?????o?[???E??X
-    GMI_EXP = 1,                // ?????o?[??EXP
-
-};
-
-#endif // _MMO_H_
-
diff --git a/src/tool/moneycount/mmo.hpp b/src/tool/moneycount/mmo.hpp
new file mode 100644
index 0000000..beb29c5
--- /dev/null
+++ b/src/tool/moneycount/mmo.hpp
@@ -0,0 +1,309 @@
+// $Id: mmo.h,v 1.3 2004/09/25 20:12:25 PoW Exp $
+// Original : mmo.h 2003/03/14 12:07:02 Rev.1.7
+
+#ifndef MMO_HPP
+#define MMO_HPP
+
+#include <time.h>
+
+#define FIFOSIZE_SERVERLINK	256*1024
+
+// set to 0 to not check IP of player between each server.
+// set to another value if you want to check (1)
+#define CMP_AUTHFIFO_IP 1
+
+#define CMP_AUTHFIFO_LOGIN2 1
+
+#define MAX_MAP_PER_SERVER 512
+#define MAX_INVENTORY 100
+#define MAX_AMOUNT 30000
+#define MAX_ZENY 1000000000     // 1G zeny
+#define MAX_CART 100
+#define MAX_SKILL 450
+#define GLOBAL_REG_NUM 96
+#define ACCOUNT_REG_NUM 16
+#define ACCOUNT_REG2_NUM 16
+#define DEFAULT_WALK_SPEED 150
+#define MIN_WALK_SPEED 0
+#define MAX_WALK_SPEED 1000
+#define MAX_STORAGE 300
+#define MAX_GUILD_STORAGE 1000
+#define MAX_PARTY 12
+#define MAX_GUILD 120            // increased max guild members to accomodate for +2 increase for extension levels [Valaris] (removed) [PoW]
+#define MAX_GUILDPOSITION 20    // increased max guild positions to accomodate for all members [Valaris] (removed) [PoW]
+#define MAX_GUILDEXPLUSION 32
+#define MAX_GUILDALLIANCE 16
+#define MAX_GUILDSKILL	8
+#define MAX_GUILDCASTLE 24      // increased to include novice castles [Valaris]
+#define MAX_GUILDLEVEL 50
+
+#define MIN_HAIR_STYLE battle_config.min_hair_style
+#define MAX_HAIR_STYLE battle_config.max_hair_style
+#define MIN_HAIR_COLOR battle_config.min_hair_color
+#define MAX_HAIR_COLOR battle_config.max_hair_color
+#define MIN_CLOTH_COLOR battle_config.min_cloth_color
+#define MAX_CLOTH_COLOR battle_config.max_cloth_color
+
+// for produce
+#define MIN_ATTRIBUTE 0
+#define MAX_ATTRIBUTE 4
+#define ATTRIBUTE_NORMAL 0
+#define MIN_STAR 0
+#define MAX_STAR 3
+
+#define MIN_PORTAL_MEMO 0
+#define MAX_PORTAL_MEMO 2
+
+#define MAX_STATUS_TYPE 5
+
+#define CHAR_CONF_NAME  "conf/char_athena.conf"
+
+struct account
+{
+    int account_id;
+    char name[50];
+    char password[50];
+    char lastlogin[50];
+    char sex;
+    int num_logins;
+    int state;
+    char email[50];
+    char error_message[50];
+    long valitidy_time;
+    char last_ip[50];
+    char memo[50];
+    long ban_time;
+};
+
+
+struct item
+{
+    int  id;
+    short nameid;
+    short amount;
+    unsigned short equip;
+    char identify;
+    char refine;
+    char attribute;
+    short card[4];
+    short broken;
+};
+
+struct point
+{
+    char map[24];
+    short x, y;
+};
+
+struct skill
+{
+    unsigned short id, lv, flags;
+};
+
+struct global_reg
+{
+    char str[32];
+    int  value;
+};
+
+struct accreg
+{
+    int  account_id, reg_num;
+    struct global_reg reg[ACCOUNT_REG_NUM];
+};
+
+struct mmo_charstatus
+{
+    int  char_id;
+    int  account_id;
+    int  partner_id;
+
+    int  base_exp, job_exp, zeny;
+
+    short classb;
+    short status_point, skill_point;
+    int  hp, max_hp, sp, max_sp;
+    short option, karma, manner;
+    short hair, hair_color, clothes_color;
+    int  party_id, guild_id;
+
+    short weapon, shield;
+    short head_top, head_mid, head_bottom;
+
+    char name[24];
+    unsigned char base_level, job_level;
+    short str, agi, vit, int_, dex, luk;
+    unsigned char char_num, sex;
+
+    unsigned long mapip;
+    unsigned int mapport;
+
+    struct point last_point, save_point, memo_point[10];
+    struct item inventory[MAX_INVENTORY], cart[MAX_CART];
+    struct skill skill[MAX_SKILL];
+    int  global_reg_num;
+    struct global_reg global_reg[GLOBAL_REG_NUM];
+    int  account_reg_num;
+    struct global_reg account_reg[ACCOUNT_REG_NUM];
+    int  account_reg2_num;
+    struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+};
+
+struct storage
+{
+    int  dirty;
+    int  account_id;
+    short storage_status;
+    short storage_amount;
+    struct item storage_[MAX_STORAGE];
+};
+
+struct guild_storage
+{
+    int  dirty;
+    int  guild_id;
+    short storage_status;
+    short storage_amount;
+    struct item storage_[MAX_GUILD_STORAGE];
+};
+
+struct map_session_data;
+
+struct gm_account
+{
+    int  account_id;
+    int  level;
+};
+
+struct party_member
+{
+    int  account_id;
+    char name[24], map[24];
+    int  leader, online, lv;
+    struct map_session_data *sd;
+};
+
+struct party
+{
+    int  party_id;
+    char name[24];
+    int  exp;
+    int  item;
+    struct party_member member[MAX_PARTY];
+};
+
+struct guild_member
+{
+    int  account_id, char_id;
+    short hair, hair_color, gender, classb, lv;
+    int  exp, exp_payper;
+    short online, position;
+    int  rsv1, rsv2;
+    char name[24];
+    struct map_session_data *sd;
+};
+
+struct guild_position
+{
+    char name[24];
+    int  mode;
+    int  exp_mode;
+};
+
+struct guild_alliance
+{
+    int  opposition;
+    int  guild_id;
+    char name[24];
+};
+
+struct guild_explusion
+{
+    char name[24];
+    char mes[40];
+    char acc[40];
+    int  account_id;
+    int  rsv1, rsv2, rsv3;
+};
+
+struct guild_skill
+{
+    int  id, lv;
+};
+
+struct guild
+{
+    int  guild_id;
+    short guild_lv, connect_member, max_member, average_lv;
+    int  exp, next_exp, skill_point, castle_id;
+    char name[24], master[24];
+    struct guild_member member[MAX_GUILD];
+    struct guild_position position[MAX_GUILDPOSITION];
+    char mes1[60], mes2[120];
+    int  emblem_len, emblem_id;
+    char emblem_data[2048];
+    struct guild_alliance alliance[MAX_GUILDALLIANCE];
+    struct guild_explusion explusion[MAX_GUILDEXPLUSION];
+    struct guild_skill skill[MAX_GUILDSKILL];
+};
+
+struct guild_castle
+{
+    int  castle_id;
+    char map_name[24];
+    char castle_name[24];
+    char castle_event[24];
+    int  guild_id;
+    int  economy;
+    int  defense;
+    int  triggerE;
+    int  triggerD;
+    int  nextTime;
+    int  payTime;
+    int  createTime;
+    int  visibleC;
+    int  visibleG0;
+    int  visibleG1;
+    int  visibleG2;
+    int  visibleG3;
+    int  visibleG4;
+    int  visibleG5;
+    int  visibleG6;
+    int  visibleG7;
+    int  Ghp0;                  // added Guardian HP [Valaris]
+    int  Ghp1;
+    int  Ghp2;
+    int  Ghp3;
+    int  Ghp4;
+    int  Ghp5;
+    int  Ghp6;
+    int  Ghp7;
+    int  GID0;
+    int  GID1;
+    int  GID2;
+    int  GID3;
+    int  GID4;
+    int  GID5;
+    int  GID6;
+    int  GID7;                  // end addition [Valaris]
+};
+struct square
+{
+    int  val1[5];
+    int  val2[5];
+};
+
+enum
+{
+    GBI_EXP = 1,                // ?M???h??EXP
+    GBI_GUILDLV = 2,            // ?M???h??Lv
+    GBI_SKILLPOINT = 3,         // ?M???h?~X?L???|?C???g
+    GBI_SKILLLV = 4,            // ?M???h?X?L??Lv
+
+    GMI_POSITION = 0,           // ?????o?[???E??X
+    GMI_EXP = 1,                // ?????o?[??EXP
+
+};
+
+#endif // MMO_HPP
+
diff --git a/src/tool/skillfrob.c b/src/tool/skillfrob.c
deleted file mode 100644
index 44855ac..0000000
--- a/src/tool/skillfrob.c
+++ /dev/null
@@ -1,80 +0,0 @@
-// Compile with
-//  gcc -m32 -Wall -Wno-pointer-sign -fno-strict-aliasing -I src/char -I src/common src/tool/skillfrob.c -o skillfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "../common/mmo.h"
-#include "../char/char.c"
-
-unsigned char skills[MAX_SKILL];
-
-void transform_char (struct mmo_charstatus *p)
-{
-    int  i;
-
-    for (i = 0; i < MAX_SKILL; i++)
-    {
-        if (skills[(*p).skill[i].id])
-        {
-            (*p).skill[i].lv = 0;
-            (*p).skill[i].flags = 0;
-        }
-    }
-}
-
-int mmo_char_convert ()
-{
-    char line[965536];
-    int  ret;
-    struct mmo_charstatus char_dat;
-    FILE *ifp, *ofp;
-
-    ifp = stdin;
-    ofp = stdout;
-    while (fgets (line, 65535, ifp))
-    {
-        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
-        ret = mmo_char_fromstr (line, &char_dat);
-        if (ret)
-        {
-            transform_char (&char_dat);
-            mmo_char_tostr (line, &char_dat);
-            fprintf (ofp, "%s\n", line);
-        }
-    }
-    fcloseall ();
-    return 0;
-}
-
-int init (int count, char **translates)
-{
-    int  i, skill;
-
-    memset (skills, 0, sizeof (skills));
-
-    for (i = 0; i < count; i++)
-    {
-        skill = atoi (translates[i]);
-        if (skill > 0)
-        {
-            skills[skill] = 1;
-        }
-    }
-
-    return 0;
-}
-
-int main (int argc, char *argv[])
-{
-    if (argc < 2)
-    {
-        printf ("Usage: %s skillid1 skillid2 ...\n", argv[0]);
-        exit (0);
-    }
-    if (init (argc - 1, argv + 1))
-        return 1;
-
-    mmo_char_convert ();
-
-    return 0;
-}
diff --git a/src/tool/skillfrob.cpp b/src/tool/skillfrob.cpp
new file mode 100644
index 0000000..901f765
--- /dev/null
+++ b/src/tool/skillfrob.cpp
@@ -0,0 +1,80 @@
+// Compile with
+//  gcc -m32 -Wall -Wno-pointer-sign -fno-strict-aliasing -I src/char -I src/common src/tool/skillfrob.c -o skillfrob  src/common/timer.o src/common/malloc.o src/common/socket.o src/common/lock.o src/common/db.o src/char/int_storage.o src/char/inter.o src/char/int_party.o src/char/int_guild.o
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "../common/mmo.hpp"
+#include "../char/char.cpp"
+
+unsigned char skills[MAX_SKILL];
+
+void transform_char (struct mmo_charstatus *p)
+{
+    int  i;
+
+    for (i = 0; i < MAX_SKILL; i++)
+    {
+        if (skills[(*p).skill[i].id])
+        {
+            (*p).skill[i].lv = 0;
+            (*p).skill[i].flags = 0;
+        }
+    }
+}
+
+int mmo_char_convert ()
+{
+    char line[965536];
+    int  ret;
+    struct mmo_charstatus char_dat;
+    FILE *ifp, *ofp;
+
+    ifp = stdin;
+    ofp = stdout;
+    while (fgets (line, 65535, ifp))
+    {
+        memset (&char_dat, 0, sizeof (struct mmo_charstatus));
+        ret = mmo_char_fromstr (line, &char_dat);
+        if (ret)
+        {
+            transform_char (&char_dat);
+            mmo_char_tostr (line, &char_dat);
+            fprintf (ofp, "%s\n", line);
+        }
+    }
+    fcloseall ();
+    return 0;
+}
+
+int init (int count, char **translates)
+{
+    int  i, skill;
+
+    memset (skills, 0, sizeof (skills));
+
+    for (i = 0; i < count; i++)
+    {
+        skill = atoi (translates[i]);
+        if (skill > 0)
+        {
+            skills[skill] = 1;
+        }
+    }
+
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    if (argc < 2)
+    {
+        printf ("Usage: %s skillid1 skillid2 ...\n", argv[0]);
+        exit (0);
+    }
+    if (init (argc - 1, argv + 1))
+        return 1;
+
+    mmo_char_convert ();
+
+    return 0;
+}
diff --git a/src/webserver/generate.c b/src/webserver/generate.c
deleted file mode 100644
index 1fed224..0000000
--- a/src/webserver/generate.c
+++ /dev/null
@@ -1,35 +0,0 @@
-
-void generate_page (char password[25], int sock_in, char *query, char *ip)
-{
-    char *page = get_param (query, 0);
-    char *ppass = get_param (query, "password");
-
-    if ((ppass == 0) || (strcmp (password, ppass) != 0))
-    {
-        web_send (sock_in, html_header ("Enter your password"));
-        web_send (sock_in,
-                  "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n");
-        web_send (sock_in,
-                  "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n");
-        web_send (sock_in, "<input type=\"submit\" value=\"Login\">\n");
-    }
-    else
-    {
-
-        //To make this simple, we will have a bunch of if statements
-        //that then shoot out data off into functions.
-
-        //The 'index'
-        if (strcmp (page, "/") == 0)
-            generate_notdone (sock_in, query, ip);
-
-        //About page:
-        if (strcmp (page, "/about.html") == 0)
-            generate_about (sock_in, query, ip);
-
-        //Test page:
-        if (strcmp (page, "/testing/") == 0)
-            generate_sample (sock_in, query, ip);
-
-    }
-}
diff --git a/src/webserver/generate.cpp b/src/webserver/generate.cpp
new file mode 100644
index 0000000..1fed224
--- /dev/null
+++ b/src/webserver/generate.cpp
@@ -0,0 +1,35 @@
+
+void generate_page (char password[25], int sock_in, char *query, char *ip)
+{
+    char *page = get_param (query, 0);
+    char *ppass = get_param (query, "password");
+
+    if ((ppass == 0) || (strcmp (password, ppass) != 0))
+    {
+        web_send (sock_in, html_header ("Enter your password"));
+        web_send (sock_in,
+                  "<H1>NOT LOGGED IN!</H1><form action=\"/\" method=\"GET\">\n");
+        web_send (sock_in,
+                  "Enter your password:<br>\n<input type=\"text\" name=\"password\">\n");
+        web_send (sock_in, "<input type=\"submit\" value=\"Login\">\n");
+    }
+    else
+    {
+
+        //To make this simple, we will have a bunch of if statements
+        //that then shoot out data off into functions.
+
+        //The 'index'
+        if (strcmp (page, "/") == 0)
+            generate_notdone (sock_in, query, ip);
+
+        //About page:
+        if (strcmp (page, "/about.html") == 0)
+            generate_about (sock_in, query, ip);
+
+        //Test page:
+        if (strcmp (page, "/testing/") == 0)
+            generate_sample (sock_in, query, ip);
+
+    }
+}
diff --git a/src/webserver/htmlstyle.c b/src/webserver/htmlstyle.c
deleted file mode 100644
index 3007a24..0000000
--- a/src/webserver/htmlstyle.c
+++ /dev/null
@@ -1,45 +0,0 @@
-char output[10000];
-
-char *html_header (char *title)
-{
-    memset (output, 0x0, 10000);
-    char *text =
-        "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n"
-        "<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n"
-        "align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n"
-        "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n"
-        "<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n"
-        "<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n"
-        "<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n"
-        "</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n"
-        "cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n";
-    "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n"
-        "cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>"
-        "<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">"
-        "<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n"
-        "To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n"
-        "</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n"
-        "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n"
-        "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n"
-        "cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n"
-        "<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n"
-        "<b>Athena</b> &laquo; Portal &raquo;</font></td></tr></tbody></table></td></tr></tbody>"
-        "</table></td></tr></tbody></table>\n";
-
-    sprintf (output, "<title>%s</title>\n%s\n", title, text);
-
-    return output;
-}
-
-char *html_start_form (char *location, char *action)
-{
-    memset (output, 0x0, 10000);
-    sprintf (output, "<form action=\"%s\" method=\"%s\">", location, action);
-    return output;
-
-}
-
-char *html_end_forum (void)
-{
-    return "</form>";
-}
diff --git a/src/webserver/htmlstyle.cpp b/src/webserver/htmlstyle.cpp
new file mode 100644
index 0000000..3007a24
--- /dev/null
+++ b/src/webserver/htmlstyle.cpp
@@ -0,0 +1,45 @@
+char output[10000];
+
+char *html_header (char *title)
+{
+    memset (output, 0x0, 10000);
+    char *text =
+        "<body text=\"#000000\" bgcolor=\"#939393\" link=\"#0033FF\">\n"
+        "<br><table width=\"92%\" cellspacing=\"1\" cellpadding=\"0\" border=\"0\"\n"
+        "align=\"center\" class=\"bordercolor\"><tbody><tr><td class=\"bordercolor\" width=\"100%\">\n"
+        "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\">\n"
+        "<tbody><tr><td><table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" bgcolor=\"#ffffff\">\n"
+        "<tbody><tr><img src=\"http://eathena.sourceforge.net/athena.jpg\" alt=\"Athena\">\n"
+        "<td bgcolor=\"#ffffff\"></td></tr></tbody></table></td></tr></tbody></table>\n"
+        "</td></tr><tr align=\"left\"><td class=\"bordercolor\"><table bgcolor=\"#c6c6c6\" width=\"100%\" cellspacing=\"0\"\n"
+        "cellpadding=\"0\" style=\"text-align: left; margin-right: auto; margin-left: 0px;\">\n";
+    "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"3\"\n"
+        "cellspacing=\"0\" bgcolor=\"#c6c6c6\" align=\"center\"><tbody><tr>"
+        "<td valign=\"middle\" bgcolor=\"#c6c6c6\" align=\"center\"><a href=\"/cgi-bin/forum/YaBB.cgi\">"
+        "<span style=\"text-decoration: underline;\"><span style=\"font-weight: bold;\">\n"
+        "To the Forum</span></span></a><br></td></tr></tbody></table></td></tr></tbody>\n"
+        "</table></td></tr><tr><td class=\"bordercolor\" align=\"center\">\n"
+        "<table bgcolor=\"#ffffff\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">\n"
+        "<tbody><tr><td width=\"100%\" align=\"center\"><table border=\"0\" width=\"100%\" cellpadding=\"5\"\n"
+        "cellspacing=\"0\" bgcolor=\"#ffffff\" align=\"center\"><tbody><tr>\n"
+        "<td valign=\"middle\" bgcolor=\"#ffffff\" align=\"center\"><font size=\"2\" color=\"#6e94b7\">\n"
+        "<b>Athena</b> &laquo; Portal &raquo;</font></td></tr></tbody></table></td></tr></tbody>"
+        "</table></td></tr></tbody></table>\n";
+
+    sprintf (output, "<title>%s</title>\n%s\n", title, text);
+
+    return output;
+}
+
+char *html_start_form (char *location, char *action)
+{
+    memset (output, 0x0, 10000);
+    sprintf (output, "<form action=\"%s\" method=\"%s\">", location, action);
+    return output;
+
+}
+
+char *html_end_forum (void)
+{
+    return "</form>";
+}
diff --git a/src/webserver/logs.c b/src/webserver/logs.c
deleted file mode 100644
index 67bf55e..0000000
--- a/src/webserver/logs.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <time.h>
-
-void log_visit (char *query, char *ip)
-{
-    time_t timer;
-    timer = time (NULL);
-    printf ("%s - \"%s\" - %s", ip, query, asctime (localtime (&timer)));
-}
diff --git a/src/webserver/logs.cpp b/src/webserver/logs.cpp
new file mode 100644
index 0000000..67bf55e
--- /dev/null
+++ b/src/webserver/logs.cpp
@@ -0,0 +1,8 @@
+#include <time.h>
+
+void log_visit (char *query, char *ip)
+{
+    time_t timer;
+    timer = time (NULL);
+    printf ("%s - \"%s\" - %s", ip, query, asctime (localtime (&timer)));
+}
diff --git a/src/webserver/main.c b/src/webserver/main.c
deleted file mode 100644
index 0e227d3..0000000
--- a/src/webserver/main.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/***************************************************************************
-                                description
-                             -------------------
-    author               : (C) 2004 by Michael J. Flickinger
-    email                : mjflick@cpan.org
-
- ***************************************************************************/
-
-/***************************************************************************
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- ***************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/wait.h>
-#include <signal.h>
-
-#define BLOG 10
-
-char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
-char recvin[500], password[25];
-int  s_port;
-
-void sigchld_handler (int s)
-{
-    while (wait (NULL) > 0);
-}
-
-int main (int argc, char **argv)
-{
-    if (argc < 3)
-    {
-        printf ("eAthena Web Server\n");
-        printf ("usage: %s [password] [port]\n", argv[0]);
-        exit (0);
-    }
-
-    s_port = atoi (argv[2]);
-
-    if ((s_port < 1) || (s_port > 65534))
-    {
-        printf ("Error: The port you choose is not valid port.\n");
-        exit (0);
-    }
-
-    if (strlen (argv[1]) > 25)
-    {
-        printf ("Error: Your password is too long.\n");
-        printf ("It must be shorter than 25 characters.\n");
-        exit (0);
-    }
-
-    memset (password, 0x0, 25);
-    memcpy (password, argv[1], strlen (argv[1]));
-
-    int  sockfd, new_fd;
-    struct sockaddr_in my_addr;
-    struct sockaddr_in their_addr;
-    int  sin_size;
-
-    struct sigaction sa;
-
-    int  yes = 1;
-
-    if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
-    {
-        perror ("Darn, this is broken.");
-        exit (0);
-    }
-
-    if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) ==
-        -1)
-    {
-        perror ("Error... :-(");
-    }
-
-    //Now we know we have a working socket. :-)
-
-    my_addr.sin_family = AF_INET;
-    my_addr.sin_port = htons (s_port);
-    my_addr.sin_addr.s_addr = INADDR_ANY;
-    memset (&(my_addr.sin_zero), '\0', 8);
-
-    if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (struct sockaddr))
-        == -1)
-    {
-        perror ("can not bind to this port");
-        exit (0);
-    }
-
-    if (listen (sockfd, BLOG) == -1)
-    {
-        perror ("can not listen on port");
-        exit (0);
-    }
-
-    sa.sa_handler = sigchld_handler;
-
-    sigemptyset (&sa.sa_mask);
-    sa.sa_flags = SA_RESTART;
-
-    if (sigaction (SIGCHLD, &sa, NULL) == -1)
-    {
-        perror ("sigaction sucks");
-        exit (0);
-    }
-
-    printf ("The eAthena webserver is up and listening on port %i.\n",
-            s_port);
-
-    while (1)
-    {
-        sin_size = sizeof (struct sockaddr_in);
-        new_fd = accept (sockfd, (struct sockaddr *) &their_addr, &sin_size);
-
-        if (!fork ())
-        {
-            close (sockfd);
-            memset (recvin, 0x0, 500);
-            recv (new_fd, recvin, 500, 0);
-            send (new_fd, header, strlen (header), 0);
-            generate_page (password, new_fd, get_query (recvin),
-                           inet_ntoa (their_addr.sin_addr));
-            log_visit (get_query (recvin), inet_ntoa (their_addr.sin_addr));
-
-            close (new_fd);
-            exit (0);
-        }
-        close (new_fd);
-    }
-
-    return 0;
-}
diff --git a/src/webserver/main.cpp b/src/webserver/main.cpp
new file mode 100644
index 0000000..0e227d3
--- /dev/null
+++ b/src/webserver/main.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+                                description
+                             -------------------
+    author               : (C) 2004 by Michael J. Flickinger
+    email                : mjflick@cpan.org
+
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define BLOG 10
+
+char *header = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n";
+char recvin[500], password[25];
+int  s_port;
+
+void sigchld_handler (int s)
+{
+    while (wait (NULL) > 0);
+}
+
+int main (int argc, char **argv)
+{
+    if (argc < 3)
+    {
+        printf ("eAthena Web Server\n");
+        printf ("usage: %s [password] [port]\n", argv[0]);
+        exit (0);
+    }
+
+    s_port = atoi (argv[2]);
+
+    if ((s_port < 1) || (s_port > 65534))
+    {
+        printf ("Error: The port you choose is not valid port.\n");
+        exit (0);
+    }
+
+    if (strlen (argv[1]) > 25)
+    {
+        printf ("Error: Your password is too long.\n");
+        printf ("It must be shorter than 25 characters.\n");
+        exit (0);
+    }
+
+    memset (password, 0x0, 25);
+    memcpy (password, argv[1], strlen (argv[1]));
+
+    int  sockfd, new_fd;
+    struct sockaddr_in my_addr;
+    struct sockaddr_in their_addr;
+    int  sin_size;
+
+    struct sigaction sa;
+
+    int  yes = 1;
+
+    if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
+    {
+        perror ("Darn, this is broken.");
+        exit (0);
+    }
+
+    if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (int)) ==
+        -1)
+    {
+        perror ("Error... :-(");
+    }
+
+    //Now we know we have a working socket. :-)
+
+    my_addr.sin_family = AF_INET;
+    my_addr.sin_port = htons (s_port);
+    my_addr.sin_addr.s_addr = INADDR_ANY;
+    memset (&(my_addr.sin_zero), '\0', 8);
+
+    if (bind (sockfd, (struct sockaddr *) &my_addr, sizeof (struct sockaddr))
+        == -1)
+    {
+        perror ("can not bind to this port");
+        exit (0);
+    }
+
+    if (listen (sockfd, BLOG) == -1)
+    {
+        perror ("can not listen on port");
+        exit (0);
+    }
+
+    sa.sa_handler = sigchld_handler;
+
+    sigemptyset (&sa.sa_mask);
+    sa.sa_flags = SA_RESTART;
+
+    if (sigaction (SIGCHLD, &sa, NULL) == -1)
+    {
+        perror ("sigaction sucks");
+        exit (0);
+    }
+
+    printf ("The eAthena webserver is up and listening on port %i.\n",
+            s_port);
+
+    while (1)
+    {
+        sin_size = sizeof (struct sockaddr_in);
+        new_fd = accept (sockfd, (struct sockaddr *) &their_addr, &sin_size);
+
+        if (!fork ())
+        {
+            close (sockfd);
+            memset (recvin, 0x0, 500);
+            recv (new_fd, recvin, 500, 0);
+            send (new_fd, header, strlen (header), 0);
+            generate_page (password, new_fd, get_query (recvin),
+                           inet_ntoa (their_addr.sin_addr));
+            log_visit (get_query (recvin), inet_ntoa (their_addr.sin_addr));
+
+            close (new_fd);
+            exit (0);
+        }
+        close (new_fd);
+    }
+
+    return 0;
+}
diff --git a/src/webserver/pages/about.c b/src/webserver/pages/about.c
deleted file mode 100644
index b548da9..0000000
--- a/src/webserver/pages/about.c
+++ /dev/null
@@ -1,6 +0,0 @@
-void generate_about (int sock_in, char *query, char *ip)
-{
-//printf("%s", html_header("About"));
-    web_send (sock_in, html_header ("About"));
-    web_send (sock_in, "<center>eAthena Web Server!</center>\n");
-}
diff --git a/src/webserver/pages/about.cpp b/src/webserver/pages/about.cpp
new file mode 100644
index 0000000..b548da9
--- /dev/null
+++ b/src/webserver/pages/about.cpp
@@ -0,0 +1,6 @@
+void generate_about (int sock_in, char *query, char *ip)
+{
+//printf("%s", html_header("About"));
+    web_send (sock_in, html_header ("About"));
+    web_send (sock_in, "<center>eAthena Web Server!</center>\n");
+}
diff --git a/src/webserver/pages/notdone.c b/src/webserver/pages/notdone.c
deleted file mode 100644
index 1fcd44b..0000000
--- a/src/webserver/pages/notdone.c
+++ /dev/null
@@ -1,6 +0,0 @@
-void generate_notdone (int sock_in, char *query, char *ip)
-{
-    web_send (sock_in, "<title>Not here!</title>\n");
-    web_send (sock_in,
-              "<h2><center>This page/feature is not done yet.</center>\n</h2>");
-}
diff --git a/src/webserver/pages/notdone.cpp b/src/webserver/pages/notdone.cpp
new file mode 100644
index 0000000..1fcd44b
--- /dev/null
+++ b/src/webserver/pages/notdone.cpp
@@ -0,0 +1,6 @@
+void generate_notdone (int sock_in, char *query, char *ip)
+{
+    web_send (sock_in, "<title>Not here!</title>\n");
+    web_send (sock_in,
+              "<h2><center>This page/feature is not done yet.</center>\n</h2>");
+}
diff --git a/src/webserver/pages/sample.c b/src/webserver/pages/sample.c
deleted file mode 100644
index 6a33dc0..0000000
--- a/src/webserver/pages/sample.c
+++ /dev/null
@@ -1,22 +0,0 @@
-
-void generate_sample (int sock_in, char *query, char *ip)
-{
-
-    char *name = get_param (query, "name");
-
-    web_send (sock_in, "<title>SAMPLE</title>\n");
-
-    //If a name was not entered...
-    if (name == '\0')
-    {
-        web_send (sock_in, "<form action=\"/testing/\" method=\"GET\">\n");
-        web_send (sock_in, "<input type=\"text\" name=\"name\">\n");
-        web_send (sock_in, "<input type=\"submit\">\n");
-    }
-    else
-    {
-        web_send (sock_in, "Your name is: ");
-        web_send (sock_in, get_param (query, "name"));
-    }
-    printf ("OK!\n");
-}
diff --git a/src/webserver/pages/sample.cpp b/src/webserver/pages/sample.cpp
new file mode 100644
index 0000000..6a33dc0
--- /dev/null
+++ b/src/webserver/pages/sample.cpp
@@ -0,0 +1,22 @@
+
+void generate_sample (int sock_in, char *query, char *ip)
+{
+
+    char *name = get_param (query, "name");
+
+    web_send (sock_in, "<title>SAMPLE</title>\n");
+
+    //If a name was not entered...
+    if (name == '\0')
+    {
+        web_send (sock_in, "<form action=\"/testing/\" method=\"GET\">\n");
+        web_send (sock_in, "<input type=\"text\" name=\"name\">\n");
+        web_send (sock_in, "<input type=\"submit\">\n");
+    }
+    else
+    {
+        web_send (sock_in, "Your name is: ");
+        web_send (sock_in, get_param (query, "name"));
+    }
+    printf ("OK!\n");
+}
diff --git a/src/webserver/parse.c b/src/webserver/parse.c
deleted file mode 100644
index 66ef43b..0000000
--- a/src/webserver/parse.c
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <stdlib.h>
-
-char filtered_query[2000];
-char rdata[500];
-char param_n[500];
-char param_d[500];
-
-char *get_query (char *inquery)
-{
-    memset (filtered_query, 0x0, 2000);
-    sscanf (inquery, "GET %s %[$]", filtered_query);
-    return (filtered_query);
-}
-
-void web_send (int sockin, char *in_data)
-{
-    send (sockin, in_data, strlen (in_data), 0);
-}
-
-//THIS IS BAD CODE BE CAREFULL WITH IT!
-//Watch out for buffer overflow...
-//When using please make sure to check the string size.
-
-//Also note:
-//I take no pride in this code, it is a really bad way of doing this...
-char *get_param (char in_string[500], char swhat[500])
-{
-    int  i = 0;
-    int  marker, iswitch, pint, dint;
-    char flux[500];
-    memset (flux, 0x0, 500);
-
-    //Get the path of out "page"
-    if (swhat == 0)
-    {
-        //while i is not equal to array size
-        while (i != 500)
-        {
-            //if there is a question mark, halt!
-            if (in_string[i] == '?')
-            {
-                i = 499;
-            }
-            else
-                rdata[i] = in_string[i];
-
-            i++;
-        }
-        return rdata;
-    }
-    else                        //so, we want a param...
-    {
-        //calculate where param begins
-        while (i != 500)
-        {
-            if (in_string[i] == '?')
-            {
-                marker = i + 1;
-                i = 499;
-            }
-            i++;
-        }
-
-        i = 0;
-
-        //keep morons from trying to crash this
-        if ((marker > 500) || (marker < 1))
-            marker = 500;
-
-        while (marker != 500)
-        {
-            if ((in_string[marker] != '&') && (in_string[marker] != '\0'))
-            {
-                flux[i] = in_string[marker];
-                i++;
-            }
-            else
-            {
-
-                //we have a param, now we must dig through it
-
-                //clear temp vars
-                memset (param_n, 0x0, 500);
-                memset (param_d, 0x0, 500);
-                iswitch = 0;
-                pint = 0;
-                dint = 0;
-                i = 0;
-
-                //split result into param_n and param_d
-                while (i != 500)
-                {
-                    if ((flux[i] != '=') && (flux[i] != '\0'))
-                    {
-                        if (iswitch == 0)
-                        {
-                            param_n[pint] = flux[i];
-                            pint++;
-                        }
-                        else
-                        {
-                            param_d[dint] = flux[i];
-                            dint++;
-                        }
-                    }
-                    else
-                    {
-                        iswitch = 1;
-                    }
-                    if (flux[i] == '\0')
-                        i = 499;
-
-                    i++;
-                }
-
-                if (strcmp (param_n, swhat) == 0)
-                {
-                    return param_d;
-                }
-
-                i = 0;
-            }
-
-            if (in_string[marker] == '\0')
-            {
-                marker = 499;
-            }
-            marker++;
-        }
-        return 0;
-    }
-}
diff --git a/src/webserver/parse.cpp b/src/webserver/parse.cpp
new file mode 100644
index 0000000..66ef43b
--- /dev/null
+++ b/src/webserver/parse.cpp
@@ -0,0 +1,132 @@
+#include <stdlib.h>
+
+char filtered_query[2000];
+char rdata[500];
+char param_n[500];
+char param_d[500];
+
+char *get_query (char *inquery)
+{
+    memset (filtered_query, 0x0, 2000);
+    sscanf (inquery, "GET %s %[$]", filtered_query);
+    return (filtered_query);
+}
+
+void web_send (int sockin, char *in_data)
+{
+    send (sockin, in_data, strlen (in_data), 0);
+}
+
+//THIS IS BAD CODE BE CAREFULL WITH IT!
+//Watch out for buffer overflow...
+//When using please make sure to check the string size.
+
+//Also note:
+//I take no pride in this code, it is a really bad way of doing this...
+char *get_param (char in_string[500], char swhat[500])
+{
+    int  i = 0;
+    int  marker, iswitch, pint, dint;
+    char flux[500];
+    memset (flux, 0x0, 500);
+
+    //Get the path of out "page"
+    if (swhat == 0)
+    {
+        //while i is not equal to array size
+        while (i != 500)
+        {
+            //if there is a question mark, halt!
+            if (in_string[i] == '?')
+            {
+                i = 499;
+            }
+            else
+                rdata[i] = in_string[i];
+
+            i++;
+        }
+        return rdata;
+    }
+    else                        //so, we want a param...
+    {
+        //calculate where param begins
+        while (i != 500)
+        {
+            if (in_string[i] == '?')
+            {
+                marker = i + 1;
+                i = 499;
+            }
+            i++;
+        }
+
+        i = 0;
+
+        //keep morons from trying to crash this
+        if ((marker > 500) || (marker < 1))
+            marker = 500;
+
+        while (marker != 500)
+        {
+            if ((in_string[marker] != '&') && (in_string[marker] != '\0'))
+            {
+                flux[i] = in_string[marker];
+                i++;
+            }
+            else
+            {
+
+                //we have a param, now we must dig through it
+
+                //clear temp vars
+                memset (param_n, 0x0, 500);
+                memset (param_d, 0x0, 500);
+                iswitch = 0;
+                pint = 0;
+                dint = 0;
+                i = 0;
+
+                //split result into param_n and param_d
+                while (i != 500)
+                {
+                    if ((flux[i] != '=') && (flux[i] != '\0'))
+                    {
+                        if (iswitch == 0)
+                        {
+                            param_n[pint] = flux[i];
+                            pint++;
+                        }
+                        else
+                        {
+                            param_d[dint] = flux[i];
+                            dint++;
+                        }
+                    }
+                    else
+                    {
+                        iswitch = 1;
+                    }
+                    if (flux[i] == '\0')
+                        i = 499;
+
+                    i++;
+                }
+
+                if (strcmp (param_n, swhat) == 0)
+                {
+                    return param_d;
+                }
+
+                i = 0;
+            }
+
+            if (in_string[marker] == '\0')
+            {
+                marker = 499;
+            }
+            marker++;
+        }
+        return 0;
+    }
+}
-- 
cgit v1.2.3-70-g09d2